Add lab option to show hidden events in timeline

+ cleaning labs settings
This commit is contained in:
Valere 2019-06-27 16:48:07 +02:00 committed by Benoit Marty
parent b92cc524b6
commit b14a6224ba
10 changed files with 175 additions and 155 deletions

View File

@ -92,7 +92,6 @@ android {
debug {
resValue "bool", "debug_mode", "true"
buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
buildConfigField "boolean", "SHOW_HIDDEN_TIMELINE_EVENTS", "false"

signingConfig signingConfigs.debug
}
@ -100,7 +99,6 @@ android {
release {
resValue "bool", "debug_mode", "false"
buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
buildConfigField "boolean", "SHOW_HIDDEN_TIMELINE_EVENTS", "false"

minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

View File

@ -0,0 +1,28 @@
/*
* 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.riotredesign.core.resources

import android.content.Context
import im.vector.riotredesign.features.settings.PreferencesManager
import javax.inject.Inject

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

fun shouldShowHiddenEvents(): Boolean {
return PreferencesManager.shouldShowHiddenEvents(context)
}
}

View File

@ -37,6 +37,7 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.rx.rx
import im.vector.riotredesign.R
import im.vector.riotredesign.core.platform.VectorViewModel
import im.vector.riotredesign.core.resources.UserPreferencesProvider
import im.vector.riotredesign.core.utils.LiveEvent
import im.vector.riotredesign.features.command.CommandParser
import im.vector.riotredesign.features.command.ParsedCommand
@ -51,6 +52,7 @@ import java.util.concurrent.TimeUnit


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

@ -58,7 +60,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
private val roomId = initialState.roomId
private val eventId = initialState.eventId
private val displayedEventsObservable = BehaviorRelay.create<RoomDetailActions.EventDisplayed>()
private val allowedTypes = if (TimelineDisplayableEvents.DEBUG_HIDDEN_EVENT) {
private val allowedTypes = if (userPreferencesProvider.shouldShowHiddenEvents()) {
TimelineDisplayableEvents.DEBUG_DISPLAYABLE_TYPES
} else {
TimelineDisplayableEvents.DISPLAYABLE_TYPES
@ -77,13 +79,9 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: RoomDetailViewState): RoomDetailViewModel? {
val fragment: RoomDetailFragment = (viewModelContext as FragmentViewModelContext).fragment()

return fragment.roomDetailViewModelFactory.create(state)
}

override fun initialState(viewModelContext: ViewModelContext): RoomDetailViewState? {

return super.initialState(viewModelContext)
}
}

init {

View File

@ -30,6 +30,7 @@ import im.vector.matrix.android.api.session.room.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.riotredesign.core.epoxy.LoadingItem_
import im.vector.riotredesign.core.extensions.localDateTime
import im.vector.riotredesign.core.resources.UserPreferencesProvider
import im.vector.riotredesign.features.home.AvatarRenderer
import im.vector.riotredesign.features.home.room.detail.timeline.factory.TimelineItemFactory
import im.vector.riotredesign.features.home.room.detail.timeline.helper.*
@ -47,7 +48,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
private val avatarRenderer: AvatarRenderer,
@TimelineEventControllerHandler
private val backgroundHandler: Handler
private val backgroundHandler: Handler,
userPreferencesProvider: UserPreferencesProvider
) : EpoxyController(backgroundHandler, backgroundHandler), Timeline.Listener {

interface Callback : ReactionPillCallback, AvatarCallback, BaseCallback, UrlClickCallback {
@ -132,6 +134,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim
}
}

private val showHiddenEvents = userPreferencesProvider.shouldShowHiddenEvents()

init {
requestModelBuild()
}
@ -234,7 +238,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Tim

private fun buildItemModels(currentPosition: Int, items: List<TimelineEvent>): CacheItemData {
val event = items[currentPosition]
val nextEvent = items.nextDisplayableEvent(currentPosition)
val nextEvent = items.nextDisplayableEvent(currentPosition, showHiddenEvents)
val date = event.root.localDateTime()
val nextDate = nextEvent?.root?.localDateTime()
val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()

View File

@ -17,16 +17,14 @@
package im.vector.riotredesign.features.home.room.detail.timeline.factory

import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.model.message.MessageDefaultContent
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.riotredesign.core.epoxy.EmptyItem_
import im.vector.riotredesign.core.epoxy.VectorEpoxyModel
import im.vector.riotredesign.features.home.AvatarRenderer
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
import im.vector.riotredesign.features.home.room.detail.timeline.helper.senderAvatar
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTextItem_
import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem_
import timber.log.Timber
import javax.inject.Inject

@ -34,7 +32,8 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
private val encryptionItemFactory: EncryptionItemFactory,
private val encryptedItemFactory: EncryptedItemFactory,
private val noticeItemFactory: NoticeItemFactory,
private val defaultItemFactory: DefaultItemFactory) {
private val defaultItemFactory: DefaultItemFactory,
private val avatarRenderer: AvatarRenderer) {

fun create(event: TimelineEvent,
nextEvent: TimelineEvent?,
@ -65,30 +64,21 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me

else -> {
//These are just for debug to display hidden event, they should be filtered out in normal mode
if (TimelineDisplayableEvents.DEBUG_HIDDEN_EVENT) {
val informationData = MessageInformationData(eventId = event.root.eventId
?: "?",
senderId = event.root.senderId ?: "",
sendState = event.sendState,
time = "",
avatarUrl = null,
memberName = "",
showInformation = false
)
val messageContent = event.root.content.toModel<MessageContent>()
?: MessageDefaultContent("", "", null, null)
MessageTextItem_()
.informationData(informationData)
.message("{ \"type\": ${event.root.type} }")
.highlighted(highlight)
.longClickListener { view ->
return@longClickListener callback?.onEventLongClicked(informationData, messageContent, view)
?: false
}
} else {
Timber.w("Ignored event (type: ${event.root.type}")
null
}
val informationData = MessageInformationData(
eventId = event.root.eventId ?: "?",
senderId = event.root.senderId ?: "",
sendState = event.sendState,
time = "",
avatarUrl = event.senderAvatar(),
memberName = "",
showInformation = false
)
NoticeItem_()
.avatarRenderer(avatarRenderer)
.informationData(informationData)
.noticeText("{ \"type\": ${event.root.type} }")
.highlighted(highlight)
.baseCallback(callback)
}
}
} catch (e: Exception) {

View File

@ -22,14 +22,10 @@ import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.RoomMember
import im.vector.matrix.android.api.session.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.riotredesign.BuildConfig
import im.vector.riotredesign.core.extensions.localDateTime

object TimelineDisplayableEvents {

//Debug helper, to show invisible items in time line (reaction, redacts)
val DEBUG_HIDDEN_EVENT = BuildConfig.SHOW_HIDDEN_TIMELINE_EVENTS

val DISPLAYABLE_TYPES = listOf(
EventType.MESSAGE,
EventType.STATE_ROOM_NAME,
@ -52,8 +48,10 @@ object TimelineDisplayableEvents {
)
}

fun TimelineEvent.isDisplayable(): Boolean {
if (!TimelineDisplayableEvents.DISPLAYABLE_TYPES.contains(root.type)) {
fun TimelineEvent.isDisplayable(showHiddenEvent: Boolean): Boolean {
val allowed = TimelineDisplayableEvents.DEBUG_DISPLAYABLE_TYPES.takeIf { showHiddenEvent }
?: TimelineDisplayableEvents.DISPLAYABLE_TYPES
if (!allowed.contains(root.type)) {
return false
}
if (root.content.isNullOrEmpty()) {
@ -132,10 +130,10 @@ fun List<TimelineEvent>.prevSameTypeEvents(index: Int, minSize: Int): List<Timel
.reversed()
}

fun List<TimelineEvent>.nextDisplayableEvent(index: Int): TimelineEvent? {
fun List<TimelineEvent>.nextDisplayableEvent(index: Int, showHiddenEvent: Boolean): TimelineEvent? {
return if (index >= size - 1) {
null
} else {
subList(index + 1, this.size).firstOrNull { it.isDisplayable() }
subList(index + 1, this.size).firstOrNull { it.isDisplayable(showHiddenEvent) }
}
}

View File

@ -155,6 +155,8 @@ public class PreferencesManager {
private static final String SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY = "SETTINGS_USE_NATIVE_CAMERA_PREFERENCE_KEY";
private static final String SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY = "SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY";

private static final String SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY = "SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY";

// analytics
public static final String SETTINGS_USE_ANALYTICS_KEY = "SETTINGS_USE_ANALYTICS_KEY";
public static final String SETTINGS_USE_RAGE_SHAKE_KEY = "SETTINGS_USE_RAGE_SHAKE_KEY";
@ -253,6 +255,10 @@ public class PreferencesManager {
.apply();
}

public static boolean shouldShowHiddenEvents(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY, false);
}

/**
* Tells if we have already asked the user to disable battery optimisations on android >= M devices.
*

View File

@ -16,11 +16,6 @@

package im.vector.riotredesign.features.settings

import android.text.TextUtils
import androidx.appcompat.app.AlertDialog
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.SwitchPreference
import im.vector.riotredesign.R

class VectorSettingsLabsFragment : VectorSettingsBaseFragment() {
@ -28,101 +23,97 @@ class VectorSettingsLabsFragment : VectorSettingsBaseFragment() {
override var titleRes = R.string.room_settings_labs_pref_title
override val preferenceXmlRes = R.xml.vector_settings_labs

private val mLabsCategory by lazy {
findPreference(PreferencesManager.SETTINGS_LABS_PREFERENCE_KEY) as PreferenceCategory
}

override fun bindPref() {
// Lab
val useCryptoPref = findPreference(PreferencesManager.SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY) as SwitchPreference
val cryptoIsEnabledPref = findPreference(PreferencesManager.SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_IS_ACTIVE_PREFERENCE_KEY)
// val useCryptoPref = findPreference(PreferencesManager.SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY) as SwitchPreference
// val cryptoIsEnabledPref = findPreference(PreferencesManager.SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_IS_ACTIVE_PREFERENCE_KEY)


if (session.isCryptoEnabled()) {
mLabsCategory.removePreference(useCryptoPref)

cryptoIsEnabledPref.isEnabled = false
// mLabsCategory.removePreference(useCryptoPref)
//
// cryptoIsEnabledPref.isEnabled = false
} else {
mLabsCategory.removePreference(cryptoIsEnabledPref)

useCryptoPref.isChecked = false

useCryptoPref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValueAsVoid ->
if (TextUtils.isEmpty(session.sessionParams.credentials.deviceId)) {
activity?.let { activity ->
AlertDialog.Builder(activity)
.setMessage(R.string.room_settings_labs_end_to_end_warnings)
.setPositiveButton(R.string.logout) { _, _ ->
notImplemented()
// TODO CommonActivityUtils.logout(activity)
}
.setNegativeButton(R.string.cancel) { _, _ ->
useCryptoPref.isChecked = false
}
.setOnCancelListener {
useCryptoPref.isChecked = false
}
.show()
}
} else {
val newValue = newValueAsVoid as Boolean

if (session.isCryptoEnabled() != newValue) {
notImplemented()
/* TODO
displayLoadingView()

session.enableCrypto(newValue, object : MatrixCallback<Unit> {
private fun refresh() {
activity?.runOnUiThread {
hideLoadingView()
useCryptoPref.isChecked = session.isCryptoEnabled

if (session.isCryptoEnabled) {
mLabsCategory.removePreference(useCryptoPref)
mLabsCategory.addPreference(cryptoIsEnabledPref)
}
}
}

override fun onSuccess(info: Void?) {
useCryptoPref.isEnabled = false
refresh()
}

override fun onNetworkError(e: Exception) {
useCryptoPref.isChecked = false
}

override fun onMatrixError(e: MatrixError) {
useCryptoPref.isChecked = false
}

override fun onUnexpectedError(e: Exception) {
useCryptoPref.isChecked = false
}
})
*/
}
}

true
}
// mLabsCategory.removePreference(cryptoIsEnabledPref)
//
// useCryptoPref.isChecked = false
//
// useCryptoPref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValueAsVoid ->
// if (TextUtils.isEmpty(mSession.sessionParams.credentials.deviceId)) {
// activity?.let { activity ->
// AlertDialog.Builder(activity)
// .setMessage(R.string.room_settings_labs_end_to_end_warnings)
// .setPositiveButton(R.string.logout) { _, _ ->
// notImplemented()
// // TODO CommonActivityUtils.logout(activity)
// }
// .setNegativeButton(R.string.cancel) { _, _ ->
// useCryptoPref.isChecked = false
// }
// .setOnCancelListener {
// useCryptoPref.isChecked = false
// }
// .show()
// }
// } else {
// val newValue = newValueAsVoid as Boolean
//
// if (mSession.isCryptoEnabled() != newValue) {
// notImplemented()
// /* TODO
// displayLoadingView()
//
// session.enableCrypto(newValue, object : MatrixCallback<Unit> {
// private fun refresh() {
// activity?.runOnUiThread {
// hideLoadingView()
// useCryptoPref.isChecked = session.isCryptoEnabled
//
// if (session.isCryptoEnabled) {
// mLabsCategory.removePreference(useCryptoPref)
// mLabsCategory.addPreference(cryptoIsEnabledPref)
// }
// }
// }
//
// override fun onSuccess(info: Void?) {
// useCryptoPref.isEnabled = false
// refresh()
// }
//
// override fun onNetworkError(e: Exception) {
// useCryptoPref.isChecked = false
// }
//
// override fun onMatrixError(e: MatrixError) {
// useCryptoPref.isChecked = false
// }
//
// override fun onUnexpectedError(e: Exception) {
// useCryptoPref.isChecked = false
// }
// })
// */
// }
// }
//
// true
// }
}

// SaveMode Management
findPreference(PreferencesManager.SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY)
.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
notImplemented()
/* TODO
val sessions = Matrix.getMXSessions(activity)
for (session in sessions) {
session.setUseDataSaveMode(newValue as Boolean)
}
*/

true
}
// findPreference(PreferencesManager.SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY)
// .onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
// notImplemented()
// /* TODO
// val sessions = Matrix.getMXSessions(activity)
// for (session in sessions) {
// session.setUseDataSaveMode(newValue as Boolean)
// }
// */
//
// true
// }
}

}

View File

@ -46,4 +46,6 @@
<string name="send_suggestion_sent">Thanks, the suggestion has been successfully sent</string>
<string name="send_suggestion_failed">The suggestion failed to be sent (%s)</string>

<string name="settings_labs_show_hidden_events_in_timeline">Show hidden events in timeline</string>

</resources>

View File

@ -3,28 +3,28 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<im.vector.riotredesign.core.preference.VectorPreferenceCategory
android:key="SETTINGS_LABS_PREFERENCE_KEY"
android:title="@string/room_settings_labs_pref_title">
<!--<im.vector.riotredesign.core.preference.VectorPreferenceCategory-->
<!--android:key="SETTINGS_LABS_PREFERENCE_KEY"-->
<!--android:title="@string/room_settings_labs_pref_title">-->

<im.vector.riotredesign.core.preference.VectorPreference
android:focusable="false"
android:key="labs_warning"
android:title="@string/room_settings_labs_warning_message" />
android:summary="@string/room_settings_labs_warning_message" />

<im.vector.riotredesign.core.preference.VectorSwitchPreference
android:key="SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY"
android:title="@string/room_settings_labs_end_to_end" />
<!--<im.vector.riotredesign.core.preference.VectorSwitchPreference-->
<!--android:key="SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_PREFERENCE_KEY"-->
<!--android:title="@string/room_settings_labs_end_to_end" />-->

<im.vector.riotredesign.core.preference.VectorPreference
android:focusable="false"
android:key="SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_IS_ACTIVE_PREFERENCE_KEY"
android:title="@string/room_settings_labs_end_to_end_is_active" />
<!--<im.vector.riotredesign.core.preference.VectorPreference-->
<!--android:focusable="false"-->
<!--android:key="SETTINGS_ROOM_SETTINGS_LABS_END_TO_END_IS_ACTIVE_PREFERENCE_KEY"-->
<!--android:title="@string/room_settings_labs_end_to_end_is_active" />-->

<im.vector.riotredesign.core.preference.VectorSwitchPreference
android:key="SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY"
android:summary="@string/settings_data_save_mode_summary"
android:title="@string/settings_data_save_mode" />
<!--<im.vector.riotredesign.core.preference.VectorSwitchPreference-->
<!--android:key="SETTINGS_DATA_SAVE_MODE_PREFERENCE_KEY"-->
<!--android:summary="@string/settings_data_save_mode_summary"-->
<!--android:title="@string/settings_data_save_mode" />-->

<im.vector.riotredesign.core.preference.VectorSwitchPreference
android:defaultValue="true"
@ -36,6 +36,11 @@
android:summary="@string/settings_labs_enable_send_voice_summary"
android:title="@string/settings_labs_enable_send_voice" />

</im.vector.riotredesign.core.preference.VectorPreferenceCategory>
<im.vector.riotredesign.core.preference.VectorSwitchPreference
android:key="SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY"
android:defaultValue="false"
android:title="@string/settings_labs_show_hidden_events_in_timeline" />

<!--</im.vector.riotredesign.core.preference.VectorPreferenceCategory>-->

</androidx.preference.PreferenceScreen>