refactor: making radio options and adapter and list items generic

This commit is contained in:
0x330a 2023-08-09 16:36:19 +10:00
parent 9dc8f18b86
commit 317ecf6cee
7 changed files with 141 additions and 83 deletions

View file

@ -18,12 +18,12 @@ import kotlinx.coroutines.launch
import network.loki.messenger.BuildConfig import network.loki.messenger.BuildConfig
import network.loki.messenger.R import network.loki.messenger.R
import network.loki.messenger.databinding.ActivityExpirationSettingsBinding import network.loki.messenger.databinding.ActivityExpirationSettingsBinding
import network.loki.messenger.libsession_util.util.ExpiryMode
import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.messaging.messages.ExpirationConfiguration
import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.database.RecipientDatabase import org.thoughtcrime.securesms.database.RecipientDatabase
import org.thoughtcrime.securesms.database.ThreadDatabase import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.preferences.RadioOption import org.thoughtcrime.securesms.preferences.ExpirationRadioOption
import org.thoughtcrime.securesms.preferences.RadioOptionAdapter import org.thoughtcrime.securesms.preferences.RadioOptionAdapter
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
import javax.inject.Inject import javax.inject.Inject
@ -45,19 +45,25 @@ class ExpirationSettingsActivity: PassphraseRequiredActionBarActivity() {
private val viewModel: ExpirationSettingsViewModel by viewModels { private val viewModel: ExpirationSettingsViewModel by viewModels {
val afterReadOptions = resources.getIntArray(R.array.read_expiration_time_values).map(Int::toString) val afterReadOptions = resources.getIntArray(R.array.read_expiration_time_values).map(Int::toString)
.zip(resources.getStringArray(R.array.read_expiration_time_names)) { value, name -> .zip(resources.getStringArray(R.array.read_expiration_time_names)) { value, name ->
RadioOption(value, name, getString(R.string.AccessibilityId_time_option)) ExpirationRadioOption(ExpiryMode.AfterRead(value.toLong()), name, getString(R.string.AccessibilityId_time_option))
} }
val afterSendOptions = resources.getIntArray(R.array.send_expiration_time_values).map(Int::toString) val afterSendOptions = resources.getIntArray(R.array.send_expiration_time_values).map(Int::toString)
.zip(resources.getStringArray(R.array.send_expiration_time_names)) { value, name -> .zip(resources.getStringArray(R.array.send_expiration_time_names)) { value, name ->
RadioOption(value, name, getString(R.string.AccessibilityId_time_option)) ExpirationRadioOption(ExpiryMode.AfterSend(value.toLong()), name, getString(R.string.AccessibilityId_time_option))
} }
viewModelFactory.create(threadId, mayAddTestExpiryOption(afterReadOptions), mayAddTestExpiryOption(afterSendOptions)) viewModelFactory.create(threadId, mayAddTestExpiryOption(afterReadOptions), mayAddTestExpiryOption(afterSendOptions))
} }
private fun mayAddTestExpiryOption(expiryOptions: List<RadioOption>): List<RadioOption> { private fun mayAddTestExpiryOption(expiryOptions: List<ExpirationRadioOption>): List<ExpirationRadioOption> {
return if (BuildConfig.DEBUG) { return if (BuildConfig.DEBUG) {
val options = expiryOptions.toMutableList() val options = expiryOptions.toMutableList()
options.add(1, RadioOption("60", "1 Minute (for testing purposes)")) val added = when (options.first().value) {
is ExpiryMode.AfterRead -> ExpiryMode.AfterRead(60)
is ExpiryMode.AfterSend -> ExpiryMode.AfterSend(60)
is ExpiryMode.Legacy -> ExpiryMode.Legacy(60)
ExpiryMode.NONE -> ExpiryMode.NONE // shouldn't happen
}
options.add(1, ExpirationRadioOption(added, "1 Minute (for testing purposes)"))
options options
} else expiryOptions } else expiryOptions
} }
@ -129,7 +135,7 @@ class ExpirationSettingsActivity: PassphraseRequiredActionBarActivity() {
lifecycleScope.launch { lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) { repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.selectedExpirationType.collect { type -> viewModel.selectedExpirationType.collect { type ->
val position = deleteTypeOptions.indexOfFirst { it.value.toIntOrNull() == type } val position = deleteTypeOptions.indexOfFirst { it.value == type }
deleteTypeOptionAdapter.setSelectedPosition(max(0, position)) deleteTypeOptionAdapter.setSelectedPosition(max(0, position))
} }
} }
@ -170,32 +176,61 @@ class ExpirationSettingsActivity: PassphraseRequiredActionBarActivity() {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show() Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
} }
private fun getDeleteOptions(): List<RadioOption> { private fun getDeleteOptions(): List<ExpirationRadioOption> {
if (!viewModel.uiState.value.showExpirationTypeSelector) return emptyList() if (!viewModel.uiState.value.showExpirationTypeSelector) return emptyList()
val deleteTypeOptions = mutableListOf<RadioOption>() val deleteTypeOptions = mutableListOf<ExpirationRadioOption>()
if (ExpirationConfiguration.isNewConfigEnabled) { if (ExpirationConfiguration.isNewConfigEnabled) {
if (viewModel.recipient.value?.isContactRecipient == true && viewModel.recipient.value?.isLocalNumber == false) { if (viewModel.recipient.value?.isContactRecipient == true && viewModel.recipient.value?.isLocalNumber == false) {
deleteTypeOptions.addAll( deleteTypeOptions.addAll(
listOf( listOf(
RadioOption( ExpirationRadioOption(
value = "-1", value = ExpiryMode.NONE,
title = getString(R.string.expiration_off), title = getString(R.string.expiration_off),
enabled = viewModel.uiState.value.isSelfAdmin,
contentDescription = getString(R.string.AccessibilityId_disable_disappearing_messages) contentDescription = getString(R.string.AccessibilityId_disable_disappearing_messages)
), ),
RadioOption( ExpirationRadioOption(
value = ExpirationType.DELETE_AFTER_READ_VALUE.toString(), value = ExpiryMode.AfterRead(0),
title = getString(R.string.expiration_type_disappear_after_read), title = getString(R.string.expiration_type_disappear_after_read),
subtitle = getString(R.string.expiration_type_disappear_after_read_description), subtitle = getString(R.string.expiration_type_disappear_after_read_description),
enabled = viewModel.uiState.value.isSelfAdmin,
contentDescription = getString(R.string.AccessibilityId_disappear_after_read_option) contentDescription = getString(R.string.AccessibilityId_disappear_after_read_option)
), ),
RadioOption( ExpirationRadioOption(
value = ExpirationType.DELETE_AFTER_SEND_VALUE.toString(), value = ExpiryMode.AfterSend(0),
title = getString(R.string.expiration_type_disappear_after_send),
subtitle = getString(R.string.expiration_type_disappear_after_send_description),
contentDescription = getString(R.string.AccessibilityId_disappear_after_send_option)
)
)
)
} else if (viewModel.recipient.value?.isLocalNumber == true) {
deleteTypeOptions.addAll(
listOf(
ExpirationRadioOption(
value = ExpiryMode.NONE,
title = getString(R.string.expiration_off),
contentDescription = getString(R.string.AccessibilityId_disable_disappearing_messages)
),
ExpirationRadioOption(
value = ExpiryMode.AfterSend(0),
title = getString(R.string.expiration_type_disappear_after_send),
subtitle = getString(R.string.expiration_type_disappear_after_send_description),
contentDescription = getString(R.string.AccessibilityId_disappear_after_send_option)
)
)
)
} else if (viewModel.recipient.value?.isClosedGroupRecipient == true) {
deleteTypeOptions.addAll(
listOf(
ExpirationRadioOption(
value = ExpiryMode.NONE,
title = getString(R.string.expiration_off),
contentDescription = getString(R.string.AccessibilityId_disable_disappearing_messages)
),
ExpirationRadioOption(
value = ExpiryMode.AfterSend(0),
title = getString(R.string.expiration_type_disappear_after_send), title = getString(R.string.expiration_type_disappear_after_send),
subtitle = getString(R.string.expiration_type_disappear_after_send_description), subtitle = getString(R.string.expiration_type_disappear_after_send_description),
enabled = viewModel.uiState.value.isSelfAdmin,
contentDescription = getString(R.string.AccessibilityId_disappear_after_send_option) contentDescription = getString(R.string.AccessibilityId_disappear_after_send_option)
) )
) )
@ -205,25 +240,25 @@ class ExpirationSettingsActivity: PassphraseRequiredActionBarActivity() {
if (viewModel.recipient.value?.isContactRecipient == true && viewModel.recipient.value?.isLocalNumber == false) { if (viewModel.recipient.value?.isContactRecipient == true && viewModel.recipient.value?.isLocalNumber == false) {
deleteTypeOptions.addAll( deleteTypeOptions.addAll(
listOf( listOf(
RadioOption( ExpirationRadioOption(
value = "-1", value = ExpiryMode.NONE,
title = getString(R.string.expiration_off), title = getString(R.string.expiration_off),
contentDescription = getString(R.string.AccessibilityId_disable_disappearing_messages) contentDescription = getString(R.string.AccessibilityId_disable_disappearing_messages)
), ),
RadioOption( ExpirationRadioOption(
value = "0", value = ExpiryMode.Legacy(0),
title = getString(R.string.expiration_type_disappear_legacy), title = getString(R.string.expiration_type_disappear_legacy),
subtitle = getString(R.string.expiration_type_disappear_legacy_description) subtitle = getString(R.string.expiration_type_disappear_legacy_description)
), ),
RadioOption( ExpirationRadioOption(
value = ExpirationType.DELETE_AFTER_READ_VALUE.toString(), value = ExpiryMode.AfterRead(0),
title = getString(R.string.expiration_type_disappear_after_read), title = getString(R.string.expiration_type_disappear_after_read),
subtitle = getString(R.string.expiration_type_disappear_after_read_description), subtitle = getString(R.string.expiration_type_disappear_after_read_description),
enabled = false, enabled = false,
contentDescription = getString(R.string.AccessibilityId_disappear_after_read_option) contentDescription = getString(R.string.AccessibilityId_disappear_after_read_option)
), ),
RadioOption( ExpirationRadioOption(
value = ExpirationType.DELETE_AFTER_SEND_VALUE.toString(), value = ExpiryMode.AfterSend(0),
title = getString(R.string.expiration_type_disappear_after_send), title = getString(R.string.expiration_type_disappear_after_send),
subtitle = getString(R.string.expiration_type_disappear_after_send_description), subtitle = getString(R.string.expiration_type_disappear_after_send_description),
enabled = false, enabled = false,
@ -234,14 +269,14 @@ class ExpirationSettingsActivity: PassphraseRequiredActionBarActivity() {
} else { } else {
deleteTypeOptions.addAll( deleteTypeOptions.addAll(
listOf( listOf(
RadioOption(value = "-1", title = getString(R.string.expiration_off)), ExpirationRadioOption(value = ExpiryMode.NONE, title = getString(R.string.expiration_off)),
RadioOption( ExpirationRadioOption(
value = "0", value = ExpiryMode.Legacy(0),
title = getString(R.string.expiration_type_disappear_legacy), title = getString(R.string.expiration_type_disappear_legacy),
subtitle = getString(R.string.expiration_type_disappear_legacy_description) subtitle = getString(R.string.expiration_type_disappear_legacy_description)
), ),
RadioOption( ExpirationRadioOption(
value = ExpirationType.DELETE_AFTER_SEND_VALUE.toString(), value = ExpiryMode.AfterSend(0),
title = getString(R.string.expiration_type_disappear_after_send), title = getString(R.string.expiration_type_disappear_after_send),
subtitle = getString(R.string.expiration_type_disappear_after_send_description), subtitle = getString(R.string.expiration_type_disappear_after_send_description),
enabled = false, enabled = false,
@ -258,7 +293,7 @@ class ExpirationSettingsActivity: PassphraseRequiredActionBarActivity() {
setSupportActionBar(binding.toolbar) setSupportActionBar(binding.toolbar)
val actionBar = supportActionBar ?: return val actionBar = supportActionBar ?: return
actionBar.title = getString(R.string.activity_expiration_settings_title) actionBar.title = getString(R.string.activity_expiration_settings_title)
actionBar.subtitle = if (viewModel.selectedExpirationType.value == ExpirationType.DELETE_AFTER_SEND.number) { actionBar.subtitle = if (viewModel.selectedExpirationType.value is ExpiryMode.AfterSend) {
getString(R.string.activity_expiration_settings_subtitle_sent) getString(R.string.activity_expiration_settings_subtitle_sent)
} else { } else {
getString(R.string.activity_expiration_settings_subtitle) getString(R.string.activity_expiration_settings_subtitle)

View file

@ -19,20 +19,17 @@ import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.snode.SnodeAPI import org.session.libsession.snode.SnodeAPI
import org.session.libsession.utilities.SSKEnvironment.MessageExpirationManagerProtocol import org.session.libsession.utilities.SSKEnvironment.MessageExpirationManagerProtocol
import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.expiryType
import org.session.libsession.utilities.recipients.Recipient import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.typeRadioIndex
import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType
import org.thoughtcrime.securesms.database.GroupDatabase import org.thoughtcrime.securesms.database.GroupDatabase
import org.thoughtcrime.securesms.database.Storage import org.thoughtcrime.securesms.database.Storage
import org.thoughtcrime.securesms.database.ThreadDatabase import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.preferences.RadioOption import org.thoughtcrime.securesms.preferences.ExpirationRadioOption
import kotlin.reflect.KClass import kotlin.reflect.KClass
class ExpirationSettingsViewModel( class ExpirationSettingsViewModel(
private val threadId: Long, private val threadId: Long,
private val afterReadOptions: List<RadioOption>, private val afterReadOptions: List<ExpirationRadioOption>,
private val afterSendOptions: List<RadioOption>, private val afterSendOptions: List<ExpirationRadioOption>,
private val textSecurePreferences: TextSecurePreferences, private val textSecurePreferences: TextSecurePreferences,
private val messageExpirationManager: MessageExpirationManagerProtocol, private val messageExpirationManager: MessageExpirationManagerProtocol,
private val threadDb: ThreadDatabase, private val threadDb: ThreadDatabase,
@ -48,14 +45,14 @@ class ExpirationSettingsViewModel(
private val _recipient = MutableStateFlow<Recipient?>(null) private val _recipient = MutableStateFlow<Recipient?>(null)
val recipient: StateFlow<Recipient?> = _recipient val recipient: StateFlow<Recipient?> = _recipient
private val _selectedExpirationType = MutableStateFlow(-1) private val _selectedExpirationType: MutableStateFlow<ExpiryMode> = MutableStateFlow(ExpiryMode.NONE)
val selectedExpirationType: StateFlow<Int> = _selectedExpirationType val selectedExpirationType: StateFlow<ExpiryMode> = _selectedExpirationType
private val _selectedExpirationTimer = MutableStateFlow(afterSendOptions.firstOrNull()) private val _selectedExpirationTimer = MutableStateFlow(afterSendOptions.firstOrNull())
val selectedExpirationTimer: StateFlow<RadioOption?> = _selectedExpirationTimer val selectedExpirationTimer: StateFlow<ExpirationRadioOption?> = _selectedExpirationTimer
private val _expirationTimerOptions = MutableStateFlow<List<RadioOption>>(emptyList()) private val _expirationTimerOptions = MutableStateFlow<List<ExpirationRadioOption>>(emptyList())
val expirationTimerOptions: StateFlow<List<RadioOption>> = _expirationTimerOptions val expirationTimerOptions: StateFlow<List<ExpirationRadioOption>> = _expirationTimerOptions
init { init {
// SETUP // SETUP
@ -70,24 +67,26 @@ class ExpirationSettingsViewModel(
_uiState.update { currentUiState -> _uiState.update { currentUiState ->
currentUiState.copy( currentUiState.copy(
isSelfAdmin = groupInfo == null || groupInfo.admins.any{ it.serialize() == textSecurePreferences.getLocalNumber() }, isSelfAdmin = groupInfo == null || groupInfo.admins.any{ it.serialize() == textSecurePreferences.getLocalNumber() },
showExpirationTypeSelector = !ExpirationConfiguration.isNewConfigEnabled || (recipient?.isContactRecipient == true && !recipient.isLocalNumber) showExpirationTypeSelector = true
) )
} }
_selectedExpirationType.value = if (ExpirationConfiguration.isNewConfigEnabled) { _selectedExpirationType.value = if (ExpirationConfiguration.isNewConfigEnabled) {
expirationType.typeRadioIndex() expirationType ?: ExpiryMode.NONE
} else { } else {
if (expirationType != null && expirationType != ExpiryMode.NONE) 0 else -1 if (expirationType != null && expirationType != ExpiryMode.NONE)
ExpiryMode.Legacy(expirationType.expirySeconds)
else ExpiryMode.NONE
} }
_selectedExpirationTimer.value = when(expirationType) { _selectedExpirationTimer.value = when(expirationType) {
is ExpiryMode.AfterSend -> afterSendOptions.find { it.value.toIntOrNull() == expirationType.expirySeconds.toInt() } is ExpiryMode.AfterSend -> afterSendOptions.find { it.value == expirationType }
is ExpiryMode.AfterRead -> afterReadOptions.find { it.value.toIntOrNull() == expirationType.expirySeconds.toInt() } is ExpiryMode.AfterRead -> afterReadOptions.find { it.value == expirationType }
else -> afterSendOptions.firstOrNull() else -> afterSendOptions.firstOrNull()
} }
} }
selectedExpirationType.mapLatest { selectedExpirationType.mapLatest {
when (it) { when (it) {
0, ExpirationType.DELETE_AFTER_SEND.number -> afterSendOptions is ExpiryMode.Legacy, is ExpiryMode.AfterSend -> afterSendOptions
ExpirationType.DELETE_AFTER_READ.number -> afterReadOptions is ExpiryMode.AfterRead -> afterReadOptions
else -> emptyList() else -> emptyList()
} }
}.onEach { options -> }.onEach { options ->
@ -100,12 +99,12 @@ class ExpirationSettingsViewModel(
}.launchIn(viewModelScope) }.launchIn(viewModelScope)
} }
fun onExpirationTypeSelected(option: RadioOption) { fun onExpirationTypeSelected(option: ExpirationRadioOption) {
_selectedExpirationType.value = option.value.toIntOrNull() ?: -1 _selectedExpirationType.value = option.value
_selectedExpirationTimer.value = _expirationTimerOptions.value.firstOrNull() _selectedExpirationTimer.value = _expirationTimerOptions.value.firstOrNull()
} }
fun onExpirationTimerSelected(option: RadioOption) { fun onExpirationTimerSelected(option: ExpirationRadioOption) {
_selectedExpirationTimer.value = option _selectedExpirationTimer.value = option
} }
@ -116,15 +115,9 @@ class ExpirationSettingsViewModel(
} }
fun onSetClick() = viewModelScope.launch { fun onSetClick() = viewModelScope.launch {
var typeValue = _selectedExpirationType.value val expiryMode = _selectedExpirationTimer.value?.value ?: ExpiryMode.NONE
if (typeValue == 0) {
typeValue = ExpirationType.DELETE_AFTER_READ_VALUE
}
val expirationTimer = _selectedExpirationTimer.value?.value?.toIntOrNull() ?: 0
val expiryTypeClass = typeValue.expiryType()
val expiryMode = expiryTypeClass?.withTime(expirationTimer.toLong())
val address = recipient.value?.address val address = recipient.value?.address
if (address == null || (expirationConfig?.expiryMode?.javaClass == expiryTypeClass && expirationConfig?.expiryMode?.expirySeconds?.toInt() == expirationTimer)) { if (address == null || (expirationConfig?.expiryMode != expiryMode)) {
_uiState.update { _uiState.update {
it.copy(settingsSaved = false) it.copy(settingsSaved = false)
} }
@ -134,7 +127,7 @@ class ExpirationSettingsViewModel(
val expiryChangeTimestampMs = SnodeAPI.nowWithOffset val expiryChangeTimestampMs = SnodeAPI.nowWithOffset
storage.setExpirationConfiguration(ExpirationConfiguration(threadId, expiryMode, expiryChangeTimestampMs)) storage.setExpirationConfiguration(ExpirationConfiguration(threadId, expiryMode, expiryChangeTimestampMs))
val message = ExpirationTimerUpdate(expirationTimer) val message = ExpirationTimerUpdate(expiryMode.expirySeconds.toInt())
message.sender = textSecurePreferences.getLocalNumber() message.sender = textSecurePreferences.getLocalNumber()
message.recipient = address.serialize() message.recipient = address.serialize()
message.sentTimestamp = expiryChangeTimestampMs message.sentTimestamp = expiryChangeTimestampMs
@ -150,16 +143,16 @@ class ExpirationSettingsViewModel(
interface AssistedFactory { interface AssistedFactory {
fun create( fun create(
threadId: Long, threadId: Long,
@Assisted("afterRead") afterReadOptions: List<RadioOption>, @Assisted("afterRead") afterReadOptions: List<ExpirationRadioOption>,
@Assisted("afterSend") afterSendOptions: List<RadioOption> @Assisted("afterSend") afterSendOptions: List<ExpirationRadioOption>
): Factory ): Factory
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
class Factory @AssistedInject constructor( class Factory @AssistedInject constructor(
@Assisted private val threadId: Long, @Assisted private val threadId: Long,
@Assisted("afterRead") private val afterReadOptions: List<RadioOption>, @Assisted("afterRead") private val afterReadOptions: List<ExpirationRadioOption>,
@Assisted("afterSend") private val afterSendOptions: List<RadioOption>, @Assisted("afterSend") private val afterSendOptions: List<ExpirationRadioOption>,
private val textSecurePreferences: TextSecurePreferences, private val textSecurePreferences: TextSecurePreferences,
private val messageExpirationManager: MessageExpirationManagerProtocol, private val messageExpirationManager: MessageExpirationManagerProtocol,
private val threadDb: ThreadDatabase, private val threadDb: ThreadDatabase,

View file

@ -9,24 +9,26 @@ import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import network.loki.messenger.R import network.loki.messenger.R
import network.loki.messenger.databinding.ItemSelectableBinding import network.loki.messenger.databinding.ItemSelectableBinding
import network.loki.messenger.libsession_util.util.ExpiryMode
import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideApp
import java.util.Objects
class RadioOptionAdapter( class RadioOptionAdapter<T>(
private var selectedOptionPosition: Int = 0, private var selectedOptionPosition: Int = 0,
private val onClickListener: (RadioOption) -> Unit private val onClickListener: (RadioOption<T>) -> Unit
) : ListAdapter<RadioOption, RadioOptionAdapter.ViewHolder>(RadioOptionDiffer()) { ) : ListAdapter<RadioOption<T>, RadioOptionAdapter.ViewHolder<T>>(RadioOptionDiffer()) {
class RadioOptionDiffer: DiffUtil.ItemCallback<RadioOption>() { class RadioOptionDiffer<T>: DiffUtil.ItemCallback<RadioOption<T>>() {
override fun areItemsTheSame(oldItem: RadioOption, newItem: RadioOption) = oldItem.title == newItem.title override fun areItemsTheSame(oldItem: RadioOption<T>, newItem: RadioOption<T>) = oldItem.title == newItem.title
override fun areContentsTheSame(oldItem: RadioOption, newItem: RadioOption) = oldItem.value == newItem.value override fun areContentsTheSame(oldItem: RadioOption<T>, newItem: RadioOption<T>) = Objects.equals(oldItem.value,newItem.value)
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<T> {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_selectable, parent, false) val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_selectable, parent, false)
return ViewHolder(itemView) return ViewHolder<T>(itemView)
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder<T>, position: Int) {
val option = getItem(position) val option = getItem(position)
val isSelected = position == selectedOptionPosition val isSelected = position == selectedOptionPosition
holder.bind(option, isSelected) { holder.bind(option, isSelected) {
@ -41,12 +43,12 @@ class RadioOptionAdapter(
notifyDataSetChanged() notifyDataSetChanged()
} }
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) { class ViewHolder<T>(itemView: View): RecyclerView.ViewHolder(itemView) {
val glide = GlideApp.with(itemView) val glide = GlideApp.with(itemView)
val binding = ItemSelectableBinding.bind(itemView) val binding = ItemSelectableBinding.bind(itemView)
fun bind(option: RadioOption, isSelected: Boolean, toggleSelection: (RadioOption) -> Unit) { fun bind(option: RadioOption<T>, isSelected: Boolean, toggleSelection: (RadioOption<T>) -> Unit) {
val alpha = if (option.enabled) 1f else 0.5f val alpha = if (option.enabled) 1f else 0.5f
binding.root.isEnabled = option.enabled binding.root.isEnabled = option.enabled
binding.root.contentDescription = option.contentDescription binding.root.contentDescription = option.contentDescription
@ -66,10 +68,36 @@ class RadioOptionAdapter(
} }
data class RadioOption( sealed class RadioOption<T>(
val value: String, val value: T,
val title: String, val title: String,
val subtitle: String? = null, val subtitle: String? = null,
val enabled: Boolean = true, val enabled: Boolean = true,
val contentDescription: String = "" val contentDescription: String = ""
) )
class StringRadioOption(value: String,
title: String,
subtitle: String? = null,
enabled: Boolean = true,
contentDescription: String = ""): RadioOption<String>(
value,
title,
subtitle,
enabled,
contentDescription
)
class ExpirationRadioOption(
value: ExpiryMode,
title: String,
subtitle: String? = null,
enabled: Boolean = true,
contentDescription: String = ""
): RadioOption<ExpiryMode>(
value,
title,
subtitle,
enabled,
contentDescription
)

View file

@ -2,6 +2,7 @@ package network.loki.messenger.libsession_util.util
sealed class ExpiryMode(val expirySeconds: Long) { sealed class ExpiryMode(val expirySeconds: Long) {
object NONE: ExpiryMode(0) object NONE: ExpiryMode(0)
class Legacy(seconds: Long): ExpiryMode(seconds) // after read
class AfterSend(seconds: Long): ExpiryMode(seconds) class AfterSend(seconds: Long): ExpiryMode(seconds)
class AfterRead(seconds: Long): ExpiryMode(seconds) class AfterRead(seconds: Long): ExpiryMode(seconds)
} }

View file

@ -10,8 +10,7 @@ data class ExpirationConfiguration(
val isEnabled = expiryMode != null && expiryMode.expirySeconds > 0 val isEnabled = expiryMode != null && expiryMode.expirySeconds > 0
companion object { companion object {
val isNewConfigEnabled = false /* TODO: System.currentTimeMillis() > 1_676_851_200_000 // 13/02/2023 */ val isNewConfigEnabled = true /* TODO: System.currentTimeMillis() > 1_676_851_200_000 // 13/02/2023 */
const val LAST_READ_TEST = 1673587663000L
} }
} }

View file

@ -70,7 +70,7 @@ abstract class Message {
when (expiryMode) { when (expiryMode) {
is ExpiryMode.AfterSend -> expirationType = ExpirationType.DELETE_AFTER_SEND is ExpiryMode.AfterSend -> expirationType = ExpirationType.DELETE_AFTER_SEND
is ExpiryMode.AfterRead -> expirationType = ExpirationType.DELETE_AFTER_READ is ExpiryMode.AfterRead -> expirationType = ExpirationType.DELETE_AFTER_READ
ExpiryMode.NONE -> { /* do nothing */ } is ExpiryMode.Legacy, ExpiryMode.NONE -> { /* do nothing */ }
} }
} }
} }

View file

@ -8,6 +8,7 @@ fun ExpiryMode?.typeRadioIndex(): Int {
return when (this) { return when (this) {
is ExpiryMode.AfterRead -> SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ_VALUE is ExpiryMode.AfterRead -> SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ_VALUE
is ExpiryMode.AfterSend -> SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND_VALUE is ExpiryMode.AfterSend -> SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND_VALUE
is ExpiryMode.Legacy -> SignalServiceProtos.Content.ExpirationType.UNKNOWN_VALUE
else -> -1 else -> -1
} }
} }
@ -16,7 +17,7 @@ fun SignalServiceProtos.Content.ExpirationType?.expiryMode(durationSeconds: Long
null -> null null -> null
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ -> ExpiryMode.AfterRead(durationSeconds) SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ -> ExpiryMode.AfterRead(durationSeconds)
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND -> ExpiryMode.AfterSend(durationSeconds) SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND -> ExpiryMode.AfterSend(durationSeconds)
SignalServiceProtos.Content.ExpirationType.UNKNOWN -> null SignalServiceProtos.Content.ExpirationType.UNKNOWN -> ExpiryMode.Legacy(durationSeconds)
} }
fun Int.expiryType(): KClass<out ExpiryMode>? { fun Int.expiryType(): KClass<out ExpiryMode>? {
@ -24,6 +25,7 @@ fun Int.expiryType(): KClass<out ExpiryMode>? {
return when (this) { return when (this) {
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ_VALUE -> ExpiryMode.AfterSend::class SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ_VALUE -> ExpiryMode.AfterSend::class
SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND_VALUE -> ExpiryMode.AfterRead::class SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_SEND_VALUE -> ExpiryMode.AfterRead::class
SignalServiceProtos.Content.ExpirationType.UNKNOWN_VALUE -> ExpiryMode.Legacy::class
else -> ExpiryMode.NONE::class else -> ExpiryMode.NONE::class
} }
} }