Merge branch 'develop' into feature/timeline_read_receipts

This commit is contained in:
ganfra 2019-08-13 15:16:10 +02:00
commit 25a4240a5a
30 changed files with 619 additions and 452 deletions

View File

@ -1,8 +1,30 @@
Changes in RiotX 0.3.0 (2019-XX-XX) Changes in RiotX 0.4.0 (2019-XX-XX)
===================================================

Features:
-

Improvements:
-

Other changes:
-

Bugfix:
-

Translations:
-

Build:
-

Changes in RiotX 0.3.0 (2019-08-08)
=================================================== ===================================================


Features: Features:
- Create Direct Room flow - Create Direct Room flow
- Handle `/markdown` command


Improvements: Improvements:
- UI for pending edits (#193) - UI for pending edits (#193)
@ -11,9 +33,10 @@ Improvements:
- Enable proper cancellation of suspending functions (including db transaction) - Enable proper cancellation of suspending functions (including db transaction)
- Enhances network connectivity checks in SDK - Enhances network connectivity checks in SDK
- Add "View Edit History" item in the message bottom sheet (#401) - Add "View Edit History" item in the message bottom sheet (#401)
- Cancel sync request on pause and timeout to 0 after pause (#404)


Other changes: Other changes:
- - Show sync progress also in room detail screen (#403)


Bugfix: Bugfix:
- Edited message: link confusion when (edited) appears in body (#398) - Edited message: link confusion when (edited) appears in body (#398)
@ -23,9 +46,6 @@ Bugfix:
- Fix clear cache (#408) and Logout (#205) - Fix clear cache (#408) and Logout (#205)
- Fix `(edited)` link can be copied to clipboard (#402) - Fix `(edited)` link can be copied to clipboard (#402)


Translations:
-

Build: Build:
- Split APK: generate one APK per arch, to reduce APK size of about 30% - Split APK: generate one APK per arch, to reduce APK size of about 30%



View File

@ -30,6 +30,7 @@ import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.TaskThread import im.vector.matrix.android.internal.task.TaskThread
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
import kotlinx.coroutines.CancellationException
import timber.log.Timber import timber.log.Timber
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
@ -70,6 +71,8 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
if (state is SyncState.RUNNING) { if (state is SyncState.RUNNING) {
Timber.v("Pause sync...") Timber.v("Pause sync...")
updateStateTo(SyncState.PAUSED) updateStateTo(SyncState.PAUSED)
cancelableTask?.cancel()
lock.notify()
} }
} }


@ -90,18 +93,25 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
backgroundDetectionObserver.register(this) backgroundDetectionObserver.register(this)


while (state != SyncState.KILLING) { while (state != SyncState.KILLING) {
Timber.v("Entering loop, state: $state")

if (!networkConnectivityChecker.isConnected() || state == SyncState.PAUSED) { if (!networkConnectivityChecker.isConnected() || state == SyncState.PAUSED) {
Timber.v("Sync is Paused. Waiting...") Timber.v("No network or sync is Paused. Waiting...")
synchronized(lock) { synchronized(lock) {
lock.wait() lock.wait()
} }
Timber.v("...unlocked")
} else { } else {
if (state !is SyncState.RUNNING) { if (state !is SyncState.RUNNING) {
updateStateTo(SyncState.RUNNING(afterPause = true)) updateStateTo(SyncState.RUNNING(afterPause = true))
} }
Timber.v("[$this] Execute sync request with timeout $DEFAULT_LONG_POOL_TIMEOUT")
// No timeout after a pause
val timeout = state.let { if (it is SyncState.RUNNING && it.afterPause) 0 else DEFAULT_LONG_POOL_TIMEOUT }

Timber.v("Execute sync request with timeout $timeout")
val latch = CountDownLatch(1) val latch = CountDownLatch(1)
val params = SyncTask.Params(DEFAULT_LONG_POOL_TIMEOUT) val params = SyncTask.Params(timeout)


cancelableTask = syncTask.configureWith(params) { cancelableTask = syncTask.configureWith(params) {
this.callbackThread = TaskThread.SYNC this.callbackThread = TaskThread.SYNC
@ -109,29 +119,31 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
this.callback = object : MatrixCallback<Unit> { this.callback = object : MatrixCallback<Unit> {


override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
Timber.v("onSuccess")
latch.countDown() latch.countDown()
} }


override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
if (failure is Failure.NetworkConnection if (failure is Failure.NetworkConnection && failure.cause is SocketTimeoutException) {
&& failure.cause is SocketTimeoutException) {
// Timeout are not critical // Timeout are not critical
Timber.v("Timeout") Timber.v("Timeout")
} else { } else if (failure is Failure.Unknown && failure.throwable is CancellationException) {
Timber.e(failure) Timber.v("Cancelled")
} } else if (failure is Failure.ServerError

if (failure !is Failure.NetworkConnection
|| failure.cause is JsonEncodingException) {
// Wait 10s before retrying
sleep(RETRY_WAIT_TIME_MS)
}

if (failure is Failure.ServerError
&& (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) { && (failure.error.code == MatrixError.UNKNOWN_TOKEN || failure.error.code == MatrixError.MISSING_TOKEN)) {
// No token or invalid token, stop the thread // No token or invalid token, stop the thread
Timber.w(failure)
updateStateTo(SyncState.KILLING) updateStateTo(SyncState.KILLING)
} else {
Timber.e(failure)

if (failure !is Failure.NetworkConnection || failure.cause is JsonEncodingException) {
// Wait 10s before retrying
Timber.v("Wait 10s")
sleep(RETRY_WAIT_TIME_MS)
}
} }

latch.countDown() latch.countDown()
} }
} }
@ -139,8 +151,10 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
.executeBy(taskExecutor) .executeBy(taskExecutor)


latch.await() latch.await()
if (state is SyncState.RUNNING) { state.let {
updateStateTo(SyncState.RUNNING(afterPause = false)) if (it is SyncState.RUNNING && it.afterPause) {
updateStateTo(SyncState.RUNNING(afterPause = false))
}
} }


Timber.v("...Continue") Timber.v("...Continue")

View File

@ -71,9 +71,7 @@ android {
targetSdkVersion 28 targetSdkVersion 28
multiDexEnabled true multiDexEnabled true


// For release, use generateVersionCodeFromVersionName() // Note: versionCode is depending on the build variant
versionCode generateVersionCodeFromTimestamp()
//versionCode generateVersionCodeFromVersionName()


versionName "${versionMajor}.${versionMinor}.${versionPatch}-dev" versionName "${versionMajor}.${versionMinor}.${versionPatch}-dev"


@ -117,9 +115,10 @@ android {
} }
} }


android.applicationVariants.all { variant -> applicationVariants.all { variant ->
variant.outputs.each { output -> variant.outputs.each { output ->
def baseAbiVersionCode = project.ext.abiVersionCodes.get(output.getFilter(OutputFile.ABI)) def baseAbiVersionCode = project.ext.abiVersionCodes.get(output.getFilter(OutputFile.ABI))
// Known limitation: it does not modify the value in the BuildConfig.java generated file
output.versionCodeOverride = baseAbiVersionCode * 10_000_000 + variant.versionCode output.versionCodeOverride = baseAbiVersionCode * 10_000_000 + variant.versionCode
} }
} }
@ -162,6 +161,8 @@ android {
gplay { gplay {
dimension "store" dimension "store"


versionCode = generateVersionCodeFromVersionName()

buildConfigField "boolean", "ALLOW_FCM_USE", "true" buildConfigField "boolean", "ALLOW_FCM_USE", "true"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\"" buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\"" buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
@ -170,6 +171,8 @@ android {
fdroid { fdroid {
dimension "store" dimension "store"


versionCode = generateVersionCodeFromTimestamp()

buildConfigField "boolean", "ALLOW_FCM_USE", "false" buildConfigField "boolean", "ALLOW_FCM_USE", "false"
buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\"" buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\"" buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""

View File

@ -15,7 +15,6 @@
*/ */
package im.vector.riotx.fdroid.features.settings.troubleshoot package im.vector.riotx.fdroid.features.settings.troubleshoot


import androidx.appcompat.app.AppCompatActivity
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.resources.StringProvider
import im.vector.riotx.features.settings.VectorPreferences import im.vector.riotx.features.settings.VectorPreferences
@ -25,12 +24,12 @@ import javax.inject.Inject
/** /**
* Test that the application is started on boot * Test that the application is started on boot
*/ */
class TestAutoStartBoot @Inject constructor(private val context: AppCompatActivity, class TestAutoStartBoot @Inject constructor(private val vectorPreferences: VectorPreferences,
private val stringProvider: StringProvider) private val stringProvider: StringProvider)
: TroubleshootTest(R.string.settings_troubleshoot_test_service_boot_title) { : TroubleshootTest(R.string.settings_troubleshoot_test_service_boot_title) {


override fun perform() { override fun perform() {
if (VectorPreferences.autoStartOnBoot(context)) { if (vectorPreferences.autoStartOnBoot()) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_service_boot_success) description = stringProvider.getString(R.string.settings_troubleshoot_test_service_boot_success)
status = TestStatus.SUCCESS status = TestStatus.SUCCESS
quickFix = null quickFix = null
@ -38,7 +37,7 @@ class TestAutoStartBoot @Inject constructor(private val context: AppCompatActivi
description = stringProvider.getString(R.string.settings_troubleshoot_test_service_boot_failed) description = stringProvider.getString(R.string.settings_troubleshoot_test_service_boot_failed)
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_service_boot_quickfix) { quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_service_boot_quickfix) {
override fun doFix() { override fun doFix() {
VectorPreferences.setAutoStartOnBoot(context, true) vectorPreferences.setAutoStartOnBoot(true)
manager?.retry() manager?.retry()
} }
} }

View File

@ -63,9 +63,9 @@ object FcmHelper {
AlarmSyncBroadcastReceiver.cancelAlarm(context) AlarmSyncBroadcastReceiver.cancelAlarm(context)
} }


fun onEnterBackground(context: Context, activeSessionHolder: ActiveSessionHolder) { fun onEnterBackground(context: Context, vectorPreferences: VectorPreferences, activeSessionHolder: ActiveSessionHolder) {
//We need to use alarm in this mode //We need to use alarm in this mode
if (VectorPreferences.areNotificationEnabledForDevice(context) && activeSessionHolder.hasActiveSession()) { if (vectorPreferences.areNotificationEnabledForDevice() && activeSessionHolder.hasActiveSession()) {
val currentSession = activeSessionHolder.getActiveSession() val currentSession = activeSessionHolder.getActiveSession()
AlarmSyncBroadcastReceiver.scheduleAlarm(context, currentSession.myUserId, 4_000L) AlarmSyncBroadcastReceiver.scheduleAlarm(context, currentSession.myUserId, 4_000L)
Timber.i("Alarm scheduled to restart service") Timber.i("Alarm scheduled to restart service")

View File

@ -52,6 +52,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
private lateinit var notifiableEventResolver: NotifiableEventResolver private lateinit var notifiableEventResolver: NotifiableEventResolver
private lateinit var pusherManager: PushersManager private lateinit var pusherManager: PushersManager
private lateinit var activeSessionHolder: ActiveSessionHolder private lateinit var activeSessionHolder: ActiveSessionHolder
private lateinit var vectorPreferences: VectorPreferences


// UI handler // UI handler
private val mUIHandler by lazy { private val mUIHandler by lazy {
@ -64,6 +65,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
notifiableEventResolver = vectorComponent().notifiableEventResolver() notifiableEventResolver = vectorComponent().notifiableEventResolver()
pusherManager = vectorComponent().pusherManager() pusherManager = vectorComponent().pusherManager()
activeSessionHolder = vectorComponent().activeSessionHolder() activeSessionHolder = vectorComponent().activeSessionHolder()
vectorPreferences = vectorComponent().vectorPreferences()
} }


/** /**
@ -72,7 +74,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
* @param message the message * @param message the message
*/ */
override fun onMessageReceived(message: RemoteMessage?) { override fun onMessageReceived(message: RemoteMessage?) {
if (!VectorPreferences.areNotificationEnabledForDevice(applicationContext)) { if (!vectorPreferences.areNotificationEnabledForDevice()) {
Timber.i("Notification are disabled for this device") Timber.i("Notification are disabled for this device")
return return
} }
@ -107,7 +109,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
if (refreshedToken == null) { if (refreshedToken == null) {
Timber.w("onNewToken:received null token") Timber.w("onNewToken:received null token")
} else { } else {
if (VectorPreferences.areNotificationEnabledForDevice(applicationContext) && activeSessionHolder.hasActiveSession()) { if (vectorPreferences.areNotificationEnabledForDevice() && activeSessionHolder.hasActiveSession()) {
pusherManager.registerPusherWithFcmKey(refreshedToken) pusherManager.registerPusherWithFcmKey(refreshedToken)
} }
} }

View File

@ -27,6 +27,7 @@ import com.google.firebase.iid.FirebaseInstanceId
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.di.ActiveSessionHolder
import im.vector.riotx.core.pushers.PushersManager import im.vector.riotx.core.pushers.PushersManager
import im.vector.riotx.features.settings.VectorPreferences
import timber.log.Timber import timber.log.Timber


/** /**
@ -105,7 +106,7 @@ object FcmHelper {
// No op // No op
} }


fun onEnterBackground(context: Context, activeSessionHolder: ActiveSessionHolder) { fun onEnterBackground(context: Context, vectorPreferences: VectorPreferences, activeSessionHolder: ActiveSessionHolder) {
// TODO FCM fallback // TODO FCM fallback
} }
} }

View File

@ -42,6 +42,7 @@ import im.vector.riotx.core.di.DaggerVectorComponent
import im.vector.riotx.core.di.HasVectorInjector import im.vector.riotx.core.di.HasVectorInjector
import im.vector.riotx.core.di.VectorComponent import im.vector.riotx.core.di.VectorComponent
import im.vector.riotx.core.extensions.configureAndStart import im.vector.riotx.core.extensions.configureAndStart
import im.vector.riotx.core.utils.initKnownEmojiHashSet
import im.vector.riotx.features.configuration.VectorConfiguration import im.vector.riotx.features.configuration.VectorConfiguration
import im.vector.riotx.features.lifecycle.VectorActivityLifecycleCallbacks import im.vector.riotx.features.lifecycle.VectorActivityLifecycleCallbacks
import im.vector.riotx.features.notifications.NotificationDrawerManager import im.vector.riotx.features.notifications.NotificationDrawerManager
@ -49,12 +50,12 @@ import im.vector.riotx.features.notifications.NotificationUtils
import im.vector.riotx.features.notifications.PushRuleTriggerListener import im.vector.riotx.features.notifications.PushRuleTriggerListener
import im.vector.riotx.features.rageshake.VectorFileLogger import im.vector.riotx.features.rageshake.VectorFileLogger
import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
import im.vector.riotx.features.version.getVersion import im.vector.riotx.features.settings.VectorPreferences
import im.vector.riotx.features.version.VersionProvider
import im.vector.riotx.push.fcm.FcmHelper import im.vector.riotx.push.fcm.FcmHelper
import timber.log.Timber import timber.log.Timber
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import im.vector.riotx.core.utils.initKnownEmojiHashSet
import javax.inject.Inject import javax.inject.Inject


class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.Provider, androidx.work.Configuration.Provider { class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.Provider, androidx.work.Configuration.Provider {
@ -69,6 +70,8 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
@Inject lateinit var activeSessionHolder: ActiveSessionHolder @Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager @Inject lateinit var notificationDrawerManager: NotificationDrawerManager
@Inject lateinit var pushRuleTriggerListener: PushRuleTriggerListener @Inject lateinit var pushRuleTriggerListener: PushRuleTriggerListener
@Inject lateinit var vectorPreferences: VectorPreferences
@Inject lateinit var versionProvider: VersionProvider
lateinit var vectorComponent: VectorComponent lateinit var vectorComponent: VectorComponent
private var fontThreadHandler: Handler? = null private var fontThreadHandler: Handler? = null


@ -122,7 +125,7 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
fun entersBackground() { fun entersBackground() {
Timber.i("App entered background") // call persistInfo Timber.i("App entered background") // call persistInfo
notificationDrawerManager.persistInfo() notificationDrawerManager.persistInfo()
FcmHelper.onEnterBackground(appContext, activeSessionHolder) FcmHelper.onEnterBackground(appContext, vectorPreferences, activeSessionHolder)
} }
}) })
//This should be done as early as possible //This should be done as early as possible
@ -138,7 +141,7 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
} }


private fun logInfo() { private fun logInfo() {
val appVersion = getVersion(longFormat = true, useBuildNumber = true) val appVersion = versionProvider.getVersion(longFormat = true, useBuildNumber = true)
val sdkVersion = Matrix.getSdkVersion() val sdkVersion = Matrix.getSdkVersion()
val date = SimpleDateFormat("MM-dd HH:mm:ss.SSSZ", Locale.US).format(Date()) val date = SimpleDateFormat("MM-dd HH:mm:ss.SSSZ", Locale.US).format(Date())



View File

@ -64,10 +64,7 @@ import im.vector.riotx.features.roomdirectory.createroom.CreateRoomActivity
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomFragment import im.vector.riotx.features.roomdirectory.createroom.CreateRoomFragment
import im.vector.riotx.features.roomdirectory.picker.RoomDirectoryPickerFragment import im.vector.riotx.features.roomdirectory.picker.RoomDirectoryPickerFragment
import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewNoPreviewFragment import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewNoPreviewFragment
import im.vector.riotx.features.settings.VectorSettingsActivity import im.vector.riotx.features.settings.*
import im.vector.riotx.features.settings.VectorSettingsNotificationPreferenceFragment
import im.vector.riotx.features.settings.VectorSettingsNotificationsTroubleshootFragment
import im.vector.riotx.features.settings.VectorSettingsPreferencesFragment
import im.vector.riotx.features.settings.push.PushGatewaysFragment import im.vector.riotx.features.settings.push.PushGatewaysFragment


@Component(dependencies = [VectorComponent::class], modules = [ViewModelModule::class, HomeModule::class]) @Component(dependencies = [VectorComponent::class], modules = [ViewModelModule::class, HomeModule::class])
@ -158,6 +155,12 @@ interface ScreenComponent {


fun inject(vectorSettingsPreferencesFragment: VectorSettingsPreferencesFragment) fun inject(vectorSettingsPreferencesFragment: VectorSettingsPreferencesFragment)


fun inject(vectorSettingsAdvancedNotificationPreferenceFragment: VectorSettingsAdvancedNotificationPreferenceFragment)

fun inject(vectorSettingsSecurityPrivacyFragment: VectorSettingsSecurityPrivacyFragment)

fun inject(vectorSettingsHelpAboutFragment: VectorSettingsHelpAboutFragment)

fun inject(userAvatarPreference: UserAvatarPreference) fun inject(userAvatarPreference: UserAvatarPreference)


fun inject(vectorSettingsNotificationsTroubleshootFragment: VectorSettingsNotificationsTroubleshootFragment) fun inject(vectorSettingsNotificationsTroubleshootFragment: VectorSettingsNotificationsTroubleshootFragment)

View File

@ -41,6 +41,7 @@ import im.vector.riotx.features.notifications.NotificationDrawerManager
import im.vector.riotx.features.notifications.PushRuleTriggerListener import im.vector.riotx.features.notifications.PushRuleTriggerListener
import im.vector.riotx.features.rageshake.BugReporter import im.vector.riotx.features.rageshake.BugReporter
import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
import im.vector.riotx.features.settings.VectorPreferences
import javax.inject.Singleton import javax.inject.Singleton


@Component(modules = [VectorModule::class]) @Component(modules = [VectorModule::class])
@ -95,6 +96,8 @@ interface VectorComponent {


fun notifiableEventResolver(): NotifiableEventResolver fun notifiableEventResolver(): NotifiableEventResolver


fun vectorPreferences(): VectorPreferences

@Component.Factory @Component.Factory
interface Factory { interface Factory {
fun create(@BindsInstance context: Context): VectorComponent fun create(@BindsInstance context: Context): VectorComponent

View File

@ -16,13 +16,12 @@


package im.vector.riotx.core.resources package im.vector.riotx.core.resources


import android.content.Context
import im.vector.riotx.features.settings.VectorPreferences import im.vector.riotx.features.settings.VectorPreferences
import javax.inject.Inject import javax.inject.Inject


class UserPreferencesProvider @Inject constructor(private val context: Context) { class UserPreferencesProvider @Inject constructor(private val vectorPreferences: VectorPreferences) {


fun shouldShowHiddenEvents(): Boolean { fun shouldShowHiddenEvents(): Boolean {
return VectorPreferences.shouldShowHiddenEvents(context) return vectorPreferences.shouldShowHiddenEvents()
} }
} }

View File

@ -0,0 +1,40 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package im.vector.riotx.core.resources

import android.content.Context
import android.os.Build
import androidx.annotation.NonNull
import javax.inject.Inject

class VersionCodeProvider @Inject constructor(private val context: Context) {

/**
* Returns the version code, read from the Manifest. It is not the same than BuildConfig.VERSION_CODE due to versionCodeOverride
*/
@NonNull
fun getVersionCode(): Long {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)

return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
packageInfo.longVersionCode
} else {
@Suppress("DEPRECATION")
packageInfo.versionCode.toLong()
}
}
}

View File

@ -65,6 +65,7 @@ import im.vector.matrix.android.api.session.room.send.SendState
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent
import im.vector.matrix.android.api.session.room.timeline.getTextEditableContent import im.vector.matrix.android.api.session.room.timeline.getTextEditableContent
import im.vector.matrix.android.api.session.sync.SyncState
import im.vector.matrix.android.api.session.user.model.User import im.vector.matrix.android.api.session.user.model.User
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.di.ScreenComponent
@ -185,6 +186,7 @@ class RoomDetailFragment :
private lateinit var scrollOnNewMessageCallback: ScrollOnNewMessageCallback private lateinit var scrollOnNewMessageCallback: ScrollOnNewMessageCallback
private lateinit var scrollOnHighlightedEventCallback: ScrollOnHighlightedEventCallback private lateinit var scrollOnHighlightedEventCallback: ScrollOnHighlightedEventCallback
@Inject lateinit var eventHtmlRenderer: EventHtmlRenderer @Inject lateinit var eventHtmlRenderer: EventHtmlRenderer
@Inject lateinit var vectorPreferences: VectorPreferences




override fun getLayoutResId() = R.layout.fragment_room_detail override fun getLayoutResId() = R.layout.fragment_room_detail
@ -247,6 +249,14 @@ class RoomDetailFragment :
is SendMode.REPLY -> enterSpecialMode(mode.timelineEvent, R.drawable.ic_reply, false) is SendMode.REPLY -> enterSpecialMode(mode.timelineEvent, R.drawable.ic_reply, false)
} }
} }

roomDetailViewModel.selectSubscribe(RoomDetailViewState::syncState) { syncState ->
syncProgressBar.visibility = when (syncState) {
is SyncState.RUNNING -> if (syncState.afterPause) View.VISIBLE else View.GONE
else -> View.GONE
}
syncProgressBarWrap.visibility = syncProgressBar.visibility
}
} }


private fun setupNotificationView() { private fun setupNotificationView() {
@ -390,7 +400,7 @@ class RoomDetailFragment :
recyclerView.setController(timelineEventController) recyclerView.setController(timelineEventController)
timelineEventController.callback = this timelineEventController.callback = this


if (VectorPreferences.swipeToReplyIsEnabled(requireContext())) { if (vectorPreferences.swipeToReplyIsEnabled()) {
val swipeCallback = RoomMessageTouchHelperCallback(requireContext(), val swipeCallback = RoomMessageTouchHelperCallback(requireContext(),
R.drawable.ic_reply, R.drawable.ic_reply,
object : RoomMessageTouchHelperCallback.QuickReplayHandler { object : RoomMessageTouchHelperCallback.QuickReplayHandler {
@ -483,7 +493,7 @@ class RoomDetailFragment :
composerLayout.sendButton.setOnClickListener { composerLayout.sendButton.setOnClickListener {
val textMessage = composerLayout.composerEditText.text.toString() val textMessage = composerLayout.composerEditText.text.toString()
if (textMessage.isNotBlank()) { if (textMessage.isNotBlank()) {
roomDetailViewModel.process(RoomDetailActions.SendMessage(textMessage, VectorPreferences.isMarkdownEnabled(requireContext()))) roomDetailViewModel.process(RoomDetailActions.SendMessage(textMessage, vectorPreferences.isMarkdownEnabled()))
} }
} }
composerLayout.composerRelatedMessageCloseButton.setOnClickListener { composerLayout.composerRelatedMessageCloseButton.setOnClickListener {
@ -508,7 +518,7 @@ class RoomDetailFragment :
items.add(DialogListItem.SendFile) items.add(DialogListItem.SendFile)
// Send voice // Send voice


if (VectorPreferences.isSendVoiceFeatureEnabled(this)) { if (vectorPreferences.isSendVoiceFeatureEnabled()) {
items.add(DialogListItem.SendVoice.INSTANCE) items.add(DialogListItem.SendVoice.INSTANCE)
} }


@ -517,7 +527,7 @@ class RoomDetailFragment :
//items.add(DialogListItem.SendSticker) //items.add(DialogListItem.SendSticker)
// Camera // Camera


//if (VectorPreferences.useNativeCamera(this)) { //if (vectorPreferences.useNativeCamera()) {
items.add(DialogListItem.TakePhoto) items.add(DialogListItem.TakePhoto)
items.add(DialogListItem.TakeVideo) items.add(DialogListItem.TakeVideo)
//} else { //} else {
@ -639,8 +649,12 @@ class RoomDetailFragment :


private fun renderSendMessageResult(sendMessageResult: SendMessageResult) { private fun renderSendMessageResult(sendMessageResult: SendMessageResult) {
when (sendMessageResult) { when (sendMessageResult) {
is SendMessageResult.MessageSent, is SendMessageResult.MessageSent -> {
// Clear composer
composerLayout.composerEditText.text = null
}
is SendMessageResult.SlashCommandHandled -> { is SendMessageResult.SlashCommandHandled -> {
sendMessageResult.messageRes?.let { showSnackWithMessage(getString(it)) }
// Clear composer // Clear composer
composerLayout.composerEditText.text = null composerLayout.composerEditText.text = null
} }
@ -965,7 +979,7 @@ class RoomDetailFragment :
// vibrate = true // vibrate = true
} }


// if (vibrate && VectorPreferences.vibrateWhenMentioning(context)) { // if (vibrate && vectorPreferences.vibrateWhenMentioning()) {
// val v= context.getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator // val v= context.getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator
// if (v?.hasVibrator() == true) { // if (v?.hasVibrator() == true) {
// v.vibrate(100) // v.vibrate(100)

View File

@ -57,6 +57,7 @@ import im.vector.riotx.core.utils.subscribeLogError
import im.vector.riotx.features.command.CommandParser import im.vector.riotx.features.command.CommandParser
import im.vector.riotx.features.command.ParsedCommand import im.vector.riotx.features.command.ParsedCommand
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDisplayableEvents import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
import im.vector.riotx.features.settings.VectorPreferences
import io.reactivex.rxkotlin.subscribeBy import io.reactivex.rxkotlin.subscribeBy
import org.commonmark.parser.Parser import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer import org.commonmark.renderer.html.HtmlRenderer
@ -67,6 +68,7 @@ import java.util.concurrent.TimeUnit


class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: RoomDetailViewState, class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: RoomDetailViewState,
userPreferencesProvider: UserPreferencesProvider, userPreferencesProvider: UserPreferencesProvider,
private val vectorPreferences: VectorPreferences,
private val session: Session private val session: Session
) : VectorViewModel<RoomDetailViewState>(initialState) { ) : VectorViewModel<RoomDetailViewState>(initialState) {


@ -103,6 +105,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
} }


init { init {
observeSyncState()
observeRoomSummary() observeRoomSummary()
observeEventDisplayedActions() observeEventDisplayedActions()
observeSummaryState() observeSummaryState()
@ -245,8 +248,9 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
_sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandNotImplemented) _sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandNotImplemented)
} }
is ParsedCommand.SetMarkdown -> { is ParsedCommand.SetMarkdown -> {
// TODO vectorPreferences.setMarkdownEnabled(slashCommandResult.enable)
_sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandNotImplemented) _sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandHandled(
if (slashCommandResult.enable) R.string.markdown_has_been_enabled else R.string.markdown_has_been_disabled))
} }
is ParsedCommand.UnbanUser -> { is ParsedCommand.UnbanUser -> {
// TODO // TODO
@ -270,7 +274,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
} }
is ParsedCommand.SendEmote -> { is ParsedCommand.SendEmote -> {
room.sendTextMessage(slashCommandResult.message, msgType = MessageType.MSGTYPE_EMOTE) room.sendTextMessage(slashCommandResult.message, msgType = MessageType.MSGTYPE_EMOTE)
_sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandHandled) _sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandHandled())
} }
is ParsedCommand.ChangeTopic -> { is ParsedCommand.ChangeTopic -> {
handleChangeTopicSlashCommand(slashCommandResult) handleChangeTopicSlashCommand(slashCommandResult)
@ -350,8 +354,6 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
} }
} }
} }
// Handle slash command

} }


private fun legacyRiotQuoteText(quotedText: String?, myText: String): String { private fun legacyRiotQuoteText(quotedText: String?, myText: String): String {
@ -373,7 +375,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
} }


private fun handleChangeTopicSlashCommand(changeTopic: ParsedCommand.ChangeTopic) { private fun handleChangeTopicSlashCommand(changeTopic: ParsedCommand.ChangeTopic) {
_sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandHandled) _sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandHandled())


room.updateTopic(changeTopic.topic, object : MatrixCallback<Unit> { room.updateTopic(changeTopic.topic, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
@ -387,7 +389,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
} }


private fun handleInviteSlashCommand(invite: ParsedCommand.Invite) { private fun handleInviteSlashCommand(invite: ParsedCommand.Invite) {
_sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandHandled) _sendMessageResultLiveData.postLiveEvent(SendMessageResult.SlashCommandHandled())


room.invite(invite.userId, object : MatrixCallback<Unit> { room.invite(invite.userId, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) { override fun onSuccess(data: Unit) {
@ -632,6 +634,17 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
.disposeOnClear() .disposeOnClear()
} }


private fun observeSyncState() {
session.rx()
.liveSyncState()
.subscribe { syncState ->
setState {
copy(syncState = syncState)
}
}
.disposeOnClear()
}

private fun observeRoomSummary() { private fun observeRoomSummary() {
room.rx().liveRoomSummary() room.rx().liveRoomSummary()
.execute { async -> .execute { async ->

View File

@ -21,9 +21,9 @@ import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.Uninitialized
import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.tombstone.RoomTombstoneContent
import im.vector.matrix.android.api.session.room.timeline.Timeline import im.vector.matrix.android.api.session.room.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.api.session.sync.SyncState
import im.vector.matrix.android.api.session.user.model.User import im.vector.matrix.android.api.session.user.model.User


/** /**
@ -50,7 +50,8 @@ data class RoomDetailViewState(
val sendMode: SendMode = SendMode.REGULAR, val sendMode: SendMode = SendMode.REGULAR,
val isEncrypted: Boolean = false, val isEncrypted: Boolean = false,
val tombstoneEvent: Event? = null, val tombstoneEvent: Event? = null,
val tombstoneEventHandling: Async<String> = Uninitialized val tombstoneEventHandling: Async<String> = Uninitialized,
val syncState: SyncState = SyncState.IDLE
) : MvRxState { ) : MvRxState {


constructor(args: RoomDetailArgs) : this(roomId = args.roomId, eventId = args.eventId) constructor(args: RoomDetailArgs) : this(roomId = args.roomId, eventId = args.eventId)

View File

@ -16,13 +16,14 @@


package im.vector.riotx.features.home.room.detail package im.vector.riotx.features.home.room.detail


import androidx.annotation.StringRes
import im.vector.riotx.features.command.Command import im.vector.riotx.features.command.Command


sealed class SendMessageResult { sealed class SendMessageResult {
object MessageSent : SendMessageResult() object MessageSent : SendMessageResult()
class SlashCommandError(val command: Command) : SendMessageResult() class SlashCommandError(val command: Command) : SendMessageResult()
class SlashCommandUnknown(val command: String) : SendMessageResult() class SlashCommandUnknown(val command: String) : SendMessageResult()
object SlashCommandHandled : SendMessageResult() data class SlashCommandHandled(@StringRes val messageRes: Int? = null) : SendMessageResult()
object SlashCommandResultOk : SendMessageResult() object SlashCommandResultOk : SendMessageResult()
class SlashCommandResultError(val throwable: Throwable) : SendMessageResult() class SlashCommandResultError(val throwable: Throwable) : SendMessageResult()
// TODO Remove // TODO Remove

View File

@ -44,6 +44,7 @@ import javax.inject.Singleton
*/ */
@Singleton @Singleton
class NotificationDrawerManager @Inject constructor(private val context: Context, class NotificationDrawerManager @Inject constructor(private val context: Context,
private val vectorPreferences: VectorPreferences,
private val activeSessionHolder: ActiveSessionHolder, private val activeSessionHolder: ActiveSessionHolder,
private val iconLoader: IconLoader, private val iconLoader: IconLoader,
private val bitmapLoader: BitmapLoader, private val bitmapLoader: BitmapLoader,
@ -73,7 +74,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
Events might be grouped and there might not be one notification per event! Events might be grouped and there might not be one notification per event!
*/ */
fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent) { fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent) {
if (!VectorPreferences.areNotificationEnabledForDevice(context)) { if (!vectorPreferences.areNotificationEnabledForDevice()) {
Timber.i("Notification are disabled for this device") Timber.i("Notification are disabled for this device")
return return
} }
@ -326,7 +327,13 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
globalLastMessageTimestamp = lastMessageTimestamp globalLastMessageTimestamp = lastMessageTimestamp
} }


NotificationUtils.buildMessagesListNotification(context, style, roomEventGroupInfo, largeBitmap, lastMessageTimestamp, myUserDisplayName) NotificationUtils.buildMessagesListNotification(context,
vectorPreferences,
style,
roomEventGroupInfo,
largeBitmap,
lastMessageTimestamp,
myUserDisplayName)
?.let { ?.let {
//is there an id for this room? //is there an id for this room?
notifications.add(it) notifications.add(it)
@ -344,7 +351,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
for (event in simpleEvents) { for (event in simpleEvents) {
//We build a simple event //We build a simple event
if (firstTime || !event.hasBeenDisplayed) { if (firstTime || !event.hasBeenDisplayed) {
NotificationUtils.buildSimpleEventNotification(context, event, null, session.myUserId)?.let { NotificationUtils.buildSimpleEventNotification(context, vectorPreferences, event, null, session.myUserId)?.let {
notifications.add(it) notifications.add(it)
NotificationUtils.showNotificationMessage(context, event.eventId, ROOM_EVENT_NOTIFICATION_ID, it) NotificationUtils.showNotificationMessage(context, event.eventId, ROOM_EVENT_NOTIFICATION_ID, it)
event.hasBeenDisplayed = true //we can consider it as displayed event.hasBeenDisplayed = true //we can consider it as displayed
@ -383,6 +390,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context


NotificationUtils.buildSummaryListNotification( NotificationUtils.buildSummaryListNotification(
context, context,
vectorPreferences,
summaryInboxStyle, summaryInboxStyle,
sumTitle, sumTitle,
noisy = hasNewEvent && summaryIsNoisy, noisy = hasNewEvent && summaryIsNoisy,

View File

@ -367,6 +367,7 @@ object NotificationUtils {
* Build a notification for a Room * Build a notification for a Room
*/ */
fun buildMessagesListNotification(context: Context, fun buildMessagesListNotification(context: Context,
vectorPreferences: VectorPreferences,
messageStyle: NotificationCompat.MessagingStyle, messageStyle: NotificationCompat.MessagingStyle,
roomInfo: RoomEventGroupInfo, roomInfo: RoomEventGroupInfo,
largeIcon: Bitmap?, largeIcon: Bitmap?,
@ -420,7 +421,7 @@ object NotificationUtils {
priority = NotificationCompat.PRIORITY_DEFAULT priority = NotificationCompat.PRIORITY_DEFAULT
if (roomInfo.shouldBing) { if (roomInfo.shouldBing) {
//Compat //Compat
VectorPreferences.getNotificationRingTone(context)?.let { vectorPreferences.getNotificationRingTone()?.let {
setSound(it) setSound(it)
} }
setLights(accentColor, 500, 500) setLights(accentColor, 500, 500)
@ -476,7 +477,11 @@ object NotificationUtils {
} }




fun buildSimpleEventNotification(context: Context, simpleNotifiableEvent: NotifiableEvent, largeIcon: Bitmap?, matrixId: String): Notification? { fun buildSimpleEventNotification(context: Context,
vectorPreferences: VectorPreferences,
simpleNotifiableEvent: NotifiableEvent,
largeIcon: Bitmap?,
matrixId: String): Notification? {
val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color)
// Build the pending intent for when the notification is clicked // Build the pending intent for when the notification is clicked
val smallIcon = R.drawable.ic_status_bar val smallIcon = R.drawable.ic_status_bar
@ -534,7 +539,7 @@ object NotificationUtils {
if (simpleNotifiableEvent.noisy) { if (simpleNotifiableEvent.noisy) {
//Compat //Compat
priority = NotificationCompat.PRIORITY_DEFAULT priority = NotificationCompat.PRIORITY_DEFAULT
VectorPreferences.getNotificationRingTone(context)?.let { vectorPreferences.getNotificationRingTone()?.let {
setSound(it) setSound(it)
} }
setLights(accentColor, 500, 500) setLights(accentColor, 500, 500)
@ -606,6 +611,7 @@ object NotificationUtils {
* Build the summary notification * Build the summary notification
*/ */
fun buildSummaryListNotification(context: Context, fun buildSummaryListNotification(context: Context,
vectorPreferences: VectorPreferences,
style: NotificationCompat.InboxStyle, style: NotificationCompat.InboxStyle,
compatSummary: String, compatSummary: String,
noisy: Boolean, noisy: Boolean,
@ -630,7 +636,7 @@ object NotificationUtils {
if (noisy) { if (noisy) {
//Compat //Compat
priority = NotificationCompat.PRIORITY_DEFAULT priority = NotificationCompat.PRIORITY_DEFAULT
VectorPreferences.getNotificationRingTone(context)?.let { vectorPreferences.getNotificationRingTone()?.let {
setSound(it) setSound(it)
} }
setLights(accentColor, 500, 500) setLights(accentColor, 500, 500)

View File

@ -35,7 +35,7 @@ import im.vector.riotx.core.extensions.toOnOff
import im.vector.riotx.core.utils.getDeviceLocale import im.vector.riotx.core.utils.getDeviceLocale
import im.vector.riotx.features.settings.VectorLocale import im.vector.riotx.features.settings.VectorLocale
import im.vector.riotx.features.themes.ThemeUtils import im.vector.riotx.features.themes.ThemeUtils
import im.vector.riotx.features.version.getVersion import im.vector.riotx.features.version.VersionProvider
import okhttp3.* import okhttp3.*
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
@ -51,7 +51,8 @@ import javax.inject.Singleton
* BugReporter creates and sends the bug reports. * BugReporter creates and sends the bug reports.
*/ */
@Singleton @Singleton
class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) { class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
private val versionProvider: VersionProvider) {
var inMultiWindowMode = false var inMultiWindowMode = false


companion object { companion object {
@ -225,7 +226,7 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
.addFormDataPart("user_agent", Matrix.getInstance(context).getUserAgent()) .addFormDataPart("user_agent", Matrix.getInstance(context).getUserAgent())
.addFormDataPart("user_id", userId) .addFormDataPart("user_id", userId)
.addFormDataPart("device_id", deviceId) .addFormDataPart("device_id", deviceId)
.addFormDataPart("version", getVersion(longFormat = true, useBuildNumber = false)) .addFormDataPart("version", versionProvider.getVersion(longFormat = true, useBuildNumber = false))
.addFormDataPart("branch_name", context.getString(R.string.git_branch_name)) .addFormDataPart("branch_name", context.getString(R.string.git_branch_name))
.addFormDataPart("matrix_sdk_version", Matrix.getSdkVersion()) .addFormDataPart("matrix_sdk_version", Matrix.getSdkVersion())
.addFormDataPart("olm_version", olmVersion) .addFormDataPart("olm_version", olmVersion)

View File

@ -21,8 +21,8 @@ import android.os.Build
import androidx.core.content.edit import androidx.core.content.edit
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.Matrix
import im.vector.riotx.BuildConfig import im.vector.riotx.core.resources.VersionCodeProvider
import im.vector.riotx.features.version.getVersion import im.vector.riotx.features.version.VersionProvider
import timber.log.Timber import timber.log.Timber
import java.io.PrintWriter import java.io.PrintWriter
import java.io.StringWriter import java.io.StringWriter
@ -30,16 +30,15 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton


@Singleton @Singleton
class VectorUncaughtExceptionHandler @Inject constructor(private val bugReporter: BugReporter) : Thread.UncaughtExceptionHandler { class VectorUncaughtExceptionHandler @Inject constructor(private val bugReporter: BugReporter,
private val versionProvider: VersionProvider,
private val versionCodeProvider: VersionCodeProvider) : Thread.UncaughtExceptionHandler {


// key to save the crash status // key to save the crash status
companion object { companion object {
private const val PREFS_CRASH_KEY = "PREFS_CRASH_KEY" private const val PREFS_CRASH_KEY = "PREFS_CRASH_KEY"
} }


private val vectorVersion = getVersion(longFormat = true, useBuildNumber = true)
private val matrixSdkVersion = Matrix.getSdkVersion()

private var previousHandler: Thread.UncaughtExceptionHandler? = null private var previousHandler: Thread.UncaughtExceptionHandler? = null


private lateinit var context: Context private lateinit var context: Context
@ -68,9 +67,9 @@ class VectorUncaughtExceptionHandler @Inject constructor(private val bugReporter
val b = StringBuilder() val b = StringBuilder()
val appName = "RiotX" // TODO Matrix.getApplicationName() val appName = "RiotX" // TODO Matrix.getApplicationName()


b.append(appName + " Build : " + BuildConfig.VERSION_CODE + "\n") b.append(appName + " Build : " + versionCodeProvider.getVersionCode() + "\n")
b.append("$appName Version : $vectorVersion\n") b.append("$appName Version : ${versionProvider.getVersion(longFormat = true, useBuildNumber = true)}\n")
b.append("SDK Version : $matrixSdkVersion\n") b.append("SDK Version : ${Matrix.getSdkVersion()}\n")
b.append("Phone : " + Build.MODEL.trim() + " (" + Build.VERSION.INCREMENTAL + " " + Build.VERSION.RELEASE + " " + Build.VERSION.CODENAME + ")\n") b.append("Phone : " + Build.MODEL.trim() + " (" + Build.VERSION.INCREMENTAL + " " + Build.VERSION.RELEASE + " " + Build.VERSION.CODENAME + ")\n")


b.append("Memory statuses \n") b.append("Memory statuses \n")
@ -94,14 +93,6 @@ class VectorUncaughtExceptionHandler @Inject constructor(private val bugReporter
b.append("Thread: ") b.append("Thread: ")
b.append(thread.name) b.append(thread.name)


/*
val a = VectorApp.getCurrentActivity()
if (a != null) {
b.append(", Activity:")
b.append(a.localClassName)
}
*/

b.append(", Exception: ") b.append(", Exception: ")


val sw = StringWriter() val sw = StringWriter()

View File

@ -31,187 +31,192 @@ import im.vector.riotx.features.themes.ThemeUtils
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
import java.util.* import java.util.*
import javax.inject.Inject


object VectorPreferences { class VectorPreferences @Inject constructor(private val context: Context) {


const val SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY = "SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY_2" companion object {
const val SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY = "SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY" const val SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY = "SETTINGS_MESSAGES_SENT_BY_BOT_PREFERENCE_KEY_2"
const val SETTINGS_VERSION_PREFERENCE_KEY = "SETTINGS_VERSION_PREFERENCE_KEY" const val SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY = "SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY"
const val SETTINGS_SDK_VERSION_PREFERENCE_KEY = "SETTINGS_SDK_VERSION_PREFERENCE_KEY" const val SETTINGS_VERSION_PREFERENCE_KEY = "SETTINGS_VERSION_PREFERENCE_KEY"
const val SETTINGS_OLM_VERSION_PREFERENCE_KEY = "SETTINGS_OLM_VERSION_PREFERENCE_KEY" const val SETTINGS_SDK_VERSION_PREFERENCE_KEY = "SETTINGS_SDK_VERSION_PREFERENCE_KEY"
const val SETTINGS_LOGGED_IN_PREFERENCE_KEY = "SETTINGS_LOGGED_IN_PREFERENCE_KEY" const val SETTINGS_OLM_VERSION_PREFERENCE_KEY = "SETTINGS_OLM_VERSION_PREFERENCE_KEY"
const val SETTINGS_HOME_SERVER_PREFERENCE_KEY = "SETTINGS_HOME_SERVER_PREFERENCE_KEY" const val SETTINGS_LOGGED_IN_PREFERENCE_KEY = "SETTINGS_LOGGED_IN_PREFERENCE_KEY"
const val SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY = "SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY" const val SETTINGS_HOME_SERVER_PREFERENCE_KEY = "SETTINGS_HOME_SERVER_PREFERENCE_KEY"
const val SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY = "SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY" const val SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY = "SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY"
const val SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY = "SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY" const val SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY = "SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY"
const val SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY = "SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY"


const val SETTINGS_NOTIFICATION_TROUBLESHOOT_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_TROUBLESHOOT_PREFERENCE_KEY" const val SETTINGS_NOTIFICATION_TROUBLESHOOT_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_TROUBLESHOOT_PREFERENCE_KEY"
const val SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY" const val SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY"
const val SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY" const val SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY"
const val SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY" const val SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY"
const val SETTINGS_COPYRIGHT_PREFERENCE_KEY = "SETTINGS_COPYRIGHT_PREFERENCE_KEY" const val SETTINGS_COPYRIGHT_PREFERENCE_KEY = "SETTINGS_COPYRIGHT_PREFERENCE_KEY"
const val SETTINGS_CLEAR_CACHE_PREFERENCE_KEY = "SETTINGS_CLEAR_CACHE_PREFERENCE_KEY" const val SETTINGS_CLEAR_CACHE_PREFERENCE_KEY = "SETTINGS_CLEAR_CACHE_PREFERENCE_KEY"
const val SETTINGS_CLEAR_MEDIA_CACHE_PREFERENCE_KEY = "SETTINGS_CLEAR_MEDIA_CACHE_PREFERENCE_KEY" const val SETTINGS_CLEAR_MEDIA_CACHE_PREFERENCE_KEY = "SETTINGS_CLEAR_MEDIA_CACHE_PREFERENCE_KEY"
const val SETTINGS_USER_SETTINGS_PREFERENCE_KEY = "SETTINGS_USER_SETTINGS_PREFERENCE_KEY" const val SETTINGS_USER_SETTINGS_PREFERENCE_KEY = "SETTINGS_USER_SETTINGS_PREFERENCE_KEY"
const val SETTINGS_CONTACT_PREFERENCE_KEYS = "SETTINGS_CONTACT_PREFERENCE_KEYS" const val SETTINGS_CONTACT_PREFERENCE_KEYS = "SETTINGS_CONTACT_PREFERENCE_KEYS"
const val SETTINGS_NOTIFICATIONS_TARGETS_PREFERENCE_KEY = "SETTINGS_NOTIFICATIONS_TARGETS_PREFERENCE_KEY" const val SETTINGS_NOTIFICATIONS_TARGETS_PREFERENCE_KEY = "SETTINGS_NOTIFICATIONS_TARGETS_PREFERENCE_KEY"
const val SETTINGS_NOTIFICATIONS_TARGET_DIVIDER_PREFERENCE_KEY = "SETTINGS_NOTIFICATIONS_TARGET_DIVIDER_PREFERENCE_KEY" const val SETTINGS_NOTIFICATIONS_TARGET_DIVIDER_PREFERENCE_KEY = "SETTINGS_NOTIFICATIONS_TARGET_DIVIDER_PREFERENCE_KEY"
const val SETTINGS_IGNORED_USERS_PREFERENCE_KEY = "SETTINGS_IGNORED_USERS_PREFERENCE_KEY" const val SETTINGS_IGNORED_USERS_PREFERENCE_KEY = "SETTINGS_IGNORED_USERS_PREFERENCE_KEY"
const val SETTINGS_IGNORE_USERS_DIVIDER_PREFERENCE_KEY = "SETTINGS_IGNORE_USERS_DIVIDER_PREFERENCE_KEY" const val SETTINGS_IGNORE_USERS_DIVIDER_PREFERENCE_KEY = "SETTINGS_IGNORE_USERS_DIVIDER_PREFERENCE_KEY"
const val SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY = "SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY" const val SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY = "SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY"
const val SETTINGS_BACKGROUND_SYNC_DIVIDER_PREFERENCE_KEY = "SETTINGS_BACKGROUND_SYNC_DIVIDER_PREFERENCE_KEY" const val SETTINGS_BACKGROUND_SYNC_DIVIDER_PREFERENCE_KEY = "SETTINGS_BACKGROUND_SYNC_DIVIDER_PREFERENCE_KEY"
const val SETTINGS_LABS_PREFERENCE_KEY = "SETTINGS_LABS_PREFERENCE_KEY" const val SETTINGS_LABS_PREFERENCE_KEY = "SETTINGS_LABS_PREFERENCE_KEY"
const val SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY" const val SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_PREFERENCE_KEY"
const val SETTINGS_CRYPTOGRAPHY_DIVIDER_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_DIVIDER_PREFERENCE_KEY" const val SETTINGS_CRYPTOGRAPHY_DIVIDER_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_DIVIDER_PREFERENCE_KEY"
const val SETTINGS_CRYPTOGRAPHY_MANAGE_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_MANAGE_PREFERENCE_KEY" const val SETTINGS_CRYPTOGRAPHY_MANAGE_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_MANAGE_PREFERENCE_KEY"
const val SETTINGS_CRYPTOGRAPHY_MANAGE_DIVIDER_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_MANAGE_DIVIDER_PREFERENCE_KEY" const val SETTINGS_CRYPTOGRAPHY_MANAGE_DIVIDER_PREFERENCE_KEY = "SETTINGS_CRYPTOGRAPHY_MANAGE_DIVIDER_PREFERENCE_KEY"
const val SETTINGS_DEVICES_LIST_PREFERENCE_KEY = "SETTINGS_DEVICES_LIST_PREFERENCE_KEY" const val SETTINGS_DEVICES_LIST_PREFERENCE_KEY = "SETTINGS_DEVICES_LIST_PREFERENCE_KEY"
const val SETTINGS_DEVICES_DIVIDER_PREFERENCE_KEY = "SETTINGS_DEVICES_DIVIDER_PREFERENCE_KEY" const val SETTINGS_DEVICES_DIVIDER_PREFERENCE_KEY = "SETTINGS_DEVICES_DIVIDER_PREFERENCE_KEY"
const val SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY = "SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY" const val SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY = "SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY"
const val SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_IS_ACTIVE_PREFERENCE_KEY = "SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_IS_ACTIVE_PREFERENCE_KEY" const val SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_IS_ACTIVE_PREFERENCE_KEY = "SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_IS_ACTIVE_PREFERENCE_KEY"
const val SETTINGS_ENCRYPTION_INFORMATION_DEVICE_NAME_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_INFORMATION_DEVICE_NAME_PREFERENCE_KEY" const val SETTINGS_ENCRYPTION_INFORMATION_DEVICE_NAME_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_INFORMATION_DEVICE_NAME_PREFERENCE_KEY"
const val SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY" const val SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_INFORMATION_DEVICE_ID_PREFERENCE_KEY"
const val SETTINGS_ENCRYPTION_EXPORT_E2E_ROOM_KEYS_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_EXPORT_E2E_ROOM_KEYS_PREFERENCE_KEY" const val SETTINGS_ENCRYPTION_EXPORT_E2E_ROOM_KEYS_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_EXPORT_E2E_ROOM_KEYS_PREFERENCE_KEY"
const val SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY" const val SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY"
const val SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY" const val SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY"
const val SETTINGS_ENCRYPTION_INFORMATION_DEVICE_KEY_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_INFORMATION_DEVICE_KEY_PREFERENCE_KEY" const val SETTINGS_ENCRYPTION_INFORMATION_DEVICE_KEY_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_INFORMATION_DEVICE_KEY_PREFERENCE_KEY"


const val SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY = "SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY" const val SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY = "SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY"


// user // user
const val SETTINGS_DISPLAY_NAME_PREFERENCE_KEY = "SETTINGS_DISPLAY_NAME_PREFERENCE_KEY" const val SETTINGS_DISPLAY_NAME_PREFERENCE_KEY = "SETTINGS_DISPLAY_NAME_PREFERENCE_KEY"
const val SETTINGS_PROFILE_PICTURE_PREFERENCE_KEY = "SETTINGS_PROFILE_PICTURE_PREFERENCE_KEY" const val SETTINGS_PROFILE_PICTURE_PREFERENCE_KEY = "SETTINGS_PROFILE_PICTURE_PREFERENCE_KEY"


// contacts // contacts
const val SETTINGS_CONTACTS_PHONEBOOK_COUNTRY_PREFERENCE_KEY = "SETTINGS_CONTACTS_PHONEBOOK_COUNTRY_PREFERENCE_KEY" const val SETTINGS_CONTACTS_PHONEBOOK_COUNTRY_PREFERENCE_KEY = "SETTINGS_CONTACTS_PHONEBOOK_COUNTRY_PREFERENCE_KEY"


// interface // interface
const val SETTINGS_INTERFACE_LANGUAGE_PREFERENCE_KEY = "SETTINGS_INTERFACE_LANGUAGE_PREFERENCE_KEY" const val SETTINGS_INTERFACE_LANGUAGE_PREFERENCE_KEY = "SETTINGS_INTERFACE_LANGUAGE_PREFERENCE_KEY"
const val SETTINGS_INTERFACE_TEXT_SIZE_KEY = "SETTINGS_INTERFACE_TEXT_SIZE_KEY" const val SETTINGS_INTERFACE_TEXT_SIZE_KEY = "SETTINGS_INTERFACE_TEXT_SIZE_KEY"
const val SETTINGS_SHOW_URL_PREVIEW_KEY = "SETTINGS_SHOW_URL_PREVIEW_KEY" const val SETTINGS_SHOW_URL_PREVIEW_KEY = "SETTINGS_SHOW_URL_PREVIEW_KEY"
private const val SETTINGS_SEND_TYPING_NOTIF_KEY = "SETTINGS_SEND_TYPING_NOTIF_KEY" private const val SETTINGS_SEND_TYPING_NOTIF_KEY = "SETTINGS_SEND_TYPING_NOTIF_KEY"
private const val SETTINGS_ENABLE_MARKDOWN_KEY = "SETTINGS_ENABLE_MARKDOWN_KEY" private const val SETTINGS_ENABLE_MARKDOWN_KEY = "SETTINGS_ENABLE_MARKDOWN_KEY"
private const val SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY = "SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY" private const val SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY = "SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY"
private const val SETTINGS_12_24_TIMESTAMPS_KEY = "SETTINGS_12_24_TIMESTAMPS_KEY" private const val SETTINGS_12_24_TIMESTAMPS_KEY = "SETTINGS_12_24_TIMESTAMPS_KEY"
private const val SETTINGS_SHOW_READ_RECEIPTS_KEY = "SETTINGS_SHOW_READ_RECEIPTS_KEY" private const val SETTINGS_SHOW_READ_RECEIPTS_KEY = "SETTINGS_SHOW_READ_RECEIPTS_KEY"
private const val SETTINGS_SHOW_JOIN_LEAVE_MESSAGES_KEY = "SETTINGS_SHOW_JOIN_LEAVE_MESSAGES_KEY" private const val SETTINGS_SHOW_JOIN_LEAVE_MESSAGES_KEY = "SETTINGS_SHOW_JOIN_LEAVE_MESSAGES_KEY"
private const val SETTINGS_SHOW_AVATAR_DISPLAY_NAME_CHANGES_MESSAGES_KEY = "SETTINGS_SHOW_AVATAR_DISPLAY_NAME_CHANGES_MESSAGES_KEY" private const val SETTINGS_SHOW_AVATAR_DISPLAY_NAME_CHANGES_MESSAGES_KEY = "SETTINGS_SHOW_AVATAR_DISPLAY_NAME_CHANGES_MESSAGES_KEY"
private const val SETTINGS_VIBRATE_ON_MENTION_KEY = "SETTINGS_VIBRATE_ON_MENTION_KEY" private const val SETTINGS_VIBRATE_ON_MENTION_KEY = "SETTINGS_VIBRATE_ON_MENTION_KEY"
private const val SETTINGS_SEND_MESSAGE_WITH_ENTER = "SETTINGS_SEND_MESSAGE_WITH_ENTER" private const val SETTINGS_SEND_MESSAGE_WITH_ENTER = "SETTINGS_SEND_MESSAGE_WITH_ENTER"


// home // home
private const val SETTINGS_PIN_UNREAD_MESSAGES_PREFERENCE_KEY = "SETTINGS_PIN_UNREAD_MESSAGES_PREFERENCE_KEY" private const val SETTINGS_PIN_UNREAD_MESSAGES_PREFERENCE_KEY = "SETTINGS_PIN_UNREAD_MESSAGES_PREFERENCE_KEY"
private const val SETTINGS_PIN_MISSED_NOTIFICATIONS_PREFERENCE_KEY = "SETTINGS_PIN_MISSED_NOTIFICATIONS_PREFERENCE_KEY" private const val SETTINGS_PIN_MISSED_NOTIFICATIONS_PREFERENCE_KEY = "SETTINGS_PIN_MISSED_NOTIFICATIONS_PREFERENCE_KEY"


// flair // flair
const val SETTINGS_GROUPS_FLAIR_KEY = "SETTINGS_GROUPS_FLAIR_KEY" const val SETTINGS_GROUPS_FLAIR_KEY = "SETTINGS_GROUPS_FLAIR_KEY"


// notifications // notifications
const val SETTINGS_NOTIFICATIONS_KEY = "SETTINGS_NOTIFICATIONS_KEY" const val SETTINGS_NOTIFICATIONS_KEY = "SETTINGS_NOTIFICATIONS_KEY"
const val SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY = "SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY" const val SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY = "SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY"
const val SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY = "SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY" const val SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY = "SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"
// public static final String SETTINGS_TURN_SCREEN_ON_PREFERENCE_KEY = "SETTINGS_TURN_SCREEN_ON_PREFERENCE_KEY"; // public static final String SETTINGS_TURN_SCREEN_ON_PREFERENCE_KEY = "SETTINGS_TURN_SCREEN_ON_PREFERENCE_KEY";
const val SETTINGS_SYSTEM_CALL_NOTIFICATION_PREFERENCE_KEY = "SETTINGS_SYSTEM_CALL_NOTIFICATION_PREFERENCE_KEY" const val SETTINGS_SYSTEM_CALL_NOTIFICATION_PREFERENCE_KEY = "SETTINGS_SYSTEM_CALL_NOTIFICATION_PREFERENCE_KEY"
const val SETTINGS_SYSTEM_NOISY_NOTIFICATION_PREFERENCE_KEY = "SETTINGS_SYSTEM_NOISY_NOTIFICATION_PREFERENCE_KEY" const val SETTINGS_SYSTEM_NOISY_NOTIFICATION_PREFERENCE_KEY = "SETTINGS_SYSTEM_NOISY_NOTIFICATION_PREFERENCE_KEY"
const val SETTINGS_SYSTEM_SILENT_NOTIFICATION_PREFERENCE_KEY = "SETTINGS_SYSTEM_SILENT_NOTIFICATION_PREFERENCE_KEY" const val SETTINGS_SYSTEM_SILENT_NOTIFICATION_PREFERENCE_KEY = "SETTINGS_SYSTEM_SILENT_NOTIFICATION_PREFERENCE_KEY"
const val SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY" const val SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY"
const val SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY" const val SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY"
const val SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY = "SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY_2" const val SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY = "SETTINGS_CONTAINING_MY_DISPLAY_NAME_PREFERENCE_KEY_2"
const val SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY = "SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY_2" const val SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY = "SETTINGS_CONTAINING_MY_USER_NAME_PREFERENCE_KEY_2"
const val SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY_2" const val SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_ONE_TO_ONE_PREFERENCE_KEY_2"
const val SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY_2" const val SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY = "SETTINGS_MESSAGES_IN_GROUP_CHAT_PREFERENCE_KEY_2"
const val SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY = "SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY_2" const val SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY = "SETTINGS_INVITED_TO_ROOM_PREFERENCE_KEY_2"
const val SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY = "SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY_2" const val SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY = "SETTINGS_CALL_INVITATIONS_PREFERENCE_KEY_2"


// media // media
private const val SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY = "SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY" private const val SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY = "SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY"
private const val SETTINGS_DEFAULT_MEDIA_SOURCE_KEY = "SETTINGS_DEFAULT_MEDIA_SOURCE_KEY" private const val SETTINGS_DEFAULT_MEDIA_SOURCE_KEY = "SETTINGS_DEFAULT_MEDIA_SOURCE_KEY"
private const val SETTINGS_PREVIEW_MEDIA_BEFORE_SENDING_KEY = "SETTINGS_PREVIEW_MEDIA_BEFORE_SENDING_KEY" private const val SETTINGS_PREVIEW_MEDIA_BEFORE_SENDING_KEY = "SETTINGS_PREVIEW_MEDIA_BEFORE_SENDING_KEY"
private const val SETTINGS_PLAY_SHUTTER_SOUND_KEY = "SETTINGS_PLAY_SHUTTER_SOUND_KEY" private const val SETTINGS_PLAY_SHUTTER_SOUND_KEY = "SETTINGS_PLAY_SHUTTER_SOUND_KEY"


// background sync // background sync
const val SETTINGS_START_ON_BOOT_PREFERENCE_KEY = "SETTINGS_START_ON_BOOT_PREFERENCE_KEY" const val SETTINGS_START_ON_BOOT_PREFERENCE_KEY = "SETTINGS_START_ON_BOOT_PREFERENCE_KEY"
const val SETTINGS_ENABLE_BACKGROUND_SYNC_PREFERENCE_KEY = "SETTINGS_ENABLE_BACKGROUND_SYNC_PREFERENCE_KEY" const val SETTINGS_ENABLE_BACKGROUND_SYNC_PREFERENCE_KEY = "SETTINGS_ENABLE_BACKGROUND_SYNC_PREFERENCE_KEY"
const val SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY = "SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY" const val SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY = "SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY"
const val SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY = "SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY" const val SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY = "SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY"


// Calls // Calls
const val SETTINGS_CALL_RINGTONE_USE_RIOT_PREFERENCE_KEY = "SETTINGS_CALL_RINGTONE_USE_RIOT_PREFERENCE_KEY" const val SETTINGS_CALL_RINGTONE_USE_RIOT_PREFERENCE_KEY = "SETTINGS_CALL_RINGTONE_USE_RIOT_PREFERENCE_KEY"
const val SETTINGS_CALL_RINGTONE_URI_PREFERENCE_KEY = "SETTINGS_CALL_RINGTONE_URI_PREFERENCE_KEY" const val SETTINGS_CALL_RINGTONE_URI_PREFERENCE_KEY = "SETTINGS_CALL_RINGTONE_URI_PREFERENCE_KEY"


// labs // labs
const val SETTINGS_LAZY_LOADING_PREFERENCE_KEY = "SETTINGS_LAZY_LOADING_PREFERENCE_KEY" const val SETTINGS_LAZY_LOADING_PREFERENCE_KEY = "SETTINGS_LAZY_LOADING_PREFERENCE_KEY"
const val SETTINGS_USER_REFUSED_LAZY_LOADING_PREFERENCE_KEY = "SETTINGS_USER_REFUSED_LAZY_LOADING_PREFERENCE_KEY" const val SETTINGS_USER_REFUSED_LAZY_LOADING_PREFERENCE_KEY = "SETTINGS_USER_REFUSED_LAZY_LOADING_PREFERENCE_KEY"
const val SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY = "SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY" const val SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY = "SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY"
private const val SETTINGS_USE_JITSI_CONF_PREFERENCE_KEY = "SETTINGS_USE_JITSI_CONF_PREFERENCE_KEY" private const val SETTINGS_USE_JITSI_CONF_PREFERENCE_KEY = "SETTINGS_USE_JITSI_CONF_PREFERENCE_KEY"
private const val SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY = "SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY" private const val SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY = "SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY"
private const val SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY = "SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY" private const val SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY = "SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY"


private const val SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY = "SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY" private const val SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY = "SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY"
private const val SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY = "SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY" private const val SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY = "SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY"


// analytics // analytics
const val SETTINGS_USE_ANALYTICS_KEY = "SETTINGS_USE_ANALYTICS_KEY" const val SETTINGS_USE_ANALYTICS_KEY = "SETTINGS_USE_ANALYTICS_KEY"
const val SETTINGS_USE_RAGE_SHAKE_KEY = "SETTINGS_USE_RAGE_SHAKE_KEY" const val SETTINGS_USE_RAGE_SHAKE_KEY = "SETTINGS_USE_RAGE_SHAKE_KEY"


// other // other
const val SETTINGS_MEDIA_SAVING_PERIOD_KEY = "SETTINGS_MEDIA_SAVING_PERIOD_KEY" const val SETTINGS_MEDIA_SAVING_PERIOD_KEY = "SETTINGS_MEDIA_SAVING_PERIOD_KEY"
private const val SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY = "SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY" private const val SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY = "SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY"
private const val DID_ASK_TO_IGNORE_BATTERY_OPTIMIZATIONS_KEY = "DID_ASK_TO_IGNORE_BATTERY_OPTIMIZATIONS_KEY" private const val DID_ASK_TO_IGNORE_BATTERY_OPTIMIZATIONS_KEY = "DID_ASK_TO_IGNORE_BATTERY_OPTIMIZATIONS_KEY"
private const val DID_MIGRATE_TO_NOTIFICATION_REWORK = "DID_MIGRATE_TO_NOTIFICATION_REWORK" private const val DID_MIGRATE_TO_NOTIFICATION_REWORK = "DID_MIGRATE_TO_NOTIFICATION_REWORK"
private const val DID_ASK_TO_USE_ANALYTICS_TRACKING_KEY = "DID_ASK_TO_USE_ANALYTICS_TRACKING_KEY" private const val DID_ASK_TO_USE_ANALYTICS_TRACKING_KEY = "DID_ASK_TO_USE_ANALYTICS_TRACKING_KEY"
const val SETTINGS_DEACTIVATE_ACCOUNT_KEY = "SETTINGS_DEACTIVATE_ACCOUNT_KEY" const val SETTINGS_DEACTIVATE_ACCOUNT_KEY = "SETTINGS_DEACTIVATE_ACCOUNT_KEY"
private const val SETTINGS_DISPLAY_ALL_EVENTS_KEY = "SETTINGS_DISPLAY_ALL_EVENTS_KEY" private const val SETTINGS_DISPLAY_ALL_EVENTS_KEY = "SETTINGS_DISPLAY_ALL_EVENTS_KEY"


private const val MEDIA_SAVING_3_DAYS = 0 private const val MEDIA_SAVING_3_DAYS = 0
private const val MEDIA_SAVING_1_WEEK = 1 private const val MEDIA_SAVING_1_WEEK = 1
private const val MEDIA_SAVING_1_MONTH = 2 private const val MEDIA_SAVING_1_MONTH = 2
private const val MEDIA_SAVING_FOREVER = 3 private const val MEDIA_SAVING_FOREVER = 3


// some preferences keys must be kept after a logout // some preferences keys must be kept after a logout
private val mKeysToKeepAfterLogout = Arrays.asList( private val mKeysToKeepAfterLogout = Arrays.asList(
SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY, SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY,
SETTINGS_DEFAULT_MEDIA_SOURCE_KEY, SETTINGS_DEFAULT_MEDIA_SOURCE_KEY,
SETTINGS_PLAY_SHUTTER_SOUND_KEY, SETTINGS_PLAY_SHUTTER_SOUND_KEY,


SETTINGS_SEND_TYPING_NOTIF_KEY, SETTINGS_SEND_TYPING_NOTIF_KEY,
SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY, SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY,
SETTINGS_12_24_TIMESTAMPS_KEY, SETTINGS_12_24_TIMESTAMPS_KEY,
SETTINGS_SHOW_READ_RECEIPTS_KEY, SETTINGS_SHOW_READ_RECEIPTS_KEY,
SETTINGS_SHOW_JOIN_LEAVE_MESSAGES_KEY, SETTINGS_SHOW_JOIN_LEAVE_MESSAGES_KEY,
SETTINGS_SHOW_AVATAR_DISPLAY_NAME_CHANGES_MESSAGES_KEY, SETTINGS_SHOW_AVATAR_DISPLAY_NAME_CHANGES_MESSAGES_KEY,
SETTINGS_MEDIA_SAVING_PERIOD_KEY, SETTINGS_MEDIA_SAVING_PERIOD_KEY,
SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY, SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY,
SETTINGS_PREVIEW_MEDIA_BEFORE_SENDING_KEY, SETTINGS_PREVIEW_MEDIA_BEFORE_SENDING_KEY,
SETTINGS_SEND_MESSAGE_WITH_ENTER, SETTINGS_SEND_MESSAGE_WITH_ENTER,


SETTINGS_PIN_UNREAD_MESSAGES_PREFERENCE_KEY, SETTINGS_PIN_UNREAD_MESSAGES_PREFERENCE_KEY,
SETTINGS_PIN_MISSED_NOTIFICATIONS_PREFERENCE_KEY, SETTINGS_PIN_MISSED_NOTIFICATIONS_PREFERENCE_KEY,
// Do not keep SETTINGS_LAZY_LOADING_PREFERENCE_KEY because the user may log in on a server which does not support lazy loading // Do not keep SETTINGS_LAZY_LOADING_PREFERENCE_KEY because the user may log in on a server which does not support lazy loading
SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY, SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY,
SETTINGS_START_ON_BOOT_PREFERENCE_KEY, SETTINGS_START_ON_BOOT_PREFERENCE_KEY,
SETTINGS_INTERFACE_TEXT_SIZE_KEY, SETTINGS_INTERFACE_TEXT_SIZE_KEY,
SETTINGS_USE_JITSI_CONF_PREFERENCE_KEY, SETTINGS_USE_JITSI_CONF_PREFERENCE_KEY,
SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY, SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY,
SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY, SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY,


SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY, SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY,
SETTINGS_CONTACTS_PHONEBOOK_COUNTRY_PREFERENCE_KEY, SETTINGS_CONTACTS_PHONEBOOK_COUNTRY_PREFERENCE_KEY,
SETTINGS_INTERFACE_LANGUAGE_PREFERENCE_KEY, SETTINGS_INTERFACE_LANGUAGE_PREFERENCE_KEY,
SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY, SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY,
SETTINGS_ENABLE_BACKGROUND_SYNC_PREFERENCE_KEY, SETTINGS_ENABLE_BACKGROUND_SYNC_PREFERENCE_KEY,
SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY, SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY,
SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY, SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY,


SETTINGS_USE_RAGE_SHAKE_KEY SETTINGS_USE_RAGE_SHAKE_KEY
) )
}

private val defaultPrefs = PreferenceManager.getDefaultSharedPreferences(context)


/** /**
* Clear the preferences. * Clear the preferences.
* *
* @param context the context * @param context the context
*/ */
fun clearPreferences(context: Context) { fun clearPreferences() {
val keysToKeep = HashSet(mKeysToKeepAfterLogout) val keysToKeep = HashSet(mKeysToKeepAfterLogout)


// home server urls // home server urls
@ -221,37 +226,35 @@ object VectorPreferences {
// theme // theme
keysToKeep.add(ThemeUtils.APPLICATION_THEME_KEY) keysToKeep.add(ThemeUtils.APPLICATION_THEME_KEY)


val preferences = PreferenceManager.getDefaultSharedPreferences(context) // get all the existing keys
preferences.edit { val keys = defaultPrefs.all.keys
// get all the existing keys
val keys = preferences.all.keys
// remove the one to keep


keys.removeAll(keysToKeep) // remove the one to keep
keys.removeAll(keysToKeep)


defaultPrefs.edit {
for (key in keys) { for (key in keys) {
remove(key) remove(key)
} }
} }
} }


fun areNotificationEnabledForDevice(context: Context): Boolean { fun areNotificationEnabledForDevice(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY, true) return defaultPrefs.getBoolean(SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY, true)
} }


fun setNotificationEnabledForDevice(context: Context, enabled: Boolean?) { fun setNotificationEnabledForDevice(enabled: Boolean?) {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putBoolean(SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY, enabled!!)
putBoolean(SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY, enabled!!) }
}
} }


fun shouldShowHiddenEvents(context: Context): Boolean { fun shouldShowHiddenEvents(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY, false) return defaultPrefs.getBoolean(SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY, false)
} }


fun swipeToReplyIsEnabled(context: Context): Boolean { fun swipeToReplyIsEnabled(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY, true) return defaultPrefs.getBoolean(SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY, true)
} }


/** /**
@ -260,8 +263,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if it was already requested * @return true if it was already requested
*/ */
fun didAskUserToIgnoreBatteryOptimizations(context: Context): Boolean { fun didAskUserToIgnoreBatteryOptimizations(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(DID_ASK_TO_IGNORE_BATTERY_OPTIMIZATIONS_KEY, false) return defaultPrefs.getBoolean(DID_ASK_TO_IGNORE_BATTERY_OPTIMIZATIONS_KEY, false)
} }


/** /**
@ -269,22 +272,20 @@ object VectorPreferences {
* *
* @param context the context * @param context the context
*/ */
fun setDidAskUserToIgnoreBatteryOptimizations(context: Context) { fun setDidAskUserToIgnoreBatteryOptimizations() {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putBoolean(DID_ASK_TO_IGNORE_BATTERY_OPTIMIZATIONS_KEY, true)
putBoolean(DID_ASK_TO_IGNORE_BATTERY_OPTIMIZATIONS_KEY, true) }
}
} }


fun didMigrateToNotificationRework(context: Context): Boolean { fun didMigrateToNotificationRework(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(DID_MIGRATE_TO_NOTIFICATION_REWORK, false) return defaultPrefs.getBoolean(DID_MIGRATE_TO_NOTIFICATION_REWORK, false)
} }


fun setDidMigrateToNotificationRework(context: Context) { fun setDidMigrateToNotificationRework() {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putBoolean(DID_MIGRATE_TO_NOTIFICATION_REWORK, true)
putBoolean(DID_MIGRATE_TO_NOTIFICATION_REWORK, true) }
}
} }


/** /**
@ -293,8 +294,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the time must be displayed in 12h format * @return true if the time must be displayed in 12h format
*/ */
fun displayTimeIn12hFormat(context: Context): Boolean { fun displayTimeIn12hFormat(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_12_24_TIMESTAMPS_KEY, false) return defaultPrefs.getBoolean(SETTINGS_12_24_TIMESTAMPS_KEY, false)
} }


/** /**
@ -303,8 +304,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the join and leave membership events should be shown in the messages list * @return true if the join and leave membership events should be shown in the messages list
*/ */
fun showJoinLeaveMessages(context: Context): Boolean { fun showJoinLeaveMessages(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_SHOW_JOIN_LEAVE_MESSAGES_KEY, true) return defaultPrefs.getBoolean(SETTINGS_SHOW_JOIN_LEAVE_MESSAGES_KEY, true)
} }


/** /**
@ -313,8 +314,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true true if the avatar and display name events should be shown in the messages list. * @return true true if the avatar and display name events should be shown in the messages list.
*/ */
fun showAvatarDisplayNameChangeMessages(context: Context): Boolean { fun showAvatarDisplayNameChangeMessages(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_SHOW_AVATAR_DISPLAY_NAME_CHANGES_MESSAGES_KEY, true) return defaultPrefs.getBoolean(SETTINGS_SHOW_AVATAR_DISPLAY_NAME_CHANGES_MESSAGES_KEY, true)
} }


/** /**
@ -323,8 +324,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true to use the native camera app to record video or take photo. * @return true to use the native camera app to record video or take photo.
*/ */
fun useNativeCamera(context: Context): Boolean { fun useNativeCamera(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY, false) return defaultPrefs.getBoolean(SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY, false)
} }


/** /**
@ -333,8 +334,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the send voice feature is enabled. * @return true if the send voice feature is enabled.
*/ */
fun isSendVoiceFeatureEnabled(context: Context): Boolean { fun isSendVoiceFeatureEnabled(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY, false) return defaultPrefs.getBoolean(SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY, false)
} }


/** /**
@ -343,8 +344,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return the selected compression level * @return the selected compression level
*/ */
fun getSelectedDefaultMediaCompressionLevel(context: Context): Int { fun getSelectedDefaultMediaCompressionLevel(): Int {
return Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(context).getString(SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY, "0")!!) return Integer.parseInt(defaultPrefs.getString(SETTINGS_DEFAULT_MEDIA_COMPRESSION_KEY, "0")!!)
} }


/** /**
@ -353,8 +354,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return the selected media source * @return the selected media source
*/ */
fun getSelectedDefaultMediaSource(context: Context): Int { fun getSelectedDefaultMediaSource(): Int {
return Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(context).getString(SETTINGS_DEFAULT_MEDIA_SOURCE_KEY, "0")!!) return Integer.parseInt(defaultPrefs.getString(SETTINGS_DEFAULT_MEDIA_SOURCE_KEY, "0")!!)
} }


/** /**
@ -363,8 +364,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if shutter sound should play * @return true if shutter sound should play
*/ */
fun useShutterSound(context: Context): Boolean { fun useShutterSound(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_PLAY_SHUTTER_SOUND_KEY, true) return defaultPrefs.getBoolean(SETTINGS_PLAY_SHUTTER_SOUND_KEY, true)
} }


/** /**
@ -373,9 +374,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @param uri the new notification ringtone, or null for no RingTone * @param uri the new notification ringtone, or null for no RingTone
*/ */
fun setNotificationRingTone(context: Context, uri: Uri?) { fun setNotificationRingTone(uri: Uri?) {
PreferenceManager.getDefaultSharedPreferences(context).edit { defaultPrefs.edit {

var value = "" var value = ""


if (null != uri) { if (null != uri) {
@ -399,8 +399,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return the selected ring tone or null for no RingTone * @return the selected ring tone or null for no RingTone
*/ */
fun getNotificationRingTone(context: Context): Uri? { fun getNotificationRingTone(): Uri? {
val url = PreferenceManager.getDefaultSharedPreferences(context).getString(SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY, null) val url = defaultPrefs.getString(SETTINGS_NOTIFICATION_RINGTONE_PREFERENCE_KEY, null)


// the user selects "None" // the user selects "None"
if (TextUtils.equals(url, "")) { if (TextUtils.equals(url, "")) {
@ -433,8 +433,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return the filename or null if "None" is selected * @return the filename or null if "None" is selected
*/ */
fun getNotificationRingToneName(context: Context): String? { fun getNotificationRingToneName(): String? {
val toneUri = getNotificationRingTone(context) ?: return null val toneUri = getNotificationRingTone() ?: return null


var name: String? = null var name: String? = null


@ -467,11 +467,10 @@ object VectorPreferences {
* @param context the context * @param context the context
* @param newValue true to enable lazy loading, false to disable it * @param newValue true to enable lazy loading, false to disable it
*/ */
fun setUseLazyLoading(context: Context, newValue: Boolean) { fun setUseLazyLoading(newValue: Boolean) {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putBoolean(SETTINGS_LAZY_LOADING_PREFERENCE_KEY, newValue)
putBoolean(SETTINGS_LAZY_LOADING_PREFERENCE_KEY, newValue) }
}
} }


/** /**
@ -480,8 +479,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the lazy loading of room members is enabled * @return true if the lazy loading of room members is enabled
*/ */
fun useLazyLoading(context: Context): Boolean { fun useLazyLoading(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_LAZY_LOADING_PREFERENCE_KEY, false) return defaultPrefs.getBoolean(SETTINGS_LAZY_LOADING_PREFERENCE_KEY, false)
} }


/** /**
@ -489,11 +488,10 @@ object VectorPreferences {
* *
* @param context the context * @param context the context
*/ */
fun setUserRefuseLazyLoading(context: Context) { fun setUserRefuseLazyLoading() {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putBoolean(SETTINGS_USER_REFUSED_LAZY_LOADING_PREFERENCE_KEY, true)
putBoolean(SETTINGS_USER_REFUSED_LAZY_LOADING_PREFERENCE_KEY, true) }
}
} }


/** /**
@ -502,8 +500,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the user has explicitly refuse the lazy loading of room members * @return true if the user has explicitly refuse the lazy loading of room members
*/ */
fun hasUserRefusedLazyLoading(context: Context): Boolean { fun hasUserRefusedLazyLoading(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_USER_REFUSED_LAZY_LOADING_PREFERENCE_KEY, false) return defaultPrefs.getBoolean(SETTINGS_USER_REFUSED_LAZY_LOADING_PREFERENCE_KEY, false)
} }


/** /**
@ -512,8 +510,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the data save mode is enabled * @return true if the data save mode is enabled
*/ */
fun useDataSaveMode(context: Context): Boolean { fun useDataSaveMode(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY, false) return defaultPrefs.getBoolean(SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY, false)
} }


/** /**
@ -522,8 +520,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the conference call must be done with jitsi. * @return true if the conference call must be done with jitsi.
*/ */
fun useJitsiConfCall(context: Context): Boolean { fun useJitsiConfCall(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_USE_JITSI_CONF_PREFERENCE_KEY, true) return defaultPrefs.getBoolean(SETTINGS_USE_JITSI_CONF_PREFERENCE_KEY, true)
} }


/** /**
@ -532,8 +530,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the application must be started on boot * @return true if the application must be started on boot
*/ */
fun autoStartOnBoot(context: Context): Boolean { fun autoStartOnBoot(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_START_ON_BOOT_PREFERENCE_KEY, true) return defaultPrefs.getBoolean(SETTINGS_START_ON_BOOT_PREFERENCE_KEY, true)
} }


/** /**
@ -542,11 +540,10 @@ object VectorPreferences {
* @param context the context * @param context the context
* @param value true to start the application on boot * @param value true to start the application on boot
*/ */
fun setAutoStartOnBoot(context: Context, value: Boolean) { fun setAutoStartOnBoot(value: Boolean) {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putBoolean(SETTINGS_START_ON_BOOT_PREFERENCE_KEY, value)
putBoolean(SETTINGS_START_ON_BOOT_PREFERENCE_KEY, value) }
}
} }


/** /**
@ -555,8 +552,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return the selected period * @return the selected period
*/ */
fun getSelectedMediasSavingPeriod(context: Context): Int { fun getSelectedMediasSavingPeriod(): Int {
return PreferenceManager.getDefaultSharedPreferences(context).getInt(SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY, MEDIA_SAVING_1_WEEK) return defaultPrefs.getInt(SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY, MEDIA_SAVING_1_WEEK)
} }


/** /**
@ -565,11 +562,10 @@ object VectorPreferences {
* @param context the context * @param context the context
* @param index the selected period index * @param index the selected period index
*/ */
fun setSelectedMediasSavingPeriod(context: Context, index: Int) { fun setSelectedMediasSavingPeriod(index: Int) {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putInt(SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY, index)
putInt(SETTINGS_MEDIA_SAVING_PERIOD_SELECTED_KEY, index) }
}
} }


/** /**
@ -578,8 +574,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return the min last access time (in seconds) * @return the min last access time (in seconds)
*/ */
fun getMinMediasLastAccessTime(context: Context): Long { fun getMinMediasLastAccessTime(): Long {
val selection = getSelectedMediasSavingPeriod(context) val selection = getSelectedMediasSavingPeriod()


when (selection) { when (selection) {
MEDIA_SAVING_3_DAYS -> return System.currentTimeMillis() / 1000 - 3 * 24 * 60 * 60 MEDIA_SAVING_3_DAYS -> return System.currentTimeMillis() / 1000 - 3 * 24 * 60 * 60
@ -597,8 +593,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return the selected period * @return the selected period
*/ */
fun getSelectedMediasSavingPeriodString(context: Context): String { fun getSelectedMediasSavingPeriodString(): String {
val selection = getSelectedMediasSavingPeriod(context) val selection = getSelectedMediasSavingPeriod()


when (selection) { when (selection) {
MEDIA_SAVING_3_DAYS -> return context.getString(R.string.media_saving_period_3_days) MEDIA_SAVING_3_DAYS -> return context.getString(R.string.media_saving_period_3_days)
@ -612,7 +608,7 @@ object VectorPreferences {
/** /**
* Fix some migration issues * Fix some migration issues
*/ */
fun fixMigrationIssues(context: Context) { fun fixMigrationIssues() {
// Nothing to do for the moment // Nothing to do for the moment
} }


@ -622,8 +618,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the markdown is enabled * @return true if the markdown is enabled
*/ */
fun isMarkdownEnabled(context: Context): Boolean { fun isMarkdownEnabled(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_ENABLE_MARKDOWN_KEY, true) return defaultPrefs.getBoolean(SETTINGS_ENABLE_MARKDOWN_KEY, true)
} }


/** /**
@ -632,11 +628,10 @@ object VectorPreferences {
* @param context the context * @param context the context
* @param isEnabled true to enable the markdown * @param isEnabled true to enable the markdown
*/ */
fun setMarkdownEnabled(context: Context, isEnabled: Boolean) { fun setMarkdownEnabled(isEnabled: Boolean) {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putBoolean(SETTINGS_ENABLE_MARKDOWN_KEY, isEnabled)
putBoolean(SETTINGS_ENABLE_MARKDOWN_KEY, isEnabled) }
}
} }


/** /**
@ -645,8 +640,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the read receipts should be shown * @return true if the read receipts should be shown
*/ */
fun showReadReceipts(context: Context): Boolean { fun showReadReceipts(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_SHOW_READ_RECEIPTS_KEY, true) return defaultPrefs.getBoolean(SETTINGS_SHOW_READ_RECEIPTS_KEY, true)
} }


/** /**
@ -655,8 +650,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the message timestamps must be always shown * @return true if the message timestamps must be always shown
*/ */
fun alwaysShowTimeStamps(context: Context): Boolean { fun alwaysShowTimeStamps(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY, false) return defaultPrefs.getBoolean(SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY, false)
} }


/** /**
@ -665,8 +660,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true to send the typing notifs * @return true to send the typing notifs
*/ */
fun sendTypingNotifs(context: Context): Boolean { fun sendTypingNotifs(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_SEND_TYPING_NOTIF_KEY, true) return defaultPrefs.getBoolean(SETTINGS_SEND_TYPING_NOTIF_KEY, true)
} }


/** /**
@ -675,8 +670,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true to move the missed notifications to the left side * @return true to move the missed notifications to the left side
*/ */
fun pinMissedNotifications(context: Context): Boolean { fun pinMissedNotifications(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_PIN_MISSED_NOTIFICATIONS_PREFERENCE_KEY, true) return defaultPrefs.getBoolean(SETTINGS_PIN_MISSED_NOTIFICATIONS_PREFERENCE_KEY, true)
} }


/** /**
@ -685,8 +680,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true to move the unread room to the left side * @return true to move the unread room to the left side
*/ */
fun pinUnreadMessages(context: Context): Boolean { fun pinUnreadMessages(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_PIN_UNREAD_MESSAGES_PREFERENCE_KEY, true) return defaultPrefs.getBoolean(SETTINGS_PIN_UNREAD_MESSAGES_PREFERENCE_KEY, true)
} }


/** /**
@ -695,8 +690,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true * @return true
*/ */
fun vibrateWhenMentioning(context: Context): Boolean { fun vibrateWhenMentioning(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_VIBRATE_ON_MENTION_KEY, false) return defaultPrefs.getBoolean(SETTINGS_VIBRATE_ON_MENTION_KEY, false)
} }


/** /**
@ -705,8 +700,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if a dialog has been displayed to ask to use the analytics tracking * @return true if a dialog has been displayed to ask to use the analytics tracking
*/ */
fun didAskToUseAnalytics(context: Context): Boolean { fun didAskToUseAnalytics(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(DID_ASK_TO_USE_ANALYTICS_TRACKING_KEY, false) return defaultPrefs.getBoolean(DID_ASK_TO_USE_ANALYTICS_TRACKING_KEY, false)
} }


/** /**
@ -714,11 +709,10 @@ object VectorPreferences {
* *
* @param context the context * @param context the context
*/ */
fun setDidAskToUseAnalytics(context: Context) { fun setDidAskToUseAnalytics() {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putBoolean(DID_ASK_TO_USE_ANALYTICS_TRACKING_KEY, true)
putBoolean(DID_ASK_TO_USE_ANALYTICS_TRACKING_KEY, true) }
}
} }


/** /**
@ -727,8 +721,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the analytics tracking is authorized * @return true if the analytics tracking is authorized
*/ */
fun useAnalytics(context: Context): Boolean { fun useAnalytics(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_USE_ANALYTICS_KEY, false) return defaultPrefs.getBoolean(SETTINGS_USE_ANALYTICS_KEY, false)
} }


/** /**
@ -737,11 +731,10 @@ object VectorPreferences {
* @param context the context * @param context the context
* @param useAnalytics true to enable the analytics tracking * @param useAnalytics true to enable the analytics tracking
*/ */
fun setUseAnalytics(context: Context, useAnalytics: Boolean) { fun setUseAnalytics(useAnalytics: Boolean) {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putBoolean(SETTINGS_USE_ANALYTICS_KEY, useAnalytics)
putBoolean(SETTINGS_USE_ANALYTICS_KEY, useAnalytics) }
}
} }


/** /**
@ -750,8 +743,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true to preview media * @return true to preview media
*/ */
fun previewMediaWhenSending(context: Context): Boolean { fun previewMediaWhenSending(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_PREVIEW_MEDIA_BEFORE_SENDING_KEY, false) return defaultPrefs.getBoolean(SETTINGS_PREVIEW_MEDIA_BEFORE_SENDING_KEY, false)
} }


/** /**
@ -760,8 +753,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true to send message with enter * @return true to send message with enter
*/ */
fun sendMessageWithEnter(context: Context): Boolean { fun sendMessageWithEnter(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_SEND_MESSAGE_WITH_ENTER, false) return defaultPrefs.getBoolean(SETTINGS_SEND_MESSAGE_WITH_ENTER, false)
} }


/** /**
@ -770,8 +763,8 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true if the rage shake is used * @return true if the rage shake is used
*/ */
fun useRageshake(context: Context): Boolean { fun useRageshake(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_USE_RAGE_SHAKE_KEY, true) return defaultPrefs.getBoolean(SETTINGS_USE_RAGE_SHAKE_KEY, true)
} }


/** /**
@ -780,11 +773,10 @@ object VectorPreferences {
* @param context the context * @param context the context
* @param isEnabled true to enable the rage shake * @param isEnabled true to enable the rage shake
*/ */
fun setUseRageshake(context: Context, isEnabled: Boolean) { fun setUseRageshake(isEnabled: Boolean) {
PreferenceManager.getDefaultSharedPreferences(context) defaultPrefs.edit {
.edit { putBoolean(SETTINGS_USE_RAGE_SHAKE_KEY, isEnabled)
putBoolean(SETTINGS_USE_RAGE_SHAKE_KEY, isEnabled) }
}
} }


/** /**
@ -793,7 +785,7 @@ object VectorPreferences {
* @param context the context * @param context the context
* @return true to display all the events even the redacted ones. * @return true to display all the events even the redacted ones.
*/ */
fun displayAllEvents(context: Context): Boolean { fun displayAllEvents(): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_DISPLAY_ALL_EVENTS_KEY, false) return defaultPrefs.getBoolean(SETTINGS_DISPLAY_ALL_EVENTS_KEY, false)
} }
} }

View File

@ -24,11 +24,13 @@ import androidx.core.content.edit
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.di.ScreenComponent
import im.vector.riotx.core.extensions.withArgs import im.vector.riotx.core.extensions.withArgs
import im.vector.riotx.core.preference.BingRule import im.vector.riotx.core.preference.BingRule
import im.vector.riotx.core.preference.BingRulePreference import im.vector.riotx.core.preference.BingRulePreference
import im.vector.riotx.features.notifications.NotificationUtils import im.vector.riotx.features.notifications.NotificationUtils
import im.vector.riotx.features.notifications.supportNotificationChannels import im.vector.riotx.features.notifications.supportNotificationChannels
import javax.inject.Inject


class VectorSettingsAdvancedNotificationPreferenceFragment : VectorSettingsBaseFragment() { class VectorSettingsAdvancedNotificationPreferenceFragment : VectorSettingsBaseFragment() {


@ -45,6 +47,13 @@ class VectorSettingsAdvancedNotificationPreferenceFragment : VectorSettingsBaseF


override val preferenceXmlRes = R.xml.vector_settings_notification_advanced_preferences override val preferenceXmlRes = R.xml.vector_settings_notification_advanced_preferences


@Inject lateinit var vectorPreferences: VectorPreferences

override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}


override fun bindPref() { override fun bindPref() {
val callNotificationsSystemOptions = findPreference(VectorPreferences.SETTINGS_SYSTEM_CALL_NOTIFICATION_PREFERENCE_KEY) val callNotificationsSystemOptions = findPreference(VectorPreferences.SETTINGS_SYSTEM_CALL_NOTIFICATION_PREFERENCE_KEY)
if (supportNotificationChannels()) { if (supportNotificationChannels()) {
@ -83,13 +92,13 @@ class VectorSettingsAdvancedNotificationPreferenceFragment : VectorSettingsBaseF
if (supportNotificationChannels()) { if (supportNotificationChannels()) {
ringtonePreference.isVisible = false ringtonePreference.isVisible = false
} else { } else {
ringtonePreference.summary = VectorPreferences.getNotificationRingToneName(requireContext()) ringtonePreference.summary = vectorPreferences.getNotificationRingToneName()
ringtonePreference.onPreferenceClickListener = Preference.OnPreferenceClickListener { ringtonePreference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER) val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION) intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION)


if (null != VectorPreferences.getNotificationRingTone(requireContext())) { if (null != vectorPreferences.getNotificationRingTone()) {
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, VectorPreferences.getNotificationRingTone(requireContext())) intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, vectorPreferences.getNotificationRingTone())
} }


startActivityForResult(intent, REQUEST_NOTIFICATION_RINGTONE) startActivityForResult(intent, REQUEST_NOTIFICATION_RINGTONE)
@ -152,13 +161,12 @@ class VectorSettingsAdvancedNotificationPreferenceFragment : VectorSettingsBaseF
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
when (requestCode) { when (requestCode) {
REQUEST_NOTIFICATION_RINGTONE -> { REQUEST_NOTIFICATION_RINGTONE -> {
VectorPreferences.setNotificationRingTone(requireContext(), vectorPreferences.setNotificationRingTone(data?.getParcelableExtra<Parcelable>(RingtoneManager.EXTRA_RINGTONE_PICKED_URI) as Uri?)
data?.getParcelableExtra<Parcelable>(RingtoneManager.EXTRA_RINGTONE_PICKED_URI) as Uri?)


// test if the selected ring tone can be played // test if the selected ring tone can be played
val notificationRingToneName = VectorPreferences.getNotificationRingToneName(requireContext()) val notificationRingToneName = vectorPreferences.getNotificationRingToneName()
if (null != notificationRingToneName) { if (null != notificationRingToneName) {
VectorPreferences.setNotificationRingTone(requireContext(), VectorPreferences.getNotificationRingTone(requireContext())) vectorPreferences.setNotificationRingTone(vectorPreferences.getNotificationRingTone())
findPreference(VectorPreferences.SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY).summary = notificationRingToneName findPreference(VectorPreferences.SETTINGS_NOTIFICATION_RINGTONE_SELECTION_PREFERENCE_KEY).summary = notificationRingToneName
} }
} }

View File

@ -23,15 +23,23 @@ import androidx.preference.Preference
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.Matrix
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.di.ScreenComponent
import im.vector.riotx.core.utils.copyToClipboard import im.vector.riotx.core.utils.copyToClipboard
import im.vector.riotx.core.utils.displayInWebView import im.vector.riotx.core.utils.displayInWebView
import im.vector.riotx.features.version.getVersion import im.vector.riotx.features.version.VersionProvider
import javax.inject.Inject


class VectorSettingsHelpAboutFragment : VectorSettingsBaseFragment() { class VectorSettingsHelpAboutFragment : VectorSettingsBaseFragment() {


override var titleRes = R.string.preference_root_help_about override var titleRes = R.string.preference_root_help_about
override val preferenceXmlRes = R.xml.vector_settings_help_about override val preferenceXmlRes = R.xml.vector_settings_help_about


@Inject lateinit var versionProvider: VersionProvider

override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}

override fun bindPref() { override fun bindPref() {
// preference to start the App info screen, to facilitate App permissions access // preference to start the App info screen, to facilitate App permissions access
findPreference(APP_INFO_LINK_PREFERENCE_KEY) findPreference(APP_INFO_LINK_PREFERENCE_KEY)
@ -54,7 +62,7 @@ class VectorSettingsHelpAboutFragment : VectorSettingsBaseFragment() {


// application version // application version
(findPreference(VectorPreferences.SETTINGS_VERSION_PREFERENCE_KEY)).let { (findPreference(VectorPreferences.SETTINGS_VERSION_PREFERENCE_KEY)).let {
it.summary = getVersion(longFormat = false, useBuildNumber = true) it.summary = versionProvider.getVersion(longFormat = false, useBuildNumber = true)


it.setOnPreferenceClickListener { pref -> it.setOnPreferenceClickListener { pref ->
copyToClipboard(requireContext(), pref.summary) copyToClipboard(requireContext(), pref.summary)

View File

@ -36,6 +36,7 @@ class VectorSettingsNotificationPreferenceFragment : VectorSettingsBaseFragment(


@Inject lateinit var pushManager: PushersManager @Inject lateinit var pushManager: PushersManager
@Inject lateinit var activeSessionHolder: ActiveSessionHolder @Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var vectorPreferences: VectorPreferences


override fun bindPref() { override fun bindPref() {
findPreference(VectorPreferences.SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY).let { pref -> findPreference(VectorPreferences.SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY).let { pref ->
@ -84,7 +85,7 @@ class VectorSettingsNotificationPreferenceFragment : VectorSettingsBaseFragment(
val switchPref = preference as SwitchPreference val switchPref = preference as SwitchPreference
if (switchPref.isChecked) { if (switchPref.isChecked) {
FcmHelper.getFcmToken(requireContext())?.let { FcmHelper.getFcmToken(requireContext())?.let {
if (VectorPreferences.areNotificationEnabledForDevice(requireContext())) { if (vectorPreferences.areNotificationEnabledForDevice()) {
pushManager.registerPusherWithFcmKey(it) pushManager.registerPusherWithFcmKey(it)
} }
} }

View File

@ -44,6 +44,7 @@ class VectorSettingsPreferencesFragment : VectorSettingsBaseFragment() {
} }


@Inject lateinit var vectorConfiguration: VectorConfiguration @Inject lateinit var vectorConfiguration: VectorConfiguration
@Inject lateinit var vectorPreferences: VectorPreferences


override fun injectWith(injector: ScreenComponent) { override fun injectWith(injector: ScreenComponent) {
injector.inject(this) injector.inject(this)
@ -113,17 +114,17 @@ class VectorSettingsPreferencesFragment : VectorSettingsBaseFragment() {


// update keep medias period // update keep medias period
findPreference(VectorPreferences.SETTINGS_MEDIA_SAVING_PERIOD_KEY).let { findPreference(VectorPreferences.SETTINGS_MEDIA_SAVING_PERIOD_KEY).let {
it.summary = VectorPreferences.getSelectedMediasSavingPeriodString(requireContext()) it.summary = vectorPreferences.getSelectedMediasSavingPeriodString()


it.onPreferenceClickListener = Preference.OnPreferenceClickListener { it.onPreferenceClickListener = Preference.OnPreferenceClickListener {
context?.let { context: Context -> context?.let { context: Context ->
AlertDialog.Builder(context) AlertDialog.Builder(context)
.setSingleChoiceItems(R.array.media_saving_choice, .setSingleChoiceItems(R.array.media_saving_choice,
VectorPreferences.getSelectedMediasSavingPeriod(context)) { d, n -> vectorPreferences.getSelectedMediasSavingPeriod()) { d, n ->
VectorPreferences.setSelectedMediasSavingPeriod(context, n) vectorPreferences.setSelectedMediasSavingPeriod(n)
d.cancel() d.cancel()


it.summary = VectorPreferences.getSelectedMediasSavingPeriodString(context) it.summary = vectorPreferences.getSelectedMediasSavingPeriodString()
} }
.show() .show()
} }

View File

@ -42,6 +42,7 @@ import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.di.ScreenComponent
import im.vector.riotx.core.dialogs.ExportKeysDialog import im.vector.riotx.core.dialogs.ExportKeysDialog
import im.vector.riotx.core.intent.ExternalIntentData import im.vector.riotx.core.intent.ExternalIntentData
import im.vector.riotx.core.intent.analyseIntent import im.vector.riotx.core.intent.analyseIntent
@ -57,6 +58,7 @@ import timber.log.Timber
import java.text.DateFormat import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import javax.inject.Inject


class VectorSettingsSecurityPrivacyFragment : VectorSettingsBaseFragment() { class VectorSettingsSecurityPrivacyFragment : VectorSettingsBaseFragment() {


@ -127,6 +129,12 @@ class VectorSettingsSecurityPrivacyFragment : VectorSettingsBaseFragment() {
findPreference(VectorPreferences.SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY) as SwitchPreference findPreference(VectorPreferences.SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY) as SwitchPreference
} }


@Inject lateinit var vectorPreferences: VectorPreferences

override fun injectWith(injector: ScreenComponent) {
injector.inject(this)
}

override fun bindPref() { override fun bindPref() {
// Push target // Push target
refreshPushersList() refreshPushersList()
@ -142,20 +150,20 @@ class VectorSettingsSecurityPrivacyFragment : VectorSettingsBaseFragment() {
// Analytics tracking management // Analytics tracking management
(findPreference(VectorPreferences.SETTINGS_USE_ANALYTICS_KEY) as SwitchPreference).let { (findPreference(VectorPreferences.SETTINGS_USE_ANALYTICS_KEY) as SwitchPreference).let {
// On if the analytics tracking is activated // On if the analytics tracking is activated
it.isChecked = VectorPreferences.useAnalytics(requireContext()) it.isChecked = vectorPreferences.useAnalytics()


it.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> it.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
VectorPreferences.setUseAnalytics(requireContext(), newValue as Boolean) vectorPreferences.setUseAnalytics(newValue as Boolean)
true true
} }
} }


// Rageshake Management // Rageshake Management
(findPreference(VectorPreferences.SETTINGS_USE_RAGE_SHAKE_KEY) as SwitchPreference).let { (findPreference(VectorPreferences.SETTINGS_USE_RAGE_SHAKE_KEY) as SwitchPreference).let {
it.isChecked = VectorPreferences.useRageshake(requireContext()) it.isChecked = vectorPreferences.useRageshake()


it.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> it.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
VectorPreferences.setUseRageshake(requireContext(), newValue as Boolean) vectorPreferences.setUseRageshake(newValue as Boolean)
true true
} }
} }

View File

@ -15,7 +15,6 @@
*/ */
package im.vector.riotx.features.settings.troubleshoot package im.vector.riotx.features.settings.troubleshoot


import androidx.appcompat.app.AppCompatActivity
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.resources.StringProvider
import im.vector.riotx.features.settings.VectorPreferences import im.vector.riotx.features.settings.VectorPreferences
@ -24,20 +23,20 @@ import javax.inject.Inject
/** /**
* Checks if notifications are enable in the system settings for this app. * Checks if notifications are enable in the system settings for this app.
*/ */
class TestDeviceSettings @Inject constructor(private val context: AppCompatActivity, class TestDeviceSettings @Inject constructor(private val vectorPreferences: VectorPreferences,
private val stringProvider: StringProvider) private val stringProvider: StringProvider)
: TroubleshootTest(R.string.settings_troubleshoot_test_device_settings_title) { : TroubleshootTest(R.string.settings_troubleshoot_test_device_settings_title) {


override fun perform() { override fun perform() {


if (VectorPreferences.areNotificationEnabledForDevice(context)) { if (vectorPreferences.areNotificationEnabledForDevice()) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_device_settings_success) description = stringProvider.getString(R.string.settings_troubleshoot_test_device_settings_success)
quickFix = null quickFix = null
status = TestStatus.SUCCESS status = TestStatus.SUCCESS
} else { } else {
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_device_settings_quickfix) { quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_device_settings_quickfix) {
override fun doFix() { override fun doFix() {
VectorPreferences.setNotificationEnabledForDevice(context, true) vectorPreferences.setNotificationEnabledForDevice(true)
manager?.retry() manager?.retry()
} }
} }

View File

@ -1,49 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package im.vector.riotx.features.version

import im.vector.riotx.BuildConfig

fun getVersion(longFormat: Boolean, useBuildNumber: Boolean): String {
var result = "${BuildConfig.VERSION_NAME} [${BuildConfig.VERSION_CODE}]"

var flavor = BuildConfig.SHORT_FLAVOR_DESCRIPTION

if (flavor.isNotBlank()) {
flavor += "-"
}

var gitVersion = BuildConfig.GIT_REVISION
val gitRevisionDate = BuildConfig.GIT_REVISION_DATE
val buildNumber = BuildConfig.BUILD_NUMBER

var useLongFormat = longFormat

if (useBuildNumber && buildNumber != "0") {
// It's a build from CI
gitVersion = "b$buildNumber"
useLongFormat = false
}

result += if (useLongFormat) {
" ($flavor$gitVersion-$gitRevisionDate)"
} else {
" ($flavor$gitVersion)"
}

return result
}

View File

@ -0,0 +1,54 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package im.vector.riotx.features.version

import im.vector.riotx.BuildConfig
import im.vector.riotx.core.resources.VersionCodeProvider
import javax.inject.Inject

class VersionProvider @Inject constructor(private val versionCodeProvider: VersionCodeProvider) {

fun getVersion(longFormat: Boolean, useBuildNumber: Boolean): String {
var result = "${BuildConfig.VERSION_NAME} [${versionCodeProvider.getVersionCode()}]"

var flavor = BuildConfig.SHORT_FLAVOR_DESCRIPTION

if (flavor.isNotBlank()) {
flavor += "-"
}

var gitVersion = BuildConfig.GIT_REVISION
val gitRevisionDate = BuildConfig.GIT_REVISION_DATE
val buildNumber = BuildConfig.BUILD_NUMBER

var useLongFormat = longFormat

if (useBuildNumber && buildNumber != "0") {
// It's a build from CI
gitVersion = "b$buildNumber"
useLongFormat = false
}

result += if (useLongFormat) {
" ($flavor$gitVersion-$gitRevisionDate)"
} else {
" ($flavor$gitVersion)"
}

return result
}
}

View File

@ -11,8 +11,8 @@
style="@style/VectorToolbarStyle" style="@style/VectorToolbarStyle"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="?actionBarSize" android:layout_height="?actionBarSize"
android:transitionName="toolbar"
android:elevation="4dp" android:elevation="4dp"
android:transitionName="toolbar"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
@ -71,6 +71,29 @@


</androidx.appcompat.widget.Toolbar> </androidx.appcompat.widget.Toolbar>


<!-- Trick to remove surrounding padding (clip frome wrapping frame) -->
<FrameLayout
android:id="@+id/syncProgressBarWrap"
android:layout_width="match_parent"
android:layout_height="3dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/roomToolbar"
tools:visibility="visible">

<ProgressBar
android:id="@+id/syncProgressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="14dp"
android:layout_gravity="center"
android:background="?riotx_header_panel_background"
android:indeterminate="true"
android:visibility="gone"
tools:visibility="visible" />
</FrameLayout>

<com.airbnb.epoxy.EpoxyRecyclerView <com.airbnb.epoxy.EpoxyRecyclerView
android:id="@+id/recyclerView" android:id="@+id/recyclerView"
android:layout_width="0dp" android:layout_width="0dp"
@ -78,7 +101,7 @@
app:layout_constraintBottom_toTopOf="@+id/recyclerViewBarrier" app:layout_constraintBottom_toTopOf="@+id/recyclerViewBarrier"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/roomToolbar" app:layout_constraintTop_toBottomOf="@id/syncProgressBarWrap"
tools:listitem="@layout/item_timeline_event_base" /> tools:listitem="@layout/item_timeline_event_base" />


<androidx.constraintlayout.widget.Barrier <androidx.constraintlayout.widget.Barrier