kopia lustrzana https://github.com/ryukoposting/Signal-Android
Story privacy screen updates.
rodzic
15e52a8b88
commit
f341e02fb7
|
@ -18,7 +18,6 @@ import org.thoughtcrime.securesms.components.InputAwareLayout
|
|||
import org.thoughtcrime.securesms.components.emoji.EmojiEventListener
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.DonationEvent
|
||||
|
@ -36,6 +35,7 @@ import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardPageFragment
|
|||
import org.thoughtcrime.securesms.keyboard.emoji.search.EmojiSearchFragment
|
||||
import org.thoughtcrime.securesms.util.Debouncer
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.fragments.requireListener
|
||||
|
||||
/**
|
||||
|
@ -75,7 +75,7 @@ class GiftFlowConfirmationFragment :
|
|||
private val eventPublisher = PublishSubject.create<TextInput.TextInputEvent>()
|
||||
private val debouncer = Debouncer(100L)
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
RecipientPreference.register(adapter)
|
||||
GiftRowItem.register(adapter)
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|||
import org.signal.core.util.DimensionUnit
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.DonationPaymentComponent
|
||||
|
@ -18,6 +17,7 @@ import org.thoughtcrime.securesms.components.settings.models.IndeterminateLoadin
|
|||
import org.thoughtcrime.securesms.components.settings.models.SplashImage
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.fragments.requireListener
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
|
@ -35,7 +35,7 @@ class GiftFlowStartFragment : DSLSettingsFragment(
|
|||
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
CurrencySelection.register(adapter)
|
||||
GiftRowItem.register(adapter)
|
||||
NetworkFailure.register(adapter)
|
||||
|
|
|
@ -13,11 +13,11 @@ import org.thoughtcrime.securesms.badges.Badges.displayBadges
|
|||
import org.thoughtcrime.securesms.badges.models.Badge
|
||||
import org.thoughtcrime.securesms.badges.models.BadgePreview
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
|
||||
/**
|
||||
* Fragment which allows user to select one of their badges to be their "Featured" badge.
|
||||
|
@ -50,7 +50,7 @@ class SelectFeaturedBadgeFragment : DSLSettingsFragment(
|
|||
return Material3OnScrollHelper(requireActivity(), scrollShadow)
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
Badge.register(adapter) { badge, isSelected, _ ->
|
||||
if (!isSelected) {
|
||||
viewModel.setSelectedBadge(badge)
|
||||
|
|
|
@ -10,7 +10,6 @@ import org.thoughtcrime.securesms.badges.Badges.displayBadges
|
|||
import org.thoughtcrime.securesms.badges.models.Badge
|
||||
import org.thoughtcrime.securesms.badges.view.ViewBadgeBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.SubscriptionsRepository
|
||||
|
@ -18,6 +17,7 @@ import org.thoughtcrime.securesms.components.settings.configure
|
|||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
/**
|
||||
|
@ -35,7 +35,7 @@ class BadgesOverviewFragment : DSLSettingsFragment(
|
|||
}
|
||||
)
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
Badge.register(adapter) { badge, _, isFaded ->
|
||||
if (badge.isExpired() || isFaded) {
|
||||
findNavController().safeNavigate(BadgesOverviewFragmentDirections.actionBadgeManageFragmentToExpiredBadgeDialog(badge, null, null))
|
||||
|
|
|
@ -12,10 +12,13 @@ import androidx.annotation.StringRes
|
|||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import java.lang.UnsupportedOperationException
|
||||
|
||||
abstract class DSLSettingsFragment(
|
||||
@StringRes private val titleId: Int = -1,
|
||||
|
@ -27,9 +30,11 @@ abstract class DSLSettingsFragment(
|
|||
protected var recyclerView: RecyclerView? = null
|
||||
private set
|
||||
|
||||
private var toolbar: Toolbar? = null
|
||||
|
||||
@CallSuper
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val toolbar: Toolbar? = view.findViewById(R.id.toolbar)
|
||||
toolbar = view.findViewById(R.id.toolbar)
|
||||
|
||||
if (titleId != -1) {
|
||||
toolbar?.setTitle(titleId)
|
||||
|
@ -44,7 +49,13 @@ abstract class DSLSettingsFragment(
|
|||
toolbar?.setOnMenuItemClickListener { onOptionsItemSelected(it) }
|
||||
}
|
||||
|
||||
val settingsAdapter = DSLSettingsAdapter()
|
||||
val config = ConcatAdapter.Config.Builder().setIsolateViewTypes(false).build()
|
||||
val settingsAdapters = createAdapters()
|
||||
val settingsAdapter: RecyclerView.Adapter<out RecyclerView.ViewHolder> = when {
|
||||
settingsAdapters.size > 1 -> ConcatAdapter(config, *settingsAdapters)
|
||||
settingsAdapters.size == 1 -> settingsAdapters.first()
|
||||
else -> error("Require one or more settings adapters.")
|
||||
}
|
||||
|
||||
recyclerView = view.findViewById<RecyclerView>(R.id.recycler).apply {
|
||||
edgeEffectFactory = EdgeEffectFactory()
|
||||
|
@ -56,7 +67,11 @@ abstract class DSLSettingsFragment(
|
|||
}
|
||||
}
|
||||
|
||||
bindAdapter(settingsAdapter)
|
||||
when (settingsAdapter) {
|
||||
is ConcatAdapter -> bindAdapters(settingsAdapter)
|
||||
is MappingAdapter -> bindAdapter(settingsAdapter)
|
||||
else -> error("Illegal adapter subtype: ${settingsAdapter.javaClass.simpleName}")
|
||||
}
|
||||
}
|
||||
|
||||
open fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper? {
|
||||
|
@ -76,7 +91,25 @@ abstract class DSLSettingsFragment(
|
|||
recyclerView = null
|
||||
}
|
||||
|
||||
abstract fun bindAdapter(adapter: DSLSettingsAdapter)
|
||||
fun setTitle(@StringRes resId: Int) {
|
||||
toolbar?.setTitle(resId)
|
||||
}
|
||||
|
||||
fun setTitle(title: CharSequence) {
|
||||
toolbar?.title = title
|
||||
}
|
||||
|
||||
open fun createAdapters(): Array<MappingAdapter> {
|
||||
return arrayOf(DSLSettingsAdapter())
|
||||
}
|
||||
|
||||
open fun bindAdapter(adapter: MappingAdapter) {
|
||||
throw UnsupportedOperationException("This method is not implemented.")
|
||||
}
|
||||
|
||||
open fun bindAdapters(adapter: ConcatAdapter) {
|
||||
throw UnsupportedOperationException("This method is not implemented.")
|
||||
}
|
||||
|
||||
private class EdgeEffectFactory : RecyclerView.EdgeEffectFactory() {
|
||||
override fun createEdgeEffect(view: RecyclerView, direction: Int): EdgeEffect {
|
||||
|
|
|
@ -9,7 +9,6 @@ import org.thoughtcrime.securesms.R
|
|||
import org.thoughtcrime.securesms.badges.BadgeImageView
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
|
@ -23,6 +22,7 @@ import org.thoughtcrime.securesms.util.FeatureFlags
|
|||
import org.thoughtcrime.securesms.util.PlayServicesUtil
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingViewHolder
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
|
@ -30,7 +30,7 @@ class AppSettingsFragment : DSLSettingsFragment(R.string.text_secure_normal__men
|
|||
|
||||
private val viewModel: AppSettingsViewModel by viewModels()
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
adapter.registerFactory(BioPreference::class.java, LayoutFactory(::BioPreferenceViewHolder, R.layout.bio_preference_item))
|
||||
adapter.registerFactory(PaymentsPreference::class.java, LayoutFactory(::PaymentsPreferenceViewHolder, R.layout.dsl_payments_preference))
|
||||
adapter.registerFactory(SubscriptionPreference::class.java, LayoutFactory(::SubscriptionPreferenceViewHolder, R.layout.dsl_preference_item))
|
||||
|
|
|
@ -20,7 +20,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import com.google.android.material.snackbar.Snackbar
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -33,6 +32,7 @@ import org.thoughtcrime.securesms.lock.v2.PinKeyboardType
|
|||
import org.thoughtcrime.securesms.pin.RegistrationLockV2Dialog
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
class AccountSettingsFragment : DSLSettingsFragment(R.string.AccountSettingsFragment__account) {
|
||||
|
@ -50,7 +50,7 @@ class AccountSettingsFragment : DSLSettingsFragment(R.string.AccountSettingsFrag
|
|||
viewModel.refreshState()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
viewModel = ViewModelProvider(this)[AccountSettingsViewModel::class.java]
|
||||
|
||||
viewModel.state.observe(viewLifecycleOwner) { state ->
|
||||
|
|
|
@ -4,11 +4,11 @@ import androidx.lifecycle.ViewModelProvider
|
|||
import androidx.navigation.Navigation
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.keyvalue.SettingsValues
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
class AppearanceSettingsFragment : DSLSettingsFragment(R.string.preferences__appearance) {
|
||||
|
@ -24,7 +24,7 @@ class AppearanceSettingsFragment : DSLSettingsFragment(R.string.preferences__app
|
|||
private val languageLabels by lazy { resources.getStringArray(R.array.language_entries) }
|
||||
private val languageValues by lazy { resources.getStringArray(R.array.language_values) }
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
viewModel = ViewModelProvider(this)[AppearanceSettingsViewModel::class.java]
|
||||
|
||||
viewModel.state.observe(viewLifecycleOwner) { state ->
|
||||
|
|
|
@ -4,10 +4,10 @@ import androidx.lifecycle.ViewModelProvider
|
|||
import androidx.navigation.Navigation
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
class ChatsSettingsFragment : DSLSettingsFragment(R.string.preferences_chats__chats) {
|
||||
|
@ -19,7 +19,7 @@ class ChatsSettingsFragment : DSLSettingsFragment(R.string.preferences_chats__ch
|
|||
viewModel.refresh()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
val repository = ChatsSettingsRepository()
|
||||
val factory = ChatsSettingsViewModel.Factory(repository)
|
||||
viewModel = ViewModelProvider(this, factory)[ChatsSettingsViewModel::class.java]
|
||||
|
|
|
@ -8,13 +8,13 @@ import androidx.lifecycle.ViewModelProvider
|
|||
import androidx.navigation.Navigation
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.SmsUtil
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
private const val SMS_REQUEST_CODE: Short = 1234
|
||||
|
@ -28,7 +28,7 @@ class SmsSettingsFragment : DSLSettingsFragment(R.string.preferences__sms_mms) {
|
|||
viewModel.checkSmsEnabled()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
viewModel = ViewModelProvider(this)[SmsSettingsViewModel::class.java]
|
||||
|
||||
viewModel.state.observe(viewLifecycleOwner) {
|
||||
|
|
|
@ -5,12 +5,12 @@ import androidx.navigation.Navigation
|
|||
import androidx.preference.PreferenceManager
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.mms.SentMediaQuality
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.webrtc.CallBandwidthMode
|
||||
import kotlin.math.abs
|
||||
|
@ -31,7 +31,7 @@ class DataAndStorageSettingsFragment : DSLSettingsFragment(R.string.preferences_
|
|||
viewModel.refresh()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
val repository = DataAndStorageSettingsRepository()
|
||||
val factory = DataAndStorageSettingsViewModel.Factory(preferences, repository)
|
||||
|
|
|
@ -4,15 +4,15 @@ import androidx.navigation.Navigation
|
|||
import org.thoughtcrime.securesms.BuildConfig
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
class HelpSettingsFragment : DSLSettingsFragment(R.string.preferences__help) {
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
adapter.submitList(getConfiguration().toMappingModelList())
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import org.signal.ringrtc.CallManager
|
|||
import org.thoughtcrime.securesms.BuildConfig
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -42,6 +41,7 @@ import org.thoughtcrime.securesms.payments.DataExportUtil
|
|||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.util.ConversationUtil
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import java.util.Optional
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
@ -51,7 +51,7 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
|
|||
|
||||
private lateinit var viewModel: InternalSettingsViewModel
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
val repository = InternalSettingsRepository(requireContext())
|
||||
val factory = InternalSettingsViewModel.Factory(repository)
|
||||
viewModel = ViewModelProvider(this, factory)[InternalSettingsViewModel::class.java]
|
||||
|
|
|
@ -5,19 +5,19 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|||
import org.signal.donations.StripeDeclineCode
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.errors.UnexpectedSubscriptionCancellation
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
|
||||
class DonorErrorConfigurationFragment : DSLSettingsFragment() {
|
||||
|
||||
private val viewModel: DonorErrorConfigurationViewModel by viewModels()
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
lifecycleDisposable += viewModel.state.observeOn(AndroidSchedulers.mainThread()).subscribe { state ->
|
||||
adapter.submitList(getConfiguration(state).toMappingModelList())
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import androidx.preference.PreferenceManager
|
|||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.PreferenceModel
|
||||
|
@ -35,6 +34,7 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels
|
|||
import org.thoughtcrime.securesms.util.RingtoneUtil
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
private const val MESSAGE_SOUND_SELECT: Int = 1
|
||||
|
@ -70,7 +70,7 @@ class NotificationsSettingsFragment : DSLSettingsFragment(R.string.preferences__
|
|||
}
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
adapter.registerFactory(
|
||||
LedColorPreference::class.java,
|
||||
LayoutFactory(::LedColorPreferenceViewHolder, R.layout.dsl_preference_item)
|
||||
|
|
|
@ -8,7 +8,6 @@ import com.google.android.material.snackbar.Snackbar
|
|||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.app.notifications.profiles.models.NotificationProfileAddMembers
|
||||
import org.thoughtcrime.securesms.components.settings.app.notifications.profiles.models.NotificationProfileRecipient
|
||||
|
@ -18,6 +17,7 @@ import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile
|
|||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
|
||||
|
||||
|
@ -42,7 +42,7 @@ class AddAllowedMembersFragment : DSLSettingsFragment(layoutId = R.layout.fragme
|
|||
}
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
NotificationProfileAddMembers.register(adapter)
|
||||
NotificationProfileRecipient.register(adapter)
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.signal.core.util.BreakIteratorCompat
|
|||
import org.signal.core.util.EditTextUtil
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiUtil
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.app.notifications.profiles.EditNotificationProfileViewModel.SaveNotificationProfileResult
|
||||
import org.thoughtcrime.securesms.components.settings.app.notifications.profiles.models.NotificationProfileNamePreset
|
||||
|
@ -25,6 +24,7 @@ import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiBottomSheetDial
|
|||
import org.thoughtcrime.securesms.util.BottomSheetUtil
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.text.AfterTextChanged
|
||||
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
|
||||
|
@ -131,7 +131,7 @@ class EditNotificationProfileFragment : DSLSettingsFragment(layoutId = R.layout.
|
|||
this.emojiView = emojiView
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
NotificationProfileNamePreset.register(adapter)
|
||||
|
||||
val onClick = { preset: NotificationProfileNamePreset.Model ->
|
||||
|
|
|
@ -13,7 +13,6 @@ import io.reactivex.rxjava3.kotlin.subscribeBy
|
|||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiUtil
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
|
@ -31,6 +30,7 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
|||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.formatHours
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.orderOfDaysInWeek
|
||||
|
@ -65,7 +65,7 @@ class NotificationProfileDetailsFragment : DSLSettingsFragment() {
|
|||
toolbar = null
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
NotificationProfilePreference.register(adapter)
|
||||
NotificationProfileAddMembers.register(adapter)
|
||||
NotificationProfileRecipient.register(adapter)
|
||||
|
|
|
@ -8,7 +8,6 @@ import androidx.navigation.fragment.findNavController
|
|||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiUtil
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
|
@ -20,6 +19,7 @@ import org.thoughtcrime.securesms.components.settings.conversation.preferences.L
|
|||
import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile
|
||||
import org.thoughtcrime.securesms.notifications.profiles.NotificationProfiles
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
/**
|
||||
|
@ -48,7 +48,7 @@ class NotificationProfilesFragment : DSLSettingsFragment() {
|
|||
toolbar = null
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
NoNotificationProfiles.register(adapter)
|
||||
LargeIconClickPreference.register(adapter)
|
||||
NotificationProfilePreference.register(adapter)
|
||||
|
|
|
@ -20,14 +20,12 @@ import androidx.preference.PreferenceManager
|
|||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import mobi.upod.timedurationpicker.TimeDurationPicker
|
||||
import mobi.upod.timedurationpicker.TimeDurationPickerDialog
|
||||
import org.signal.core.util.DimensionUnit
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.PassphraseChangeActivity
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.ClickPreference
|
||||
import org.thoughtcrime.securesms.components.settings.ClickPreferenceViewHolder
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.PreferenceModel
|
||||
|
@ -36,12 +34,8 @@ import org.thoughtcrime.securesms.components.settings.configure
|
|||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil
|
||||
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues
|
||||
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues.PhoneNumberListingMode
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
import org.thoughtcrime.securesms.stories.settings.custom.PrivateStorySettingsFragmentArgs
|
||||
import org.thoughtcrime.securesms.stories.settings.story.PrivateStoryItem
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
import org.thoughtcrime.securesms.util.ConversationUtil
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil
|
||||
|
@ -50,6 +44,7 @@ import org.thoughtcrime.securesms.util.ServiceUtil
|
|||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import java.lang.Integer.max
|
||||
import java.util.Locale
|
||||
|
@ -76,9 +71,8 @@ class PrivacySettingsFragment : DSLSettingsFragment(R.string.preferences__privac
|
|||
viewModel.refreshBlockedCount()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
adapter.registerFactory(ValueClickPreference::class.java, LayoutFactory(::ValueClickPreferenceViewHolder, R.layout.value_click_preference_item))
|
||||
PrivateStoryItem.register(adapter)
|
||||
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
val repository = PrivacySettingsRepository()
|
||||
|
@ -297,50 +291,13 @@ class PrivacySettingsFragment : DSLSettingsFragment(R.string.preferences__privac
|
|||
)
|
||||
|
||||
if (Stories.isFeatureAvailable()) {
|
||||
|
||||
dividerPref()
|
||||
|
||||
sectionHeaderPref(R.string.ConversationListTabs__stories)
|
||||
|
||||
if (!SignalStore.storyValues().isFeatureDisabled) {
|
||||
customPref(
|
||||
PrivateStoryItem.RecipientModel(
|
||||
recipient = Recipient.self(),
|
||||
onClick = { findNavController().safeNavigate(R.id.action_privacySettings_to_myStorySettings) }
|
||||
)
|
||||
)
|
||||
|
||||
space(DimensionUnit.DP.toPixels(24f).toInt())
|
||||
|
||||
customPref(
|
||||
PrivateStoryItem.NewModel(
|
||||
onClick = {
|
||||
findNavController().safeNavigate(R.id.action_privacySettings_to_newPrivateStory)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
state.privateStories.forEach {
|
||||
customPref(
|
||||
PrivateStoryItem.PartialModel(
|
||||
privateStoryItemData = it,
|
||||
onClick = { model ->
|
||||
findNavController().safeNavigate(
|
||||
R.id.action_privacySettings_to_privateStorySettings,
|
||||
PrivateStorySettingsFragmentArgs.Builder(model.privateStoryItemData.id).build().toBundle()
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
switchPref(
|
||||
title = DSLSettingsText.from(R.string.PrivacySettingsFragment__share_and_view_stories),
|
||||
summary = DSLSettingsText.from(R.string.PrivacySettingsFragment__you_will_no_longer_be_able),
|
||||
isChecked = state.isStoriesEnabled,
|
||||
clickPref(
|
||||
title = DSLSettingsText.from(R.string.preferences__stories),
|
||||
summary = DSLSettingsText.from(R.string.PrivacySettingsFragment__manage_your_stories),
|
||||
onClick = {
|
||||
viewModel.setStoriesEnabled(!state.isStoriesEnabled)
|
||||
findNavController().safeNavigate(PrivacySettingsFragmentDirections.actionPrivacySettingsFragmentToStoryPrivacySettings(R.string.preferences__stories))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.components.settings.app.privacy
|
|||
import android.content.Context
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPartialRecord
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceConfigurationUpdateJob
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
|
@ -23,12 +22,6 @@ class PrivacySettingsRepository {
|
|||
}
|
||||
}
|
||||
|
||||
fun getPrivateStories(consumer: (List<DistributionListPartialRecord>) -> Unit) {
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
consumer(SignalDatabase.distributionLists.getCustomListsForUi())
|
||||
}
|
||||
}
|
||||
|
||||
fun syncReadReceiptState() {
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
SignalDatabase.recipients.markNeedsSync(Recipient.self().id)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.thoughtcrime.securesms.components.settings.app.privacy
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPartialRecord
|
||||
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues
|
||||
|
||||
data class PrivacySettingsState(
|
||||
|
@ -16,7 +15,5 @@ data class PrivacySettingsState(
|
|||
val isObsoletePasswordEnabled: Boolean,
|
||||
val isObsoletePasswordTimeoutEnabled: Boolean,
|
||||
val obsoletePasswordTimeout: Int,
|
||||
val universalExpireTimer: Int,
|
||||
val privateStories: List<DistributionListPartialRecord>,
|
||||
val isStoriesEnabled: Boolean
|
||||
val universalExpireTimer: Int
|
||||
)
|
||||
|
|
|
@ -27,11 +27,6 @@ class PrivacySettingsViewModel(
|
|||
store.update { it.copy(blockedCount = count) }
|
||||
refresh()
|
||||
}
|
||||
|
||||
repository.getPrivateStories { privateStories ->
|
||||
store.update { it.copy(privateStories = privateStories) }
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
fun setReadReceiptsEnabled(enabled: Boolean) {
|
||||
|
@ -89,11 +84,6 @@ class PrivacySettingsViewModel(
|
|||
refresh()
|
||||
}
|
||||
|
||||
fun setStoriesEnabled(isStoriesEnabled: Boolean) {
|
||||
SignalStore.storyValues().isFeatureDisabled = !isStoriesEnabled
|
||||
refresh()
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
store.update(this::updateState)
|
||||
}
|
||||
|
@ -112,14 +102,12 @@ class PrivacySettingsViewModel(
|
|||
isObsoletePasswordEnabled = !TextSecurePreferences.isPasswordDisabled(ApplicationDependencies.getApplication()),
|
||||
isObsoletePasswordTimeoutEnabled = TextSecurePreferences.isPassphraseTimeoutEnabled(ApplicationDependencies.getApplication()),
|
||||
obsoletePasswordTimeout = TextSecurePreferences.getPassphraseTimeoutInterval(ApplicationDependencies.getApplication()),
|
||||
universalExpireTimer = SignalStore.settings().universalExpireTimer,
|
||||
privateStories = emptyList(),
|
||||
isStoriesEnabled = !SignalStore.storyValues().isFeatureDisabled
|
||||
universalExpireTimer = SignalStore.settings().universalExpireTimer
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateState(state: PrivacySettingsState): PrivacySettingsState {
|
||||
return getState().copy(blockedCount = state.blockedCount, privateStories = state.privateStories)
|
||||
return getState().copy(blockedCount = state.blockedCount)
|
||||
}
|
||||
|
||||
class Factory(
|
||||
|
|
|
@ -19,7 +19,6 @@ import androidx.preference.PreferenceManager
|
|||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -29,6 +28,7 @@ import org.thoughtcrime.securesms.registration.RegistrationNavigationActivity
|
|||
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
|
||||
class AdvancedPrivacySettingsFragment : DSLSettingsFragment(R.string.preferences__advanced) {
|
||||
|
||||
|
@ -75,7 +75,7 @@ class AdvancedPrivacySettingsFragment : DSLSettingsFragment(R.string.preferences
|
|||
unregisterNetworkReceiver()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
val repository = AdvancedPrivacySettingsRepository(requireContext())
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
val factory = AdvancedPrivacySettingsViewModel.Factory(preferences, repository)
|
||||
|
|
|
@ -10,7 +10,6 @@ import androidx.navigation.fragment.NavHostFragment
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -18,6 +17,7 @@ import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason
|
|||
import org.thoughtcrime.securesms.groups.ui.GroupErrors
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.livedata.ProcessState
|
||||
import org.thoughtcrime.securesms.util.livedata.distinctUntilChanged
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
@ -48,7 +48,7 @@ class ExpireTimerSettingsFragment : DSLSettingsFragment(
|
|||
recycler.clipToPadding = false
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
val provider = ViewModelProvider(
|
||||
NavHostFragment.findNavController(this).getViewModelStoreOwner(R.id.app_settings_expire_timer),
|
||||
ExpireTimerSettingsViewModel.Factory(requireContext(), arguments.toConfig())
|
||||
|
|
|
@ -12,7 +12,6 @@ import org.thoughtcrime.securesms.badges.gifts.ExpiredGiftSheet
|
|||
import org.thoughtcrime.securesms.badges.gifts.flow.GiftFlowActivity
|
||||
import org.thoughtcrime.securesms.badges.models.BadgePreview
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
|
@ -28,6 +27,7 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
|||
import org.thoughtcrime.securesms.subscription.Subscription
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription
|
||||
import java.util.Currency
|
||||
|
@ -60,7 +60,7 @@ class ManageDonationsFragment : DSLSettingsFragment(), ExpiredGiftSheet.Callback
|
|||
viewModel.refresh()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
ActiveSubscriptionPreference.register(adapter)
|
||||
IndeterminateLoadingCircle.register(adapter)
|
||||
BadgePreview.register(adapter)
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.signal.core.util.concurrent.SimpleTask
|
|||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -26,6 +25,7 @@ import org.thoughtcrime.securesms.database.model.DonationReceiptRecord
|
|||
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.util.Locale
|
||||
|
||||
|
@ -42,7 +42,7 @@ class DonationReceiptDetailFragment : DSLSettingsFragment(layoutId = R.layout.do
|
|||
}
|
||||
)
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
SplashImage.register(adapter)
|
||||
|
||||
val sharePngButton: MaterialButton = requireView().findViewById(R.id.share_png)
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.thoughtcrime.securesms.R
|
|||
import org.thoughtcrime.securesms.badges.models.Badge
|
||||
import org.thoughtcrime.securesms.badges.models.BadgePreview
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
|
||||
|
@ -37,6 +36,7 @@ import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
|||
import org.thoughtcrime.securesms.subscription.Subscription
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.fragments.requireListener
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
|
@ -82,7 +82,7 @@ class SubscribeFragment : DSLSettingsFragment(
|
|||
viewModel.refreshActiveSubscription()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
donationPaymentComponent = requireListener()
|
||||
viewModel.refresh()
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ import org.thoughtcrime.securesms.badges.view.ViewBadgeBottomSheetDialogFragment
|
|||
import org.thoughtcrime.securesms.components.AvatarImageView
|
||||
import org.thoughtcrime.securesms.components.recyclerview.OnScrollAnimationHelper
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
|
@ -85,6 +84,7 @@ import org.thoughtcrime.securesms.util.ExpirationUtil
|
|||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog
|
||||
import org.thoughtcrime.securesms.verify.VerifyIdentityActivity
|
||||
|
@ -202,7 +202,7 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
|||
}
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
val args = ConversationSettingsFragmentArgs.fromBundle(requireArguments())
|
||||
|
||||
BioTextPreference.register(adapter)
|
||||
|
|
|
@ -12,7 +12,6 @@ import org.signal.core.util.concurrent.SignalExecutors
|
|||
import org.thoughtcrime.securesms.MainActivity
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -27,6 +26,7 @@ import org.thoughtcrime.securesms.subscription.Subscriber
|
|||
import org.thoughtcrime.securesms.util.Base64
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.livedata.Store
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import java.util.Objects
|
||||
|
@ -45,7 +45,7 @@ class InternalConversationSettingsFragment : DSLSettingsFragment(
|
|||
}
|
||||
)
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
viewModel.state.observe(viewLifecycleOwner) { state ->
|
||||
adapter.submitList(getConfiguration(state).toMappingModelList())
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@ import androidx.annotation.StringRes
|
|||
import androidx.fragment.app.viewModels
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.groups.ParcelableGroupId
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupErrors
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
|
||||
class PermissionsSettingsFragment : DSLSettingsFragment(
|
||||
titleId = R.string.ConversationSettingsFragment__permissions
|
||||
|
@ -30,7 +30,7 @@ class PermissionsSettingsFragment : DSLSettingsFragment(
|
|||
}
|
||||
)
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
viewModel.state.observe(viewLifecycleOwner) { state ->
|
||||
adapter.submitList(getConfiguration(state).toMappingModelList())
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import org.thoughtcrime.securesms.MuteDialog
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
|
@ -14,6 +13,7 @@ import org.thoughtcrime.securesms.components.settings.configure
|
|||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.Utils.formatMutedUntil
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
class SoundsAndNotificationsSettingsFragment : DSLSettingsFragment(
|
||||
|
@ -38,7 +38,7 @@ class SoundsAndNotificationsSettingsFragment : DSLSettingsFragment(
|
|||
viewModel.channelConsistencyCheck()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
viewModel.state.observe(viewLifecycleOwner) { state ->
|
||||
if (state.channelConsistencyCheckComplete && state.recipientId != Recipient.UNKNOWN.id) {
|
||||
adapter.submitList(getConfiguration(state).toMappingModelList())
|
||||
|
|
|
@ -14,7 +14,6 @@ import androidx.fragment.app.viewModels
|
|||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -22,6 +21,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase
|
|||
import org.thoughtcrime.securesms.notifications.NotificationChannels
|
||||
import org.thoughtcrime.securesms.util.ConversationUtil
|
||||
import org.thoughtcrime.securesms.util.RingtoneUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
|
||||
private val TAG = Log.tag(CustomNotificationsSettingsFragment::class.java)
|
||||
|
||||
|
@ -48,7 +48,7 @@ class CustomNotificationsSettingsFragment : DSLSettingsFragment(R.string.CustomN
|
|||
viewModel.channelConsistencyCheck()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
messageSoundResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||
handleResult(result, viewModel::setMessageSound)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.thoughtcrime.securesms.contacts.paged
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.HeaderAction
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
/**
|
||||
|
@ -12,7 +13,7 @@ sealed class ContactSearchData(val contactSearchKey: ContactSearchKey) {
|
|||
*
|
||||
* Note that if the recipient is a group, it's participant list size is used instead of viewerCount.
|
||||
*/
|
||||
data class Story(val recipient: Recipient, val viewerCount: Int) : ContactSearchData(ContactSearchKey.RecipientSearchKey.Story(recipient.id))
|
||||
data class Story(val recipient: Recipient, val viewerCount: Int, val privacyMode: DistributionListPrivacyMode) : ContactSearchData(ContactSearchKey.RecipientSearchKey.Story(recipient.id))
|
||||
|
||||
/**
|
||||
* A row displaying a known recipient.
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.thoughtcrime.securesms.components.AvatarImageView
|
|||
import org.thoughtcrime.securesms.components.FromTextView
|
||||
import org.thoughtcrime.securesms.components.menu.ActionItem
|
||||
import org.thoughtcrime.securesms.components.menu.SignalContextMenu
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
|
||||
|
@ -26,6 +27,26 @@ private typealias RecipientClickListener = (View, ContactSearchData.KnownRecipie
|
|||
* Mapping Models and View Holders for ContactSearchData
|
||||
*/
|
||||
object ContactSearchItems {
|
||||
|
||||
fun registerStoryItems(
|
||||
mappingAdapter: MappingAdapter,
|
||||
displayCheckBox: Boolean = false,
|
||||
storyListener: StoryClickListener,
|
||||
storyContextMenuCallbacks: StoryContextMenuCallbacks? = null
|
||||
) {
|
||||
mappingAdapter.registerFactory(
|
||||
StoryModel::class.java,
|
||||
LayoutFactory({ StoryViewHolder(it, displayCheckBox, storyListener, storyContextMenuCallbacks) }, R.layout.contact_search_item)
|
||||
)
|
||||
}
|
||||
|
||||
fun registerHeaders(mappingAdapter: MappingAdapter) {
|
||||
mappingAdapter.registerFactory(
|
||||
HeaderModel::class.java,
|
||||
LayoutFactory({ HeaderViewHolder(it) }, R.layout.contact_search_section_header)
|
||||
)
|
||||
}
|
||||
|
||||
fun register(
|
||||
mappingAdapter: MappingAdapter,
|
||||
displayCheckBox: Boolean,
|
||||
|
@ -34,18 +55,12 @@ object ContactSearchItems {
|
|||
storyContextMenuCallbacks: StoryContextMenuCallbacks,
|
||||
expandListener: (ContactSearchData.Expand) -> Unit
|
||||
) {
|
||||
mappingAdapter.registerFactory(
|
||||
StoryModel::class.java,
|
||||
LayoutFactory({ StoryViewHolder(it, displayCheckBox, storyListener, storyContextMenuCallbacks) }, R.layout.contact_search_item)
|
||||
)
|
||||
registerStoryItems(mappingAdapter, displayCheckBox, storyListener, storyContextMenuCallbacks)
|
||||
mappingAdapter.registerFactory(
|
||||
RecipientModel::class.java,
|
||||
LayoutFactory({ KnownRecipientViewHolder(it, displayCheckBox, recipientListener) }, R.layout.contact_search_item)
|
||||
)
|
||||
mappingAdapter.registerFactory(
|
||||
HeaderModel::class.java,
|
||||
LayoutFactory({ HeaderViewHolder(it) }, R.layout.contact_search_section_header)
|
||||
)
|
||||
registerHeaders(mappingAdapter)
|
||||
mappingAdapter.registerFactory(
|
||||
ExpandModel::class.java,
|
||||
LayoutFactory({ ExpandViewHolder(it, expandListener) }, R.layout.contacts_expand_item)
|
||||
|
@ -92,7 +107,12 @@ object ContactSearchItems {
|
|||
}
|
||||
}
|
||||
|
||||
private class StoryViewHolder(itemView: View, displayCheckBox: Boolean, onClick: StoryClickListener, private val storyContextMenuCallbacks: StoryContextMenuCallbacks) : BaseRecipientViewHolder<StoryModel, ContactSearchData.Story>(itemView, displayCheckBox, onClick) {
|
||||
private class StoryViewHolder(
|
||||
itemView: View,
|
||||
displayCheckBox: Boolean,
|
||||
onClick: StoryClickListener,
|
||||
private val storyContextMenuCallbacks: StoryContextMenuCallbacks?
|
||||
) : BaseRecipientViewHolder<StoryModel, ContactSearchData.Story>(itemView, displayCheckBox, onClick) {
|
||||
override fun isSelected(model: StoryModel): Boolean = model.isSelected
|
||||
override fun getData(model: StoryModel): ContactSearchData.Story = model.story
|
||||
override fun getRecipient(model: StoryModel): Recipient = model.story.recipient
|
||||
|
@ -109,13 +129,11 @@ object ContactSearchItems {
|
|||
if (model.story.recipient.isMyStory && !model.hasBeenNotified) {
|
||||
number.setText(R.string.ContactSearchItems__tap_to_choose_your_viewers)
|
||||
} else {
|
||||
val pluralId = when {
|
||||
model.story.recipient.isGroup -> R.plurals.ContactSearchItems__group_story_d_viewers
|
||||
model.story.recipient.isMyStory -> R.plurals.SelectViewersFragment__d_viewers
|
||||
else -> R.plurals.ContactSearchItems__private_story_d_viewers
|
||||
number.text = when {
|
||||
model.story.recipient.isGroup -> context.resources.getQuantityString(R.plurals.ContactSearchItems__group_story_d_viewers, count, count)
|
||||
model.story.recipient.isMyStory -> context.resources.getQuantityString(R.plurals.ContactSearchItems__my_story_s_dot_d_viewers, count, presentPrivacyMode(model.story.privacyMode), count)
|
||||
else -> context.resources.getQuantityString(R.plurals.ContactSearchItems__private_story_d_viewers, count, count)
|
||||
}
|
||||
|
||||
number.text = context.resources.getQuantityString(pluralId, count, count)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,11 +146,15 @@ object ContactSearchItems {
|
|||
}
|
||||
|
||||
override fun bindLongPress(model: StoryModel) {
|
||||
if (storyContextMenuCallbacks == null) {
|
||||
return
|
||||
}
|
||||
|
||||
itemView.setOnLongClickListener {
|
||||
val actions: List<ActionItem> = when {
|
||||
model.story.recipient.isMyStory -> getMyStoryContextMenuActions(model)
|
||||
model.story.recipient.isGroup -> getGroupStoryContextMenuActions(model)
|
||||
model.story.recipient.isDistributionList -> getPrivateStoryContextMenuActions(model)
|
||||
model.story.recipient.isMyStory -> getMyStoryContextMenuActions(model, storyContextMenuCallbacks)
|
||||
model.story.recipient.isGroup -> getGroupStoryContextMenuActions(model, storyContextMenuCallbacks)
|
||||
model.story.recipient.isDistributionList -> getPrivateStoryContextMenuActions(model, storyContextMenuCallbacks)
|
||||
else -> error("Unsupported story target. Not a group or distribution list.")
|
||||
}
|
||||
|
||||
|
@ -144,32 +166,40 @@ object ContactSearchItems {
|
|||
}
|
||||
}
|
||||
|
||||
private fun getMyStoryContextMenuActions(model: StoryModel): List<ActionItem> {
|
||||
private fun getMyStoryContextMenuActions(model: StoryModel, callbacks: StoryContextMenuCallbacks): List<ActionItem> {
|
||||
return listOf(
|
||||
ActionItem(R.drawable.ic_settings_24, context.getString(R.string.ContactSearchItems__story_settings)) {
|
||||
storyContextMenuCallbacks.onOpenStorySettings(model.story)
|
||||
callbacks.onOpenStorySettings(model.story)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun getGroupStoryContextMenuActions(model: StoryModel): List<ActionItem> {
|
||||
private fun getGroupStoryContextMenuActions(model: StoryModel, callbacks: StoryContextMenuCallbacks): List<ActionItem> {
|
||||
return listOf(
|
||||
ActionItem(R.drawable.ic_minus_circle_20, context.getString(R.string.ContactSearchItems__remove_story)) {
|
||||
storyContextMenuCallbacks.onRemoveGroupStory(model.story, model.isSelected)
|
||||
callbacks.onRemoveGroupStory(model.story, model.isSelected)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun getPrivateStoryContextMenuActions(model: StoryModel): List<ActionItem> {
|
||||
private fun getPrivateStoryContextMenuActions(model: StoryModel, callbacks: StoryContextMenuCallbacks): List<ActionItem> {
|
||||
return listOf(
|
||||
ActionItem(R.drawable.ic_settings_24, context.getString(R.string.ContactSearchItems__story_settings)) {
|
||||
storyContextMenuCallbacks.onOpenStorySettings(model.story)
|
||||
callbacks.onOpenStorySettings(model.story)
|
||||
},
|
||||
ActionItem(R.drawable.ic_delete_24, context.getString(R.string.ContactSearchItems__delete_story), R.color.signal_colorError) {
|
||||
storyContextMenuCallbacks.onDeletePrivateStory(model.story, model.isSelected)
|
||||
callbacks.onDeletePrivateStory(model.story, model.isSelected)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun presentPrivacyMode(privacyMode: DistributionListPrivacyMode): String {
|
||||
return when (privacyMode) {
|
||||
DistributionListPrivacyMode.ONLY_WITH -> context.getString(R.string.ChooseInitialMyStoryMembershipFragment__only_share_with)
|
||||
DistributionListPrivacyMode.ALL_EXCEPT -> context.getString(R.string.ChooseInitialMyStoryMembershipFragment__all_signal_connections_except)
|
||||
DistributionListPrivacyMode.ALL -> context.getString(R.string.ChooseInitialMyStoryMembershipFragment__all_signal_connections)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.contacts.paged
|
|||
|
||||
import android.database.Cursor
|
||||
import org.signal.paging.PagedDataSource
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.StorySend
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
@ -157,7 +158,9 @@ class ContactSearchPagedDataSource(
|
|||
endIndex = endIndex,
|
||||
cursorRowToData = {
|
||||
val recipient = contactSearchPagedDataSourceRepository.getRecipientFromDistributionListCursor(it)
|
||||
ContactSearchData.Story(recipient, contactSearchPagedDataSourceRepository.getDistributionListMembershipCount(recipient))
|
||||
val count = contactSearchPagedDataSourceRepository.getDistributionListMembershipCount(recipient)
|
||||
val privacyMode = contactSearchPagedDataSourceRepository.getPrivacyModeFromDistributionListCursor(it)
|
||||
ContactSearchData.Story(recipient, count, privacyMode)
|
||||
},
|
||||
extraData = getFilteredGroupStories(section, query)
|
||||
)
|
||||
|
@ -201,7 +204,7 @@ class ContactSearchPagedDataSource(
|
|||
endIndex = endIndex,
|
||||
cursorRowToData = {
|
||||
if (section.returnAsGroupStories) {
|
||||
ContactSearchData.Story(contactSearchPagedDataSourceRepository.getRecipientFromGroupCursor(cursor), 0)
|
||||
ContactSearchData.Story(contactSearchPagedDataSourceRepository.getRecipientFromGroupCursor(cursor), 0, DistributionListPrivacyMode.ALL)
|
||||
} else {
|
||||
ContactSearchData.KnownRecipient(contactSearchPagedDataSourceRepository.getRecipientFromGroupCursor(cursor))
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.database.DistributionListDatabase
|
|||
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.keyvalue.StorySend
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
@ -76,6 +77,10 @@ open class ContactSearchPagedDataSourceRepository(
|
|||
return Recipient.resolved(RecipientId.from(CursorUtil.requireLong(cursor, DistributionListDatabase.RECIPIENT_ID)))
|
||||
}
|
||||
|
||||
open fun getPrivacyModeFromDistributionListCursor(cursor: Cursor): DistributionListPrivacyMode {
|
||||
return DistributionListPrivacyMode.deserialize(CursorUtil.requireLong(cursor, DistributionListDatabase.PRIVACY_MODE))
|
||||
}
|
||||
|
||||
open fun getRecipientFromThreadCursor(cursor: Cursor): Recipient {
|
||||
return Recipient.resolved(RecipientId.from(CursorUtil.requireLong(cursor, ThreadDatabase.RECIPIENT_ID)))
|
||||
}
|
||||
|
@ -95,7 +100,7 @@ open class ContactSearchPagedDataSourceRepository(
|
|||
open fun getGroupStories(): Set<ContactSearchData.Story> {
|
||||
return SignalDatabase.groups.groupsToDisplayAsStories.map {
|
||||
val recipient = Recipient.resolved(SignalDatabase.recipients.getOrInsertFromGroupId(it))
|
||||
ContactSearchData.Story(recipient, recipient.participantIds.size)
|
||||
ContactSearchData.Story(recipient, recipient.participantIds.size, DistributionListPrivacyMode.ALL)
|
||||
}.toSet()
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.signal.paging.LivePagedData
|
|||
import org.signal.paging.PagedData
|
||||
import org.signal.paging.PagingConfig
|
||||
import org.signal.paging.PagingController
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
|
||||
import org.thoughtcrime.securesms.groups.SelectionLimits
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.livedata.Store
|
||||
|
@ -98,7 +99,7 @@ class ContactSearchViewModel(
|
|||
state.copy(
|
||||
groupStories = state.groupStories + groupStories.map {
|
||||
val recipient = Recipient.resolved(it.recipientId)
|
||||
ContactSearchData.Story(recipient, recipient.participantIds.size)
|
||||
ContactSearchData.Story(recipient, recipient.participantIds.size, DistributionListPrivacyMode.ALL)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ class DistributionListDatabase constructor(context: Context?, databaseHelper: Si
|
|||
const val RECIPIENT_ID = ListTable.RECIPIENT_ID
|
||||
const val DISTRIBUTION_ID = ListTable.DISTRIBUTION_ID
|
||||
const val LIST_TABLE_NAME = ListTable.TABLE_NAME
|
||||
const val PRIVACY_MODE = ListTable.PRIVACY_MODE
|
||||
|
||||
fun insertInitialDistributionListAtCreationTime(db: net.zetetic.database.sqlcipher.SQLiteDatabase) {
|
||||
val recipientId = db.insert(
|
||||
|
|
|
@ -9,7 +9,7 @@ public final class ParcelableGroupId implements Parcelable {
|
|||
|
||||
private final GroupId groupId;
|
||||
|
||||
public static Parcelable from(@Nullable GroupId groupId) {
|
||||
public static ParcelableGroupId from(@Nullable GroupId groupId) {
|
||||
return new ParcelableGroupId(groupId);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.contacts.paged.ContactSearchConfiguration
|
|||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchMediator
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchSortOrder
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.sharing.ShareContact
|
||||
import org.thoughtcrime.securesms.sharing.ShareSelectionAdapter
|
||||
import org.thoughtcrime.securesms.sharing.ShareSelectionMappingModel
|
||||
|
@ -157,4 +158,10 @@ class ChooseGroupStoryBottomSheet : FixedRoundedCornerBottomSheetDialogFragment(
|
|||
)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
object ResultContract {
|
||||
fun getRecipientIds(bundle: Bundle): List<RecipientId> {
|
||||
return bundle.getParcelableArrayList(RESULT_SET)!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ package org.thoughtcrime.securesms.profiles.edit.pnp
|
|||
import androidx.fragment.app.viewModels
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
|
||||
/**
|
||||
* Allows the user to select who can see their phone number during registration.
|
||||
|
@ -18,7 +18,7 @@ class WhoCanSeeMyPhoneNumberFragment : DSLSettingsFragment(titleId = R.string.Wh
|
|||
private val viewModel: WhoCanSeeMyPhoneNumberViewModel by viewModels()
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
require(FeatureFlags.phoneNumberPrivacy())
|
||||
|
||||
lifecycleDisposable += viewModel.state.subscribe {
|
||||
|
|
|
@ -6,13 +6,13 @@ import androidx.fragment.app.viewModels
|
|||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsIcon
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupLinkUrlAndStatus
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil
|
||||
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog
|
||||
|
||||
|
@ -36,7 +36,7 @@ class ShareableGroupLinkFragment : DSLSettingsFragment(
|
|||
}
|
||||
)
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
LiveDataUtil.combineLatest(viewModel.groupLink, viewModel.canEdit) { groupLink, canEdit ->
|
||||
Pair(groupLink, canEdit)
|
||||
}.observe(viewLifecycleOwner) { (groupLink, canEdit) ->
|
||||
|
|
|
@ -9,7 +9,6 @@ import org.thoughtcrime.securesms.R
|
|||
import org.thoughtcrime.securesms.components.WrapperDialogFragment
|
||||
import org.thoughtcrime.securesms.components.menu.ActionItem
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -21,6 +20,7 @@ import org.thoughtcrime.securesms.safety.SafetyNumberBucket
|
|||
import org.thoughtcrime.securesms.safety.SafetyNumberBucketRowItem
|
||||
import org.thoughtcrime.securesms.safety.SafetyNumberRecipientRowItem
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.verify.VerifyIdentityFragment
|
||||
|
||||
/**
|
||||
|
@ -38,7 +38,7 @@ class SafetyNumberReviewConnectionsFragment : DSLSettingsFragment(
|
|||
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
SafetyNumberBucketRowItem.register(adapter)
|
||||
SafetyNumberRecipientRowItem.register(adapter)
|
||||
lifecycleDisposable.bindTo(viewLifecycleOwner)
|
||||
|
|
|
@ -62,11 +62,16 @@ object Stories {
|
|||
return isFeatureAvailable() && !SignalStore.storyValues().isFeatureDisabled
|
||||
}
|
||||
|
||||
fun getHeaderAction(fragmentManager: FragmentManager): HeaderAction {
|
||||
fun getHeaderAction(onClick: () -> Unit): HeaderAction {
|
||||
return HeaderAction(
|
||||
R.string.ContactsCursorLoader_new_story,
|
||||
R.drawable.ic_plus_20
|
||||
) {
|
||||
R.drawable.ic_plus_20,
|
||||
onClick
|
||||
)
|
||||
}
|
||||
|
||||
fun getHeaderAction(fragmentManager: FragmentManager): HeaderAction {
|
||||
return getHeaderAction {
|
||||
ChooseStoryTypeBottomSheet().show(fragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import io.reactivex.rxjava3.core.Single
|
|||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -49,6 +48,7 @@ import org.thoughtcrime.securesms.stories.tabs.ConversationListTab
|
|||
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabsViewModel
|
||||
import org.thoughtcrime.securesms.stories.viewer.StoryViewerActivity
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.fragments.requireListener
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
@ -75,7 +75,7 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
|
|||
|
||||
private val tabsViewModel: ConversationListTabsViewModel by viewModels(ownerProducer = { requireActivity() })
|
||||
|
||||
private lateinit var adapter: DSLSettingsAdapter
|
||||
private lateinit var adapter: MappingAdapter
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -92,7 +92,7 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
|
|||
viewModel.isTransitioningToAnotherScreen = false
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
this.adapter = adapter
|
||||
|
||||
StoriesLandingItem.register(adapter)
|
||||
|
|
|
@ -9,7 +9,6 @@ import androidx.core.view.ViewCompat
|
|||
import androidx.fragment.app.viewModels
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -26,6 +25,7 @@ import org.thoughtcrime.securesms.stories.dialogs.StoryDialogs
|
|||
import org.thoughtcrime.securesms.stories.viewer.StoryViewerActivity
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
|
||||
class MyStoriesFragment : DSLSettingsFragment(
|
||||
|
@ -41,7 +41,7 @@ class MyStoriesFragment : DSLSettingsFragment(
|
|||
}
|
||||
)
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
MyStoriesItem.register(adapter)
|
||||
|
||||
requireActivity().onBackPressedDispatcher.addCallback(
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.stories.settings
|
|||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.os.bundleOf
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsActivity
|
||||
|
||||
|
@ -9,7 +10,8 @@ class StorySettingsActivity : DSLSettingsActivity() {
|
|||
companion object {
|
||||
fun getIntent(context: Context): Intent {
|
||||
return Intent(context, StorySettingsActivity::class.java)
|
||||
.putExtra(ARG_NAV_GRAPH, R.navigation.story_settings)
|
||||
.putExtra(ARG_NAV_GRAPH, R.navigation.story_privacy_settings)
|
||||
.putExtra(ARG_START_BUNDLE, bundleOf("title_id" to R.string.StoriesPrivacySettingsFragment__story_privacy))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.navigation.fragment.findNavController
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.fragments.findListener
|
||||
import org.thoughtcrime.securesms.util.viewholders.RecipientMappingModel
|
||||
import org.thoughtcrime.securesms.util.viewholders.RecipientViewHolder
|
||||
|
@ -38,7 +38,7 @@ class CreateStoryWithViewersFragment : DSLSettingsFragment(
|
|||
private val recipientIds: Array<RecipientId>
|
||||
get() = CreateStoryWithViewersFragmentArgs.fromBundle(requireArguments()).recipients
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
adapter.registerFactory(RecipientMappingModel.RecipientIdMappingModel::class.java, LayoutFactory({ RecipientViewHolder(it, null) }, R.layout.stories_recipient_item))
|
||||
CreateStoryNameFieldItem.register(adapter) {
|
||||
viewModel.setLabel(it)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.story
|
||||
package org.thoughtcrime.securesms.stories.settings.custom
|
||||
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
|
@ -15,17 +15,10 @@ import org.thoughtcrime.securesms.util.adapter.mapping.MappingViewHolder
|
|||
object PrivateStoryItem {
|
||||
|
||||
fun register(mappingAdapter: MappingAdapter) {
|
||||
mappingAdapter.registerFactory(NewModel::class.java, LayoutFactory(::NewViewHolder, R.layout.stories_private_story_new_item))
|
||||
mappingAdapter.registerFactory(AddViewerModel::class.java, LayoutFactory(::AddViewerViewHolder, R.layout.stories_private_story_add_viewer_item))
|
||||
mappingAdapter.registerFactory(RecipientModel::class.java, LayoutFactory(::RecipientViewHolder, R.layout.stories_private_story_recipient_item))
|
||||
mappingAdapter.registerFactory(Model::class.java, LayoutFactory(::ViewHolder, R.layout.stories_private_story_item))
|
||||
mappingAdapter.registerFactory(PartialModel::class.java, LayoutFactory(::PartialViewHolder, R.layout.stories_private_story_item))
|
||||
}
|
||||
|
||||
class NewModel(
|
||||
val onClick: () -> Unit
|
||||
) : PreferenceModel<NewModel>() {
|
||||
override fun areItemsTheSame(newItem: NewModel): Boolean = true
|
||||
mappingAdapter.registerFactory(AddViewerModel::class.java, LayoutFactory(PrivateStoryItem::AddViewerViewHolder, R.layout.stories_private_story_add_viewer_item))
|
||||
mappingAdapter.registerFactory(RecipientModel::class.java, LayoutFactory(PrivateStoryItem::RecipientViewHolder, R.layout.stories_private_story_recipient_item))
|
||||
mappingAdapter.registerFactory(Model::class.java, LayoutFactory(PrivateStoryItem::ViewHolder, R.layout.stories_private_story_item))
|
||||
mappingAdapter.registerFactory(PartialModel::class.java, LayoutFactory(PrivateStoryItem::PartialViewHolder, R.layout.stories_private_story_item))
|
||||
}
|
||||
|
||||
class AddViewerModel(
|
||||
|
@ -36,12 +29,14 @@ object PrivateStoryItem {
|
|||
|
||||
class RecipientModel(
|
||||
val recipient: Recipient,
|
||||
val onClick: (RecipientModel) -> Unit
|
||||
val onClick: ((RecipientModel) -> Unit)? = null
|
||||
) : PreferenceModel<RecipientModel>() {
|
||||
override fun areItemsTheSame(newItem: RecipientModel): Boolean = newItem.recipient == recipient
|
||||
|
||||
override fun areContentsTheSame(newItem: RecipientModel): Boolean {
|
||||
return newItem.recipient.hasSameContent(recipient) && super.areContentsTheSame(newItem)
|
||||
return newItem.recipient.hasSameContent(recipient) &&
|
||||
(newItem.onClick != null) == (onClick != null) &&
|
||||
super.areContentsTheSame(newItem)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +74,13 @@ object PrivateStoryItem {
|
|||
private val avatar: AvatarImageView = itemView.findViewById(R.id.avatar)
|
||||
|
||||
override fun bind(model: RecipientModel) {
|
||||
itemView.setOnClickListener { model.onClick(model) }
|
||||
val onClick = model.onClick
|
||||
if (onClick != null) {
|
||||
itemView.setOnClickListener { onClick(model) }
|
||||
} else {
|
||||
itemView.setOnClickListener(null)
|
||||
}
|
||||
|
||||
avatar.setRecipient(model.recipient)
|
||||
|
||||
if (model.recipient.isSelf) {
|
||||
|
@ -90,12 +91,6 @@ object PrivateStoryItem {
|
|||
}
|
||||
}
|
||||
|
||||
private class NewViewHolder(itemView: View) : MappingViewHolder<NewModel>(itemView) {
|
||||
override fun bind(model: NewModel) {
|
||||
itemView.setOnClickListener { model.onClick() }
|
||||
}
|
||||
}
|
||||
|
||||
private class AddViewerViewHolder(itemView: View) : MappingViewHolder<AddViewerModel>(itemView) {
|
||||
override fun bind(model: AddViewerModel) {
|
||||
itemView.setOnClickListener { model.onClick() }
|
|
@ -12,14 +12,13 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.WrapperDialogFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListId
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.stories.settings.story.PrivateStoryItem
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.fragments.findListener
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.viewholders.RecipientMappingModel
|
||||
|
@ -43,7 +42,7 @@ class PrivateStorySettingsFragment : DSLSettingsFragment(
|
|||
viewModel.refresh()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
adapter.registerFactory(RecipientMappingModel.RecipientIdMappingModel::class.java, LayoutFactory({ RecipientViewHolder(it, RecipientEventListener()) }, R.layout.stories_recipient_item))
|
||||
PrivateStoryItem.register(adapter)
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.group
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
/**
|
||||
* Minimum data needed to launch ConversationActivity for a given grou
|
||||
*/
|
||||
data class GroupConversationData(
|
||||
val groupRecipientId: RecipientId,
|
||||
val groupThreadId: Long
|
||||
)
|
|
@ -0,0 +1,102 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.group
|
||||
|
||||
import android.view.MenuItem
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.signal.core.util.dp
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.menu.ActionItem
|
||||
import org.thoughtcrime.securesms.components.menu.SignalContextMenu
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.conversation.ConversationIntents
|
||||
import org.thoughtcrime.securesms.stories.settings.custom.PrivateStoryItem
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
|
||||
/**
|
||||
* Displays who can see a group story and gives the user an option to remove it.
|
||||
*/
|
||||
class GroupStorySettingsFragment : DSLSettingsFragment(menuId = R.menu.story_group_menu) {
|
||||
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
|
||||
private val viewModel: GroupStorySettingsViewModel by viewModels(factoryProducer = {
|
||||
GroupStorySettingsViewModel.Factory(GroupStorySettingsFragmentArgs.fromBundle(requireArguments()).groupId)
|
||||
})
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
val toolbar: Toolbar = requireView().findViewById(R.id.toolbar)
|
||||
if (item.itemId == R.id.action_overflow) {
|
||||
SignalContextMenu.Builder(toolbar, requireView() as ViewGroup)
|
||||
.preferredHorizontalPosition(SignalContextMenu.HorizontalPosition.END)
|
||||
.preferredVerticalPosition(SignalContextMenu.VerticalPosition.BELOW)
|
||||
.offsetX(16.dp)
|
||||
.offsetY((-4).dp)
|
||||
.show(
|
||||
listOf(
|
||||
ActionItem(
|
||||
iconRes = R.drawable.ic_open_24_tinted,
|
||||
title = getString(R.string.StoriesLandingItem__go_to_chat),
|
||||
action = {
|
||||
lifecycleDisposable += viewModel.getConversationData().subscribe { data ->
|
||||
startActivity(ConversationIntents.createBuilder(requireContext(), data.groupRecipientId, data.groupThreadId).build())
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
PrivateStoryItem.register(adapter)
|
||||
|
||||
lifecycleDisposable.bindTo(viewLifecycleOwner)
|
||||
viewModel.state.observe(viewLifecycleOwner) { state ->
|
||||
if (state.removed) {
|
||||
findNavController().popBackStack()
|
||||
return@observe
|
||||
}
|
||||
|
||||
setTitle(state.name)
|
||||
adapter.submitList(getConfiguration(state).toMappingModelList())
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConfiguration(state: GroupStorySettingsState): DSLConfiguration {
|
||||
return configure {
|
||||
sectionHeaderPref(R.string.GroupStorySettingsFragment__who_can_view_this_story)
|
||||
|
||||
state.members.forEach {
|
||||
customPref(PrivateStoryItem.RecipientModel(it))
|
||||
}
|
||||
|
||||
textPref(
|
||||
title = DSLSettingsText.from(
|
||||
getString(R.string.GroupStorySettingsFragment__members_of_the_group_s, state.name),
|
||||
DSLSettingsText.TextAppearanceModifier(R.style.Signal_Text_BodyMedium),
|
||||
DSLSettingsText.ColorModifier(ContextCompat.getColor(requireContext(), R.color.signal_colorOnSurfaceVariant))
|
||||
)
|
||||
)
|
||||
|
||||
dividerPref()
|
||||
|
||||
clickPref(
|
||||
title = DSLSettingsText.from(
|
||||
R.string.GroupStorySettingsFragment__remove_group_story,
|
||||
DSLSettingsText.ColorModifier(ContextCompat.getColor(requireContext(), R.color.signal_colorError))
|
||||
),
|
||||
onClick = {
|
||||
viewModel.doNotDisplayAsStory()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.group
|
||||
|
||||
import io.reactivex.rxjava3.core.Completable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
|
||||
class GroupStorySettingsRepository {
|
||||
fun unmarkAsGroupStory(groupId: GroupId): Completable {
|
||||
return Completable.fromAction {
|
||||
SignalDatabase.groups.markDisplayAsStory(groupId, false)
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
fun getConversationData(groupId: GroupId): Single<GroupConversationData> {
|
||||
return Single.fromCallable {
|
||||
val recipientId = SignalDatabase.recipients.getByGroupId(groupId).get()
|
||||
val threadId = SignalDatabase.threads.getThreadIdFor(recipientId) ?: -1L
|
||||
|
||||
GroupConversationData(recipientId, threadId)
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.group
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
data class GroupStorySettingsState(
|
||||
val name: String = "",
|
||||
val members: List<Recipient> = emptyList(),
|
||||
val removed: Boolean = false
|
||||
)
|
|
@ -0,0 +1,45 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.group
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.LiveGroup
|
||||
import org.thoughtcrime.securesms.groups.ParcelableGroupId
|
||||
import org.thoughtcrime.securesms.util.livedata.Store
|
||||
|
||||
/**
|
||||
* This class utilizes LiveData due to pre-existing infrastructure in LiveGroup
|
||||
*/
|
||||
class GroupStorySettingsViewModel(private val groupId: GroupId) : ViewModel() {
|
||||
|
||||
private val repository = GroupStorySettingsRepository()
|
||||
private val store = Store(GroupStorySettingsState())
|
||||
|
||||
val state: LiveData<GroupStorySettingsState> = store.stateLiveData
|
||||
|
||||
init {
|
||||
val group = LiveGroup(groupId)
|
||||
|
||||
store.update(group.fullMembers) { members, state -> state.copy(members = members.map { it.member }) }
|
||||
store.update(group.title) { title, state -> state.copy(name = title) }
|
||||
}
|
||||
|
||||
fun doNotDisplayAsStory() {
|
||||
repository.unmarkAsGroupStory(groupId).subscribe {
|
||||
store.update { it.copy(removed = true) }
|
||||
}
|
||||
}
|
||||
|
||||
fun getConversationData(): Single<GroupConversationData> {
|
||||
return repository.getConversationData(groupId).observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
|
||||
class Factory(private val parcelableGroupId: ParcelableGroupId) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||
return modelClass.cast(GroupStorySettingsViewModel(ParcelableGroupId.get(parcelableGroupId)!!)) as T
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,12 +10,12 @@ import androidx.navigation.fragment.findNavController
|
|||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.WrapperDialogFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
class MyStorySettingsFragment : DSLSettingsFragment(
|
||||
|
@ -37,7 +37,7 @@ class MyStorySettingsFragment : DSLSettingsFragment(
|
|||
viewModel.refresh()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
viewModel.state.observe(viewLifecycleOwner) { state ->
|
||||
adapter.submitList(getConfiguration(state).toMappingModelList())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.story
|
||||
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.signal.core.util.dp
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchItems
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
||||
import org.thoughtcrime.securesms.groups.ParcelableGroupId
|
||||
import org.thoughtcrime.securesms.mediasend.v2.stories.ChooseGroupStoryBottomSheet
|
||||
import org.thoughtcrime.securesms.mediasend.v2.stories.ChooseStoryTypeBottomSheet
|
||||
import org.thoughtcrime.securesms.stories.settings.create.CreateStoryFlowDialogFragment
|
||||
import org.thoughtcrime.securesms.stories.settings.create.CreateStoryWithViewersFragment
|
||||
import org.thoughtcrime.securesms.util.BottomSheetUtil
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.PagingMappingAdapter
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
/**
|
||||
* Allows the user to view their stories they can send to and modify settings.
|
||||
*/
|
||||
class StoriesPrivacySettingsFragment :
|
||||
DSLSettingsFragment(
|
||||
titleId = R.string.preferences__stories
|
||||
),
|
||||
ChooseStoryTypeBottomSheet.Callback {
|
||||
|
||||
private val viewModel: StoriesPrivacySettingsViewModel by viewModels()
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
|
||||
override fun createAdapters(): Array<MappingAdapter> {
|
||||
return arrayOf(DSLSettingsAdapter(), PagingMappingAdapter<ContactSearchKey>(), DSLSettingsAdapter())
|
||||
}
|
||||
|
||||
override fun bindAdapters(adapter: ConcatAdapter) {
|
||||
lifecycleDisposable.bindTo(viewLifecycleOwner)
|
||||
|
||||
val titleId = StoriesPrivacySettingsFragmentArgs.fromBundle(requireArguments()).titleId
|
||||
setTitle(titleId)
|
||||
|
||||
val (top, middle, bottom) = adapter.adapters
|
||||
|
||||
findNavController().addOnDestinationChangedListener { _, destination, _ ->
|
||||
if (destination.id == R.id.storiesPrivacySettingsFragment) {
|
||||
viewModel.pagingController.onDataInvalidated()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
ContactSearchItems.registerStoryItems(
|
||||
mappingAdapter = middle as PagingMappingAdapter<ContactSearchKey>,
|
||||
storyListener = { _, story, _ ->
|
||||
when {
|
||||
story.recipient.isMyStory -> findNavController().safeNavigate(StoriesPrivacySettingsFragmentDirections.actionStoryPrivacySettingsToMyStorySettings())
|
||||
story.recipient.isGroup -> findNavController().safeNavigate(StoriesPrivacySettingsFragmentDirections.actionStoryPrivacySettingsToGroupStorySettings(ParcelableGroupId.from(story.recipient.requireGroupId())))
|
||||
else -> findNavController().safeNavigate(StoriesPrivacySettingsFragmentDirections.actionStoryPrivacySettingsToPrivateStorySettings(story.recipient.requireDistributionListId()))
|
||||
}
|
||||
}
|
||||
)
|
||||
ContactSearchItems.registerHeaders(middle)
|
||||
|
||||
middle.setPagingController(viewModel.pagingController)
|
||||
|
||||
parentFragmentManager.setFragmentResultListener(ChooseGroupStoryBottomSheet.GROUP_STORY, viewLifecycleOwner) { _, bundle ->
|
||||
val results = ChooseGroupStoryBottomSheet.ResultContract.getRecipientIds(bundle)
|
||||
viewModel.displayGroupsAsStories(results)
|
||||
}
|
||||
|
||||
parentFragmentManager.setFragmentResultListener(CreateStoryWithViewersFragment.REQUEST_KEY, viewLifecycleOwner) { _, _ ->
|
||||
viewModel.pagingController.onDataInvalidated()
|
||||
}
|
||||
|
||||
lifecycleDisposable += viewModel.headerActionRequests.subscribe {
|
||||
ChooseStoryTypeBottomSheet().show(childFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
}
|
||||
|
||||
lifecycleDisposable += viewModel.state.subscribe { state ->
|
||||
(top as MappingAdapter).submitList(getTopConfiguration(state).toMappingModelList())
|
||||
middle.submitList(getMiddleConfiguration(state).toMappingModelList())
|
||||
(bottom as MappingAdapter).submitList(getBottomConfiguration(state).toMappingModelList())
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTopConfiguration(state: StoriesPrivacySettingsState): DSLConfiguration {
|
||||
return configure {
|
||||
if (state.areStoriesEnabled) {
|
||||
space(16.dp)
|
||||
|
||||
noPadTextPref(
|
||||
title = DSLSettingsText.from(
|
||||
R.string.StoriesPrivacySettingsFragment__stories_automatically_disappear,
|
||||
DSLSettingsText.TextAppearanceModifier(R.style.Signal_Text_BodyMedium),
|
||||
DSLSettingsText.ColorModifier(ContextCompat.getColor(requireContext(), R.color.signal_colorOnSurfaceVariant))
|
||||
)
|
||||
)
|
||||
|
||||
space(20.dp)
|
||||
} else {
|
||||
clickPref(
|
||||
title = DSLSettingsText.from(R.string.StoriesPrivacySettingsFragment__turn_on_stories),
|
||||
summary = DSLSettingsText.from(R.string.StoriesPrivacySettingsFragment__share_and_view),
|
||||
onClick = {
|
||||
viewModel.setStoriesEnabled(true)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMiddleConfiguration(state: StoriesPrivacySettingsState): DSLConfiguration {
|
||||
return if (state.areStoriesEnabled) {
|
||||
configure {
|
||||
ContactSearchItems.toMappingModelList(
|
||||
state.storyContactItems,
|
||||
emptySet()
|
||||
).forEach {
|
||||
customPref(it)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
configure { }
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBottomConfiguration(state: StoriesPrivacySettingsState): DSLConfiguration {
|
||||
return if (state.areStoriesEnabled) {
|
||||
configure {
|
||||
dividerPref()
|
||||
|
||||
clickPref(
|
||||
title = DSLSettingsText.from(R.string.StoriesPrivacySettingsFragment__turn_off_stories),
|
||||
summary = DSLSettingsText.from(
|
||||
R.string.StoriesPrivacySettingsFragment__if_you_opt_out,
|
||||
DSLSettingsText.TextAppearanceModifier(R.style.Signal_Text_BodyMedium),
|
||||
DSLSettingsText.ColorModifier(ContextCompat.getColor(requireContext(), R.color.signal_colorOnSurfaceVariant))
|
||||
),
|
||||
onClick = {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.StoriesPrivacySettingsFragment__turn_off_stories_question)
|
||||
.setMessage(R.string.StoriesPrivacySettingsFragment__you_will_no_longer_be_able_to)
|
||||
.setPositiveButton(R.string.StoriesPrivacySettingsFragment__turn_off_stories) { _, _ -> viewModel.setStoriesEnabled(false) }
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
.show()
|
||||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
configure { }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGroupStoryClicked() {
|
||||
ChooseGroupStoryBottomSheet().show(parentFragmentManager, ChooseGroupStoryBottomSheet.GROUP_STORY)
|
||||
}
|
||||
|
||||
override fun onNewStoryClicked() {
|
||||
CreateStoryFlowDialogFragment().show(parentFragmentManager, CreateStoryWithViewersFragment.REQUEST_KEY)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.story
|
||||
|
||||
import io.reactivex.rxjava3.core.Completable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
class StoriesPrivacySettingsRepository {
|
||||
fun markGroupsAsStories(groups: List<RecipientId>): Completable {
|
||||
return Completable.fromCallable {
|
||||
groups
|
||||
.map { Recipient.resolved(it) }
|
||||
.forEach { SignalDatabase.groups.markDisplayAsStory(it.requireGroupId()) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.story
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchData
|
||||
|
||||
data class StoriesPrivacySettingsState(
|
||||
val areStoriesEnabled: Boolean,
|
||||
val storyContactItems: List<ContactSearchData> = emptyList()
|
||||
)
|
|
@ -0,0 +1,82 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.story
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import org.signal.paging.PagedData
|
||||
import org.signal.paging.PagingConfig
|
||||
import org.signal.paging.ProxyPagingController
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchConfiguration
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchPagedDataSource
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
import org.thoughtcrime.securesms.util.rx.RxStore
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class StoriesPrivacySettingsViewModel : ViewModel() {
|
||||
|
||||
private val repository = StoriesPrivacySettingsRepository()
|
||||
|
||||
private val store = RxStore(
|
||||
StoriesPrivacySettingsState(
|
||||
areStoriesEnabled = Stories.isFeatureEnabled()
|
||||
)
|
||||
)
|
||||
|
||||
private val pagingConfig = PagingConfig.Builder()
|
||||
.setBufferPages(1)
|
||||
.setPageSize(20)
|
||||
.setStartIndex(0)
|
||||
.build()
|
||||
|
||||
private val disposables = CompositeDisposable()
|
||||
private val headerActionRequestSubject = PublishSubject.create<Unit>()
|
||||
|
||||
val state: Flowable<StoriesPrivacySettingsState> = store.stateFlowable.observeOn(AndroidSchedulers.mainThread())
|
||||
val pagingController = ProxyPagingController<ContactSearchKey>()
|
||||
val headerActionRequests: Observable<Unit> = headerActionRequestSubject.debounce(100, TimeUnit.MILLISECONDS)
|
||||
|
||||
init {
|
||||
val configuration = ContactSearchConfiguration.build {
|
||||
addSection(
|
||||
ContactSearchConfiguration.Section.Stories(
|
||||
includeHeader = true,
|
||||
headerAction = Stories.getHeaderAction {
|
||||
headerActionRequestSubject.onNext(Unit)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val pagedDataSource = ContactSearchPagedDataSource(configuration)
|
||||
val observablePagedData = PagedData.createForObservable(pagedDataSource, pagingConfig)
|
||||
|
||||
pagingController.set(observablePagedData.controller)
|
||||
|
||||
store.update(observablePagedData.data.toFlowable(BackpressureStrategy.LATEST)) { data, state ->
|
||||
state.copy(storyContactItems = data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
disposables.clear()
|
||||
}
|
||||
|
||||
fun setStoriesEnabled(isEnabled: Boolean) {
|
||||
SignalStore.storyValues().isFeatureDisabled = !isEnabled
|
||||
store.update { it.copy(areStoriesEnabled = Stories.isFeatureEnabled()) }
|
||||
}
|
||||
|
||||
fun displayGroupsAsStories(recipientIds: List<RecipientId>) {
|
||||
disposables += repository.markGroupsAsStories(recipientIds).subscribe {
|
||||
pagingController.onDataInvalidated()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.story
|
||||
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
class StorySettingsFragment : DSLSettingsFragment(
|
||||
titleId = R.string.StorySettingsFragment__story_settings
|
||||
) {
|
||||
|
||||
private val viewModel: StorySettingsViewModel by viewModels(
|
||||
factoryProducer = {
|
||||
StorySettingsViewModel.Factory(StorySettingsRepository())
|
||||
}
|
||||
)
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
viewModel.refresh()
|
||||
}
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
PrivateStoryItem.register(adapter)
|
||||
|
||||
viewModel.state.observe(viewLifecycleOwner) { state ->
|
||||
adapter.submitList(getConfiguration(state).toMappingModelList())
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConfiguration(state: StorySettingsState): DSLConfiguration {
|
||||
return configure {
|
||||
customPref(
|
||||
PrivateStoryItem.RecipientModel(
|
||||
recipient = Recipient.self(),
|
||||
onClick = {
|
||||
findNavController().safeNavigate(R.id.action_storySettings_to_myStorySettings)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
dividerPref()
|
||||
sectionHeaderPref(R.string.StorySettingsFragment__private_stories)
|
||||
|
||||
customPref(
|
||||
PrivateStoryItem.NewModel(
|
||||
onClick = {
|
||||
findNavController().safeNavigate(R.id.action_storySettings_to_newStory)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
state.privateStories.forEach { itemData ->
|
||||
customPref(
|
||||
PrivateStoryItem.PartialModel(
|
||||
privateStoryItemData = itemData,
|
||||
onClick = {
|
||||
findNavController().safeNavigate(StorySettingsFragmentDirections.actionStorySettingsToPrivateStorySettings(it.privateStoryItemData.id))
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
textPref(summary = DSLSettingsText.from(R.string.StorySettingsFragment__private_stories_can_only_be_viewed))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.story
|
||||
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPartialRecord
|
||||
|
||||
class StorySettingsRepository {
|
||||
fun getPrivateStories(): Single<List<DistributionListPartialRecord>> {
|
||||
return Single.fromCallable {
|
||||
SignalDatabase.distributionLists.getCustomListsForUi()
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.story
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPartialRecord
|
||||
|
||||
data class StorySettingsState(
|
||||
val privateStories: List<DistributionListPartialRecord> = emptyList()
|
||||
)
|
|
@ -1,36 +0,0 @@
|
|||
package org.thoughtcrime.securesms.stories.settings.story
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||
import org.thoughtcrime.securesms.util.livedata.Store
|
||||
|
||||
class StorySettingsViewModel(
|
||||
private val repository: StorySettingsRepository
|
||||
) : ViewModel() {
|
||||
|
||||
private val store = Store(StorySettingsState())
|
||||
private val disposables = CompositeDisposable()
|
||||
|
||||
val state: LiveData<StorySettingsState> = store.stateLiveData
|
||||
|
||||
fun refresh() {
|
||||
disposables += repository.getPrivateStories().subscribe { privateStories ->
|
||||
store.update { it.copy(privateStories = privateStories) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
disposables.clear()
|
||||
}
|
||||
|
||||
class Factory(
|
||||
private val repository: StorySettingsRepository
|
||||
) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return modelClass.cast(StorySettingsViewModel(repository)) as T
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,6 @@ import androidx.fragment.app.viewModels
|
|||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
|
@ -15,6 +14,7 @@ import org.thoughtcrime.securesms.conversation.ConversationIntents
|
|||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.stories.viewer.reply.StoryViewsAndRepliesPagerChild
|
||||
import org.thoughtcrime.securesms.stories.viewer.reply.StoryViewsAndRepliesPagerParent
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.fragments.findListener
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
|
||||
|
@ -37,7 +37,7 @@ class StoryViewsFragment :
|
|||
private val storyId: Long
|
||||
get() = requireArguments().getLong(ARG_STORY_ID)
|
||||
|
||||
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
StoryViewItem.register(adapter)
|
||||
|
||||
val emptyNotice: View = requireView().findViewById(R.id.empty_notice)
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:viewBindingIgnore="true"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:minHeight="64dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="@dimen/dsl_settings_gutter">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="@drawable/circle_tintable"
|
||||
android:importantForAccessibility="no"
|
||||
android:scaleType="centerInside"
|
||||
app:backgroundTint="@color/signal_colorSurfaceVariant"
|
||||
app:srcCompat="@drawable/ic_add_members_20"
|
||||
app:tint="@color/signal_colorOnSurfaceVariant" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/StorySettingsFragment__new_private_story"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
android:textColor="@color/signal_colorOnSurface" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_overflow"
|
||||
android:icon="@drawable/ic_more_vert_24"
|
||||
android:title="@string/OverflowMenu__overflow_menu"
|
||||
app:showAsAction="always" />
|
||||
</menu>
|
|
@ -3,6 +3,6 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:title="@string/StorySettingsFragment__story_settings"
|
||||
android:title="@string/StoriesLandingFragment__story_privacy"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
|
@ -322,33 +322,19 @@
|
|||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_privacySettings_to_myStorySettings"
|
||||
app:destination="@id/my_story_settings"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
<action
|
||||
android:id="@+id/action_privacySettings_to_newPrivateStory"
|
||||
app:destination="@id/new_story"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
<action
|
||||
android:id="@+id/action_privacySettings_to_privateStorySettings"
|
||||
app:destination="@id/private_story_settings"
|
||||
android:id="@+id/action_privacySettingsFragment_to_storyPrivacySettings"
|
||||
app:destination="@+id/story_privacy_settings"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit">
|
||||
|
||||
<argument
|
||||
android:name="private_story"
|
||||
app:argType="org.thoughtcrime.securesms.database.model.DistributionListId"
|
||||
android:name="title_id"
|
||||
app:argType="integer"
|
||||
app:nullable="false" />
|
||||
|
||||
</action>
|
||||
</fragment>
|
||||
|
||||
|
@ -868,10 +854,6 @@
|
|||
|
||||
</fragment>
|
||||
|
||||
<include app:graph="@navigation/story_privacy_settings" />
|
||||
|
||||
<include app:graph="@navigation/my_story_settings" />
|
||||
|
||||
<include app:graph="@navigation/private_story_settings" />
|
||||
|
||||
<include app:graph="@navigation/new_story" />
|
||||
</navigation>
|
|
@ -1,22 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/story_settings"
|
||||
app:startDestination="@id/storySettings">
|
||||
android:id="@+id/story_privacy_settings"
|
||||
app:startDestination="@id/storiesPrivacySettingsFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/storySettings"
|
||||
android:name="org.thoughtcrime.securesms.stories.settings.story.StorySettingsFragment"
|
||||
android:label="story_settings_fragment">
|
||||
android:id="@+id/storiesPrivacySettingsFragment"
|
||||
android:name="org.thoughtcrime.securesms.stories.settings.story.StoriesPrivacySettingsFragment"
|
||||
android:label="stories_privacy_settings_fragment">
|
||||
|
||||
<argument
|
||||
android:name="title_id"
|
||||
app:argType="integer"
|
||||
app:nullable="false" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_storySettings_to_myStorySettings"
|
||||
android:id="@+id/action_storyPrivacySettings_to_myStorySettings"
|
||||
app:destination="@id/my_story_settings"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
<action
|
||||
android:id="@+id/action_storySettings_to_privateStorySettings"
|
||||
android:id="@+id/action_storyPrivacySettings_to_privateStorySettings"
|
||||
app:destination="@id/private_story_settings"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
|
@ -30,18 +36,33 @@
|
|||
|
||||
</action>
|
||||
<action
|
||||
android:id="@+id/action_storySettings_to_newStory"
|
||||
app:destination="@id/new_story"
|
||||
android:id="@+id/action_storyPrivacySettings_to_groupStorySettings"
|
||||
app:destination="@id/groupStorySettingsFragment"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
app:popExitAnim="@anim/fragment_close_exit">
|
||||
|
||||
<argument
|
||||
android:name="group_id"
|
||||
app:argType="org.thoughtcrime.securesms.groups.ParcelableGroupId"
|
||||
app:nullable="false" />
|
||||
</action>
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/groupStorySettingsFragment"
|
||||
android:name="org.thoughtcrime.securesms.stories.settings.group.GroupStorySettingsFragment"
|
||||
android:label="group_story_settings_fragment">
|
||||
|
||||
<argument
|
||||
android:name="group_id"
|
||||
app:argType="org.thoughtcrime.securesms.groups.ParcelableGroupId"
|
||||
app:nullable="false" />
|
||||
|
||||
</fragment>
|
||||
|
||||
<include app:graph="@navigation/my_story_settings" />
|
||||
|
||||
<include app:graph="@navigation/private_story_settings" />
|
||||
|
||||
<include app:graph="@navigation/new_story" />
|
||||
|
||||
</navigation>
|
|
@ -2597,6 +2597,8 @@
|
|||
<!-- Preference label for making one-time donations to Signal -->
|
||||
<string name="preferences__one_time_donation">One-time Donation</string>
|
||||
<string name="preferences__privacy">Privacy</string>
|
||||
<!-- Preference label for stories -->
|
||||
<string name="preferences__stories">Stories</string>
|
||||
<string name="preferences__mms_user_agent">MMS User Agent</string>
|
||||
<string name="preferences__advanced_mms_access_point_names">Manual MMS settings</string>
|
||||
<string name="preferences__mmsc_url">MMSC URL</string>
|
||||
|
@ -3922,6 +3924,8 @@
|
|||
<string name="PrivacySettingsFragment__signal_message_and_calls">Signal messages and calls, always relay calls, and sealed sender</string>
|
||||
<string name="PrivacySettingsFragment__default_timer_for_new_changes">Default timer for new chats</string>
|
||||
<string name="PrivacySettingsFragment__set_a_default_disappearing_message_timer_for_all_new_chats_started_by_you">Set a default disappearing message timer for all new chats started by you.</string>
|
||||
<!-- Summary for stories preference to launch into story privacy settings -->
|
||||
<string name="PrivacySettingsFragment__manage_your_stories">Manage your stories and who can view them</string>
|
||||
|
||||
<!-- AdvancedPrivacySettingsFragment -->
|
||||
<string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string>
|
||||
|
@ -4610,6 +4614,8 @@
|
|||
<string name="ConversationListTabs__stories">Stories</string>
|
||||
<!-- String for counts above 99 in conversation list tabs -->
|
||||
<string name="ConversationListTabs__99p">99+</string>
|
||||
<!-- Menu item on stories landing page -->
|
||||
<string name="StoriesLandingFragment__story_privacy">Story privacy</string>
|
||||
<!-- Title for "My Stories" row item in Stories landing page -->
|
||||
<string name="StoriesLandingFragment__my_stories">My Stories</string>
|
||||
<!-- Subtitle for "My Stories" row item when user has not added stories -->
|
||||
|
@ -4717,14 +4723,6 @@
|
|||
<string name="StoryGroupReplyItem__copy">Copy</string>
|
||||
<!-- Context menu item to delete a story response -->
|
||||
<string name="StoryGroupReplyItem__delete">Delete</string>
|
||||
<!-- Story settings page title -->
|
||||
<string name="StorySettingsFragment__story_settings">Story settings</string>
|
||||
<!-- Story settings private stories heading -->
|
||||
<string name="StorySettingsFragment__private_stories">Private stories</string>
|
||||
<!-- Note at bottom of story settings regarding who can see private stories. -->
|
||||
<string name="StorySettingsFragment__private_stories_can_only_be_viewed">Private stories can only be viewed by the people you add to them. Only you can see the story name.</string>
|
||||
<!-- Option label for creating a new private story -->
|
||||
<string name="StorySettingsFragment__new_private_story">New private story</string>
|
||||
<!-- Page title for My Story options -->
|
||||
<string name="MyStorySettingsFragment__my_story">My Story</string>
|
||||
<!-- Section heading for story visibility -->
|
||||
|
@ -4979,6 +4977,11 @@
|
|||
<item quantity="one">Group Story · %1$d viewer</item>
|
||||
<item quantity="other">Group Story · %1$d viewers</item>
|
||||
</plurals>
|
||||
<!-- Label under name for my story -->
|
||||
<plurals name="ContactSearchItems__my_story_s_dot_d_viewers">
|
||||
<item quantity="one">%1$s · %2$d viewer</item>
|
||||
<item quantity="other">%1$s · %2$d viewers</item>
|
||||
</plurals>
|
||||
<!-- Label under name for My Story when first sending to my story -->
|
||||
<string name="ContactSearchItems__tap_to_choose_your_viewers">Tap to choose your viewers</string>
|
||||
<!-- Label for context menu item to open story settings -->
|
||||
|
@ -5093,6 +5096,35 @@
|
|||
<!-- Story Info context menu label -->
|
||||
<string name="StoryInfoBottomSheetDialogFragment__info">Info</string>
|
||||
|
||||
<!-- StoriesPrivacySettingsFragment -->
|
||||
<!-- Explanation about how stories are deleted and managed -->
|
||||
<string name="StoriesPrivacySettingsFragment__stories_automatically_disappear">Stories automatically disappear after 24 hours. Choose who can view your story or create new stories with specific viewers or groups.</string>
|
||||
<!-- Preference title to turn off stories -->
|
||||
<string name="StoriesPrivacySettingsFragment__turn_off_stories">Turn off stories</string>
|
||||
<!-- Preference summary to turn off stories -->
|
||||
<string name="StoriesPrivacySettingsFragment__if_you_opt_out">If you opt out of stories you will no longer be able to share or view stories.</string>
|
||||
<!-- Preference title to turn on stories -->
|
||||
<string name="StoriesPrivacySettingsFragment__turn_on_stories">Turn on stories</string>
|
||||
<!-- Preference summary to turn on stories -->
|
||||
<string name="StoriesPrivacySettingsFragment__share_and_view">Share and view stories from others. Stories automatically disappear after 24 hours.</string>
|
||||
<!-- Dialog title to turn off stories -->
|
||||
<string name="StoriesPrivacySettingsFragment__turn_off_stories_question">Turn off stories?</string>
|
||||
<!-- Dialog message to turn off stories -->
|
||||
<string name="StoriesPrivacySettingsFragment__you_will_no_longer_be_able_to">You will no longer be able to share or view stories. Any stories you have recently sent will still be visible by others until they expire.</string>
|
||||
<!-- Page title when launched from stories landing screen -->
|
||||
<string name="StoriesPrivacySettingsFragment__story_privacy">Story privacy</string>
|
||||
|
||||
<!-- GroupStorySettingsFragment -->
|
||||
<!-- Section header for who can view a group story -->
|
||||
<string name="GroupStorySettingsFragment__who_can_view_this_story">Who can view this story</string>
|
||||
<!-- Explanation of who can view a group story -->
|
||||
<string name="GroupStorySettingsFragment__members_of_the_group_s">Members of the group "%1$s" can view and reply to this story. You can update the membership for this chat in the group.</string>
|
||||
<!-- Preference label for removing this group story -->
|
||||
<string name="GroupStorySettingsFragment__remove_group_story">Remove group story</string>
|
||||
|
||||
<!-- Generic title for overflow menus -->
|
||||
<string name="OverflowMenu__overflow_menu">Overflow menu</string>
|
||||
|
||||
<!-- EOF -->
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.mockito.kotlin.isNull
|
|||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.whenever
|
||||
import org.thoughtcrime.securesms.MockCursor
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
|
@ -19,7 +20,7 @@ class ContactSearchPagedDataSourceTest {
|
|||
|
||||
private val repository: ContactSearchPagedDataSourceRepository = mock()
|
||||
private val cursor: MockCursor = mock()
|
||||
private val groupStoryData = ContactSearchData.Story(Recipient.UNKNOWN, 0)
|
||||
private val groupStoryData = ContactSearchData.Story(Recipient.UNKNOWN, 0, DistributionListPrivacyMode.ALL)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
|
@ -27,6 +28,7 @@ class ContactSearchPagedDataSourceTest {
|
|||
whenever(repository.getRecipientFromRecipientCursor(cursor)).thenReturn(Recipient.UNKNOWN)
|
||||
whenever(repository.getRecipientFromThreadCursor(cursor)).thenReturn(Recipient.UNKNOWN)
|
||||
whenever(repository.getRecipientFromDistributionListCursor(cursor)).thenReturn(Recipient.UNKNOWN)
|
||||
whenever(repository.getPrivacyModeFromDistributionListCursor(cursor)).thenReturn(DistributionListPrivacyMode.ALL)
|
||||
whenever(repository.getGroupStories()).thenReturn(emptySet())
|
||||
whenever(repository.getLatestStorySends(any())).thenReturn(emptyList())
|
||||
whenever(cursor.moveToPosition(any())).thenCallRealMethod()
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package org.signal.core.util
|
||||
|
||||
import androidx.annotation.Px
|
||||
|
||||
/**
|
||||
* Converts the given Float DP value into Pixels.
|
||||
*/
|
||||
@get:Px
|
||||
val Float.dp: Float get() = DimensionUnit.DP.toPixels(this)
|
||||
|
||||
/**
|
||||
* Converts the given Int DP value into Pixels
|
||||
*/
|
||||
@get:Px
|
||||
val Int.dp: Int get() = this.toFloat().dp.toInt()
|
Ładowanie…
Reference in New Issue