Merge pull request #236 from vector-im/feature/lab_show_hidden_events

Feature/lab show hidden events
This commit is contained in:
Benoit Marty 2019-06-28 12:51:31 +02:00 committed by GitHub
commit d28e9862a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 195 additions and 173 deletions

View File

@ -125,7 +125,7 @@ internal class DefaultTimeline(
}
var hasChanged = false
changeSet.changes.forEach {index ->
changeSet.changes.forEach { index ->
val eventEntity = results[index]
eventEntity?.eventId?.let { eventId ->
builtEventsIdMap[eventId]?.let { builtIndex ->
@ -289,10 +289,12 @@ internal class DefaultTimeline(
private fun buildSendingEvents(): List<TimelineEvent> {
val sendingEvents = ArrayList<TimelineEvent>()
if (hasReachedEnd(Timeline.Direction.FORWARDS)) {
roomEntity?.sendingTimelineEvents?.forEach {
val timelineEvent = timelineEventFactory.create(it)
sendingEvents.add(timelineEvent)
}
roomEntity?.sendingTimelineEvents
?.filter { allowedTypes?.contains(it.type) ?: false }
?.forEach {
val timelineEvent = timelineEventFactory.create(it)
sendingEvents.add(timelineEvent)
}
}
return sendingEvents
}
@ -303,14 +305,14 @@ internal class DefaultTimeline(
private fun getPaginationState(direction: Timeline.Direction): PaginationState {
return when (direction) {
Timeline.Direction.FORWARDS -> forwardsPaginationState.get()
Timeline.Direction.FORWARDS -> forwardsPaginationState.get()
Timeline.Direction.BACKWARDS -> backwardsPaginationState.get()
}
}
private fun updatePaginationState(direction: Timeline.Direction, update: (PaginationState) -> PaginationState) {
val stateReference = when (direction) {
Timeline.Direction.FORWARDS -> forwardsPaginationState
Timeline.Direction.FORWARDS -> forwardsPaginationState
Timeline.Direction.BACKWARDS -> backwardsPaginationState
}
val currentValue = stateReference.get()

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,39 +3,44 @@
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.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:defaultValue="true"-->
<!--android:key="SETTINGS_USE_JITSI_CONF_PREFERENCE_KEY"-->
<!--android:title="@string/settings_labs_create_conference_with_jitsi" />-->
<!--<im.vector.riotredesign.core.preference.VectorSwitchPreference-->
<!--android:key="SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY"-->
<!--android:summary="@string/settings_labs_enable_send_voice_summary"-->
<!--android:title="@string/settings_labs_enable_send_voice" />-->
<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" />
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.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:defaultValue="true"
android:key="SETTINGS_USE_JITSI_CONF_PREFERENCE_KEY"
android:title="@string/settings_labs_create_conference_with_jitsi" />
<im.vector.riotredesign.core.preference.VectorSwitchPreference
android:key="SETTINGS_ENABLE_SEND_VOICE_FEATURE_PREFERENCE_KEY"
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.VectorPreferenceCategory>-->
</androidx.preference.PreferenceScreen>