diff --git a/CHANGELOG-upstream.md b/CHANGELOG-upstream.md
index 523440fd8..784c5bbb3 100644
--- a/CHANGELOG-upstream.md
+++ b/CHANGELOG-upstream.md
@@ -6,6 +6,7 @@
* Unified date display in call bubbles
* Explain at "Settings / Chats / Outgoing Media Quality" how to send original quality
* Add a basic sticker picker
+* Leave groups and channels before deletion
* Fix: keep original sent timestamp for resent messages
* Fix: make clicking on broadcast member-added messages work always
* Fix: remove notification when a message is deleted by sender
diff --git a/src/androidTest/java/com/b44t/messenger/uitests/offline/SharingTest.java b/src/androidTest/java/com/b44t/messenger/uitests/offline/SharingTest.java
index f2ae75395..11416cd1c 100644
--- a/src/androidTest/java/com/b44t/messenger/uitests/offline/SharingTest.java
+++ b/src/androidTest/java/com/b44t/messenger/uitests/offline/SharingTest.java
@@ -253,7 +253,7 @@ public class SharingTest {
*
If you save your contacts's emails in the contacts app of the phone, there are buttons to
* call them and also to write an email to them.
*
- *
If you click the email button, ArcaneChat opened but instead of opening a chat with that
+ *
If you click the email button, Delta Chat opened but instead of opening a chat with that
* contact, the chat list was show and "share with" was displayed at the top
*/
@Test
diff --git a/src/main/java/com/b44t/messenger/DcChat.java b/src/main/java/com/b44t/messenger/DcChat.java
index c8d7cf9ee..8f32f9725 100644
--- a/src/main/java/com/b44t/messenger/DcChat.java
+++ b/src/main/java/com/b44t/messenger/DcChat.java
@@ -1,5 +1,7 @@
package com.b44t.messenger;
+import org.thoughtcrime.securesms.util.Util;
+
public class DcChat {
public static final int DC_CHAT_TYPE_UNDEFINED = 0;
@@ -73,6 +75,16 @@ public class DcChat {
return type != DC_CHAT_TYPE_SINGLE;
}
+ public boolean shallLeaveBeforeDelete(DcContext dcContext) {
+ if (isInBroadcast()) {
+ final int[] members = dcContext.getChatContacts(getId());
+ return Util.contains(members, DcContact.DC_CONTACT_ID_SELF);
+ } else if (isMultiUser() && isEncrypted() && canSend() && !isOutBroadcast()) {
+ return true;
+ }
+ return false;
+ }
+
public boolean isMailingList() {
return getType() == DC_CHAT_TYPE_MAILINGLIST;
}
diff --git a/src/main/java/com/b44t/messenger/DcContext.java b/src/main/java/com/b44t/messenger/DcContext.java
index 53cfab3a5..722b76c62 100644
--- a/src/main/java/com/b44t/messenger/DcContext.java
+++ b/src/main/java/com/b44t/messenger/DcContext.java
@@ -359,7 +359,7 @@ public class DcContext {
public String getName() {
String displayname = getConfig("displayname");
if (displayname.isEmpty()) {
- displayname = getContact(DcContact.DC_CONTACT_ID_SELF).getAddr();
+ displayname = getConfig("addr");
}
return displayname;
}
diff --git a/src/main/java/org/thoughtcrime/securesms/BaseConversationListFragment.java b/src/main/java/org/thoughtcrime/securesms/BaseConversationListFragment.java
index 817e6015c..a7887863f 100644
--- a/src/main/java/org/thoughtcrime/securesms/BaseConversationListFragment.java
+++ b/src/main/java/org/thoughtcrime/securesms/BaseConversationListFragment.java
@@ -27,6 +27,7 @@ import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;
import androidx.fragment.app.Fragment;
import com.b44t.messenger.DcChat;
+import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayList;
@@ -297,12 +298,20 @@ public abstract class BaseConversationListFragment extends Fragment implements A
.getQuantityString(R.plurals.ask_delete_chat, chatsCount, chatsCount);
}
+ String alertButton = getString(R.string.delete_for_me);
+ for (long chatId : selectedChats) {
+ if (dcContext.getChat((int) chatId).shallLeaveBeforeDelete(dcContext)) {
+ alertButton = getString(R.string.menu_leave_and_delete);
+ break;
+ }
+ }
+
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
alert.setMessage(alertText);
alert.setCancelable(true);
alert.setPositiveButton(
- R.string.delete,
+ alertButton,
(dialog, which) -> {
if (!selectedChats.isEmpty()) {
new AsyncTask() {
@@ -325,6 +334,9 @@ public abstract class BaseConversationListFragment extends Fragment implements A
for (long chatId : selectedChats) {
DcHelper.getNotificationCenter(requireContext())
.removeNotifications(accountId, (int) chatId);
+ if (dcContext.getChat((int) chatId).shallLeaveBeforeDelete(dcContext)) {
+ dcContext.removeContactFromChat((int) chatId, DcContact.DC_CONTACT_ID_SELF);
+ }
dcContext.deleteChat((int) chatId);
DirectShareUtil.clearShortcut(requireContext(), (int) chatId);
}
diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java b/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java
index 608ee4053..9f148bd40 100644
--- a/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java
+++ b/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java
@@ -531,15 +531,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
menu.findItem(R.id.menu_ephemeral_messages).setVisible(false);
}
- if (isMultiUser()) {
- if (dcChat.isInBroadcast() && !dcChat.isContactRequest()) {
- menu.findItem(R.id.menu_leave).setTitle(R.string.menu_leave_channel).setVisible(true);
- } else if (dcChat.isEncrypted()
- && dcChat.canSend()
- && !dcChat.isOutBroadcast()
- && !dcChat.isMailingList()) {
- menu.findItem(R.id.menu_leave).setVisible(true);
+ if (dcChat.shallLeaveBeforeDelete(DcHelper.getContext(context))) {
+ if (dcChat.isInBroadcast()) {
+ menu.findItem(R.id.menu_leave).setTitle(R.string.menu_leave_channel);
}
+ menu.findItem(R.id.menu_leave).setVisible(true);
+ menu.findItem(R.id.menu_delete_chat).setVisible(false);
}
if (isArchived()) {
@@ -732,9 +729,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
DcHelper.getContext(context).removeContactFromChat(chatId, DcContact.DC_CONTACT_ID_SELF);
Toast.makeText(this, getString(R.string.done), Toast.LENGTH_SHORT).show();
})
- .setNegativeButton(R.string.cancel, null)
+ .setNegativeButton(R.string.menu_leave_and_delete, (d, which) -> {
+ DcHelper.getContext(context).removeContactFromChat(chatId, DcContact.DC_CONTACT_ID_SELF);
+ DcHelper.getContext(context).deleteChat(chatId);
+ DirectShareUtil.clearShortcut(this, chatId);
+ finish();
+ })
+ .setNeutralButton(R.string.cancel, null)
.show();
Util.redPositiveButton(dialog);
+ Util.redButton(dialog, AlertDialog.BUTTON_NEGATIVE);
}
private void handleArchiveChat() {
@@ -753,7 +757,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void handleDeleteChat() {
AlertDialog dialog = new AlertDialog.Builder(this)
.setMessage(getResources().getString(R.string.ask_delete_named_chat, dcChat.getName()))
- .setPositiveButton(R.string.delete, (d, which) -> {
+ .setPositiveButton(R.string.delete_for_me, (d, which) -> {
DcHelper.getContext(context).deleteChat(chatId);
DirectShareUtil.clearShortcut(this, chatId);
finish();
diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileActivity.java b/src/main/java/org/thoughtcrime/securesms/ProfileActivity.java
index 4e95ddbfb..5f9acbe6e 100644
--- a/src/main/java/org/thoughtcrime/securesms/ProfileActivity.java
+++ b/src/main/java/org/thoughtcrime/securesms/ProfileActivity.java
@@ -12,6 +12,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
+import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
@@ -415,10 +416,15 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
isContactProfile()
? dcContext.getContactEncrInfo(contactId)
: dcContext.getChatEncrInfo(chatId);
- new AlertDialog.Builder(this)
- .setMessage(infoStr)
- .setPositiveButton(android.R.string.ok, null)
- .show();
+ AlertDialog dialog =
+ new AlertDialog.Builder(this)
+ .setMessage(infoStr)
+ .setPositiveButton(android.R.string.ok, null)
+ .show();
+ TextView messageView = dialog.findViewById(android.R.id.message);
+ if (messageView != null) {
+ messageView.setTextIsSelectable(true);
+ }
}
private void onBlockContact() {
diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileAdapter.java b/src/main/java/org/thoughtcrime/securesms/ProfileAdapter.java
index 6a59a4810..94ee9fb97 100644
--- a/src/main/java/org/thoughtcrime/securesms/ProfileAdapter.java
+++ b/src/main/java/org/thoughtcrime/securesms/ProfileAdapter.java
@@ -26,6 +26,7 @@ import java.util.Set;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.contacts.ContactSelectionListItem;
import org.thoughtcrime.securesms.mms.GlideRequests;
+import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.Util;
public class ProfileAdapter extends RecyclerView.Adapter {
@@ -360,9 +361,11 @@ public class ProfileAdapter extends RecyclerView.Adapter {
String lastSeenTxt;
if (lastSeenTimestamp == 0) {
lastSeenTxt = context.getString(R.string.last_seen_unknown);
- }
- else {
- lastSeenTxt = context.getString(R.string.last_seen_at, DateUtils.getExtendedTimeSpanString(context, lastSeenTimestamp));
+ } else {
+ lastSeenTxt =
+ context.getString(
+ R.string.last_seen_at,
+ DateUtils.getExtendedTimeSpanString(context, lastSeenTimestamp));
}
itemData.add(new ItemData(ITEM_LAST_SEEN, lastSeenTxt, 0));
}
diff --git a/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java b/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java
index aa9dbf9e9..4b41c166b 100644
--- a/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java
+++ b/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java
@@ -8,14 +8,11 @@ import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
-
import androidx.annotation.NonNull;
-
-import org.thoughtcrime.securesms.R;
-import org.thoughtcrime.securesms.util.DateUtils;
-
import chat.delta.rpc.types.CallInfo;
import chat.delta.rpc.types.CallState;
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.util.DateUtils;
public class CallItemView extends FrameLayout {
private static final String TAG = CallItemView.class.getSimpleName();
@@ -43,11 +40,12 @@ public class CallItemView extends FrameLayout {
this.title = findViewById(R.id.title);
this.duration = findViewById(R.id.duration);
- setOnClickListener(v -> {
- if (viewListener != null && callInfo != null) {
- viewListener.onClick(v, callInfo);
- }
- });
+ setOnClickListener(
+ v -> {
+ if (viewListener != null && callInfo != null) {
+ viewListener.onClick(v, callInfo);
+ }
+ });
}
public void setCallClickListener(CallClickListener listener) {
@@ -58,7 +56,9 @@ public class CallItemView extends FrameLayout {
this.callInfo = callInfo;
if (callInfo.state instanceof CallState.Completed) {
- duration.setText(DateUtils.getFormattedCallDuration(getContext(), ((CallState.Completed) callInfo.state).duration));
+ duration.setText(
+ DateUtils.getFormattedCallDuration(
+ getContext(), ((CallState.Completed) callInfo.state).duration));
duration.setVisibility(VISIBLE);
} else {
duration.setVisibility(GONE);
@@ -71,22 +71,25 @@ public class CallItemView extends FrameLayout {
} else if (callInfo.state instanceof CallState.Declined) {
title.setText(R.string.declined_call);
} else if (callInfo.hasVideo) {
- title.setText(isOutgoing? R.string.outgoing_video_call : R.string.incoming_video_call);
+ title.setText(R.string.video_call);
} else {
- title.setText(isOutgoing? R.string.outgoing_audio_call : R.string.incoming_audio_call);
+ title.setText(R.string.audio_call);
}
- icon.setImageResource(callInfo.hasVideo? R.drawable.ic_videocam_white_24dp : R.drawable.baseline_call_24);
+ icon.setImageResource(
+ callInfo.hasVideo ? R.drawable.ic_videocam_white_24dp : R.drawable.baseline_call_24);
int[] attrs;
if (isOutgoing) {
- attrs = new int[]{
- R.attr.conversation_item_outgoing_text_primary_color,
- };
+ attrs =
+ new int[] {
+ R.attr.conversation_item_outgoing_text_primary_color,
+ };
} else {
- attrs = new int[]{
- R.attr.conversation_item_incoming_text_primary_color,
- };
+ attrs =
+ new int[] {
+ R.attr.conversation_item_incoming_text_primary_color,
+ };
}
try (TypedArray ta = getContext().obtainStyledAttributes(attrs)) {
icon.setColorFilter(ta.getColor(0, Color.BLACK));
@@ -94,7 +97,8 @@ public class CallItemView extends FrameLayout {
}
public String getDescription() {
- return title.getText() + (duration.getVisibility()==VISIBLE ? ("\n" + duration.getText()) : "");
+ return title.getText()
+ + (duration.getVisibility() == VISIBLE ? ("\n" + duration.getText()) : "");
}
public interface CallClickListener {
diff --git a/src/main/java/org/thoughtcrime/securesms/components/MediaView.java b/src/main/java/org/thoughtcrime/securesms/components/MediaView.java
index bd335218f..8aed3cc18 100644
--- a/src/main/java/org/thoughtcrime/securesms/components/MediaView.java
+++ b/src/main/java/org/thoughtcrime/securesms/components/MediaView.java
@@ -1,26 +1,23 @@
package org.thoughtcrime.securesms.components;
-
import android.content.Context;
import android.net.Uri;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.Window;
import android.widget.FrameLayout;
-
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import java.io.IOException;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.util.views.Stub;
import org.thoughtcrime.securesms.video.VideoPlayer;
-import java.io.IOException;
-
public class MediaView extends FrameLayout {
- private ZoomingImageView imageView;
+ private ZoomingImageView imageView;
private Stub videoView;
public MediaView(@NonNull Context context) {
@@ -38,7 +35,8 @@ public class MediaView extends FrameLayout {
initialize();
}
- public MediaView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ public MediaView(
+ @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize();
}
@@ -50,15 +48,15 @@ public class MediaView extends FrameLayout {
this.videoView = new Stub<>(findViewById(R.id.video_player_stub));
}
- public void set(@NonNull GlideRequests glideRequests,
- @NonNull Window window,
- @NonNull Uri source,
- @Nullable String fileName,
- @NonNull String mediaType,
- long size,
- boolean autoplay)
- throws IOException
- {
+ public void set(
+ @NonNull GlideRequests glideRequests,
+ @NonNull Window window,
+ @NonNull Uri source,
+ @Nullable String fileName,
+ @NonNull String mediaType,
+ long size,
+ boolean autoplay)
+ throws IOException {
if (mediaType.startsWith("image/")) {
imageView.setVisibility(View.VISIBLE);
if (videoView.resolved()) videoView.get().setVisibility(View.GONE);
@@ -67,14 +65,16 @@ public class MediaView extends FrameLayout {
imageView.setVisibility(View.GONE);
videoView.get().setVisibility(View.VISIBLE);
videoView.get().setWindow(window);
- videoView.get().setVideoSource(new VideoSlide(getContext(), source, fileName, size), autoplay);
+ videoView
+ .get()
+ .setVideoSource(new VideoSlide(getContext(), source, fileName, size), autoplay);
} else {
throw new IOException("Unsupported media type: " + mediaType);
}
}
public void pause() {
- if (this.videoView.resolved()){
+ if (this.videoView.resolved()) {
this.videoView.get().pause();
}
}
diff --git a/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java b/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java
index c9082e2d2..281cf41a1 100644
--- a/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java
+++ b/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java
@@ -220,10 +220,10 @@ public class DcHelper {
dcContext.setStockTranslation(220, context.getString(R.string.proxy_enabled));
dcContext.setStockTranslation(221, context.getString(R.string.proxy_enabled_hint));
dcContext.setStockTranslation(230, context.getString(R.string.chat_unencrypted_explanation));
- dcContext.setStockTranslation(232, context.getString(R.string.outgoing_audio_call));
- dcContext.setStockTranslation(233, context.getString(R.string.outgoing_video_call));
- dcContext.setStockTranslation(234, context.getString(R.string.incoming_audio_call));
- dcContext.setStockTranslation(235, context.getString(R.string.incoming_video_call));
+ dcContext.setStockTranslation(232, context.getString(R.string.audio_call));
+ dcContext.setStockTranslation(233, context.getString(R.string.video_call));
+ dcContext.setStockTranslation(234, context.getString(R.string.audio_call));
+ dcContext.setStockTranslation(235, context.getString(R.string.video_call));
dcContext.setStockTranslation(240, context.getString(R.string.chat_description_changed_by_you));
dcContext.setStockTranslation(241, context.getString(R.string.chat_description_changed_by_other));
}
diff --git a/src/main/java/org/thoughtcrime/securesms/notifications/InChatSounds.java b/src/main/java/org/thoughtcrime/securesms/notifications/InChatSounds.java
index 373d7bc09..549e014b9 100644
--- a/src/main/java/org/thoughtcrime/securesms/notifications/InChatSounds.java
+++ b/src/main/java/org/thoughtcrime/securesms/notifications/InChatSounds.java
@@ -4,55 +4,55 @@ import android.content.Context;
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.util.Log;
-
import org.thoughtcrime.securesms.R;
public class InChatSounds {
- private static final String TAG = InChatSounds.class.getSimpleName();
- private static volatile InChatSounds instance;
+ private static final String TAG = InChatSounds.class.getSimpleName();
+ private static volatile InChatSounds instance;
- private SoundPool soundPool = null;
- private int soundIn = 0;
- private int soundOut = 0;
+ private SoundPool soundPool = null;
+ private int soundIn = 0;
+ private int soundOut = 0;
- static public InChatSounds getInstance(Context context) {
+ public static InChatSounds getInstance(Context context) {
+ if (instance == null) {
+ synchronized (InChatSounds.class) {
if (instance == null) {
- synchronized (InChatSounds.class) {
- if (instance == null) {
- instance = new InChatSounds(context);
- }
- }
+ instance = new InChatSounds(context);
}
- return instance;
+ }
}
+ return instance;
+ }
- private InChatSounds(Context context) {
- try {
- AudioAttributes audioAttrs = new AudioAttributes.Builder()
+ private InChatSounds(Context context) {
+ try {
+ AudioAttributes audioAttrs =
+ new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
- soundPool = new SoundPool.Builder().setMaxStreams(3).setAudioAttributes(audioAttrs).build();
- soundIn = soundPool.load(context, R.raw.sound_in, 1);
- soundOut = soundPool.load(context, R.raw.sound_out, 1);
- } catch(Exception e) {
- Log.e(TAG, "cannot initialize sounds", e);
- }
+ soundPool = new SoundPool.Builder().setMaxStreams(3).setAudioAttributes(audioAttrs).build();
+ soundIn = soundPool.load(context, R.raw.sound_in, 1);
+ soundOut = soundPool.load(context, R.raw.sound_out, 1);
+ } catch (Exception e) {
+ Log.e(TAG, "cannot initialize sounds", e);
}
+ }
- public void playSendSound() {
- try {
- soundPool.play(soundOut, 1.0f, 1.0f, 1, 0, 1.0f);
- } catch(Exception e) {
- Log.e(TAG, "cannot play send sound", e);
- }
+ public void playSendSound() {
+ try {
+ soundPool.play(soundOut, 1.0f, 1.0f, 1, 0, 1.0f);
+ } catch (Exception e) {
+ Log.e(TAG, "cannot play send sound", e);
}
+ }
- public void playIncomingSound() {
- try {
- soundPool.play(soundIn, 1.0f, 1.0f, 1, 0, 1.0f);
- } catch(Exception e) {
- Log.e(TAG, "cannot play incoming sound", e);
- }
+ public void playIncomingSound() {
+ try {
+ soundPool.play(soundIn, 1.0f, 1.0f, 1, 0, 1.0f);
+ } catch (Exception e) {
+ Log.e(TAG, "cannot play incoming sound", e);
}
+ }
}
diff --git a/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java b/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java
index 3e569c744..0c4b2e75a 100644
--- a/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java
+++ b/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java
@@ -7,18 +7,17 @@ import static com.b44t.messenger.DcChat.DC_CHAT_NO_CHAT;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-
import com.b44t.messenger.DcContext;
-
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.Util;
public class MarkReadReceiver extends BroadcastReceiver {
- public static final String MARK_NOTICED_ACTION = "org.thoughtcrime.securesms.notifications.MARK_NOTICED";
- public static final String CANCEL_ACTION = "org.thoughtcrime.securesms.notifications.CANCEL";
- public static final String ACCOUNT_ID_EXTRA = "account_id";
- public static final String CHAT_ID_EXTRA = "chat_id";
- public static final String MSG_ID_EXTRA = "msg_id";
+ public static final String MARK_NOTICED_ACTION =
+ "org.thoughtcrime.securesms.notifications.MARK_NOTICED";
+ public static final String CANCEL_ACTION = "org.thoughtcrime.securesms.notifications.CANCEL";
+ public static final String ACCOUNT_ID_EXTRA = "account_id";
+ public static final String CHAT_ID_EXTRA = "chat_id";
+ public static final String MSG_ID_EXTRA = "msg_id";
@Override
public void onReceive(final Context context, Intent intent) {
@@ -34,13 +33,14 @@ public class MarkReadReceiver extends BroadcastReceiver {
return;
}
- Util.runOnAnyBackgroundThread(() -> {
- DcHelper.getNotificationCenter(context).removeNotifications(accountId, chatId);
- if (markNoticed) {
- DcContext dcContext = DcHelper.getAccounts(context).getAccount(accountId);
- dcContext.marknoticedChat(chatId);
- dcContext.markseenMsgs(new int[]{msgId});
- }
- });
+ Util.runOnAnyBackgroundThread(
+ () -> {
+ DcHelper.getNotificationCenter(context).removeNotifications(accountId, chatId);
+ if (markNoticed) {
+ DcContext dcContext = DcHelper.getAccounts(context).getAccount(accountId);
+ dcContext.marknoticedChat(chatId);
+ dcContext.markseenMsgs(new int[] {msgId});
+ }
+ });
}
}
diff --git a/src/main/java/org/thoughtcrime/securesms/notifications/RemoteReplyReceiver.java b/src/main/java/org/thoughtcrime/securesms/notifications/RemoteReplyReceiver.java
index 21c8de8b0..d036dc092 100644
--- a/src/main/java/org/thoughtcrime/securesms/notifications/RemoteReplyReceiver.java
+++ b/src/main/java/org/thoughtcrime/securesms/notifications/RemoteReplyReceiver.java
@@ -24,23 +24,17 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-
import androidx.core.app.RemoteInput;
-
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcMsg;
-
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.Util;
-
-/**
- * Get the response text from the Wearable Device and sends an message as a reply
- */
+/** Get the response text from the Wearable Device and sends an message as a reply */
public class RemoteReplyReceiver extends BroadcastReceiver {
- public static final String TAG = RemoteReplyReceiver.class.getSimpleName();
- public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY";
+ public static final String TAG = RemoteReplyReceiver.class.getSimpleName();
+ public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY";
public static final String ACCOUNT_ID_EXTRA = "account_id";
public static final String CHAT_ID_EXTRA = "chat_id";
public static final String MSG_ID_EXTRA = "msg_id";
@@ -60,20 +54,21 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
final CharSequence responseText = remoteInput.getCharSequence(EXTRA_REMOTE_REPLY);
if (responseText != null) {
- Util.runOnAnyBackgroundThread(() -> {
- DcContext dcContext = DcHelper.getAccounts(context).getAccount(accountId);
- dcContext.marknoticedChat(chatId);
- dcContext.markseenMsgs(new int[]{msgId});
- if (dcContext.getChat(chatId).isContactRequest()) {
- dcContext.acceptChat(chatId);
- }
+ Util.runOnAnyBackgroundThread(
+ () -> {
+ DcContext dcContext = DcHelper.getAccounts(context).getAccount(accountId);
+ dcContext.marknoticedChat(chatId);
+ dcContext.markseenMsgs(new int[] {msgId});
+ if (dcContext.getChat(chatId).isContactRequest()) {
+ dcContext.acceptChat(chatId);
+ }
- DcMsg msg = new DcMsg(dcContext, DcMsg.DC_MSG_TEXT);
- msg.setText(responseText.toString());
- dcContext.sendMsg(chatId, msg);
+ DcMsg msg = new DcMsg(dcContext, DcMsg.DC_MSG_TEXT);
+ msg.setText(responseText.toString());
+ dcContext.sendMsg(chatId, msg);
- DcHelper.getNotificationCenter(context).removeNotifications(accountId, chatId);
- });
+ DcHelper.getNotificationCenter(context).removeNotifications(accountId, chatId);
+ });
}
}
}
diff --git a/src/main/java/org/thoughtcrime/securesms/util/MailtoUtil.java b/src/main/java/org/thoughtcrime/securesms/util/MailtoUtil.java
index c2080270b..fbd891540 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/MailtoUtil.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/MailtoUtil.java
@@ -2,62 +2,61 @@ package org.thoughtcrime.securesms.util;
import android.net.MailTo;
import android.net.Uri;
-
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
public class MailtoUtil {
- private static final String MAILTO = "mailto";
- private static final String SUBJECT = "subject";
- private static final String BODY = "body";
- private static final String QUERY_SEPARATOR = "&";
- private static final String KEY_VALUE_SEPARATOR = "=";
+ private static final String MAILTO = "mailto";
+ private static final String SUBJECT = "subject";
+ private static final String BODY = "body";
+ private static final String QUERY_SEPARATOR = "&";
+ private static final String KEY_VALUE_SEPARATOR = "=";
- public static boolean isMailto(Uri uri) {
- return uri != null && MAILTO.equals(uri.getScheme());
+ public static boolean isMailto(Uri uri) {
+ return uri != null && MAILTO.equals(uri.getScheme());
+ }
+
+ public static String[] getRecipients(Uri uri) {
+ String[] recipientsArray = new String[0];
+ if (uri != null) {
+ MailTo mailto = MailTo.parse(uri.toString());
+ String recipientsList = mailto.getTo();
+ if (recipientsList != null && !recipientsList.trim().isEmpty()) {
+ recipientsArray = recipientsList.trim().split(",");
+ }
}
+ return recipientsArray;
+ }
- public static String[] getRecipients(Uri uri) {
- String[] recipientsArray = new String[0];
- if (uri != null) {
- MailTo mailto = MailTo.parse(uri.toString());
- String recipientsList = mailto.getTo();
- if(recipientsList != null && !recipientsList.trim().isEmpty()) {
- recipientsArray = recipientsList.trim().split(",");
- }
+ public static String getText(Uri uri) {
+ Map mailtoQueryMap = getMailtoQueryMap(uri);
+ String textToShare = mailtoQueryMap.get(SUBJECT);
+ String body = mailtoQueryMap.get(BODY);
+ if (body != null && !body.isEmpty()) {
+ if (textToShare != null && !textToShare.isEmpty()) {
+ textToShare += "\n" + body;
+ } else {
+ textToShare = body;
+ }
+ }
+ return textToShare != null ? textToShare : "";
+ }
+
+ private static Map getMailtoQueryMap(Uri uri) {
+ Map mailtoQueryMap = new HashMap<>();
+ String query = uri.getEncodedQuery();
+ if (query != null && !query.isEmpty()) {
+ String[] queryArray = query.split(QUERY_SEPARATOR);
+ for (String queryEntry : queryArray) {
+ String[] queryEntryArray = queryEntry.split(KEY_VALUE_SEPARATOR);
+ try {
+ mailtoQueryMap.put(queryEntryArray[0], URLDecoder.decode(queryEntryArray[1], "UTF-8"));
+ } catch (Exception e) {
+ e.printStackTrace();
}
- return recipientsArray;
- }
-
- public static String getText(Uri uri) {
- Map mailtoQueryMap = getMailtoQueryMap(uri);
- String textToShare = mailtoQueryMap.get(SUBJECT);
- String body = mailtoQueryMap.get(BODY);
- if (body != null && !body.isEmpty()) {
- if (textToShare != null && !textToShare.isEmpty()) {
- textToShare += "\n" + body;
- } else {
- textToShare = body;
- }
- }
- return textToShare != null? textToShare : "";
- }
-
- private static Map getMailtoQueryMap(Uri uri) {
- Map mailtoQueryMap = new HashMap<>();
- String query = uri.getEncodedQuery();
- if (query != null && !query.isEmpty()) {
- String[] queryArray = query.split(QUERY_SEPARATOR);
- for(String queryEntry : queryArray) {
- String[] queryEntryArray = queryEntry.split(KEY_VALUE_SEPARATOR);
- try {
- mailtoQueryMap.put(queryEntryArray[0], URLDecoder.decode(queryEntryArray[1], "UTF-8"));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- return mailtoQueryMap;
+ }
}
+ return mailtoQueryMap;
+ }
}
diff --git a/src/main/java/org/thoughtcrime/securesms/util/MediaUtil.java b/src/main/java/org/thoughtcrime/securesms/util/MediaUtil.java
index 7b205b992..7bdd1d7ca 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/MediaUtil.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/MediaUtil.java
@@ -8,15 +8,18 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.webkit.MimeTypeMap;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
-
import com.b44t.messenger.DcMsg;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.gif.GifDrawable;
-
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.ExecutionException;
import org.thoughtcrime.securesms.mms.AudioSlide;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
import org.thoughtcrime.securesms.mms.DocumentSlide;
@@ -30,27 +33,19 @@ import org.thoughtcrime.securesms.mms.VcardSlide;
import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.concurrent.ExecutionException;
-
public class MediaUtil {
private static final String TAG = MediaUtil.class.getSimpleName();
- public static final String IMAGE_WEBP = "image/webp";
- public static final String IMAGE_JPEG = "image/jpeg";
- public static final String IMAGE_GIF = "image/gif";
- public static final String AUDIO_AAC = "audio/aac";
+ public static final String IMAGE_WEBP = "image/webp";
+ public static final String IMAGE_JPEG = "image/jpeg";
+ public static final String IMAGE_GIF = "image/gif";
+ public static final String AUDIO_AAC = "audio/aac";
public static final String AUDIO_UNSPECIFIED = "audio/*";
public static final String VIDEO_UNSPECIFIED = "video/*";
- public static final String OCTET = "application/octet-stream";
- public static final String WEBXDC = "application/webxdc+zip";
- public static final String VCARD = "text/vcard";
-
+ public static final String OCTET = "application/octet-stream";
+ public static final String WEBXDC = "application/webxdc+zip";
+ public static final String VCARD = "text/vcard";
public static Slide getSlideForMsg(Context context, DcMsg dcMsg) {
Slide slide = null;
@@ -62,13 +57,11 @@ public class MediaUtil {
slide = new StickerSlide(context, dcMsg);
} else if (dcMsg.getType() == DcMsg.DC_MSG_VIDEO) {
slide = new VideoSlide(context, dcMsg);
- } else if (dcMsg.getType() == DcMsg.DC_MSG_AUDIO
- || dcMsg.getType() == DcMsg.DC_MSG_VOICE) {
+ } else if (dcMsg.getType() == DcMsg.DC_MSG_AUDIO || dcMsg.getType() == DcMsg.DC_MSG_VOICE) {
slide = new AudioSlide(context, dcMsg);
} else if (dcMsg.getType() == DcMsg.DC_MSG_VCARD) {
slide = new VcardSlide(context, dcMsg);
- } else if (dcMsg.getType() == DcMsg.DC_MSG_FILE
- || dcMsg.getType() == DcMsg.DC_MSG_WEBXDC) {
+ } else if (dcMsg.getType() == DcMsg.DC_MSG_FILE || dcMsg.getType() == DcMsg.DC_MSG_WEBXDC) {
slide = new DocumentSlide(context, dcMsg);
}
@@ -96,20 +89,18 @@ public class MediaUtil {
public static @Nullable String getCorrectedMimeType(@Nullable String mimeType) {
if (mimeType == null) return null;
- switch(mimeType) {
- case "image/jpg":
- return MimeTypeMap.getSingleton().hasMimeType(IMAGE_JPEG)
- ? IMAGE_JPEG
- : mimeType;
- default:
- return mimeType;
+ switch (mimeType) {
+ case "image/jpg":
+ return MimeTypeMap.getSingleton().hasMimeType(IMAGE_JPEG) ? IMAGE_JPEG : mimeType;
+ default:
+ return mimeType;
}
}
/**
- * This is a version of android.webkit.MimeTypeMap.getFileExtensionFromUrl() that
- * doesn't refuse to do its job when there are characters in the URL it doesn't know.
- * Using MimeTypeMap.getFileExtensionFromUrl() led to bugs like this one:
+ * This is a version of android.webkit.MimeTypeMap.getFileExtensionFromUrl() that doesn't refuse
+ * to do its job when there are characters in the URL it doesn't know. Using
+ * MimeTypeMap.getFileExtensionFromUrl() led to bugs like this one:
* https://github.com/deltachat/deltachat-android/issues/2306
*
* @return The url's file extension, or "" if there is none.
@@ -128,8 +119,7 @@ public class MediaUtil {
}
int filenamePos = url.lastIndexOf('/');
- String filename =
- 0 <= filenamePos ? url.substring(filenamePos + 1) : url;
+ String filename = 0 <= filenamePos ? url.substring(filenamePos + 1) : url;
if (!filename.isEmpty()) {
int dotPos = filename.lastIndexOf('.');
@@ -145,9 +135,9 @@ public class MediaUtil {
InputStream in = PartAuthority.getAttachmentStream(context, uri);
if (in == null) throw new IOException("Couldn't obtain input stream.");
- long size = 0;
+ long size = 0;
byte[] buffer = new byte[4096];
- int read;
+ int read;
while ((read = in.read(buffer)) != -1) {
size += read;
@@ -158,7 +148,8 @@ public class MediaUtil {
}
@WorkerThread
- public static Pair getDimensions(@NonNull Context context, @Nullable String contentType, @Nullable Uri uri) {
+ public static Pair getDimensions(
+ @NonNull Context context, @Nullable String contentType, @Nullable Uri uri) {
if (uri == null || !MediaUtil.isImageType(contentType)) {
return new Pair<>(0, 0);
}
@@ -167,7 +158,8 @@ public class MediaUtil {
if (MediaUtil.isGif(contentType)) {
try {
- GifDrawable drawable = GlideApp.with(context)
+ GifDrawable drawable =
+ GlideApp.with(context)
.asGif()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
@@ -257,22 +249,24 @@ public class MediaUtil {
this.width = width;
this.height = height;
}
+
public int width;
public int height;
}
- public static boolean createVideoThumbnailIfNeeded(Context context, Uri dataUri, Uri thumbnailUri, ThumbnailSize retWh) {
+ public static boolean createVideoThumbnailIfNeeded(
+ Context context, Uri dataUri, Uri thumbnailUri, ThumbnailSize retWh) {
boolean success = false;
try {
File thumbnailFile = new File(thumbnailUri.getPath());
File dataFile = new File(dataUri.getPath());
- if (!thumbnailFile.exists() || dataFile.lastModified()>thumbnailFile.lastModified()) {
+ if (!thumbnailFile.exists() || dataFile.lastModified() > thumbnailFile.lastModified()) {
Bitmap bitmap = null;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(context, dataUri);
bitmap = retriever.getFrameAtTime(-1);
- if (retWh!=null) {
+ if (retWh != null) {
retWh.width = bitmap.getWidth();
retWh.height = bitmap.getHeight();
}
@@ -284,20 +278,19 @@ public class MediaUtil {
success = true;
}
}
- }
- catch (Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
return success;
}
public static String getExtensionFromMimeType(String contentType) {
- String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(contentType);
+ String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(contentType);
if (extension != null) {
return extension;
}
- //custom handling needed for unsupported extensions on Android 4.X
+ // custom handling needed for unsupported extensions on Android 4.X
switch (contentType) {
case AUDIO_AAC:
return "aac";
@@ -310,5 +303,4 @@ public class MediaUtil {
}
return null;
}
-
}
diff --git a/src/main/java/org/thoughtcrime/securesms/util/Pair.java b/src/main/java/org/thoughtcrime/securesms/util/Pair.java
index 2492b1722..1b7a37b88 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/Pair.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/Pair.java
@@ -1,7 +1,7 @@
/**
* Copyright (C) 2014-2016 Open Whisper Systems
*
- * Licensed according to the LICENSE file in this repository.
+ * Licensed according to the LICENSE file in this repository.
*/
package org.thoughtcrime.securesms.util;
@@ -14,18 +14,18 @@ public class Pair {
this.v2 = v2;
}
- public T1 first(){
+ public T1 first() {
return v1;
}
- public T2 second(){
+ public T2 second() {
return v2;
}
public boolean equals(Object o) {
- return o instanceof Pair &&
- equal(((Pair) o).first(), first()) &&
- equal(((Pair) o).second(), second());
+ return o instanceof Pair
+ && equal(((Pair) o).first(), first())
+ && equal(((Pair) o).second(), second());
}
public int hashCode() {
diff --git a/src/main/java/org/thoughtcrime/securesms/util/ParcelUtil.java b/src/main/java/org/thoughtcrime/securesms/util/ParcelUtil.java
index c1eda1232..13055b0c6 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/ParcelUtil.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/ParcelUtil.java
@@ -24,5 +24,4 @@ public class ParcelUtil {
Parcel parcel = deserialize(bytes);
return creator.createFromParcel(parcel);
}
-
}
diff --git a/src/main/java/org/thoughtcrime/securesms/util/Prefs.java b/src/main/java/org/thoughtcrime/securesms/util/Prefs.java
index 8a5fc4b1a..13e3f76b0 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/Prefs.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/Prefs.java
@@ -7,84 +7,98 @@ import android.net.Uri;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.Settings;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
-
import com.b44t.messenger.DcContext;
-
-import org.thoughtcrime.securesms.BuildConfig;
-import org.thoughtcrime.securesms.connect.DcHelper;
-import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import org.thoughtcrime.securesms.BuildConfig;
+import org.thoughtcrime.securesms.connect.DcHelper;
+import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference;
public class Prefs {
private static final String TAG = Prefs.class.getSimpleName();
- public static final String RELIABLE_SERVICE_PREF = "pref_reliable_service";
- public static final String DISABLE_PASSPHRASE_PREF = "pref_disable_passphrase";
- public static final String THEME_PREF = "pref_theme";
- public static final String BACKGROUND_PREF = "pref_chat_background";
+ public static final String RELIABLE_SERVICE_PREF = "pref_reliable_service";
+ public static final String DISABLE_PASSPHRASE_PREF = "pref_disable_passphrase";
+ public static final String THEME_PREF = "pref_theme";
+ public static final String BACKGROUND_PREF = "pref_chat_background";
- private static final String DATABASE_ENCRYPTED_SECRET = "pref_database_encrypted_secret_"; // followed by account-id
- private static final String DATABASE_UNENCRYPTED_SECRET = "pref_database_unencrypted_secret_"; // followed by account-id
+ private static final String DATABASE_ENCRYPTED_SECRET =
+ "pref_database_encrypted_secret_"; // followed by account-id
+ private static final String DATABASE_UNENCRYPTED_SECRET =
+ "pref_database_unencrypted_secret_"; // followed by account-id
- public static final String RINGTONE_PREF = "pref_key_ringtone";
- private static final String VIBRATE_PREF = "pref_key_vibrate";
- private static final String CHAT_VIBRATE = "pref_chat_vibrate_"; // followed by chat-id
- public static final String LED_COLOR_PREF = "pref_led_color";
- private static final String CHAT_RINGTONE = "pref_chat_ringtone_"; // followed by chat-id
- public static final String SCREEN_SECURITY_PREF = "pref_screen_security";
- private static final String ENTER_SENDS_PREF = "pref_enter_sends";
- private static final String PROMPTED_DOZE_MSG_ID_PREF = "pref_prompted_doze_msg_id";
- private static final String STATS_DEVICE_MSG_ID_PREF = "pref_stats_device_msg_id";
- public static final String DOZE_ASKED_DIRECTLY = "pref_doze_asked_directly";
- public static final String ASKED_FOR_NOTIFICATION_PERMISSION= "pref_asked_for_notification_permission";
- private static final String IN_THREAD_NOTIFICATION_PREF = "pref_key_inthread_notifications";
+ public static final String RINGTONE_PREF = "pref_key_ringtone";
+ private static final String VIBRATE_PREF = "pref_key_vibrate";
+ private static final String CHAT_VIBRATE = "pref_chat_vibrate_"; // followed by chat-id
+ public static final String LED_COLOR_PREF = "pref_led_color";
+ private static final String CHAT_RINGTONE = "pref_chat_ringtone_"; // followed by chat-id
+ public static final String SCREEN_SECURITY_PREF = "pref_screen_security";
+ private static final String ENTER_SENDS_PREF = "pref_enter_sends";
+ private static final String PROMPTED_DOZE_MSG_ID_PREF = "pref_prompted_doze_msg_id";
+ private static final String STATS_DEVICE_MSG_ID_PREF = "pref_stats_device_msg_id";
+ public static final String DOZE_ASKED_DIRECTLY = "pref_doze_asked_directly";
+ public static final String ASKED_FOR_NOTIFICATION_PERMISSION =
+ "pref_asked_for_notification_permission";
+ private static final String IN_THREAD_NOTIFICATION_PREF = "pref_key_inthread_notifications";
- public static final String NOTIFICATION_PRIVACY_PREF = "pref_notification_privacy";
- public static final String NOTIFICATION_PRIORITY_PREF = "pref_notification_priority";
+ public static final String NOTIFICATION_PRIVACY_PREF = "pref_notification_privacy";
+ public static final String NOTIFICATION_PRIORITY_PREF = "pref_notification_priority";
- private static final String PROFILE_AVATAR_ID_PREF = "pref_profile_avatar_id";
- public static final String INCOGNITO_KEYBORAD_PREF = "pref_incognito_keyboard";
+ private static final String PROFILE_AVATAR_ID_PREF = "pref_profile_avatar_id";
+ public static final String INCOGNITO_KEYBORAD_PREF = "pref_incognito_keyboard";
private static final String PREF_CONTACT_PHOTO_IDENTIFIERS = "pref_contact_photo_identifiers";
- public static final String ALWAYS_LOAD_REMOTE_CONTENT = "pref_always_load_remote_content";
- public static final boolean ALWAYS_LOAD_REMOTE_CONTENT_DEFAULT = false;
+ public static final String ALWAYS_LOAD_REMOTE_CONTENT = "pref_always_load_remote_content";
+ public static final boolean ALWAYS_LOAD_REMOTE_CONTENT_DEFAULT = false;
- public static final String LAST_DEVICE_MSG_LABEL = "pref_last_device_msg_id";
- public static final String WEBXDC_STORE_URL_PREF = "pref_webxdc_store_url";
- public static final String DEFAULT_WEBXDC_STORE_URL = "https://webxdc.org/apps/";
+ public static final String LAST_DEVICE_MSG_LABEL = "pref_last_device_msg_id";
+ public static final String WEBXDC_STORE_URL_PREF = "pref_webxdc_store_url";
+ public static final String DEFAULT_WEBXDC_STORE_URL = "https://webxdc.org/apps/";
public enum VibrateState {
- DEFAULT(0), ENABLED(1), DISABLED(2);
+ DEFAULT(0),
+ ENABLED(1),
+ DISABLED(2);
private final int id;
- VibrateState(int id) { this.id = id; }
- public int getId() { return id; }
- public static VibrateState fromId(int id) { return values()[id]; }
+
+ VibrateState(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public static VibrateState fromId(int id) {
+ return values()[id];
+ }
}
- public static void setDatabaseEncryptedSecret(@NonNull Context context, @NonNull String secret, int accountId) {
+ public static void setDatabaseEncryptedSecret(
+ @NonNull Context context, @NonNull String secret, int accountId) {
setStringPreference(context, DATABASE_ENCRYPTED_SECRET + accountId, secret);
}
- public static void setDatabaseUnencryptedSecret(@NonNull Context context, @Nullable String secret, int accountId) {
+ public static void setDatabaseUnencryptedSecret(
+ @NonNull Context context, @Nullable String secret, int accountId) {
setStringPreference(context, DATABASE_UNENCRYPTED_SECRET + accountId, secret);
}
- public static @Nullable String getDatabaseUnencryptedSecret(@NonNull Context context, int accountId) {
+ public static @Nullable String getDatabaseUnencryptedSecret(
+ @NonNull Context context, int accountId) {
return getStringPreference(context, DATABASE_UNENCRYPTED_SECRET + accountId, null);
}
- public static @Nullable String getDatabaseEncryptedSecret(@NonNull Context context, int accountId) {
+ public static @Nullable String getDatabaseEncryptedSecret(
+ @NonNull Context context, int accountId) {
return getStringPreference(context, DATABASE_ENCRYPTED_SECRET + accountId, null);
}
@@ -101,11 +115,14 @@ public class Prefs {
}
public static int getNotificationPriority(Context context) {
- return Integer.valueOf(getStringPreference(context, NOTIFICATION_PRIORITY_PREF, String.valueOf(NotificationCompat.PRIORITY_HIGH)));
+ return Integer.valueOf(
+ getStringPreference(
+ context, NOTIFICATION_PRIORITY_PREF, String.valueOf(NotificationCompat.PRIORITY_HIGH)));
}
public static NotificationPrivacyPreference getNotificationPrivacy(Context context) {
- return new NotificationPrivacyPreference(getStringPreference(context, NOTIFICATION_PRIVACY_PREF, "all"));
+ return new NotificationPrivacyPreference(
+ getStringPreference(context, NOTIFICATION_PRIVACY_PREF, "all"));
}
public static boolean isInChatNotifications(Context context) {
@@ -133,7 +150,10 @@ public class Prefs {
}
public static String getTheme(Context context) {
- return getStringPreference(context, THEME_PREF, DynamicTheme.systemThemeAvailable() ? DynamicTheme.SYSTEM : DynamicTheme.LIGHT);
+ return getStringPreference(
+ context,
+ THEME_PREF,
+ DynamicTheme.systemThemeAvailable() ? DynamicTheme.SYSTEM : DynamicTheme.LIGHT);
}
public static String getWebxdcStoreUrl(Context context) {
@@ -162,11 +182,12 @@ public class Prefs {
}
public static boolean isPushEnabled(Context context) {
- return BuildConfig.USE_PLAY_SERVICES;
+ return BuildConfig.USE_PLAY_SERVICES;
}
public static boolean isHardCompressionEnabled(Context context) {
- return DcHelper.getContext(context).getConfigInt(DcHelper.CONFIG_MEDIA_QUALITY) == DcContext.DC_MEDIA_QUALITY_WORSE;
+ return DcHelper.getContext(context).getConfigInt(DcHelper.CONFIG_MEDIA_QUALITY)
+ == DcContext.DC_MEDIA_QUALITY_WORSE;
}
public static boolean isLocationStreamingEnabled(Context context) {
@@ -177,7 +198,6 @@ public class Prefs {
return true;
}
-
public static boolean isCallsEnabled(Context context) {
return true;
}
@@ -185,7 +205,9 @@ public class Prefs {
// ringtone
public static @NonNull Uri getNotificationRingtone(Context context) {
- String result = getStringPreference(context, RINGTONE_PREF, Settings.System.DEFAULT_NOTIFICATION_URI.toString());
+ String result =
+ getStringPreference(
+ context, RINGTONE_PREF, Settings.System.DEFAULT_NOTIFICATION_URI.toString());
if (result != null && result.startsWith("file:")) {
result = Settings.System.DEFAULT_NOTIFICATION_URI.toString();
@@ -203,19 +225,20 @@ public class Prefs {
}
public static void setChatRingtone(Context context, int accountId, int chatId, Uri ringtone) {
- final String KEY = (accountId != 0 && chatId != 0)? CHAT_RINGTONE+accountId+"."+chatId : CHAT_RINGTONE;
- if(ringtone!=null) {
+ final String KEY =
+ (accountId != 0 && chatId != 0) ? CHAT_RINGTONE + accountId + "." + chatId : CHAT_RINGTONE;
+ if (ringtone != null) {
setStringPreference(context, KEY, ringtone.toString());
- }
- else {
+ } else {
removePreference(context, KEY);
}
}
public static @Nullable Uri getChatRingtone(Context context, int accountId, int chatId) {
- final String KEY = (accountId != 0 && chatId != 0)? CHAT_RINGTONE+accountId+"."+chatId : CHAT_RINGTONE;
+ final String KEY =
+ (accountId != 0 && chatId != 0) ? CHAT_RINGTONE + accountId + "." + chatId : CHAT_RINGTONE;
String result = getStringPreference(context, KEY, null);
- return result==null? null : Uri.parse(result);
+ return result == null ? null : Uri.parse(result);
}
public static void setReliableService(Context context, boolean value) {
@@ -227,7 +250,8 @@ public class Prefs {
if (prefs.contains(RELIABLE_SERVICE_PREF)) {
try {
return prefs.getBoolean(RELIABLE_SERVICE_PREF, true);
- } catch(Exception e) {}
+ } catch (Exception e) {
+ }
}
// if the key was unset, then calculate default value
@@ -240,18 +264,20 @@ public class Prefs {
return getBooleanPreference(context, VIBRATE_PREF, true);
}
- public static void setChatVibrate(Context context, int accountId, int chatId, VibrateState vibrateState) {
- final String KEY = (accountId != 0 && chatId != 0)? CHAT_VIBRATE+accountId+"."+chatId : CHAT_VIBRATE;
- if(vibrateState!=VibrateState.DEFAULT) {
+ public static void setChatVibrate(
+ Context context, int accountId, int chatId, VibrateState vibrateState) {
+ final String KEY =
+ (accountId != 0 && chatId != 0) ? CHAT_VIBRATE + accountId + "." + chatId : CHAT_VIBRATE;
+ if (vibrateState != VibrateState.DEFAULT) {
setIntegerPreference(context, KEY, vibrateState.getId());
- }
- else {
+ } else {
removePreference(context, KEY);
}
}
public static VibrateState getChatVibrate(Context context, int accountId, int chatId) {
- final String KEY = (accountId != 0 && chatId != 0)? CHAT_VIBRATE+accountId+"."+chatId : CHAT_VIBRATE;
+ final String KEY =
+ (accountId != 0 && chatId != 0) ? CHAT_VIBRATE + accountId + "." + chatId : CHAT_VIBRATE;
return VibrateState.fromId(getIntegerPreference(context, KEY, VibrateState.DEFAULT.getId()));
}
@@ -264,16 +290,16 @@ public class Prefs {
// misc.
public static String getBackgroundImagePath(Context context, int accountId) {
- return getStringPreference(context, BACKGROUND_PREF+accountId, "");
+ return getStringPreference(context, BACKGROUND_PREF + accountId, "");
}
public static void setBackgroundImagePath(Context context, int accountId, String path) {
- setStringPreference(context, BACKGROUND_PREF+accountId, path);
+ setStringPreference(context, BACKGROUND_PREF + accountId, path);
}
public static boolean getAlwaysLoadRemoteContent(Context context) {
- return getBooleanPreference(context, Prefs.ALWAYS_LOAD_REMOTE_CONTENT,
- Prefs.ALWAYS_LOAD_REMOTE_CONTENT_DEFAULT);
+ return getBooleanPreference(
+ context, Prefs.ALWAYS_LOAD_REMOTE_CONTENT, Prefs.ALWAYS_LOAD_REMOTE_CONTENT_DEFAULT);
}
// generic preference functions
@@ -314,7 +340,8 @@ public class Prefs {
PreferenceManager.getDefaultSharedPreferences(context).edit().remove(key).apply();
}
- private static Set getStringSetPreference(Context context, String key, Set defaultValues) {
+ private static Set getStringSetPreference(
+ Context context, String key, Set defaultValues) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (prefs.contains(key)) {
return prefs.getStringSet(key, Collections.emptySet());
@@ -324,12 +351,17 @@ public class Prefs {
}
public static void setSystemContactPhotos(Context context, Set contactPhotoIdentifiers) {
- PreferenceManager.getDefaultSharedPreferences(context).edit().putStringSet(PREF_CONTACT_PHOTO_IDENTIFIERS, contactPhotoIdentifiers).apply();
+ PreferenceManager.getDefaultSharedPreferences(context)
+ .edit()
+ .putStringSet(PREF_CONTACT_PHOTO_IDENTIFIERS, contactPhotoIdentifiers)
+ .apply();
}
public static Uri getSystemContactPhoto(Context context, String identifier) {
- List contactPhotoIdentifiers = new ArrayList<>(getStringSetPreference(context, PREF_CONTACT_PHOTO_IDENTIFIERS, new HashSet<>()));
- for(String contactPhotoIdentifier : contactPhotoIdentifiers) {
+ List contactPhotoIdentifiers =
+ new ArrayList<>(
+ getStringSetPreference(context, PREF_CONTACT_PHOTO_IDENTIFIERS, new HashSet<>()));
+ for (String contactPhotoIdentifier : contactPhotoIdentifiers) {
if (contactPhotoIdentifier.contains(identifier)) {
String[] parts = contactPhotoIdentifier.split("\\|");
long contactId = Long.valueOf(parts[1]);
@@ -338,5 +370,4 @@ public class Prefs {
}
return null;
}
-
}
diff --git a/src/main/java/org/thoughtcrime/securesms/util/ResUtil.java b/src/main/java/org/thoughtcrime/securesms/util/ResUtil.java
index 865fc3fcc..847b34c25 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/ResUtil.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/ResUtil.java
@@ -1,20 +1,17 @@
/**
* Copyright (C) 2015 Open Whisper Systems
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ *
You should have received a copy of the GNU General Public License along with this program. If
+ * not, see .
*/
-
package org.thoughtcrime.securesms.util;
import android.content.Context;
@@ -22,15 +19,14 @@ import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
-
import androidx.annotation.AttrRes;
import androidx.core.content.ContextCompat;
public class ResUtil {
public static int getColor(Context context, @AttrRes int attr) {
- final TypedArray styledAttributes = context.obtainStyledAttributes(new int[]{attr});
- final int result = styledAttributes.getColor(0, -1);
+ final TypedArray styledAttributes = context.obtainStyledAttributes(new int[] {attr});
+ final int result = styledAttributes.getColor(0, -1);
styledAttributes.recycle();
return result;
}
diff --git a/src/main/java/org/thoughtcrime/securesms/util/concurrent/AssertedSuccessListener.java b/src/main/java/org/thoughtcrime/securesms/util/concurrent/AssertedSuccessListener.java
index 90a4eedb4..90abcd27a 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/concurrent/AssertedSuccessListener.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/concurrent/AssertedSuccessListener.java
@@ -1,8 +1,7 @@
package org.thoughtcrime.securesms.util.concurrent;
-import java.util.concurrent.ExecutionException;
-
import chat.delta.util.ListenableFuture;
+import java.util.concurrent.ExecutionException;
public abstract class AssertedSuccessListener implements ListenableFuture.Listener {
@Override
diff --git a/src/main/java/org/thoughtcrime/securesms/util/spans/CenterAlignedRelativeSizeSpan.java b/src/main/java/org/thoughtcrime/securesms/util/spans/CenterAlignedRelativeSizeSpan.java
index b15c96137..f2c47b9ce 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/spans/CenterAlignedRelativeSizeSpan.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/spans/CenterAlignedRelativeSizeSpan.java
@@ -1,6 +1,5 @@
package org.thoughtcrime.securesms.util.spans;
-
import android.text.TextPaint;
import android.text.style.MetricAffectingSpan;
diff --git a/src/main/java/org/thoughtcrime/securesms/util/task/ProgressDialogAsyncTask.java b/src/main/java/org/thoughtcrime/securesms/util/task/ProgressDialogAsyncTask.java
index 23d76efcd..5c1f2c0a5 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/task/ProgressDialogAsyncTask.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/task/ProgressDialogAsyncTask.java
@@ -3,27 +3,25 @@ package org.thoughtcrime.securesms.util.task;
import android.content.Context;
import android.content.DialogInterface.OnCancelListener;
import android.os.AsyncTask;
-
import androidx.annotation.Nullable;
-
+import java.lang.ref.WeakReference;
import org.thoughtcrime.securesms.util.views.ProgressDialog;
-import java.lang.ref.WeakReference;
-
-public abstract class ProgressDialogAsyncTask extends AsyncTask {
+public abstract class ProgressDialogAsyncTask
+ extends AsyncTask {
private final WeakReference contextReference;
- private ProgressDialog progress;
- private final String title;
- private final String message;
- private boolean cancelable;
- private OnCancelListener onCancelListener;
+ private ProgressDialog progress;
+ private final String title;
+ private final String message;
+ private boolean cancelable;
+ private OnCancelListener onCancelListener;
public ProgressDialogAsyncTask(Context context, String title, String message) {
super();
this.contextReference = new WeakReference<>(context);
- this.title = title;
- this.message = message;
+ this.title = title;
+ this.message = message;
}
public void setCancelable(@Nullable OnCancelListener onCancelListener) {
@@ -43,7 +41,7 @@ public abstract class ProgressDialogAsyncTask extends
protected void onPostExecute(Result result) {
try {
if (progress != null) progress.dismiss();
- } catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
@@ -52,4 +50,3 @@ public abstract class ProgressDialogAsyncTask extends
return contextReference.get();
}
}
-
diff --git a/src/main/java/org/thoughtcrime/securesms/util/task/SnackbarAsyncTask.java b/src/main/java/org/thoughtcrime/securesms/util/task/SnackbarAsyncTask.java
index 19e644a81..f0e8d0201 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/task/SnackbarAsyncTask.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/task/SnackbarAsyncTask.java
@@ -2,48 +2,43 @@ package org.thoughtcrime.securesms.util.task;
import android.os.AsyncTask;
import android.view.View;
-
import androidx.annotation.Nullable;
-
import com.google.android.material.snackbar.Snackbar;
-
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.views.ProgressDialog;
-public abstract class SnackbarAsyncTask
- extends AsyncTask
- implements View.OnClickListener
-{
+public abstract class SnackbarAsyncTask extends AsyncTask
+ implements View.OnClickListener {
- private final View view;
- private final String snackbarText;
- private final String snackbarActionText;
- private final int snackbarDuration;
+ private final View view;
+ private final String snackbarText;
+ private final String snackbarActionText;
+ private final int snackbarDuration;
private final boolean showProgress;
- private @Nullable Params reversibleParameter;
+ private @Nullable Params reversibleParameter;
private @Nullable ProgressDialog progressDialog;
- public SnackbarAsyncTask(View view,
- String snackbarText,
- String snackbarActionText,
- int snackbarDuration,
- boolean showProgress)
- {
- this.view = view;
- this.snackbarText = snackbarText;
- this.snackbarActionText = snackbarActionText;
- this.snackbarDuration = snackbarDuration;
- this.showProgress = showProgress;
+ public SnackbarAsyncTask(
+ View view,
+ String snackbarText,
+ String snackbarActionText,
+ int snackbarDuration,
+ boolean showProgress) {
+ this.view = view;
+ this.snackbarText = snackbarText;
+ this.snackbarActionText = snackbarActionText;
+ this.snackbarDuration = snackbarDuration;
+ this.showProgress = showProgress;
}
@Override
protected void onPreExecute() {
if (this.showProgress) {
- this.progressDialog = ProgressDialog.show(view.getContext(),
- "", view.getContext().getString(R.string.one_moment), true, false);
- }
- else {
+ this.progressDialog =
+ ProgressDialog.show(
+ view.getContext(), "", view.getContext().getString(R.string.one_moment), true, false);
+ } else {
this.progressDialog = null;
}
}
@@ -51,7 +46,7 @@ public abstract class SnackbarAsyncTask
@SafeVarargs
@Override
protected final Void doInBackground(Params... params) {
- this.reversibleParameter = params != null && params.length > 0 ?params[0] : null;
+ this.reversibleParameter = params != null && params.length > 0 ? params[0] : null;
executeAction(reversibleParameter);
return null;
}
@@ -64,9 +59,9 @@ public abstract class SnackbarAsyncTask
}
Snackbar.make(view, snackbarText, snackbarDuration)
- .setAction(snackbarActionText, this)
- .setActionTextColor(view.getResources().getColor(R.color.white))
- .show();
+ .setAction(snackbarActionText, this)
+ .setActionTextColor(view.getResources().getColor(R.color.white))
+ .show();
}
@Override
@@ -75,7 +70,7 @@ public abstract class SnackbarAsyncTask
@Override
protected void onPreExecute() {
if (showProgress) progressDialog = ProgressDialog.show(view.getContext(), "", "", true);
- else progressDialog = null;
+ else progressDialog = null;
}
@Override
@@ -95,6 +90,6 @@ public abstract class SnackbarAsyncTask
}
protected abstract void executeAction(@Nullable Params parameter);
- protected abstract void reverseAction(@Nullable Params parameter);
+ protected abstract void reverseAction(@Nullable Params parameter);
}
diff --git a/src/main/java/org/thoughtcrime/securesms/util/views/ConversationAdaptiveActionsToolbar.java b/src/main/java/org/thoughtcrime/securesms/util/views/ConversationAdaptiveActionsToolbar.java
index df2ba39b4..c02abd5ed 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/views/ConversationAdaptiveActionsToolbar.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/views/ConversationAdaptiveActionsToolbar.java
@@ -5,22 +5,23 @@ import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuItem;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
-
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.ViewUtil;
/**
- * This class was pulled from Signal (AdaptiveActionsToolbar) and then adapted to the ConversationActivity.
+ * This class was pulled from Signal (AdaptiveActionsToolbar) and then adapted to the
+ * ConversationActivity.
*/
public class ConversationAdaptiveActionsToolbar extends Toolbar {
- private static final int NAVIGATION_DP = 56;
- private static final int TITLE_DP = 48; // estimated, only a number (if >1 items are selected there is more room anyway as there are fewer options)
- private static final int ACTION_VIEW_WIDTH_DP = 48;
+ private static final int NAVIGATION_DP = 56;
+ private static final int TITLE_DP =
+ 48; // estimated, only a number (if >1 items are selected there is more room anyway as there
+ // are fewer options)
+ private static final int ACTION_VIEW_WIDTH_DP = 48;
private static final int OVERFLOW_VIEW_WIDTH_DP = 36;
private static final int ID_ACTION_1 = R.id.menu_context_edit;
@@ -29,20 +30,23 @@ public class ConversationAdaptiveActionsToolbar extends Toolbar {
private static final int ID_ACTION_4 = R.id.menu_context_forward;
private static final int ID_ACTION_5 = R.id.menu_context_delete_message;
- private final int maxShown;
+ private final int maxShown;
public ConversationAdaptiveActionsToolbar(@NonNull Context context) {
this(context, null);
}
- public ConversationAdaptiveActionsToolbar(@NonNull Context context, @Nullable AttributeSet attrs) {
+ public ConversationAdaptiveActionsToolbar(
+ @NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, R.attr.toolbarStyle);
}
- public ConversationAdaptiveActionsToolbar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ public ConversationAdaptiveActionsToolbar(
+ @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ConversationAdaptiveActionsToolbar);
+ TypedArray array =
+ context.obtainStyledAttributes(attrs, R.styleable.ConversationAdaptiveActionsToolbar);
maxShown = array.getInteger(R.styleable.ConversationAdaptiveActionsToolbar_aat_max_shown, 100);
@@ -77,11 +81,12 @@ public class ConversationAdaptiveActionsToolbar extends Toolbar {
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
- boolean showAsAction = item.getItemId() == ID_ACTION_1
- || item.getItemId() == ID_ACTION_2
- || item.getItemId() == ID_ACTION_3
- || item.getItemId() == ID_ACTION_4
- || item.getItemId() == ID_ACTION_5;
+ boolean showAsAction =
+ item.getItemId() == ID_ACTION_1
+ || item.getItemId() == ID_ACTION_2
+ || item.getItemId() == ID_ACTION_3
+ || item.getItemId() == ID_ACTION_4
+ || item.getItemId() == ID_ACTION_5;
if (showAsAction && item.isVisible() && nItemsToShow > 0) {
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
diff --git a/src/main/java/org/thoughtcrime/securesms/util/views/ProgressDialog.java b/src/main/java/org/thoughtcrime/securesms/util/views/ProgressDialog.java
index 583c0f893..a9fe62da9 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/views/ProgressDialog.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/views/ProgressDialog.java
@@ -9,59 +9,123 @@ import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
-
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
-
import org.thoughtcrime.securesms.R;
public class ProgressDialog extends AlertDialog {
- private boolean indeterminate;
- private String message;
- private TextView textView;
- private ProgressBar progressBar;
+ private boolean indeterminate;
+ private String message;
+ private TextView textView;
+ private ProgressBar progressBar;
- public ProgressDialog(@NonNull Context context) {
- super(context);
+ public ProgressDialog(@NonNull Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ View dialogView = View.inflate(getContext(), R.layout.dialog_progress, null);
+ setView(dialogView);
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void setMessage(CharSequence message) {
+ this.message = message.toString();
+ if (textView != null) {
+ textView.setText(message);
+ }
+ }
+
+ private boolean isButtonVisible(int which) {
+ Button button = getButton(which);
+ if (button == null) {
+ return false;
+ }
+ return button.getVisibility() == View.VISIBLE;
+ }
+
+ @Override
+ public void show() {
+ super.show();
+
+ if (isButtonVisible(Dialog.BUTTON_POSITIVE)
+ || isButtonVisible(Dialog.BUTTON_NEGATIVE)
+ || isButtonVisible(Dialog.BUTTON_NEUTRAL)) {
+ findViewById(R.id.noButtonsSpacer).setVisibility(View.GONE);
}
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- View dialogView = View.inflate(getContext(), R.layout.dialog_progress, null);
- setView(dialogView);
- super.onCreate(savedInstanceState);
+ progressBar = findViewById(R.id.progressBar);
+ textView = findViewById(R.id.text);
+ setupProgressBar();
+ setupTextView();
+ }
+
+ private void setupProgressBar() {
+ if (progressBar != null) {
+ progressBar
+ .getIndeterminateDrawable()
+ .setColorFilter(
+ ContextCompat.getColor(getContext(), R.color.delta_accent), PorterDuff.Mode.SRC_IN);
+ progressBar.setIndeterminate(indeterminate);
}
+ }
- @Override
- public void setMessage(CharSequence message) {
- this.message = message.toString();
- if (textView != null) {
- textView.setText(message);
- }
+ private void setupTextView() {
+ if (textView != null && message != null && !message.isEmpty()) {
+ textView.setText(message);
}
+ }
- private boolean isButtonVisible(int which) {
- Button button = getButton(which);
- if (button==null) {
- return false;
- }
- return button.getVisibility()==View.VISIBLE;
+ private void setIndeterminate(boolean indeterminate) {
+ this.indeterminate = indeterminate;
+ if (progressBar != null) {
+ progressBar.setIndeterminate(indeterminate);
}
+ }
- @Override
- public void show() {
- super.show();
+ // Source:
+ // https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/ProgressDialog.java
+ public static ProgressDialog show(
+ Context context, CharSequence title, CharSequence message, boolean indeterminate) {
+ return show(context, title, message, indeterminate, false, null);
+ }
- if (isButtonVisible(Dialog.BUTTON_POSITIVE) || isButtonVisible(Dialog.BUTTON_NEGATIVE) || isButtonVisible(Dialog.BUTTON_NEUTRAL)) {
- findViewById(R.id.noButtonsSpacer).setVisibility(View.GONE);
- }
+ // Source:
+ // https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/ProgressDialog.java
+ public static ProgressDialog show(
+ Context context,
+ CharSequence title,
+ CharSequence message,
+ boolean indeterminate,
+ boolean cancelable) {
+ return show(context, title, message, indeterminate, cancelable, null);
+ }
- progressBar = findViewById(R.id.progressBar);
- textView = findViewById(R.id.text);
- setupProgressBar();
- setupTextView();
+ // Source:
+ // https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/ProgressDialog.java
+ public static ProgressDialog show(
+ Context context,
+ CharSequence title,
+ CharSequence message,
+ boolean indeterminate,
+ boolean cancelable,
+ OnCancelListener cancelListener) {
+ ProgressDialog dialog = new ProgressDialog(context);
+ dialog.setTitle(title);
+ dialog.setMessage(message);
+ dialog.setIndeterminate(indeterminate);
+ dialog.setCancelable(cancelable);
+ dialog.setOnCancelListener(cancelListener);
+ if (cancelable) {
+ dialog.setCanceledOnTouchOutside(false);
+ dialog.setButton(
+ DialogInterface.BUTTON_NEGATIVE,
+ context.getString(R.string.cancel),
+ ((dialog1, which) -> cancelListener.onCancel(dialog)));
}
private void setupProgressBar() {
diff --git a/src/main/java/org/thoughtcrime/securesms/util/views/Stub.java b/src/main/java/org/thoughtcrime/securesms/util/views/Stub.java
index 7d9648444..1ba1dbd93 100644
--- a/src/main/java/org/thoughtcrime/securesms/util/views/Stub.java
+++ b/src/main/java/org/thoughtcrime/securesms/util/views/Stub.java
@@ -1,8 +1,6 @@
package org.thoughtcrime.securesms.util.views;
-
import android.view.ViewStub;
-
import androidx.annotation.NonNull;
public class Stub {
@@ -16,7 +14,7 @@ public class Stub {
public T get() {
if (view == null) {
- view = (T)viewStub.inflate();
+ view = (T) viewStub.inflate();
viewStub = null;
}
@@ -26,5 +24,4 @@ public class Stub {
public boolean resolved() {
return view != null;
}
-
}
diff --git a/src/main/java/org/thoughtcrime/securesms/video/VideoPlayer.java b/src/main/java/org/thoughtcrime/securesms/video/VideoPlayer.java
index eb46b5f8f..f0f11f1d2 100644
--- a/src/main/java/org/thoughtcrime/securesms/video/VideoPlayer.java
+++ b/src/main/java/org/thoughtcrime/securesms/video/VideoPlayer.java
@@ -21,10 +21,8 @@ import android.util.AttributeSet;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.MediaItem;
@@ -41,7 +39,6 @@ import com.google.android.exoplayer2.ui.StyledPlayerView;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
-
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.util.ViewUtil;
@@ -51,8 +48,8 @@ public class VideoPlayer extends FrameLayout {
@Nullable private final StyledPlayerView exoView;
- @Nullable private SimpleExoPlayer exoPlayer;
- @Nullable private Window window;
+ @Nullable private SimpleExoPlayer exoPlayer;
+ @Nullable private Window window;
public VideoPlayer(Context context) {
this(context, null);
@@ -70,8 +67,7 @@ public class VideoPlayer extends FrameLayout {
this.exoView = ViewUtil.findById(this, R.id.video_view);
}
- public void setVideoSource(@NonNull VideoSlide videoSource, boolean autoplay)
- {
+ public void setVideoSource(@NonNull VideoSlide videoSource, boolean autoplay) {
setExoViewSource(videoSource, autoplay);
}
@@ -91,27 +87,30 @@ public class VideoPlayer extends FrameLayout {
this.window = window;
}
- private void setExoViewSource(@NonNull VideoSlide videoSource, boolean autoplay)
- {
- BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter.Builder(getContext()).build();
- TrackSelector trackSelector = new DefaultTrackSelector(getContext());
- LoadControl loadControl = new DefaultLoadControl();
+ private void setExoViewSource(@NonNull VideoSlide videoSource, boolean autoplay) {
+ BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter.Builder(getContext()).build();
+ TrackSelector trackSelector = new DefaultTrackSelector(getContext());
+ LoadControl loadControl = new DefaultLoadControl();
- exoPlayer = new SimpleExoPlayer.Builder(getContext())
- .setTrackSelector(trackSelector)
- .setBandwidthMeter(bandwidthMeter)
- .setLoadControl(loadControl)
- .build();
+ exoPlayer =
+ new SimpleExoPlayer.Builder(getContext())
+ .setTrackSelector(trackSelector)
+ .setBandwidthMeter(bandwidthMeter)
+ .setLoadControl(loadControl)
+ .build();
exoPlayer.addListener(new ExoPlayerListener(window));
//noinspection ConstantConditions
exoView.setPlayer(exoPlayer);
- DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(getContext(), "GenericUserAgent", null);
- AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(defaultDataSourceFactory);
- ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
+ DefaultDataSourceFactory defaultDataSourceFactory =
+ new DefaultDataSourceFactory(getContext(), "GenericUserAgent", null);
+ AttachmentDataSourceFactory attachmentDataSourceFactory =
+ new AttachmentDataSourceFactory(defaultDataSourceFactory);
+ ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
- MediaSource mediaSource = new ProgressiveMediaSource.Factory(attachmentDataSourceFactory, extractorsFactory)
- .createMediaSource(MediaItem.fromUri(videoSource.getUri()));
+ MediaSource mediaSource =
+ new ProgressiveMediaSource.Factory(attachmentDataSourceFactory, extractorsFactory)
+ .createMediaSource(MediaItem.fromUri(videoSource.getUri()));
exoPlayer.prepare(new LoopingMediaSource(mediaSource));
exoPlayer.setPlayWhenReady(autoplay);
@@ -126,7 +125,7 @@ public class VideoPlayer extends FrameLayout {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
- switch(playbackState) {
+ switch (playbackState) {
case Player.STATE_IDLE:
case Player.STATE_BUFFERING:
case Player.STATE_ENDED:
@@ -144,6 +143,4 @@ public class VideoPlayer extends FrameLayout {
}
}
}
-
-
}
diff --git a/src/main/java/org/thoughtcrime/securesms/video/exo/AttachmentDataSource.java b/src/main/java/org/thoughtcrime/securesms/video/exo/AttachmentDataSource.java
index af37ca8d0..656e1cf45 100644
--- a/src/main/java/org/thoughtcrime/securesms/video/exo/AttachmentDataSource.java
+++ b/src/main/java/org/thoughtcrime/securesms/video/exo/AttachmentDataSource.java
@@ -1,13 +1,10 @@
package org.thoughtcrime.securesms.video.exo;
-
import android.net.Uri;
-
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
-
import java.io.IOException;
import java.util.Collections;
import java.util.List;
@@ -24,8 +21,7 @@ public class AttachmentDataSource implements DataSource {
}
@Override
- public void addTransferListener(TransferListener transferListener) {
- }
+ public void addTransferListener(TransferListener transferListener) {}
@Override
public long open(DataSpec dataSpec) throws IOException {
diff --git a/src/main/java/org/thoughtcrime/securesms/video/exo/AttachmentDataSourceFactory.java b/src/main/java/org/thoughtcrime/securesms/video/exo/AttachmentDataSourceFactory.java
index 1638db7d4..a9a243abe 100644
--- a/src/main/java/org/thoughtcrime/securesms/video/exo/AttachmentDataSourceFactory.java
+++ b/src/main/java/org/thoughtcrime/securesms/video/exo/AttachmentDataSourceFactory.java
@@ -1,8 +1,6 @@
package org.thoughtcrime.securesms.video.exo;
-
import androidx.annotation.NonNull;
-
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
@@ -10,8 +8,7 @@ public class AttachmentDataSourceFactory implements DataSource.Factory {
private final DefaultDataSourceFactory defaultDataSourceFactory;
- public AttachmentDataSourceFactory(@NonNull DefaultDataSourceFactory defaultDataSourceFactory)
- {
+ public AttachmentDataSourceFactory(@NonNull DefaultDataSourceFactory defaultDataSourceFactory) {
this.defaultDataSourceFactory = defaultDataSourceFactory;
}
diff --git a/src/main/java/org/thoughtcrime/securesms/video/recode/InputSurface.java b/src/main/java/org/thoughtcrime/securesms/video/recode/InputSurface.java
index 07ef7fdc0..c649ac81c 100644
--- a/src/main/java/org/thoughtcrime/securesms/video/recode/InputSurface.java
+++ b/src/main/java/org/thoughtcrime/securesms/video/recode/InputSurface.java
@@ -28,107 +28,109 @@ import android.view.Surface;
@TargetApi(17)
public class InputSurface {
- private static final int EGL_RECORDABLE_ANDROID = 0x3142;
- private static final int EGL_OPENGL_ES2_BIT = 4;
- private EGLDisplay mEGLDisplay;
- private EGLContext mEGLContext;
- private EGLSurface mEGLSurface;
- private Surface mSurface;
+ private static final int EGL_RECORDABLE_ANDROID = 0x3142;
+ private static final int EGL_OPENGL_ES2_BIT = 4;
+ private EGLDisplay mEGLDisplay;
+ private EGLContext mEGLContext;
+ private EGLSurface mEGLSurface;
+ private Surface mSurface;
- public InputSurface(Surface surface) {
- if (surface == null) {
- throw new NullPointerException();
- }
- mSurface = surface;
- eglSetup();
+ public InputSurface(Surface surface) {
+ if (surface == null) {
+ throw new NullPointerException();
+ }
+ mSurface = surface;
+ eglSetup();
+ }
+
+ private void eglSetup() {
+ mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+ if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
+ throw new RuntimeException("unable to get EGL14 display");
+ }
+ int[] version = new int[2];
+ if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
+ mEGLDisplay = null;
+ throw new RuntimeException("unable to initialize EGL14");
}
- private void eglSetup() {
- mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
- if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
- throw new RuntimeException("unable to get EGL14 display");
- }
- int[] version = new int[2];
- if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
- mEGLDisplay = null;
- throw new RuntimeException("unable to initialize EGL14");
- }
-
- int[] attribList = {
- EGL14.EGL_RED_SIZE, 8,
- EGL14.EGL_GREEN_SIZE, 8,
- EGL14.EGL_BLUE_SIZE, 8,
- EGL14.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RECORDABLE_ANDROID, 1,
- EGL14.EGL_NONE
- };
- EGLConfig[] configs = new EGLConfig[1];
- int[] numConfigs = new int[1];
- if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
- numConfigs, 0)) {
- throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
- }
-
- int[] attrib_list = {
- EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL14.EGL_NONE
- };
-
- mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT, attrib_list, 0);
- checkEglError("eglCreateContext");
- if (mEGLContext == null) {
- throw new RuntimeException("null context");
- }
-
- int[] surfaceAttribs = {
- EGL14.EGL_NONE
- };
- mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface,
- surfaceAttribs, 0);
- checkEglError("eglCreateWindowSurface");
- if (mEGLSurface == null) {
- throw new RuntimeException("surface was null");
- }
+ int[] attribList = {
+ EGL14.EGL_RED_SIZE,
+ 8,
+ EGL14.EGL_GREEN_SIZE,
+ 8,
+ EGL14.EGL_BLUE_SIZE,
+ 8,
+ EGL14.EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_RECORDABLE_ANDROID,
+ 1,
+ EGL14.EGL_NONE
+ };
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] numConfigs = new int[1];
+ if (!EGL14.eglChooseConfig(
+ mEGLDisplay, attribList, 0, configs, 0, configs.length, numConfigs, 0)) {
+ throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
}
- public void release() {
- if (EGL14.eglGetCurrentContext().equals(mEGLContext)) {
- EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
- }
- EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
- EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
- mSurface.release();
- mEGLDisplay = null;
- mEGLContext = null;
- mEGLSurface = null;
- mSurface = null;
+ int[] attrib_list = {EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE};
+
+ mEGLContext =
+ EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT, attrib_list, 0);
+ checkEglError("eglCreateContext");
+ if (mEGLContext == null) {
+ throw new RuntimeException("null context");
}
- public void makeCurrent() {
- if (!EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
- throw new RuntimeException("eglMakeCurrent failed");
- }
+ int[] surfaceAttribs = {EGL14.EGL_NONE};
+ mEGLSurface =
+ EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface, surfaceAttribs, 0);
+ checkEglError("eglCreateWindowSurface");
+ if (mEGLSurface == null) {
+ throw new RuntimeException("surface was null");
}
+ }
- public boolean swapBuffers() {
- return EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
+ public void release() {
+ if (EGL14.eglGetCurrentContext().equals(mEGLContext)) {
+ EGL14.eglMakeCurrent(
+ mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
}
+ EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
+ EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
+ mSurface.release();
+ mEGLDisplay = null;
+ mEGLContext = null;
+ mEGLSurface = null;
+ mSurface = null;
+ }
- public Surface getSurface() {
- return mSurface;
+ public void makeCurrent() {
+ if (!EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
+ throw new RuntimeException("eglMakeCurrent failed");
}
+ }
- public void setPresentationTime(long nsecs) {
- EGLExt.eglPresentationTimeANDROID(mEGLDisplay, mEGLSurface, nsecs);
- }
+ public boolean swapBuffers() {
+ return EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
+ }
- private void checkEglError(String msg) {
- boolean failed = false;
- while (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
- failed = true;
- }
- if (failed) {
- throw new RuntimeException("EGL error encountered (see log)");
- }
+ public Surface getSurface() {
+ return mSurface;
+ }
+
+ public void setPresentationTime(long nsecs) {
+ EGLExt.eglPresentationTimeANDROID(mEGLDisplay, mEGLSurface, nsecs);
+ }
+
+ private void checkEglError(String msg) {
+ boolean failed = false;
+ while (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
+ failed = true;
}
+ if (failed) {
+ throw new RuntimeException("EGL error encountered (see log)");
+ }
+ }
}
diff --git a/src/main/java/org/thoughtcrime/securesms/video/recode/MP4Builder.java b/src/main/java/org/thoughtcrime/securesms/video/recode/MP4Builder.java
index b5502928a..06f1989b8 100644
--- a/src/main/java/org/thoughtcrime/securesms/video/recode/MP4Builder.java
+++ b/src/main/java/org/thoughtcrime/securesms/video/recode/MP4Builder.java
@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.video.recode;
import android.annotation.TargetApi;
import android.media.MediaCodec;
import android.media.MediaFormat;
-
import com.coremedia.iso.BoxParser;
import com.coremedia.iso.IsoFile;
import com.coremedia.iso.IsoTypeWriter;
@@ -29,7 +28,6 @@ import com.coremedia.iso.boxes.TrackBox;
import com.coremedia.iso.boxes.TrackHeaderBox;
import com.googlecode.mp4parser.DataSource;
import com.googlecode.mp4parser.util.Matrix;
-
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -44,394 +42,396 @@ import java.util.List;
@TargetApi(16)
public class MP4Builder {
- private InterleaveChunkMdat mdat = null;
- private Mp4Movie currentMp4Movie = null;
- private FileOutputStream fos = null;
- private FileChannel fc = null;
+ private InterleaveChunkMdat mdat = null;
+ private Mp4Movie currentMp4Movie = null;
+ private FileOutputStream fos = null;
+ private FileChannel fc = null;
+ private long dataOffset = 0;
+ private long writedSinceLastMdat = 0;
+ private boolean writeNewMdat = true;
+ private final HashMap