mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Merge remote-tracking branch 'upstream/master' into lite
This commit is contained in:
@@ -54,6 +54,7 @@ public class DcContact {
|
||||
public native String getProfileImage();
|
||||
public native int getColor ();
|
||||
public native String getStatus ();
|
||||
public native long getLastSeen ();
|
||||
public native boolean isBlocked ();
|
||||
public native boolean isVerified ();
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ public class DcContext {
|
||||
|
||||
public native void setStockTranslation (int stockId, String translation);
|
||||
public native String getBlobdir ();
|
||||
public native String getLastError ();
|
||||
public native void configure ();
|
||||
public native void stopOngoingProcess ();
|
||||
public native int isConfigured ();
|
||||
@@ -198,6 +199,7 @@ public class DcContext {
|
||||
public native boolean wasDeviceMsgEverAdded(String label);
|
||||
public DcLot checkQr (String qr) { return new DcLot(checkQrCPtr(qr)); }
|
||||
public native String getSecurejoinQr (int chat_id);
|
||||
public native String getSecurejoinQrSvg (int chat_id);
|
||||
public native int joinSecurejoin (String qr);
|
||||
public native void sendLocationsToChat (int chat_id, int seconds);
|
||||
public native boolean isSendingLocationsToChat(int chat_id);
|
||||
|
||||
@@ -1552,7 +1552,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
// in-chat search
|
||||
|
||||
private int beforeSearchComposeVisibility = View.VISIBLE;
|
||||
private int beforeSearchAttachVisibility = View.GONE;
|
||||
|
||||
private Menu searchMenu = null;
|
||||
private int[] searchResult = {};
|
||||
@@ -1578,16 +1577,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
beforeSearchComposeVisibility = composePanel.getVisibility();
|
||||
composePanel.setVisibility(View.GONE);
|
||||
|
||||
beforeSearchAttachVisibility = attachmentManager.getVisibility();
|
||||
attachmentManager.setVisibility(View.GONE);
|
||||
|
||||
ConversationActivity.this.makeSearchMenuVisible(menu, searchItem, true);
|
||||
}
|
||||
|
||||
private void searchCollapse(final Menu menu, final MenuItem searchItem) {
|
||||
searchMenu = null;
|
||||
composePanel.setVisibility(beforeSearchComposeVisibility);
|
||||
attachmentManager.setVisibility(beforeSearchAttachVisibility);
|
||||
|
||||
ConversationActivity.this.makeSearchMenuVisible(menu, searchItem, false);
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
noMessageTextView.setText(R.string.device_talk_explain);
|
||||
}
|
||||
else {
|
||||
String message = getString(R.string.chat_no_messages_hint, dcChat.getName(), dcChat.getName());
|
||||
String message = getString(R.string.chat_new_one_to_one_hint, dcChat.getName());
|
||||
noMessageTextView.setText(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +98,10 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
msg.setText(getString(R.string.update_1_24_android) + " https://delta.chat/en/blog");
|
||||
dcContext.addDeviceMsg("update_1_24n_android", msg); // addDeviceMessage() makes sure, messages with the same id are not added twice
|
||||
|
||||
msg = new DcMsg(dcContext, DcMsg.DC_MSG_TEXT);
|
||||
msg.setText(getString(R.string.update_1_26));
|
||||
dcContext.addDeviceMsg("update_1_26c_android", msg); // addDeviceMessage() makes sure, messages with the same id are not added twice
|
||||
|
||||
// create view
|
||||
setContentView(R.layout.conversation_list_activity);
|
||||
|
||||
|
||||
@@ -116,7 +116,6 @@ public class ConversationListFragment extends Fragment
|
||||
eventCenter.addObserver(DcContext.DC_EVENT_MSG_DELIVERED, this);
|
||||
eventCenter.addObserver(DcContext.DC_EVENT_MSG_FAILED, this);
|
||||
eventCenter.addObserver(DcContext.DC_EVENT_MSG_READ, this);
|
||||
eventCenter.addObserver(DcContext.DC_EVENT_MSG_READ, this);
|
||||
eventCenter.addObserver(DcContext.DC_EVENT_CONNECTIVITY_CHANGED, this);
|
||||
eventCenter.addObserver(DcContext.DC_EVENT_SELFAVATAR_CHANGED, this);
|
||||
}
|
||||
|
||||
@@ -135,19 +135,18 @@ public class ConversationListItem extends RelativeLayout
|
||||
this.glideRequests = glideRequests;
|
||||
|
||||
int state = dcSummary.getState();
|
||||
int unreadCount = ((state==DcMsg.DC_STATE_IN_FRESH || state==DcMsg.DC_STATE_IN_NOTICED) && !thread.isContactRequest())?
|
||||
thread.getUnreadCount() : 0;
|
||||
int unreadCount = thread.getUnreadCount();
|
||||
|
||||
if (highlightSubstring != null) {
|
||||
this.fromView.setText(getHighlightedSpan(locale, recipient.getName(), highlightSubstring));
|
||||
} else {
|
||||
this.fromView.setText(recipient, unreadCount == 0);
|
||||
this.fromView.setText(recipient, state!=DcMsg.DC_STATE_IN_FRESH);
|
||||
}
|
||||
|
||||
this.subjectView.setText(thread.getDisplayBody());
|
||||
this.subjectView.setTypeface(unreadCount == 0 ? LIGHT_TYPEFACE : BOLD_TYPEFACE);
|
||||
this.subjectView.setTextColor(unreadCount == 0 ? ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_subject_color)
|
||||
: ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_unread_color));
|
||||
this.subjectView.setTypeface(state==DcMsg.DC_STATE_IN_FRESH ? BOLD_TYPEFACE : LIGHT_TYPEFACE);
|
||||
this.subjectView.setTextColor(state==DcMsg.DC_STATE_IN_FRESH ? ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_unread_color)
|
||||
: ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_subject_color));
|
||||
|
||||
if (thread.getDate() > 0) {
|
||||
CharSequence date = DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, thread.getDate());
|
||||
@@ -264,46 +263,39 @@ public class ConversationListItem extends RelativeLayout
|
||||
{
|
||||
requestBadgeView.setVisibility(View.GONE);
|
||||
archivedBadgeView.setVisibility(View.GONE);
|
||||
if (state==DcMsg.DC_STATE_IN_FRESH || state==DcMsg.DC_STATE_IN_NOTICED)
|
||||
{
|
||||
deliveryStatusIndicator.setNone();
|
||||
if(unreadCount==0) {
|
||||
unreadIndicator.setVisibility(View.GONE);
|
||||
}
|
||||
else {
|
||||
unreadIndicator.setImageDrawable(TextDrawable.builder()
|
||||
.beginConfig()
|
||||
.width(ViewUtil.dpToPx(getContext(), 24))
|
||||
.height(ViewUtil.dpToPx(getContext(), 24))
|
||||
.textColor(Color.WHITE)
|
||||
.bold()
|
||||
.endConfig()
|
||||
.buildRound(String.valueOf(unreadCount), getResources().getColor(R.color.green_A700)));
|
||||
unreadIndicator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unreadIndicator.setVisibility(View.GONE);
|
||||
if (state == DcMsg.DC_STATE_OUT_ERROR) {
|
||||
deliveryStatusIndicator.setFailed();
|
||||
} else if (state == DcMsg.DC_STATE_OUT_MDN_RCVD) {
|
||||
deliveryStatusIndicator.setRead();
|
||||
} else if (state == DcMsg.DC_STATE_OUT_DELIVERED) {
|
||||
deliveryStatusIndicator.setSent();
|
||||
} else if (state == DcMsg.DC_STATE_OUT_PREPARING) {
|
||||
deliveryStatusIndicator.setPreparing();
|
||||
} else if (state == DcMsg.DC_STATE_OUT_PENDING) {
|
||||
deliveryStatusIndicator.setPending();
|
||||
} else {
|
||||
deliveryStatusIndicator.setNone();
|
||||
}
|
||||
|
||||
if (state == DcMsg.DC_STATE_OUT_ERROR) {
|
||||
deliveryStatusIndicator.setTint(Color.RED);
|
||||
} else {
|
||||
deliveryStatusIndicator.resetTint();
|
||||
}
|
||||
if(unreadCount==0) {
|
||||
unreadIndicator.setVisibility(View.GONE);
|
||||
} else {
|
||||
unreadIndicator.setImageDrawable(TextDrawable.builder()
|
||||
.beginConfig()
|
||||
.width(ViewUtil.dpToPx(getContext(), 24))
|
||||
.height(ViewUtil.dpToPx(getContext(), 24))
|
||||
.textColor(Color.WHITE)
|
||||
.bold()
|
||||
.endConfig()
|
||||
.buildRound(String.valueOf(unreadCount), getResources().getColor(R.color.unread_count)));
|
||||
unreadIndicator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (state == DcMsg.DC_STATE_OUT_ERROR) {
|
||||
deliveryStatusIndicator.setFailed();
|
||||
} else if (state == DcMsg.DC_STATE_OUT_MDN_RCVD) {
|
||||
deliveryStatusIndicator.setRead();
|
||||
} else if (state == DcMsg.DC_STATE_OUT_DELIVERED) {
|
||||
deliveryStatusIndicator.setSent();
|
||||
} else if (state == DcMsg.DC_STATE_OUT_PREPARING) {
|
||||
deliveryStatusIndicator.setPreparing();
|
||||
} else if (state == DcMsg.DC_STATE_OUT_PENDING) {
|
||||
deliveryStatusIndicator.setPending();
|
||||
} else {
|
||||
deliveryStatusIndicator.setNone();
|
||||
}
|
||||
|
||||
if (state == DcMsg.DC_STATE_OUT_ERROR) {
|
||||
deliveryStatusIndicator.setTint(Color.RED);
|
||||
} else {
|
||||
deliveryStatusIndicator.resetTint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,17 @@ public class ConversationTitleView extends RelativeLayout {
|
||||
title.setText(dcChat.getName());
|
||||
String subtitleStr = "ErrSubtitle";
|
||||
|
||||
// set icons etc.
|
||||
int imgLeft = 0;
|
||||
int imgRight = 0;
|
||||
|
||||
if (dcChat.isMuted()) {
|
||||
imgLeft = R.drawable.ic_volume_off_white_18dp;
|
||||
}
|
||||
if (dcChat.isProtected()) {
|
||||
imgRight = R.drawable.ic_verified;
|
||||
}
|
||||
|
||||
int[] chatContacts = dcContext.getChatContacts(chatId);
|
||||
if (dcChat.isMailingList()) {
|
||||
subtitleStr = context.getString(R.string.mailing_list);
|
||||
@@ -84,23 +95,16 @@ public class ConversationTitleView extends RelativeLayout {
|
||||
subtitleStr = context.getString(R.string.device_talk_subtitle);
|
||||
}
|
||||
else {
|
||||
subtitleStr = dcContext.getContact(chatContacts[0]).getAddr();
|
||||
DcContact dcContact = dcContext.getContact(chatContacts[0]);
|
||||
subtitleStr = dcContact.getAddr();
|
||||
if (dcContact.isVerified()) {
|
||||
imgRight = R.drawable.ic_verified;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subtitle.setText(subtitleStr);
|
||||
|
||||
// set icons etc.
|
||||
int imgLeft = 0;
|
||||
int imgRight = 0;
|
||||
|
||||
if (dcChat.isMuted()) {
|
||||
imgLeft = R.drawable.ic_volume_off_white_18dp;
|
||||
}
|
||||
if (dcChat.isProtected()) {
|
||||
imgRight = R.drawable.ic_verified;
|
||||
}
|
||||
|
||||
avatar.setAvatar(glideRequests, new Recipient(getContext(), dcChat), false);
|
||||
title.setCompoundDrawablesWithIntrinsicBounds(imgLeft, 0, imgRight, 0);
|
||||
subtitle.setVisibility(showAddInfo? View.VISIBLE : View.GONE);
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.b44t.messenger.DcLot;
|
||||
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.StickyHeaderDecoration.StickyHeaderAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -235,11 +236,12 @@ public class ProfileSettingsAdapter extends RecyclerView.Adapter
|
||||
txt = context.getString(R.string.profile_shared_chats);
|
||||
break;
|
||||
case ItemData.TYPE_PRIMARY_SETTING:
|
||||
if(itemDataContact!=null && itemDataContact.isVerified()) {
|
||||
txt = context.getString(R.string.verified_contact);
|
||||
long lastSeen = (itemDataContact!=null? itemDataContact.getLastSeen() : 0);
|
||||
if (lastSeen == 0) {
|
||||
txt = context.getString(R.string.last_seen_unknown);
|
||||
}
|
||||
else {
|
||||
txt = context.getString(R.string.contact);
|
||||
txt = context.getString(R.string.last_seen_at, DateUtils.getExtendedTimeSpanString(context, locale, lastSeen));
|
||||
}
|
||||
break;
|
||||
case ItemData.TYPE_STATUS:
|
||||
|
||||
@@ -56,6 +56,7 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
|
||||
private boolean manualConfigure = true; // false: configure by QR account creation
|
||||
private ProgressDialog progressDialog = null;
|
||||
private boolean imexUserAborted;
|
||||
DcContext dcContext;
|
||||
private NotificationController notificationController;
|
||||
|
||||
@@ -164,11 +165,13 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
progressDialog = null;
|
||||
}
|
||||
|
||||
imexUserAborted = false;
|
||||
progressDialog = new ProgressDialog(this);
|
||||
progressDialog.setMessage(getResources().getString(R.string.one_moment));
|
||||
progressDialog.setCanceledOnTouchOutside(false);
|
||||
progressDialog.setCancelable(false);
|
||||
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getResources().getString(android.R.string.cancel), (dialog, which) -> {
|
||||
imexUserAborted = true;
|
||||
dcContext.stopOngoingProcess();
|
||||
notificationController.close();
|
||||
cleanupTempBackupFile();
|
||||
@@ -222,9 +225,7 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
DcHelper.getEventCenter(this).captureNextError();
|
||||
|
||||
if (!dcContext.setConfigFromQr(qrCode)) {
|
||||
Util.sleep(100); // hack to avoid a race condition, see https://github.com/deltachat/deltachat-core-rust/issues/2787 for more details and possible fix
|
||||
String err = DcHelper.getEventCenter(this).getCapturedError();
|
||||
progressError(TextUtils.isEmpty(err) ? "Cannot create account from QR code." : err);
|
||||
progressError(dcContext.getLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -281,7 +282,9 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
if (eventId== DcContext.DC_EVENT_IMEX_PROGRESS ) {
|
||||
long progress = event.getData1Int();
|
||||
if (progress==0/*error/aborted*/) {
|
||||
progressError(DcHelper.getEventCenter(this).getCapturedError());
|
||||
if (!imexUserAborted) {
|
||||
progressError(dcContext.getLastError());
|
||||
}
|
||||
notificationController.close();
|
||||
cleanupTempBackupFile();
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class AccountSelectionListItem extends LinearLayout {
|
||||
.textColor(Color.WHITE)
|
||||
.bold()
|
||||
.endConfig()
|
||||
.buildRound(String.valueOf(unreadCount), getResources().getColor(R.color.green_A700)));
|
||||
.buildRound(String.valueOf(unreadCount), getResources().getColor(R.color.unread_count)));
|
||||
unreadIndicator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,25 +95,11 @@ public class DcEventCenter {
|
||||
}
|
||||
|
||||
private final Object lastErrorLock = new Object();
|
||||
private String lastErrorString = "";
|
||||
private boolean showNextErrorAsToast = true;
|
||||
|
||||
public void captureNextError() {
|
||||
synchronized (lastErrorLock) {
|
||||
showNextErrorAsToast = false;
|
||||
lastErrorString = "";
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasCapturedError() {
|
||||
synchronized (lastErrorLock) {
|
||||
return !lastErrorString.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public String getCapturedError() {
|
||||
synchronized (lastErrorLock) {
|
||||
return lastErrorString;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +114,6 @@ public class DcEventCenter {
|
||||
boolean showAsToast;
|
||||
Log.e("DeltaChat", string);
|
||||
synchronized (lastErrorLock) {
|
||||
lastErrorString = string;
|
||||
showAsToast = showNextErrorAsToast;
|
||||
showNextErrorAsToast = true;
|
||||
}
|
||||
|
||||
@@ -18,14 +18,12 @@ import androidx.core.content.FileProvider;
|
||||
|
||||
import com.b44t.messenger.DcAccounts;
|
||||
import com.b44t.messenger.DcChat;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcLot;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.ConversationActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationCenter;
|
||||
@@ -133,7 +131,6 @@ public class DcHelper {
|
||||
dcContext.setStockTranslation(11, context.getString(R.string.audio));
|
||||
dcContext.setStockTranslation(12, context.getString(R.string.file));
|
||||
dcContext.setStockTranslation(13, context.getString(R.string.pref_default_status_text));
|
||||
dcContext.setStockTranslation(14, context.getString(R.string.group_hello_draft));
|
||||
dcContext.setStockTranslation(15, context.getString(R.string.systemmsg_group_name_changed));
|
||||
dcContext.setStockTranslation(16, context.getString(R.string.systemmsg_group_image_changed));
|
||||
dcContext.setStockTranslation(17, context.getString(R.string.systemmsg_member_added));
|
||||
@@ -202,6 +199,8 @@ public class DcHelper {
|
||||
dcContext.setStockTranslation(116, context.getString(R.string.part_of_total_used));
|
||||
dcContext.setStockTranslation(117, context.getString(R.string.secure_join_started));
|
||||
dcContext.setStockTranslation(118, context.getString(R.string.secure_join_replies));
|
||||
dcContext.setStockTranslation(119, context.getString(R.string.qrshow_join_contact_hint));
|
||||
dcContext.setStockTranslation(120, context.getString(R.string.qrshow_join_group_hint));
|
||||
}
|
||||
|
||||
public static File getImexDir() {
|
||||
|
||||
@@ -32,6 +32,8 @@ public class GeneratedContactPhoto implements FallbackContactPhoto {
|
||||
.width(targetSize)
|
||||
.height(targetSize)
|
||||
.textColor(Color.WHITE)
|
||||
.bold()
|
||||
.toUpperCase()
|
||||
.endConfig()
|
||||
.buildRound(getCharacter(name), color);
|
||||
}
|
||||
|
||||
@@ -101,8 +101,10 @@ public abstract class ListSummaryPreferenceFragment extends CorrectedPreferenceF
|
||||
protected ProgressDialog progressDialog = null;
|
||||
protected int progressWhat = 0;
|
||||
protected String imexDir = "";
|
||||
protected boolean imexUserAborted = false;
|
||||
protected void startImex(int what)
|
||||
{
|
||||
imexUserAborted = false;
|
||||
notificationController = GenericForegroundService.startForegroundTask(getContext(), getString(R.string.export_backup_desktop));
|
||||
if( progressDialog!=null ) {
|
||||
progressDialog.dismiss();
|
||||
@@ -114,6 +116,7 @@ public abstract class ListSummaryPreferenceFragment extends CorrectedPreferenceF
|
||||
progressDialog.setCanceledOnTouchOutside(false);
|
||||
progressDialog.setCancelable(false);
|
||||
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getActivity().getString(android.R.string.cancel), (dialog, which) -> {
|
||||
imexUserAborted = true;
|
||||
dcContext.stopOngoingProcess();
|
||||
notificationController.close();
|
||||
notificationController = null;
|
||||
@@ -136,9 +139,9 @@ public abstract class ListSummaryPreferenceFragment extends CorrectedPreferenceF
|
||||
DcHelper.getAccounts(context).startIo();
|
||||
progressDialog.dismiss();
|
||||
progressDialog = null;
|
||||
if (DcHelper.getEventCenter(context).hasCapturedError()) {
|
||||
if (!imexUserAborted) {
|
||||
new AlertDialog.Builder(context)
|
||||
.setMessage(DcHelper.getEventCenter(context).getCapturedError())
|
||||
.setMessage(dcContext.getLastError())
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@@ -205,16 +205,15 @@ public class QrCodeHandler {
|
||||
builder.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
|
||||
DcHelper.getEventCenter(activity).captureNextError();
|
||||
int newChatId = dcContext.joinSecurejoin(qrRawString);
|
||||
String errorString = DcHelper.getEventCenter(activity).getCapturedError();
|
||||
DcHelper.getEventCenter(activity).endCaptureNextError();
|
||||
|
||||
if (newChatId != 0) {
|
||||
Intent intent = new Intent(activity, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.CHAT_ID_EXTRA, newChatId);
|
||||
activity.startActivity(intent);
|
||||
} else if (!errorString.isEmpty()) {
|
||||
} else {
|
||||
AlertDialog.Builder builder1 = new AlertDialog.Builder(activity);
|
||||
builder1.setMessage(errorString);
|
||||
builder1.setMessage(dcContext.getLastError());
|
||||
builder1.setPositiveButton(android.R.string.ok, null);
|
||||
builder1.create().show();
|
||||
}
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
package org.thoughtcrime.securesms.qr;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -26,10 +18,10 @@ import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEvent;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
|
||||
import com.caverock.androidsvg.SVGImageView;
|
||||
import com.caverock.androidsvg.SVG;
|
||||
import com.caverock.androidsvg.SVGParseException;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
@@ -57,16 +49,6 @@ public class QrShowFragment extends Fragment implements DcEventCenter.DcEventDel
|
||||
|
||||
private DcContext dcContext;
|
||||
|
||||
private String hint;
|
||||
|
||||
private String errorHint;
|
||||
|
||||
private TextView hintBelowQr;
|
||||
|
||||
private BroadcastReceiver broadcastReceiver;
|
||||
|
||||
private Bitmap bitmap;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
@@ -86,43 +68,22 @@ public class QrShowFragment extends Fragment implements DcEventCenter.DcEventDel
|
||||
chatId = extras.getInt(CHAT_ID);
|
||||
}
|
||||
|
||||
errorHint = getString(R.string.qrshow_join_contact_no_connection_hint);
|
||||
|
||||
if (chatId != 0) {
|
||||
// verified-group
|
||||
String groupName = dcContext.getChat(chatId).getName();
|
||||
hint = String.format(this.getString(R.string.qrshow_join_group_hint), groupName);
|
||||
} else {
|
||||
// verify-contact
|
||||
String selfName = DcHelper.get(getActivity(), DcHelper.CONFIG_DISPLAY_NAME); // we cannot use MrContact.getDisplayName() as this would result in "Me" instead of
|
||||
String nameAndAddress;
|
||||
if (selfName.isEmpty()) {
|
||||
selfName = DcHelper.get(getActivity(), DcHelper.CONFIG_ADDRESS, "unknown");
|
||||
nameAndAddress = selfName;
|
||||
} else {
|
||||
nameAndAddress = String.format("%s (%s)", selfName, DcHelper.get(getActivity(), DcHelper.CONFIG_ADDRESS));
|
||||
}
|
||||
hint = String.format(this.getString(R.string.qrshow_join_contact_hint), nameAndAddress);
|
||||
}
|
||||
hintBelowQr = view.findViewById(R.id.qrShowHint);
|
||||
setHintText();
|
||||
|
||||
dcEventCenter.addObserver(DcContext.DC_EVENT_SECUREJOIN_INVITER_PROGRESS, this);
|
||||
broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
setHintText();
|
||||
}
|
||||
};
|
||||
getActivity().registerReceiver(broadcastReceiver, new IntentFilter(android.net.ConnectivityManager.CONNECTIVITY_ACTION));
|
||||
|
||||
numJoiners = 0;
|
||||
|
||||
ImageView imageView = view.findViewById(R.id.qrImage);
|
||||
SVGImageView imageView = view.findViewById(R.id.qrImage);
|
||||
try {
|
||||
bitmap = encodeAsBitmap(dcContext.getSecurejoinQr(chatId));
|
||||
imageView.setImageBitmap(bitmap);
|
||||
} catch (WriterException e) {
|
||||
String svg_txt = dcContext.getSecurejoinQrSvg(chatId);
|
||||
|
||||
// HACK: move avatar-letter down, baseline alignment not working,
|
||||
// see https://github.com/deltachat/deltachat-core-rust/pull/2815#issuecomment-978067378 ,
|
||||
// suggestions welcome :)
|
||||
svg_txt = svg_txt.replace("y=\"281.136\"", "y=\"290\"");
|
||||
|
||||
SVG svg = SVG.getFromString(svg_txt);
|
||||
imageView.setSVG(svg);
|
||||
} catch (SVGParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -135,6 +96,11 @@ public class QrShowFragment extends Fragment implements DcEventCenter.DcEventDel
|
||||
file.createNewFile();
|
||||
file.setReadable(true, false);
|
||||
FileOutputStream stream = new FileOutputStream(file);
|
||||
Bitmap bitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
canvas.drawRGB(255, 255, 255); // Clear background to white
|
||||
SVG svg = SVG.getFromString(dcContext.getSecurejoinQrSvg(chatId));
|
||||
svg.renderToCanvas(canvas);
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
|
||||
stream.flush();
|
||||
stream.close();
|
||||
@@ -142,7 +108,6 @@ public class QrShowFragment extends Fragment implements DcEventCenter.DcEventDel
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("image/png");
|
||||
intent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, hint);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.chat_share_with_title)));
|
||||
} catch (Exception e) {
|
||||
@@ -155,14 +120,6 @@ public class QrShowFragment extends Fragment implements DcEventCenter.DcEventDel
|
||||
Toast.makeText(getActivity(), getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private void setHintText() {
|
||||
if (!DcHelper.isNetworkConnected(getContext())) {
|
||||
hintBelowQr.setText(errorHint);
|
||||
} else {
|
||||
hintBelowQr.setText(hint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
@@ -175,47 +132,6 @@ public class QrShowFragment extends Fragment implements DcEventCenter.DcEventDel
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
dcEventCenter.removeObservers(this);
|
||||
getActivity().unregisterReceiver(broadcastReceiver);
|
||||
}
|
||||
|
||||
private Bitmap encodeAsBitmap(String str) throws WriterException {
|
||||
BitMatrix result;
|
||||
try {
|
||||
result = new MultiFormatWriter().encode(str,
|
||||
BarcodeFormat.QR_CODE, WIDTH, HEIGHT, null);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// Unsupported format
|
||||
return null;
|
||||
}
|
||||
|
||||
int w = result.getWidth();
|
||||
int h = result.getHeight();
|
||||
int[] pixels = new int[w * h];
|
||||
for (int y = 0; y < h; y++) {
|
||||
int offset = y * w;
|
||||
for (int x = 0; x < w; x++) {
|
||||
pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
||||
bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
|
||||
|
||||
Bitmap overlay = BitmapFactory.decodeResource(this.getResources(), R.drawable.qr_overlay);
|
||||
putOverlay(bitmap, overlay);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private void putOverlay(Bitmap bitmap, Bitmap overlay) {
|
||||
int bw = bitmap.getWidth();
|
||||
int bh = bitmap.getHeight();
|
||||
int ow = bw / 6;
|
||||
int oh = bh / 6;
|
||||
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
|
||||
canvas.drawBitmap(overlay, null, new Rect(bw / 2 - ow / 2, bh / 2 - oh / 2, bw / 2 + ow / 2, bh / 2 + oh / 2), paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -77,6 +77,19 @@ public class DateUtils extends android.text.format.DateUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getExtendedTimeSpanString(final Context c, final Locale locale, final long timestamp) {
|
||||
StringBuilder format = new StringBuilder();
|
||||
if (DateUtils.isToday(timestamp)) {}
|
||||
else if (isWithin(timestamp, 6, TimeUnit.DAYS)) format.append("EEE ");
|
||||
else if (isWithin(timestamp, 365, TimeUnit.DAYS)) format.append("MMM d, ");
|
||||
else format.append("MMM d, yyyy, ");
|
||||
|
||||
if (DateFormat.is24HourFormat(c)) format.append("HH:mm");
|
||||
else format.append("hh:mm a");
|
||||
|
||||
return getFormattedDateTime(timestamp, format.toString(), locale);
|
||||
}
|
||||
|
||||
public static String getExtendedRelativeTimeSpanString(final Context c, final Locale locale, final long timestamp) {
|
||||
if (isWithin(timestamp, 1, TimeUnit.MINUTES)) {
|
||||
return c.getString(R.string.now);
|
||||
@@ -84,16 +97,7 @@ public class DateUtils extends android.text.format.DateUtils {
|
||||
int mins = (int)TimeUnit.MINUTES.convert(System.currentTimeMillis() - timestamp, TimeUnit.MILLISECONDS);
|
||||
return c.getResources().getQuantityString(R.plurals.n_minutes, mins, mins);
|
||||
} else {
|
||||
StringBuilder format = new StringBuilder();
|
||||
if (DateUtils.isToday(timestamp)) {}
|
||||
else if (isWithin(timestamp, 6, TimeUnit.DAYS)) format.append("EEE ");
|
||||
else if (isWithin(timestamp, 365, TimeUnit.DAYS)) format.append("MMM d, ");
|
||||
else format.append("MMM d, yyyy, ");
|
||||
|
||||
if (DateFormat.is24HourFormat(c)) format.append("HH:mm");
|
||||
else format.append("hh:mm a");
|
||||
|
||||
return getFormattedDateTime(timestamp, format.toString(), locale);
|
||||
return getExtendedTimeSpanString(c, locale, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user