mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Add Banners to all reminder usages behind remote config.
This commit is contained in:
committed by
mtang-signal
parent
f296fcd716
commit
e2e6a73e8d
@@ -14,8 +14,12 @@ import android.util.AttributeSet
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.LinearLayoutCompat
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.core.transition.addListener
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.banner.Banner
|
||||
import org.thoughtcrime.securesms.banner.BannerManager
|
||||
import org.thoughtcrime.securesms.components.identity.UnverifiedBannerView
|
||||
import org.thoughtcrime.securesms.components.reminder.Reminder
|
||||
import org.thoughtcrime.securesms.components.reminder.ReminderView
|
||||
@@ -47,6 +51,7 @@ class ConversationBannerView @JvmOverloads constructor(
|
||||
) : LinearLayoutCompat(context, attrs, defStyleAttr) {
|
||||
private val unverifiedBannerStub: Stub<UnverifiedBannerView> by lazy { ViewUtil.findStubById(this, R.id.unverified_banner_stub) }
|
||||
private val reminderStub: Stub<ReminderView> by lazy { ViewUtil.findStubById(this, R.id.reminder_stub) }
|
||||
private val bannerStub: Stub<ComposeView> by lazy { ViewUtil.findStubById(this, R.id.banner_stub) }
|
||||
private val reviewBannerStub: Stub<ReviewBannerView> by lazy { ViewUtil.findStubById(this, R.id.review_banner_stub) }
|
||||
private val voiceNotePlayerStub: Stub<View> by lazy { ViewUtil.findStubById(this, R.id.voice_note_player_stub) }
|
||||
|
||||
@@ -56,6 +61,13 @@ class ConversationBannerView @JvmOverloads constructor(
|
||||
orientation = VERTICAL
|
||||
}
|
||||
|
||||
fun collectAndShowBanners(flows: Iterable<Flow<Banner>>) {
|
||||
val bannerManager = BannerManager(flows)
|
||||
show(stub = bannerStub) {
|
||||
bannerManager.setContent(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun showReminder(reminder: Reminder) {
|
||||
show(
|
||||
stub = reminderStub
|
||||
|
||||
@@ -228,6 +228,7 @@ import org.thoughtcrime.securesms.groups.ui.migration.GroupsV1MigrationInfoBotto
|
||||
import org.thoughtcrime.securesms.groups.ui.migration.GroupsV1MigrationSuggestionsDialog
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupBlockJoinRequestResult
|
||||
import org.thoughtcrime.securesms.invites.InviteActions
|
||||
import org.thoughtcrime.securesms.jobs.ServiceOutageDetectionJob
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPage
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPagerFragment
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPagerViewModel
|
||||
@@ -1016,17 +1017,38 @@ class ConversationFragment :
|
||||
VoiceMessageRecordingSessionCallbacks()
|
||||
)
|
||||
|
||||
binding.conversationBanner.listener = ConversationBannerListener()
|
||||
viewModel
|
||||
.reminder
|
||||
.subscribeBy { reminder ->
|
||||
if (reminder.isPresent) {
|
||||
binding.conversationBanner.showReminder(reminder.get())
|
||||
} else {
|
||||
binding.conversationBanner.clearReminder()
|
||||
}
|
||||
val conversationBannerListener = ConversationBannerListener()
|
||||
binding.conversationBanner.listener = conversationBannerListener
|
||||
if (RemoteConfig.newBannerUi) {
|
||||
val bannerFlows = viewModel.getBannerFlows(
|
||||
context = requireContext(),
|
||||
groupJoinClickListener = conversationBannerListener::reviewJoinRequestsAction,
|
||||
onAddMembers = {
|
||||
conversationGroupViewModel.groupRecordSnapshot?.let { groupRecord ->
|
||||
GroupsV1MigrationSuggestionsDialog.show(requireActivity(), groupRecord.id.requireV2(), groupRecord.gv1MigrationSuggestions)
|
||||
}
|
||||
},
|
||||
onNoThanks = conversationGroupViewModel::onSuggestedMembersBannerDismissed,
|
||||
bubbleClickListener = conversationBannerListener::changeBubbleSettingAction
|
||||
)
|
||||
|
||||
binding.conversationBanner.collectAndShowBanners(bannerFlows)
|
||||
|
||||
if (TextSecurePreferences.getServiceOutage(context)) {
|
||||
AppDependencies.jobManager.add(ServiceOutageDetectionJob())
|
||||
}
|
||||
.addTo(disposables)
|
||||
} else {
|
||||
viewModel
|
||||
.reminder
|
||||
.subscribeBy { reminder ->
|
||||
if (reminder.isPresent) {
|
||||
binding.conversationBanner.showReminder(reminder.get())
|
||||
} else {
|
||||
binding.conversationBanner.clearReminder()
|
||||
}
|
||||
}
|
||||
.addTo(disposables)
|
||||
}
|
||||
|
||||
viewModel
|
||||
.identityRecordsObservable
|
||||
|
||||
@@ -29,9 +29,25 @@ import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import io.reactivex.rxjava3.subjects.Subject
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flatMap
|
||||
import kotlinx.coroutines.flow.flatMapConcat
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.rx3.asFlow
|
||||
import org.signal.core.util.concurrent.subscribeWithSubject
|
||||
import org.signal.core.util.orNull
|
||||
import org.signal.paging.ProxyPagingController
|
||||
import org.thoughtcrime.securesms.banner.Banner
|
||||
import org.thoughtcrime.securesms.banner.banners.BubbleOptOutBanner
|
||||
import org.thoughtcrime.securesms.banner.banners.GroupsV1MigrationSuggestionsBanner
|
||||
import org.thoughtcrime.securesms.banner.banners.OutdatedBuildBanner
|
||||
import org.thoughtcrime.securesms.banner.banners.PendingGroupJoinRequestsBanner
|
||||
import org.thoughtcrime.securesms.banner.banners.PendingGroupJoinRequestsBanner.Producer
|
||||
import org.thoughtcrime.securesms.banner.banners.ServiceOutageBanner
|
||||
import org.thoughtcrime.securesms.banner.banners.UnauthorizedBanner
|
||||
import org.thoughtcrime.securesms.components.reminder.Reminder
|
||||
import org.thoughtcrime.securesms.contactshare.Contact
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage
|
||||
@@ -42,6 +58,7 @@ import org.thoughtcrime.securesms.conversation.v2.data.ConversationElementKey
|
||||
import org.thoughtcrime.securesms.conversation.v2.items.ChatColorsDrawable
|
||||
import org.thoughtcrime.securesms.database.DatabaseObserver
|
||||
import org.thoughtcrime.securesms.database.MessageTable
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord
|
||||
import org.thoughtcrime.securesms.database.model.Mention
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
@@ -155,6 +172,8 @@ class ConversationViewModel(
|
||||
private val refreshReminder: Subject<Unit> = PublishSubject.create()
|
||||
val reminder: Observable<Optional<Reminder>>
|
||||
|
||||
private val groupRecordFlow: Flow<GroupRecord?>
|
||||
|
||||
private val refreshIdentityRecords: Subject<Unit> = PublishSubject.create()
|
||||
private val identityRecordsStore: RxStore<IdentityRecordsState> = RxStore(IdentityRecordsState())
|
||||
val identityRecordsObservable: Observable<IdentityRecordsState> = identityRecordsStore.stateFlowable.toObservable()
|
||||
@@ -276,6 +295,8 @@ class ConversationViewModel(
|
||||
.flatMapMaybe { groupRecord -> repository.getReminder(groupRecord.orNull()) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
groupRecordFlow = recipientRepository.groupRecord.subscribeOn(Schedulers.io()).asFlow().map { it.orNull() }
|
||||
|
||||
Observable.combineLatest(
|
||||
refreshIdentityRecords.startWithItem(Unit).observeOn(Schedulers.io()),
|
||||
recipient,
|
||||
@@ -299,6 +320,36 @@ class ConversationViewModel(
|
||||
})
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun getBannerFlows(context: Context, groupJoinClickListener: () -> Unit, onAddMembers: () -> Unit, onNoThanks: () -> Unit, bubbleClickListener: (Boolean) -> Unit): List<Flow<Banner>> {
|
||||
val pendingGroupJoinFlow = groupRecordFlow.flatMapConcat {
|
||||
flow {
|
||||
if (it == null) {
|
||||
emit(PendingGroupJoinRequestsBanner(false, 0, {}, {}))
|
||||
} else {
|
||||
emitAll(Producer(it.actionableRequestingMembersCount, groupJoinClickListener).flow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val groupV1SuggestionsFlow = groupRecordFlow.map {
|
||||
if (it == null) {
|
||||
GroupsV1MigrationSuggestionsBanner(0, {}, {})
|
||||
} else {
|
||||
GroupsV1MigrationSuggestionsBanner(it.gv1MigrationSuggestions.size, onAddMembers, onNoThanks)
|
||||
}
|
||||
}
|
||||
|
||||
return listOf(
|
||||
OutdatedBuildBanner.createFlow(context, OutdatedBuildBanner.ExpiryStatus.EXPIRED_ONLY),
|
||||
UnauthorizedBanner.createFlow(context),
|
||||
ServiceOutageBanner.createFlow(context),
|
||||
pendingGroupJoinFlow,
|
||||
groupV1SuggestionsFlow,
|
||||
BubbleOptOutBanner.createFlow(inBubble = true, bubbleClickListener)
|
||||
)
|
||||
}
|
||||
|
||||
fun onChatBoundsChanged(bounds: Rect) {
|
||||
chatBounds.onNext(bounds)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user