Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ protobuf {
}
}

def canonicalVersionCode = 901
def canonicalVersionName = "5.21.4"
def canonicalVersionCode = 902
def canonicalVersionName = "5.21.5"

def postFixSize = 100
def abiPostFix = ['universal' : 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
import java.util.Set;

@SuppressLint("StaticFieldLeak")
public class ConversationFragment extends LoggingFragment {
public class ConversationFragment extends LoggingFragment implements MultiselectForwardFragment.Callback {
private static final String TAG = Log.tag(ConversationFragment.class);

private static final int SCROLL_ANIMATION_THRESHOLD = 50;
Expand Down Expand Up @@ -976,7 +976,7 @@ private void handleForwardMessageParts(Set<MultiselectPart> multiselectParts) {

MultiselectForwardFragmentArgs.create(requireContext(),
multiselectParts,
args -> MultiselectForwardFragment.show(getParentFragmentManager(), args));
args -> MultiselectForwardFragment.show(getChildFragmentManager(), args));
}

private void handleResendMessage(final MessageRecord message) {
Expand Down Expand Up @@ -1265,6 +1265,27 @@ public void onGlobalLayout() {
});
}

private @NonNull String calculateSelectedItemCount() {
ConversationAdapter adapter = getListAdapter();
if (adapter == null || adapter.getSelectedItems().isEmpty()) {
return String.valueOf(0);
}

return String.valueOf(adapter.getSelectedItems()
.stream()
.map(MultiselectPart::getConversationMessage)
.distinct()
.count());
}

@Override
public void onFinishForwardAction() {
if (actionMode != null) {
actionMode.finish();
}
}


public interface ConversationFragmentListener extends VoiceNoteMediaControllerOwner {
void setThreadId(long threadId);
void handleReplyMessage(ConversationMessage conversationMessage);
Expand Down Expand Up @@ -1368,7 +1389,7 @@ public void onItemClick(MultiselectPart item) {
actionMode.finish();
} else {
setCorrectMenuVisibility(actionMode.getMenu());
actionMode.setTitle(String.valueOf(getListAdapter().getSelectedItems().size()));
actionMode.setTitle(calculateSelectedItemCount());
}
}
}
Expand Down Expand Up @@ -1753,7 +1774,7 @@ public void onItemRangeRemoved(int positionStart, int itemCount) {
if (adapter.getSelectedItems().isEmpty()) {
actionMode.finish();
} else {
actionMode.setTitle(String.valueOf(adapter.getSelectedItems().size()));
actionMode.setTitle(calculateSelectedItemCount());
}
}
}
Expand Down Expand Up @@ -1845,7 +1866,7 @@ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.conversation_context, menu);

mode.setTitle(String.valueOf(getListAdapter().getSelectedItems().size()));
mode.setTitle(calculateSelectedItemCount());

if (Build.VERSION.SDK_INT >= 21) {
Window window = getActivity().getWindow();
Expand Down Expand Up @@ -1900,7 +1921,6 @@ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return true;
case R.id.menu_context_forward:
handleForwardMessageParts(getListAdapter().getSelectedItems());
actionMode.finish();
return true;
case R.id.menu_context_resend:
handleResendMessage(getSelectedConversationMessage().getMessageRecord());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int defaultBottomMargin = readDimen(R.dimen.message_bubble_bottom_padding);
int collapsedBottomMargin = readDimen(R.dimen.message_bubble_collapsed_bottom_padding);
if (!updatingFooter &&
!hasOnlyThumbnail(messageRecord) &&
!hasSticker(messageRecord) &&
!hasSharedContact(messageRecord) &&
!isViewOnceMessage(messageRecord) &&
getActiveFooter(messageRecord) == footer &&
!hasAudio(messageRecord) &&
isFooterVisible(messageRecord, nextMessageRecord, groupThread) &&
!bodyText.isJumbomoji() &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public boolean canPlayContent() {

@Override
public @Nullable View getHorizontalTranslationTarget() {
return null;
return background;
}

static final class RecipientObserverManager {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,37 +90,8 @@ class MultiselectItemDecoration(
}

override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val adapter = parent.adapter as ConversationAdapter
val isLtr = ViewUtil.isLtr(view)

if (adapter.selectedItems.isNotEmpty() && view is Multiselectable) {
val firstPart = view.conversationMessage.multiselectCollection.toSet().first()
val target = view.getHorizontalTranslationTarget()

if (target != null) {
val start = if (isLtr) {
target.left
} else {
parent.right - target.right
}

val translation: Float = if (isInitialAnimation()) {
max(0, gutter - start) * selectedAnimationProgressProvider(firstPart)
} else {
max(0, gutter - start).toFloat()
}

view.translationX = if (isLtr) {
translation
} else {
-translation
}
}
} else if (view is Multiselectable) {
view.translationX = 0f
}

outRect.setEmpty()
updateChildOffsets(parent, view)
}

/**
Expand All @@ -141,6 +112,8 @@ class MultiselectItemDecoration(
}

parent.children.filterIsInstance(Multiselectable::class.java).forEach { child ->
updateChildOffsets(parent, child as View)

val parts: MultiselectCollection = child.conversationMessage.multiselectCollection

val projections: List<Projection> = child.colorizerProjections
Expand All @@ -150,15 +123,14 @@ class MultiselectItemDecoration(
canvas.save()
canvas.clipPath(path, Region.Op.DIFFERENCE)

val view: View = child as View
val selectedParts: Set<MultiselectPart> = SetUtil.intersection(parts.toSet(), adapter.selectedItems)

if (selectedParts.isNotEmpty()) {
val selectedPart: MultiselectPart = selectedParts.first()
val shadeAll = selectedParts.size == parts.size || (selectedPart is MultiselectPart.Text && child.hasNonSelectableMedia())

if (shadeAll) {
rect.set(0, view.top, view.right, view.bottom)
rect.set(0, child.top, child.right, child.bottom)
} else {
rect.set(0, child.getTopBoundaryOfMultiselectPart(selectedPart), parent.right, child.getBottomBoundaryOfMultiselectPart(selectedPart))
}
Expand Down Expand Up @@ -276,4 +248,41 @@ class MultiselectItemDecoration(
c.drawCircle(centerX, centerY, circleRadius.toFloat(), unselectedPaint)
unselectedPaint.alpha = alpha
}

/**
* Update the start-aligned gutter in which the checks display. This is called in onDraw to
* ensure we don't hit situations where we try to set offsets before items are laid out, and
* called in getItemOffsets to ensure the gutter goes away when multiselect mode ends.
*/
private fun updateChildOffsets(parent: RecyclerView, child: View) {
val adapter = parent.adapter as ConversationAdapter
val isLtr = ViewUtil.isLtr(child)

if (adapter.selectedItems.isNotEmpty() && child is Multiselectable) {
val firstPart = child.conversationMessage.multiselectCollection.toSet().first()
val target = child.getHorizontalTranslationTarget()

if (target != null) {
val start = if (isLtr) {
target.left
} else {
parent.right - target.right
}

val translation: Float = if (isInitialAnimation()) {
max(0, gutter - start) * selectedAnimationProgressProvider(firstPart)
} else {
max(0, gutter - start).toFloat()
}

child.translationX = if (isLtr) {
translation
} else {
-translation
}
}
} else if (child is Multiselectable) {
child.translationX = 0f
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.components.FixedRoundedCornerBottomSheetDialog
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader
import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog
import org.thoughtcrime.securesms.database.IdentityDatabase
import org.thoughtcrime.securesms.keyboard.findListener
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.sharing.MultiShareArgs
Expand All @@ -37,7 +38,6 @@ import org.thoughtcrime.securesms.util.ViewUtil
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog
import org.thoughtcrime.securesms.util.visible
import org.whispersystems.libsignal.util.guava.Optional
import java.lang.UnsupportedOperationException
import java.util.function.Consumer

private const val ARG_MULTISHARE_ARGS = "multiselect.forward.fragment.arg.multishare.args"
Expand All @@ -57,6 +57,7 @@ class MultiselectForwardFragment :
private lateinit var selectionFragment: ContactSelectionListFragment
private lateinit var contactFilterView: ContactFilterView
private lateinit var addMessage: EditText
private lateinit var callback: Callback

private var dismissibleDialog: SimpleProgressDialog.DismissibleDialog? = null

Expand Down Expand Up @@ -91,6 +92,8 @@ class MultiselectForwardFragment :
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
callback = requireNotNull(findListener())

selectionFragment = childFragmentManager.findFragmentById(R.id.contact_selection_list_fragment) as ContactSelectionListFragment

contactFilterView = view.findViewById(R.id.contact_filter_edit_text)
Expand Down Expand Up @@ -217,6 +220,7 @@ class MultiselectForwardFragment :
private fun dismissAndShowToast(@PluralsRes toastTextResId: Int) {
val argCount = getMessageCount()

callback.onFinishForwardAction()
dismissibleDialog?.dismiss()
Toast.makeText(requireContext(), requireContext().resources.getQuantityString(toastTextResId, argCount), Toast.LENGTH_SHORT).show()
dismissAllowingStateLoss()
Expand All @@ -226,6 +230,8 @@ class MultiselectForwardFragment :

private fun handleMessageExpired() {
dismissAllowingStateLoss()

callback.onFinishForwardAction()
dismissibleDialog?.dismiss()
Toast.makeText(requireContext(), resources.getQuantityString(R.plurals.MultiselectForwardFragment__couldnt_forward_messages, getMultiShareArgs().size), Toast.LENGTH_LONG).show()
}
Expand Down Expand Up @@ -294,4 +300,8 @@ class MultiselectForwardFragment :
fragment.show(supportFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
}
}

interface Callback {
fun onFinishForwardAction()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import androidx.annotation.NonNull;

import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
Expand Down Expand Up @@ -103,7 +104,13 @@ protected void onRun() throws Exception {


Log.i(TAG, "Applying changes locally...");
StorageSyncHelper.applyAccountStorageSyncUpdates(context, Recipient.self(), accountRecord, false);
DatabaseFactory.getInstance(context).getRawDatabase().beginTransaction();
try {
StorageSyncHelper.applyAccountStorageSyncUpdates(context, Recipient.self(), accountRecord, false);
DatabaseFactory.getInstance(context).getRawDatabase().setTransactionSuccessful();
} finally {
DatabaseFactory.getInstance(context).getRawDatabase().endTransaction();
}

JobManager jobManager = ApplicationDependencies.getJobManager();

Expand Down
12 changes: 12 additions & 0 deletions app/src/main/res/values-bs/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3204,6 +3204,13 @@ prenijeli račun na svoj novi Android uređaj.</string>
<string name="DSLSettingsToolbar__navigate_up">Prema gore</string>
<string name="MultiselectForwardFragment__forward_to">Proslijedi za</string>
<string name="MultiselectForwardFragment__add_a_message">Dopiši poruku</string>
<string name="MultiselectForwardFragment__faster_forwards">Brža prosljeđivanja</string>
<string name="MultiselectForwardFragment__forwarded_messages_are_now">Proslijeđene poruke sada se šalju trenutačno.</string>
<plurals name="MultiselectForwardFragment_send_d_messages">
<item quantity="one">Pošalji %1$d poruku</item>
<item quantity="few">Pošalji %1$d poruke</item>
<item quantity="other">Pošalji %1$d poruka</item>
</plurals>
<plurals name="MultiselectForwardFragment_messages_sent">
<item quantity="one">Poruka poslana</item>
<item quantity="few">Poruke poslane</item>
Expand All @@ -3214,6 +3221,11 @@ prenijeli račun na svoj novi Android uređaj.</string>
<item quantity="few">Poruke nisu poslane</item>
<item quantity="other">Poruke nisu poslane</item>
</plurals>
<plurals name="MultiselectForwardFragment__couldnt_forward_messages">
<item quantity="one">Nije uspjelo prosljeđivanje poruke jer više nije dostupna.</item>
<item quantity="few">Nije uspjelo prosljeđivanje poruka jer više nisu dostupne.</item>
<item quantity="other">Nije uspjelo prosljeđivanje poruka jer više nisu dostupne.</item>
</plurals>
<string name="MultiselectForwardFragment__limit_reached">Dosegnut maksimum</string>
<!--EOF-->
</resources>
10 changes: 10 additions & 0 deletions app/src/main/res/values-ca/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3108,6 +3108,12 @@ S\'ha rebut un missatge d\'intercanvi de claus per a una versió del protocol no
<string name="DSLSettingsToolbar__navigate_up">Amunt</string>
<string name="MultiselectForwardFragment__forward_to">Reenvia a</string>
<string name="MultiselectForwardFragment__add_a_message">Afegiu-hi un missatge</string>
<string name="MultiselectForwardFragment__faster_forwards">Reenviaments més ràpids</string>
<string name="MultiselectForwardFragment__forwarded_messages_are_now">Ara els missatges reenviats s\'envien immediatament.</string>
<plurals name="MultiselectForwardFragment_send_d_messages">
<item quantity="one">Envia %1$d missatge</item>
<item quantity="other">Envia %1$d missatges</item>
</plurals>
<plurals name="MultiselectForwardFragment_messages_sent">
<item quantity="one">Missatge enviat</item>
<item quantity="other">Missatges enviats</item>
Expand All @@ -3116,6 +3122,10 @@ S\'ha rebut un missatge d\'intercanvi de claus per a una versió del protocol no
<item quantity="one">Ha fallat enviar el missatge.</item>
<item quantity="other">Ha fallat enviar els missatges.</item>
</plurals>
<plurals name="MultiselectForwardFragment__couldnt_forward_messages">
<item quantity="one">No s\'ha pogut reenviar el missatge perquè ja no està disponible.</item>
<item quantity="other">No s\'han pogut reenviar els missatges perquè ja no estan disponibles.</item>
</plurals>
<string name="MultiselectForwardFragment__limit_reached">S\'ha arribat al límit.</string>
<!--EOF-->
</resources>
14 changes: 14 additions & 0 deletions app/src/main/res/values-cs/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3283,6 +3283,14 @@ Obdržen požadavek na výměnu klíčů pro neplatnou verzi protokolu.
<string name="DSLSettingsToolbar__navigate_up">Přejděte nahoru</string>
<string name="MultiselectForwardFragment__forward_to">Přeposlat</string>
<string name="MultiselectForwardFragment__add_a_message">Přidat zprávu</string>
<string name="MultiselectForwardFragment__faster_forwards">Rychlejší přeposílání</string>
<string name="MultiselectForwardFragment__forwarded_messages_are_now">Přeposlané zprávy se nyní odesílají okamžitě.</string>
<plurals name="MultiselectForwardFragment_send_d_messages">
<item quantity="one">Odeslat %1$d zprávu</item>
<item quantity="few">Odeslat %1$d zprávu</item>
<item quantity="many">Odeslat %1$d zprávu</item>
<item quantity="other">Odeslat %1$d zpráv</item>
</plurals>
<plurals name="MultiselectForwardFragment_messages_sent">
<item quantity="one">Zpráva odeslána</item>
<item quantity="few">Zprávy odeslány</item>
Expand All @@ -3295,6 +3303,12 @@ Obdržen požadavek na výměnu klíčů pro neplatnou verzi protokolu.
<item quantity="many">Odeslání zpráv selhalo</item>
<item quantity="other">Odeslání zpráv selhalo</item>
</plurals>
<plurals name="MultiselectForwardFragment__couldnt_forward_messages">
<item quantity="one">Zprávu nebylo možné přeposlat, protože již není k dispozici.</item>
<item quantity="few">Zprávu nebylo možné přeposlat, protože již není k dispozici.</item>
<item quantity="many">Zprávu nebylo možné přeposlat, protože již není k dispozici.</item>
<item quantity="other">Zprávy nebylo možné přeposlat, protože již nejsou k dispozici.</item>
</plurals>
<string name="MultiselectForwardFragment__limit_reached">Dosažen limit</string>
<!--EOF-->
</resources>
Loading