Merge remote-tracking branch 'upstream/master' into lite

This commit is contained in:
adbenitez
2022-08-24 02:20:20 -04:00
57 changed files with 808 additions and 269 deletions
+1
View File
@@ -31,6 +31,7 @@ public class DcChat {
public native int getType ();
public native int getVisibility ();
public native String getName ();
public native String getMailinglistAddr();
public native String getProfileImage ();
public native int getColor ();
public native boolean isUnpromoted ();
+4
View File
@@ -52,6 +52,10 @@ public class DcMsg {
this.msgCPtr = msgCPtr;
}
public boolean isOk() {
return msgCPtr != 0;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
@@ -320,6 +320,7 @@ public class ConversationFragment extends MessageSelectorFragment
menu.findItem(R.id.menu_context_share).setVisible(false);
menu.findItem(R.id.menu_context_reply).setVisible(false);
menu.findItem(R.id.menu_context_reply_privately).setVisible(false);
menu.findItem(R.id.menu_add_to_home_screen).setVisible(false);
} else {
DcMsg messageRecord = messageRecords.iterator().next();
DcChat chat = getListAdapter().getChat();
@@ -329,17 +330,26 @@ public class ConversationFragment extends MessageSelectorFragment
menu.findItem(R.id.menu_context_reply).setVisible(chat.canSend() && canReply);
boolean showReplyPrivately = chat.isMultiUser() && !messageRecord.isOutgoing() && canReply;
menu.findItem(R.id.menu_context_reply_privately).setVisible(showReplyPrivately);
menu.findItem(R.id.menu_add_to_home_screen).setVisible(messageRecord.getType() == DcMsg.DC_MSG_WEBXDC);
}
// if one of the selected items cannot be saved, disable saving.
boolean canSave = true;
// if one of the selected items is not from self, disable resending.
boolean canResend = true;
for (DcMsg messageRecord : messageRecords) {
if (!messageRecord.hasFile()) {
if (canSave && !messageRecord.hasFile()) {
canSave = false;
}
if (canResend && !messageRecord.isOutgoing()) {
canResend = false;
}
if (!canSave && !canResend) {
break;
}
}
menu.findItem(R.id.menu_context_save_attachment).setVisible(canSave);
menu.findItem(R.id.menu_resend).setVisible(canResend);
}
static boolean canReplyToMsg(DcMsg dcMsg) {
@@ -918,6 +928,10 @@ public class ConversationFragment extends MessageSelectorFragment
handleForwardMessage(getListAdapter().getSelectedItems());
actionMode.finish();
return true;
case R.id.menu_add_to_home_screen:
WebxdcActivity.addToHomeScreen(getActivity(), getSelectedMessageRecord(getListAdapter().getSelectedItems()).getId());
actionMode.finish();
return true;
case R.id.menu_context_save_attachment:
handleSaveAttachment(getListAdapter().getSelectedItems());
return true;
@@ -1,6 +1,7 @@
package org.thoughtcrime.securesms;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
@@ -57,17 +58,17 @@ public class ConversationTitleView extends RelativeLayout {
}
public void setTitle(@NonNull GlideRequests glideRequests, @NonNull DcChat dcChat) {
setTitle(glideRequests, dcChat, true);
setTitle(glideRequests, dcChat, false);
}
public void setTitle(@NonNull GlideRequests glideRequests, @NonNull DcChat dcChat, boolean showAddInfo) {
public void setTitle(@NonNull GlideRequests glideRequests, @NonNull DcChat dcChat, boolean profileView) {
final int chatId = dcChat.getId();
final Context context = getContext();
final DcContext dcContext = DcHelper.getContext(context);
// set title and subtitle texts
title.setText(dcChat.getName());
String subtitleStr = "ErrSubtitle";
String subtitleStr = null;
// set icons etc.
int imgLeft = 0;
@@ -82,11 +83,19 @@ public class ConversationTitleView extends RelativeLayout {
int[] chatContacts = dcContext.getChatContacts(chatId);
if (dcChat.isMailingList()) {
subtitleStr = context.getString(R.string.mailing_list);
if (profileView) {
subtitleStr = dcChat.getMailinglistAddr();
} else {
subtitleStr = context.getString(R.string.mailing_list);
}
} else if (dcChat.isBroadcast()) {
subtitleStr = context.getResources().getQuantityString(R.plurals.n_recipients, chatContacts.length, chatContacts.length);
if (!profileView) {
subtitleStr = context.getResources().getQuantityString(R.plurals.n_recipients, chatContacts.length, chatContacts.length);
}
} else if( dcChat.isMultiUser() ) {
subtitleStr = context.getResources().getQuantityString(R.plurals.n_members, chatContacts.length, chatContacts.length);
if (!profileView) {
subtitleStr = context.getResources().getQuantityString(R.plurals.n_members, chatContacts.length, chatContacts.length);
}
} else if( chatContacts.length>=1 ) {
if( dcChat.isSelfTalk() ) {
subtitleStr = context.getString(R.string.chat_self_talk_subtitle);
@@ -107,10 +116,14 @@ public class ConversationTitleView extends RelativeLayout {
avatar.setAvatar(glideRequests, new Recipient(getContext(), dcChat), false);
title.setCompoundDrawablesWithIntrinsicBounds(imgLeft, 0, imgRight, 0);
subtitle.setVisibility(showAddInfo? View.VISIBLE : View.GONE);
if (!TextUtils.isEmpty(subtitleStr)) {
subtitle.setText(subtitleStr);
subtitle.setVisibility(View.VISIBLE);
} else {
subtitle.setVisibility(View.GONE);
}
boolean isEphemeral = dcContext.getChatEphemeralTimer(chatId) != 0;
ephemeralIcon.setVisibility((showAddInfo && isEphemeral)? View.VISIBLE : View.GONE);
ephemeralIcon.setVisibility(isEphemeral? View.VISIBLE : View.GONE);
}
public void setTitle(@NonNull GlideRequests glideRequests, @NonNull DcContact contact) {
@@ -259,7 +259,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
}
else if (chatId > 0) {
DcChat dcChat = dcContext.getChat(chatId);
titleView.setTitle(GlideApp.with(this), dcChat, isContactProfile());
titleView.setTitle(GlideApp.with(this), dcChat, true);
}
else if (isContactProfile()){
titleView.setTitle(GlideApp.with(this), dcContext.getContact(contactId));
@@ -362,7 +362,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
return getString(R.string.tab_gallery);
case TAB_DOCS:
return getString(R.string.tab_docs);
return getString(R.string.files);
case TAB_LINKS:
return getString(R.string.tab_links);
@@ -182,6 +182,9 @@ public class ProfileDocumentsFragment
menu.findItem(R.id.details).setVisible(singleSelection);
menu.findItem(R.id.show_in_chat).setVisible(singleSelection);
menu.findItem(R.id.share).setVisible(singleSelection);
boolean webxdcApp = singleSelection && messageRecords.iterator().next().getType() == DcMsg.DC_MSG_WEBXDC;
menu.findItem(R.id.menu_add_to_home_screen).setVisible(webxdcApp);
}
private ProfileDocumentsAdapter getListAdapter() {
@@ -225,6 +228,10 @@ public class ProfileDocumentsFragment
case R.id.share:
handleShare(getSelectedMessageRecord(getListAdapter().getSelectedMedia()));
return true;
case R.id.menu_add_to_home_screen:
WebxdcActivity.addToHomeScreen(getActivity(), getSelectedMessageRecord(getListAdapter().getSelectedMedia()).getId());
mode.finish();
return true;
case R.id.show_in_chat:
handleShowInChat(getSelectedMessageRecord(getListAdapter().getSelectedMedia()));
return true;
@@ -61,6 +61,7 @@ import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
import org.thoughtcrime.securesms.util.views.ProgressDialog;
import java.lang.ref.WeakReference;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
public class RegistrationActivity extends BaseActionBarActivity implements DcEventCenter.DcEventDelegate {
@@ -233,23 +234,19 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
int id = item.getItemId();
if (id == R.id.do_register) {
// "log in" button clicked - even if oauth2DeclinedByUser is true,
// we will ask for oauth2 to allow reverting the decision.
checkOauth2start().addListener(new ListenableFuture.Listener<Boolean>() {
@Override
public void onSuccess(Boolean oauth2started) {
if(!oauth2started) {
updateProviderInfo();
onLogin();
}
}
@Override
public void onFailure(ExecutionException e) {
updateProviderInfo();
onLogin();
}
});
String oldAddr = DcHelper.getSelfAddr(this);
String newAddr = emailInput.getText().toString();
if (!TextUtils.isEmpty(oldAddr)
&& !TextUtils.equals(oldAddr.toLowerCase(Locale.ROOT), newAddr.toLowerCase(Locale.ROOT))) {
// Tell the user about AEAP if they are about to change their address
new AlertDialog.Builder(this)
.setMessage(getString(R.string.aeap_explanation, oldAddr, newAddr))
.setNegativeButton(R.string.cancel, (d, w) -> {})
.setPositiveButton(R.string.perm_continue, (d, w) -> do_register())
.show();
} else {
do_register();
}
return true;
} else if (id == android.R.id.home) {
// handle close button click here
@@ -259,6 +256,26 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
return super.onOptionsItemSelected(item);
}
private void do_register() {
// "log in" button clicked - even if oauth2DeclinedByUser is true,
// we will ask for oauth2 to allow reverting the decision.
checkOauth2start().addListener(new ListenableFuture.Listener<Boolean>() {
@Override
public void onSuccess(Boolean oauth2started) {
if(!oauth2started) {
updateProviderInfo();
onLogin();
}
}
@Override
public void onFailure(ExecutionException e) {
updateProviderInfo();
onLogin();
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
@@ -1,7 +1,11 @@
package org.thoughtcrime.securesms;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -17,6 +21,10 @@ import android.webkit.WebView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.app.TaskStackBuilder;
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContext;
@@ -41,20 +49,43 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
private String baseURL;
private String sourceCodeUrl = "";
public static void openWebxdcActivity(Context context, DcMsg instance) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (Prefs.isDeveloperModeEnabled(context)) {
WebView.setWebContentsDebuggingEnabled(true);
}
Intent intent =new Intent(context, WebxdcActivity.class);
intent.putExtra("appMessageId", instance.getId());
context.startActivity(intent);
context.startActivity(getWebxdcIntent(context, instance.getId()));
} else {
Toast.makeText(context, "At least Android 5.0 (Lollipop) required for Webxdc.", Toast.LENGTH_LONG).show();
}
}
private static Intent getWebxdcIntent(Context context, int msgId) {
DcContext dcContext = DcHelper.getContext(context);
Intent intent = new Intent(context, WebxdcActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra("accountId", dcContext.getAccountId());
intent.putExtra("appMessageId", msgId);
return intent;
}
private static Intent[] getWebxdcIntentWithParentStack(Context context, int msgId) {
DcContext dcContext = DcHelper.getContext(context);
final Intent chatIntent = new Intent(context, ConversationActivity.class)
.putExtra(ConversationActivity.CHAT_ID_EXTRA, dcContext.getMsg(msgId).getChatId())
.setAction(Intent.ACTION_VIEW);
final Intent webxdcIntent = getWebxdcIntent(context, msgId);
return TaskStackBuilder.create(context)
.addNextIntentWithParentStack(chatIntent)
.addNextIntent(webxdcIntent)
.getIntents();
}
@Override
protected void onCreate(Bundle state, boolean ready) {
super.onCreate(state, ready);
@@ -65,7 +96,19 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
int appMessageId = b.getInt("appMessageId");
this.dcContext = DcHelper.getContext(getApplicationContext());
if (dcContext.getAccountId() != b.getInt("accountId")) {
Toast.makeText(this, "Switch to belonging account first.", Toast.LENGTH_LONG).show();
finish();
return;
}
this.dcAppMsg = this.dcContext.getMsg(appMessageId);
if (!this.dcAppMsg.isOk()) {
Toast.makeText(this, "Webxdc does no longer exist.", Toast.LENGTH_LONG).show();
finish();
return;
}
// `msg_id` in the subdomain makes sure, different apps using same files do not share the same cache entry
// (WebView may use a global cache shared across objects).
// (a random-id would also work, but would need maintenance and does not add benefits as we regard the file-part interceptRequest() only,
@@ -107,6 +150,9 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case R.id.menu_add_to_home_screen:
addToHomeScreen(this, dcAppMsg.getId());
return true;
case R.id.source_code:
openUrlInBrowser(this, sourceCodeUrl);
return true;
@@ -192,6 +238,36 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
});
}
public static void addToHomeScreen(Activity activity, int msgId) {
Context context = activity.getApplicationContext();
try {
DcContext dcContext = DcHelper.getContext(context);
DcMsg msg = dcContext.getMsg(msgId);
final JSONObject info = msg.getWebxdcInfo();
final String docName = JsonUtils.optString(info, "document");
final String xdcName = JsonUtils.optString(info, "name");
byte[] blob = msg.getWebxdcBlob(JsonUtils.optString(info, "icon"));
ByteArrayInputStream is = new ByteArrayInputStream(blob);
BitmapDrawable drawable = (BitmapDrawable) Drawable.createFromStream(is, "icon");
Bitmap bitmap = drawable.getBitmap();
ShortcutInfoCompat shortcutInfoCompat = new ShortcutInfoCompat.Builder(context, "xdc-" + dcContext.getAccountId() + "-" + msgId)
.setShortLabel(docName.isEmpty() ? xdcName : docName)
.setIcon(IconCompat.createWithAdaptiveBitmap(bitmap))
.setIntents(getWebxdcIntentWithParentStack(context, msgId))
.build();
if (ShortcutManagerCompat.requestPinShortcut(context, shortcutInfoCompat, null)) {
Toast.makeText(context, R.string.done, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "ErrAddToHomescreen: requestPinShortcut() failed", Toast.LENGTH_LONG).show();
}
} catch(Exception e) {
Toast.makeText(context, "ErrAddToHomescreen: " + e, Toast.LENGTH_LONG).show();
}
}
class InternalJSApi {
@JavascriptInterface
public String selfAddr() {
@@ -39,6 +39,7 @@ public class DcHelper {
private static final String TAG = DcHelper.class.getSimpleName();
public static final String CONFIG_ADDRESS = "addr";
public static final String CONFIG_CONFIGURED_ADDRESS = "configured_addr";
public static final String CONFIG_MAIL_SERVER = "mail_server";
public static final String CONFIG_MAIL_USER = "mail_user";
public static final String CONFIG_MAIL_PASSWORD = "mail_pw";
@@ -97,6 +98,10 @@ public class DcHelper {
return dcContext.isConfigured() == 1;
}
public static String getSelfAddr(Context context) {
DcContext dcContext = getContext(context);
return dcContext.getConfig(CONFIG_CONFIGURED_ADDRESS);
}
public static int getInt(Context context, String key) {
DcContext dcContext = getContext(context);
@@ -207,6 +212,8 @@ public class DcHelper {
// cmp. https://github.com/deltachat/deltachat-android/issues/2187
dcContext.setStockTranslation(120, context.getString(R.string.qrshow_join_group_hint).replace("\"", ""));
dcContext.setStockTranslation(121, context.getString(R.string.connectivity_not_connected));
dcContext.setStockTranslation(122, context.getString(R.string.aeap_addr_changed));
dcContext.setStockTranslation(123, context.getString(R.string.aeap_explanation));
}
public static File getImexDir() {
@@ -45,7 +45,11 @@ public abstract class ProgressDialogAsyncTask<Params, Progress, Result> extends
@Override
protected void onPostExecute(Result result) {
if (progress != null) progress.dismiss();
try {
if (progress != null) progress.dismiss();
} catch(Exception e) {
e.printStackTrace();
}
}
protected Context getContext() {
@@ -24,8 +24,9 @@ public class ConversationAdaptiveActionsToolbar extends Toolbar {
private static final int OVERFLOW_VIEW_WIDTH_DP = 36;
private static final int ID_NEVER_SHOW_AS_ACTION_1 = R.id.menu_context_reply_privately;
private static final int ID_NEVER_SHOW_AS_ACTION_2 = R.id.menu_context_save_attachment;
private static final int ID_NEVER_SHOW_AS_ACTION_3 = R.id.menu_resend;
private static final int ID_NEVER_SHOW_AS_ACTION_2 = R.id.menu_add_to_home_screen;
private static final int ID_NEVER_SHOW_AS_ACTION_3 = R.id.menu_context_save_attachment;
private static final int ID_NEVER_SHOW_AS_ACTION_4 = R.id.menu_resend;
private static final int ID_ALWAYS_SHOW_AS_ACTION = R.id.menu_context_forward;
private int maxShown;
@@ -81,7 +82,8 @@ public class ConversationAdaptiveActionsToolbar extends Toolbar {
boolean neverShowAsAction = item.getItemId() == ID_NEVER_SHOW_AS_ACTION_1
|| item.getItemId() == ID_NEVER_SHOW_AS_ACTION_2
|| item.getItemId() == ID_NEVER_SHOW_AS_ACTION_3;
|| item.getItemId() == ID_NEVER_SHOW_AS_ACTION_3
|| item.getItemId() == ID_NEVER_SHOW_AS_ACTION_4;
boolean alwaysShowAsAction = item.getItemId() == ID_ALWAYS_SHOW_AS_ACTION;
if (alwaysShowAsAction) continue;