Fixes for CFv2.
- Status bar color being incorrect when entering a screen that changes it and then returning (e.g., Message Details) - Fix crash in enter sends mode - Fix warning about non-closed cursor - Prevent message abandonment (via trim thread) when it's the first in an inactive thread - Fix payment attachment button flashing on attachment keyboard open if payments disabled - Fix reactionDelegate crash - Fix attachment preview (file, mp3, location, etc) not getting cleared on send
This commit is contained in:
parent
744f74b498
commit
ec25831a37
21 changed files with 128 additions and 56 deletions
|
@ -47,7 +47,7 @@ class SelectFeaturedBadgeFragment : DSLSettingsFragment(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper? {
|
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper? {
|
||||||
return Material3OnScrollHelper(requireActivity(), scrollShadow)
|
return Material3OnScrollHelper(requireActivity(), scrollShadow, viewLifecycleOwner)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun bindAdapter(adapter: MappingAdapter) {
|
override fun bindAdapter(adapter: MappingAdapter) {
|
||||||
|
|
|
@ -83,7 +83,7 @@ abstract class DSLSettingsFragment(
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return Material3OnScrollHelper(requireActivity(), toolbar)
|
return Material3OnScrollHelper(requireActivity(), toolbar, viewLifecycleOwner)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun onToolbarNavigationClicked() {
|
open fun onToolbarNavigationClicked() {
|
||||||
|
|
|
@ -99,7 +99,7 @@ class DonateToSignalFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper {
|
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper {
|
||||||
return object : Material3OnScrollHelper(requireActivity(), toolbar!!) {
|
return object : Material3OnScrollHelper(requireActivity(), toolbar!!, viewLifecycleOwner) {
|
||||||
override val activeColorSet: ColorSet = ColorSet(R.color.transparent, R.color.signal_colorBackground)
|
override val activeColorSet: ColorSet = ColorSet(R.color.transparent, R.color.signal_colorBackground)
|
||||||
override val inactiveColorSet: ColorSet = ColorSet(R.color.transparent, R.color.signal_colorBackground)
|
override val inactiveColorSet: ColorSet = ColorSet(R.color.transparent, R.color.signal_colorBackground)
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ class ManageDonationsFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper {
|
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper {
|
||||||
return object : Material3OnScrollHelper(requireActivity(), toolbar!!) {
|
return object : Material3OnScrollHelper(requireActivity(), toolbar!!, viewLifecycleOwner) {
|
||||||
override val activeColorSet: ColorSet = ColorSet(R.color.transparent, R.color.signal_colorBackground)
|
override val activeColorSet: ColorSet = ColorSet(R.color.transparent, R.color.signal_colorBackground)
|
||||||
override val inactiveColorSet: ColorSet = ColorSet(R.color.transparent, R.color.signal_colorBackground)
|
override val inactiveColorSet: ColorSet = ColorSet(R.color.transparent, R.color.signal_colorBackground)
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,7 +207,7 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper {
|
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper {
|
||||||
return object : Material3OnScrollHelper(requireActivity(), toolbar!!) {
|
return object : Material3OnScrollHelper(requireActivity(), toolbar!!, viewLifecycleOwner) {
|
||||||
override val inactiveColorSet = ColorSet(
|
override val inactiveColorSet = ColorSet(
|
||||||
toolbarColorRes = R.color.signal_colorBackground_0,
|
toolbarColorRes = R.color.signal_colorBackground_0,
|
||||||
statusBarColorRes = R.color.signal_colorBackground
|
statusBarColorRes = R.color.signal_colorBackground
|
||||||
|
|
|
@ -86,7 +86,7 @@ public class ContactShareEditActivity extends PassphraseRequiredActivity impleme
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
toolbar.setNavigationOnClickListener(unused -> onBackPressed());
|
toolbar.setNavigationOnClickListener(unused -> onBackPressed());
|
||||||
Material3OnScrollHelper onScrollHelper = new Material3OnScrollHelper(this, Collections.singletonList(toolbar), Collections.emptyList());
|
Material3OnScrollHelper onScrollHelper = new Material3OnScrollHelper(this, Collections.singletonList(toolbar), Collections.emptyList(), this);
|
||||||
onScrollHelper.attach(contactList);
|
onScrollHelper.attach(contactList);
|
||||||
|
|
||||||
ContactShareEditAdapter contactAdapter = new ContactShareEditAdapter(GlideApp.with(this), dynamicLanguage.getCurrentLocale(), this);
|
ContactShareEditAdapter contactAdapter = new ContactShareEditAdapter(GlideApp.with(this), dynamicLanguage.getCurrentLocale(), this);
|
||||||
|
|
|
@ -1993,7 +1993,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
|
|
||||||
voiceNoteMediaController.getVoiceNotePlaybackState().observe(getViewLifecycleOwner(), inputPanel.getPlaybackStateObserver());
|
voiceNoteMediaController.getVoiceNotePlaybackState().observe(getViewLifecycleOwner(), inputPanel.getPlaybackStateObserver());
|
||||||
|
|
||||||
material3OnScrollHelper = new Material3OnScrollHelper(requireActivity(), Collections.singletonList(toolbarBackground), Collections.emptyList()) {
|
material3OnScrollHelper = new Material3OnScrollHelper(requireActivity(), Collections.singletonList(toolbarBackground), Collections.emptyList(), getViewLifecycleOwner()) {
|
||||||
@Override
|
@Override
|
||||||
public @NonNull ColorSet getActiveColorSet() {
|
public @NonNull ColorSet getActiveColorSet() {
|
||||||
return new ColorSet(getActiveToolbarColor(wallpaper.getDrawable() != null));
|
return new ColorSet(getActiveToolbarColor(wallpaper.getDrawable() != null));
|
||||||
|
|
|
@ -58,6 +58,7 @@ import androidx.fragment.app.activityViewModels
|
||||||
import androidx.fragment.app.commit
|
import androidx.fragment.app.commit
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
@ -510,7 +511,8 @@ class ConversationFragment :
|
||||||
val conversationToolbarOnScrollHelper = ConversationToolbarOnScrollHelper(
|
val conversationToolbarOnScrollHelper = ConversationToolbarOnScrollHelper(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
binding.toolbarBackground,
|
binding.toolbarBackground,
|
||||||
viewModel::wallpaperSnapshot
|
viewModel::wallpaperSnapshot,
|
||||||
|
viewLifecycleOwner
|
||||||
)
|
)
|
||||||
conversationToolbarOnScrollHelper.attach(binding.conversationItemRecycler)
|
conversationToolbarOnScrollHelper.attach(binding.conversationItemRecycler)
|
||||||
presentWallpaper(args.wallpaper)
|
presentWallpaper(args.wallpaper)
|
||||||
|
@ -561,8 +563,6 @@ class ConversationFragment :
|
||||||
ApplicationDependencies.getMessageNotifier().setVisibleThread(ConversationId.forConversation(args.threadId))
|
ApplicationDependencies.getMessageNotifier().setVisibleThread(ConversationId.forConversation(args.threadId))
|
||||||
}
|
}
|
||||||
|
|
||||||
motionEventRelay.setDrain(MotionEventRelayDrain())
|
|
||||||
|
|
||||||
viewModel.updateIdentityRecordsInBackground()
|
viewModel.updateIdentityRecordsInBackground()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,7 +581,6 @@ class ConversationFragment :
|
||||||
|
|
||||||
viewModel.markLastSeen()
|
viewModel.markLastSeen()
|
||||||
|
|
||||||
motionEventRelay.setDrain(null)
|
|
||||||
EventBus.getDefault().unregister(this)
|
EventBus.getDefault().unregister(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -870,6 +869,7 @@ class ConversationFragment :
|
||||||
val conversationReactionStub = Stub<ConversationReactionOverlay>(binding.conversationReactionScrubberStub)
|
val conversationReactionStub = Stub<ConversationReactionOverlay>(binding.conversationReactionScrubberStub)
|
||||||
reactionDelegate = ConversationReactionDelegate(conversationReactionStub)
|
reactionDelegate = ConversationReactionDelegate(conversationReactionStub)
|
||||||
reactionDelegate.setOnReactionSelectedListener(OnReactionsSelectedListener())
|
reactionDelegate.setOnReactionSelectedListener(OnReactionsSelectedListener())
|
||||||
|
motionEventRelay.setDrain(MotionEventRelayDrain(this))
|
||||||
|
|
||||||
voiceMessageRecordingDelegate = VoiceMessageRecordingDelegate(
|
voiceMessageRecordingDelegate = VoiceMessageRecordingDelegate(
|
||||||
this,
|
this,
|
||||||
|
@ -1698,6 +1698,7 @@ class ConversationFragment :
|
||||||
onComplete = {
|
onComplete = {
|
||||||
if (clearCompose) {
|
if (clearCompose) {
|
||||||
composeText.setText("")
|
composeText.setText("")
|
||||||
|
attachmentManager.clear(GlideApp.with(this@ConversationFragment), false)
|
||||||
inputPanel.clearQuote()
|
inputPanel.clearQuote()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3030,9 +3031,15 @@ class ConversationFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class MotionEventRelayDrain : MotionEventRelay.Drain {
|
private inner class MotionEventRelayDrain(lifecycleOwner: LifecycleOwner) : MotionEventRelay.Drain {
|
||||||
|
private val lifecycle = lifecycleOwner.lifecycle
|
||||||
|
|
||||||
override fun accept(motionEvent: MotionEvent): Boolean {
|
override fun accept(motionEvent: MotionEvent): Boolean {
|
||||||
return reactionDelegate.applyTouchEvent(motionEvent)
|
return if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
||||||
|
reactionDelegate.applyTouchEvent(motionEvent)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3406,7 +3413,7 @@ class ConversationFragment :
|
||||||
sendMessage()
|
sendMessage()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onEditorAction(v: TextView, actionId: Int, event: KeyEvent): Boolean {
|
override fun onEditorAction(v: TextView, actionId: Int, event: KeyEvent?): Boolean {
|
||||||
if (actionId == EditorInfo.IME_ACTION_SEND) {
|
if (actionId == EditorInfo.IME_ACTION_SEND) {
|
||||||
if (inputPanel.isInEditMode) {
|
if (inputPanel.isInEditMode) {
|
||||||
sendEditButton.performClick()
|
sendEditButton.performClick()
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.conversation.v2
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.annotation.ColorRes
|
import androidx.annotation.ColorRes
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
|
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
|
||||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
|
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
|
||||||
|
@ -13,11 +14,12 @@ import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
|
||||||
class ConversationToolbarOnScrollHelper(
|
class ConversationToolbarOnScrollHelper(
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
toolbarBackground: View,
|
toolbarBackground: View,
|
||||||
private val wallpaperProvider: () -> ChatWallpaper?
|
private val wallpaperProvider: () -> ChatWallpaper?,
|
||||||
|
lifecycleOwner: LifecycleOwner
|
||||||
) : Material3OnScrollHelper(
|
) : Material3OnScrollHelper(
|
||||||
activity,
|
activity = activity,
|
||||||
listOf(toolbarBackground),
|
views = listOf(toolbarBackground),
|
||||||
emptyList()
|
lifecycleOwner = lifecycleOwner
|
||||||
) {
|
) {
|
||||||
override val activeColorSet: ColorSet
|
override val activeColorSet: ColorSet
|
||||||
get() = ColorSet(getActiveToolbarColor(wallpaperProvider() != null))
|
get() = ColorSet(getActiveToolbarColor(wallpaperProvider() != null))
|
||||||
|
|
|
@ -44,6 +44,7 @@ sealed interface ConversationElementKey {
|
||||||
private data class MessageBackedKey(val id: Long) : ConversationElementKey {
|
private data class MessageBackedKey(val id: Long) : ConversationElementKey {
|
||||||
override fun requireMessageId(): Long = id
|
override fun requireMessageId(): Long = id
|
||||||
}
|
}
|
||||||
|
|
||||||
private object ThreadHeaderKey : ConversationElementKey
|
private object ThreadHeaderKey : ConversationElementKey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,24 +108,27 @@ class ConversationDataSource(
|
||||||
val callHelper = CallHelper()
|
val callHelper = CallHelper()
|
||||||
val referencedIds = hashSetOf<ServiceId>()
|
val referencedIds = hashSetOf<ServiceId>()
|
||||||
|
|
||||||
MessageTable.mmsReaderFor(SignalDatabase.messages.getConversation(threadId, start.toLong(), length.toLong())).forEach { record ->
|
MessageTable.mmsReaderFor(SignalDatabase.messages.getConversation(threadId, start.toLong(), length.toLong()))
|
||||||
if (cancellationSignal.isCanceled) {
|
.use { reader ->
|
||||||
return@forEach
|
reader.forEach { record ->
|
||||||
}
|
if (cancellationSignal.isCanceled) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
|
||||||
records.add(record)
|
records.add(record)
|
||||||
mentionHelper.add(record)
|
mentionHelper.add(record)
|
||||||
quotedHelper.add(record)
|
quotedHelper.add(record)
|
||||||
reactionHelper.add(record)
|
reactionHelper.add(record)
|
||||||
attachmentHelper.add(record)
|
attachmentHelper.add(record)
|
||||||
paymentHelper.add(record)
|
paymentHelper.add(record)
|
||||||
callHelper.add(record)
|
callHelper.add(record)
|
||||||
|
|
||||||
val updateDescription = record.getUpdateDisplayBody(context, null)
|
val updateDescription = record.getUpdateDisplayBody(context, null)
|
||||||
if (updateDescription != null) {
|
if (updateDescription != null) {
|
||||||
referencedIds.addAll(updateDescription.mentioned)
|
referencedIds.addAll(updateDescription.mentioned)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (messageRequestData.includeWarningUpdateMessage() && (start + length >= totalSize)) {
|
if (messageRequestData.includeWarningUpdateMessage() && (start + length >= totalSize)) {
|
||||||
records.add(NoGroupsInCommon(threadId, messageRequestData.isGroup))
|
records.add(NoGroupsInCommon(threadId, messageRequestData.isGroup))
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||||
import org.thoughtcrime.securesms.mediasend.Media
|
import org.thoughtcrime.securesms.mediasend.Media
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
import org.thoughtcrime.securesms.permissions.Permissions
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
|
import java.util.function.Predicate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment wrapped version of [AttachmentKeyboard] to help encapsulate logic the view
|
* Fragment wrapped version of [AttachmentKeyboard] to help encapsulate logic the view
|
||||||
|
@ -44,6 +45,7 @@ class AttachmentKeyboardFragment : LoggingFragment(R.layout.attachment_keyboard_
|
||||||
private lateinit var attachmentKeyboardView: AttachmentKeyboard
|
private lateinit var attachmentKeyboardView: AttachmentKeyboard
|
||||||
|
|
||||||
private val lifecycleDisposable = LifecycleDisposable()
|
private val lifecycleDisposable = LifecycleDisposable()
|
||||||
|
private val removePaymentFilter: Predicate<AttachmentKeyboardButton> = Predicate { button -> button != AttachmentKeyboardButton.PAYMENT }
|
||||||
|
|
||||||
@Suppress("ReplaceGetOrSet")
|
@Suppress("ReplaceGetOrSet")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
@ -51,8 +53,12 @@ class AttachmentKeyboardFragment : LoggingFragment(R.layout.attachment_keyboard_
|
||||||
lifecycleDisposable.bindTo(viewLifecycleOwner)
|
lifecycleDisposable.bindTo(viewLifecycleOwner)
|
||||||
|
|
||||||
attachmentKeyboardView = view.findViewById(R.id.attachment_keyboard)
|
attachmentKeyboardView = view.findViewById(R.id.attachment_keyboard)
|
||||||
|
attachmentKeyboardView.apply {
|
||||||
attachmentKeyboardView.setCallback(this)
|
setCallback(this@AttachmentKeyboardFragment)
|
||||||
|
if (!SignalStore.paymentsValues().paymentsAvailability.isSendAllowed) {
|
||||||
|
filterAttachmentKeyboardButtons(removePaymentFilter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.getRecentMedia()
|
viewModel.getRecentMedia()
|
||||||
.subscribeBy {
|
.subscribeBy {
|
||||||
|
@ -97,7 +103,7 @@ class AttachmentKeyboardFragment : LoggingFragment(R.layout.attachment_keyboard_
|
||||||
) {
|
) {
|
||||||
attachmentKeyboardView.filterAttachmentKeyboardButtons(null)
|
attachmentKeyboardView.filterAttachmentKeyboardButtons(null)
|
||||||
} else {
|
} else {
|
||||||
attachmentKeyboardView.filterAttachmentKeyboardButtons { button -> button != AttachmentKeyboardButton.PAYMENT }
|
attachmentKeyboardView.filterAttachmentKeyboardButtons(removePaymentFilter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3193,6 +3193,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||||
return@withinTransaction kotlin.Pair(-1L, null)
|
return@withinTransaction kotlin.Pair(-1L, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
threads.markAsActiveEarly(threadId)
|
||||||
SignalDatabase.mentions.insert(threadId, messageId, mentions)
|
SignalDatabase.mentions.insert(threadId, messageId, mentions)
|
||||||
|
|
||||||
val insertedAttachments = SignalDatabase.attachments.insertAttachmentsForMessage(messageId, allAttachments, quoteAttachments)
|
val insertedAttachments = SignalDatabase.attachments.insertAttachmentsForMessage(messageId, allAttachments, quoteAttachments)
|
||||||
|
|
|
@ -1366,6 +1366,18 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a thread as active prior to an [update] call. Useful when a thread is for sure active but
|
||||||
|
* hasn't had the update call yet. e.g., inserting a message in a new thread.
|
||||||
|
*/
|
||||||
|
fun markAsActiveEarly(threadId: Long) {
|
||||||
|
writableDatabase
|
||||||
|
.update(TABLE_NAME)
|
||||||
|
.values(ACTIVE to 1)
|
||||||
|
.where("$ID = ?", threadId)
|
||||||
|
.run()
|
||||||
|
}
|
||||||
|
|
||||||
fun update(threadId: Long, unarchive: Boolean): Boolean {
|
fun update(threadId: Long, unarchive: Boolean): Boolean {
|
||||||
return update(
|
return update(
|
||||||
threadId = threadId,
|
threadId = threadId,
|
||||||
|
|
|
@ -36,7 +36,7 @@ class ExportYourSmsMessagesFragment : Fragment(R.layout.export_your_sms_messages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Material3OnScrollHelper(requireActivity(), binding.toolbar).attach(binding.scrollView)
|
Material3OnScrollHelper(requireActivity(), binding.toolbar, viewLifecycleOwner).attach(binding.scrollView)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
|
|
@ -377,7 +377,8 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
|
||||||
Material3OnScrollHelper(
|
Material3OnScrollHelper(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
listOf(_toolbarBackground),
|
listOf(_toolbarBackground),
|
||||||
listOf(_searchToolbar)
|
listOf(_searchToolbar),
|
||||||
|
viewLifecycleOwner
|
||||||
).attach(recyclerView)
|
).attach(recyclerView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,11 @@ class MediaGalleryFragment : Fragment(R.layout.v2_media_gallery_fragment) {
|
||||||
onBack()
|
onBack()
|
||||||
}
|
}
|
||||||
|
|
||||||
Material3OnScrollHelper(requireActivity(), listOf(binding.mediaGalleryToolbar, binding.mediaGalleryStatusBarBackground)).attach(binding.mediaGalleryGrid)
|
Material3OnScrollHelper(
|
||||||
|
activity = requireActivity(),
|
||||||
|
views = listOf(binding.mediaGalleryToolbar, binding.mediaGalleryStatusBarBackground),
|
||||||
|
lifecycleOwner = viewLifecycleOwner
|
||||||
|
).attach(binding.mediaGalleryGrid)
|
||||||
|
|
||||||
if (callbacks.isCameraEnabled()) {
|
if (callbacks.isCameraEnabled()) {
|
||||||
binding.mediaGalleryToolbar.setOnMenuItemClickListener { item ->
|
binding.mediaGalleryToolbar.setOnMenuItemClickListener { item ->
|
||||||
|
|
|
@ -97,7 +97,7 @@ public final class MessageDetailsFragment extends FullScreenDialogFragment imple
|
||||||
|
|
||||||
list.setAdapter(adapter);
|
list.setAdapter(adapter);
|
||||||
list.setItemAnimator(null);
|
list.setItemAnimator(null);
|
||||||
new Material3OnScrollHelper(requireActivity(), toolbarShadow).attach(list);
|
new Material3OnScrollHelper(requireActivity(), toolbarShadow, getViewLifecycleOwner()).attach(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeViewModel() {
|
private void initializeViewModel() {
|
||||||
|
|
|
@ -32,4 +32,8 @@ class CreateStoryFlowDialogFragment : DialogFragment(R.layout.create_story_flow_
|
||||||
override fun setStatusBarColor(color: Int) {
|
override fun setStatusBarColor(color: Int) {
|
||||||
WindowUtil.setStatusBarColor(requireDialog().window!!, color)
|
WindowUtil.setStatusBarColor(requireDialog().window!!, color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getStatusBarColor(): Int {
|
||||||
|
return WindowUtil.getStatusBarColor(requireDialog().window!!)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,13 @@ class CreateStoryWithViewersFragment : DSLSettingsFragment(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Material3OnScrollHelper(requireContext(), { requireListener<Callback>().setStatusBarColor(it) }, listOf(binding.toolbar)).attach(binding.appBarLayout)
|
Material3OnScrollHelper(
|
||||||
|
context = requireContext(),
|
||||||
|
setStatusBarColor = { requireListener<Callback>().setStatusBarColor(it) },
|
||||||
|
getStatusBarColor = { requireListener<Callback>().getStatusBarColor() },
|
||||||
|
views = listOf(binding.toolbar),
|
||||||
|
lifecycleOwner = viewLifecycleOwner
|
||||||
|
).attach(binding.appBarLayout)
|
||||||
ViewUtil.focusAndShowKeyboard(binding.nameField.editText)
|
ViewUtil.focusAndShowKeyboard(binding.nameField.editText)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +141,7 @@ class CreateStoryWithViewersFragment : DSLSettingsFragment(
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun setStatusBarColor(@ColorInt color: Int)
|
fun setStatusBarColor(@ColorInt color: Int)
|
||||||
|
fun getStatusBarColor(): Int
|
||||||
fun onDone(recipientId: RecipientId)
|
fun onDone(recipientId: RecipientId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import androidx.annotation.ColorInt
|
||||||
import androidx.annotation.ColorRes
|
import androidx.annotation.ColorRes
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.widget.NestedScrollView
|
import androidx.core.widget.NestedScrollView
|
||||||
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.animation.ArgbEvaluatorCompat
|
import com.google.android.material.animation.ArgbEvaluatorCompat
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
@ -22,32 +24,40 @@ import org.thoughtcrime.securesms.util.views.Stub
|
||||||
open class Material3OnScrollHelper(
|
open class Material3OnScrollHelper(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val setStatusBarColor: (Int) -> Unit,
|
private val setStatusBarColor: (Int) -> Unit,
|
||||||
|
private val getStatusBarColor: () -> Int,
|
||||||
private val views: List<View>,
|
private val views: List<View>,
|
||||||
private val viewStubs: List<Stub<out View>> = emptyList()
|
private val viewStubs: List<Stub<out View>> = emptyList(),
|
||||||
|
lifecycleOwner: LifecycleOwner
|
||||||
) {
|
) {
|
||||||
|
|
||||||
constructor(activity: Activity, views: List<View>, viewStubs: List<Stub<out View>>) : this(activity, { WindowUtil.setStatusBarColor(activity.window, it) }, views, viewStubs)
|
constructor(activity: Activity, view: View, lifecycleOwner: LifecycleOwner) : this(activity = activity, views = listOf(view), lifecycleOwner = lifecycleOwner)
|
||||||
|
|
||||||
constructor(activity: Activity, views: List<View>) : this(activity, { WindowUtil.setStatusBarColor(activity.window, it) }, views, emptyList())
|
constructor(activity: Activity, views: List<View>, viewStubs: List<Stub<out View>> = emptyList(), lifecycleOwner: LifecycleOwner) : this(
|
||||||
|
context = activity,
|
||||||
constructor(activity: Activity, view: View) : this(activity, { WindowUtil.setStatusBarColor(activity.window, it) }, listOf(view), emptyList())
|
setStatusBarColor = { WindowUtil.setStatusBarColor(activity.window, it) },
|
||||||
|
getStatusBarColor = { WindowUtil.getStatusBarColor(activity.window) },
|
||||||
/**
|
views = views,
|
||||||
* A pair of colors tied to a specific state.
|
viewStubs = viewStubs,
|
||||||
*/
|
lifecycleOwner = lifecycleOwner
|
||||||
data class ColorSet(
|
)
|
||||||
@ColorRes val toolbarColorRes: Int,
|
|
||||||
@ColorRes val statusBarColorRes: Int
|
|
||||||
) {
|
|
||||||
constructor(@ColorRes color: Int) : this(color, color)
|
|
||||||
}
|
|
||||||
|
|
||||||
open val activeColorSet: ColorSet = ColorSet(R.color.signal_colorSurface2)
|
open val activeColorSet: ColorSet = ColorSet(R.color.signal_colorSurface2)
|
||||||
open val inactiveColorSet: ColorSet = ColorSet(R.color.signal_colorBackground)
|
open val inactiveColorSet: ColorSet = ColorSet(R.color.signal_colorBackground)
|
||||||
|
|
||||||
|
protected var previousStatusBarColor: Int = getStatusBarColor()
|
||||||
|
|
||||||
private var animator: ValueAnimator? = null
|
private var animator: ValueAnimator? = null
|
||||||
private var active: Boolean? = null
|
private var active: Boolean? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||||
|
override fun onDestroy(owner: LifecycleOwner) {
|
||||||
|
animator?.cancel()
|
||||||
|
setStatusBarColor(previousStatusBarColor)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fun attach(nestedScrollView: NestedScrollView) {
|
fun attach(nestedScrollView: NestedScrollView) {
|
||||||
nestedScrollView.setOnScrollChangeListener(
|
nestedScrollView.setOnScrollChangeListener(
|
||||||
OnScrollListener().apply {
|
OnScrollListener().apply {
|
||||||
|
@ -141,4 +151,14 @@ open class Material3OnScrollHelper(
|
||||||
updateActiveState(v.canScrollVertically(-1))
|
updateActiveState(v.canScrollVertically(-1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pair of colors tied to a specific state.
|
||||||
|
*/
|
||||||
|
data class ColorSet(
|
||||||
|
@ColorRes val toolbarColorRes: Int,
|
||||||
|
@ColorRes val statusBarColorRes: Int
|
||||||
|
) {
|
||||||
|
constructor(@ColorRes color: Int) : this(color, color)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,10 @@ public final class WindowUtil {
|
||||||
window.setStatusBarColor(color);
|
window.setStatusBarColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getStatusBarColor(@NonNull Window window) {
|
||||||
|
return window.getStatusBarColor();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A sort of roundabout way of determining if the status bar is present by seeing if there's a
|
* A sort of roundabout way of determining if the status bar is present by seeing if there's a
|
||||||
* vertical window offset.
|
* vertical window offset.
|
||||||
|
|
Loading…
Add table
Reference in a new issue