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

This commit is contained in:
adbenitez
2022-04-07 17:44:28 -04:00
62 changed files with 2186 additions and 559 deletions
+1 -1
View File
@@ -199,7 +199,7 @@ public class DcContext {
public native int sendTextMsg (int chat_id, String text);
public native int sendVideochatInvitation(int chat_id);
public native boolean sendWebxdcStatusUpdate(int msg_id, String payload, String descr);
public native String getWebxdcStatusUpdates(int msg_id, int status_update_id);
public native String getWebxdcStatusUpdates(int msg_id, int last_known_serial);
public native int addDeviceMsg (String label, DcMsg msg);
public native boolean wasDeviceMsgEverAdded(String label);
public DcLot checkQr (String qr) { return new DcLot(checkQrCPtr(qr)); }
@@ -325,6 +325,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
initializeDraft();
doReinitializeDraft = false;
}
attachmentManager.onResume();
}
@Override
@@ -16,6 +16,9 @@
*/
package org.thoughtcrime.securesms;
import static com.b44t.messenger.DcContact.DC_CONTACT_ID_SELF;
import static org.thoughtcrime.securesms.util.RelayUtil.setForwardingMessageIds;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
@@ -77,10 +80,6 @@ import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import static com.b44t.messenger.DcContact.DC_CONTACT_ID_SELF;
import static org.thoughtcrime.securesms.util.RelayUtil.REQUEST_RELAY;
import static org.thoughtcrime.securesms.util.RelayUtil.setForwardingMessageIds;
@SuppressLint("StaticFieldLeak")
public class ConversationFragment extends MessageSelectorFragment
{
@@ -433,10 +432,10 @@ public class ConversationFragment extends MessageSelectorFragment
}
private void handleForwardMessage(final Set<DcMsg> messageRecords) {
Intent composeIntent = new Intent(getActivity(), ConversationListActivity.class);
Intent composeIntent = new Intent();
int[] msgIds = DcMsg.msgSetToIds(messageRecords);
setForwardingMessageIds(composeIntent, msgIds);
startActivityForResult(composeIntent, REQUEST_RELAY);
ConversationListRelayingActivity.start(this, composeIntent);
getActivity().overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out);
}
@@ -670,7 +669,7 @@ public class ConversationFragment extends MessageSelectorFragment
int index = 0;
for(int pos = firstPos; pos <= lastPos; pos++) {
DcMsg message = ((ConversationAdapter) list.getAdapter()).getMsg(pos);
if (message.getFromId() != DC_CONTACT_ID_SELF && !message.isSeen()) {
if (message.getFromId() != DC_CONTACT_ID_SELF) {
ids[index] = message.getId();
index++;
}
@@ -779,7 +778,7 @@ public class ConversationFragment extends MessageSelectorFragment
else if(DozeReminder.isDozeReminderMsg(getContext(), messageRecord)) {
DozeReminder.dozeReminderTapped(getContext());
}
else if(messageRecord.isInfo() && messageRecord.getParent() != null) {
else if(messageRecord.isInfo() && messageRecord.getParent() != null && messageRecord.getParent().getType() == DcMsg.DC_MSG_WEBXDC) {
scrollMaybeSmoothToMsgId(messageRecord.getParent().getId());
}
else {
@@ -466,7 +466,7 @@ public class ConversationItem extends BaseConversationItem
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
webxdcViewStub.get().setWebxdc(messageRecord);
webxdcViewStub.get().setWebxdc(messageRecord, "Webxdc");
webxdcViewStub.get().setWebxdcClickListener(new ThumbnailClickListener());
webxdcViewStub.get().setOnLongClickListener(passthroughClickListener);
@@ -98,12 +98,8 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
// it is not needed to keep all past update messages, however, when deleted, also the strings should be deleted.
DcContext dcContext = DcHelper.getContext(this);
DcMsg msg = new DcMsg(dcContext, DcMsg.DC_MSG_TEXT);
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
msg.setText(getString(R.string.update_1_28_android));
dcContext.addDeviceMsg("update_1_28e_android", msg); // addDeviceMessage() makes sure, messages with the same id are not added twice
// create view
setContentView(R.layout.conversation_list_activity);
@@ -0,0 +1,37 @@
package org.thoughtcrime.securesms;
import static org.thoughtcrime.securesms.util.RelayUtil.REQUEST_RELAY;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import androidx.fragment.app.Fragment;
/**
* "Relaying" means "Forwarding or Sharing".
*
* When forwarding or sharing, we show the ConversationListActivity to the user.
* However, ConversationListActivity has `launchMode="singleTask"`, which means that this will
* destroy the existing ConversationListActivity.
*
* In API 20-29, `startActivityForResult()` could be used instead of `startActivity()`
* to override this behavior and get two instances of ConversationListActivity.
*
* As this is not possible anymore starting with API 30, we needed another solution, and created
* this activity here.
*
* See https://github.com/deltachat/deltachat-android/issues/1704.
*/
public class ConversationListRelayingActivity extends ConversationListActivity {
public static void start(Fragment fragment, Intent intent) {
intent.setComponent(new ComponentName(fragment.getContext(), ConversationListRelayingActivity.class));
fragment.startActivityForResult(intent, REQUEST_RELAY);
}
public static void start(Activity activity, Intent intent) {
intent.setComponent(new ComponentName(activity, ConversationListRelayingActivity.class));
activity.startActivityForResult(intent, REQUEST_RELAY);
}
}
@@ -10,7 +10,6 @@ import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
@@ -27,6 +26,8 @@ import androidx.annotation.NonNull;
import androidx.loader.app.LoaderManager;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.soundcloud.android.crop.Crop;
import org.thoughtcrime.securesms.components.AvatarSelector;
@@ -48,12 +49,12 @@ import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.SecureRandom;
@SuppressLint("StaticFieldLeak")
public class CreateProfileActivity extends BaseActionBarActivity implements EmojiKeyboardProvider.EmojiEventListener {
@@ -74,8 +75,10 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
private View reveal;
private boolean fromWelcome;
private boolean avatarChanged;
private boolean imageLoaded;
private byte[] avatarBytes;
private Bitmap avatarBmp;
private AttachmentManager attachmentManager;
@@ -94,6 +97,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
attachmentManager = new AttachmentManager(this, () -> {});
avatarChanged = false;
initializeResources();
initializeEmojiInput();
initializeProfileName();
@@ -170,49 +174,38 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
case Crop.REQUEST_CROP:
if (resultCode == Activity.RESULT_OK) {
new AsyncTask<Void, Void, byte[]>() {
@Override
protected byte[] doInBackground(Void... params) {
try {
try {
Uri imageUri = Crop.getOutput(data);
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
} catch (Exception any) {
Log.e(TAG, "could not send raw JPG to core. Using scaled JPG.", any);
}
BitmapUtil.ScaleResult result =
BitmapUtil.createScaledBytes(CreateProfileActivity.this, Crop.getOutput(data), new ProfileMediaConstraints());
return result.getBitmap();
} catch (BitmapDecodingException e) {
Log.w(TAG, e);
return null;
}
}
@Override
protected void onPostExecute(byte[] result) {
if (result != null) {
avatarBytes = result;
GlideApp.with(CreateProfileActivity.this)
.load(avatarBytes)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.circleCrop()
.into(avatar);
} else {
Toast.makeText(CreateProfileActivity.this, R.string.error, Toast.LENGTH_LONG).show();
}
}
}.execute();
setAvatarView(data);
}
break;
}
}
private void setAvatarView(Intent data) {
final Uri output = Crop.getOutput(data);
final ProfileMediaConstraints constraints = new ProfileMediaConstraints();
GlideApp.with(this)
.asBitmap()
.load(output)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.centerCrop()
.override(constraints.getImageMaxWidth(this), constraints.getImageMaxHeight(this))
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
avatarChanged = true;
imageLoaded = true;
avatarBmp = resource;
}
});
GlideApp.with(this)
.load(output)
.circleCrop()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(avatar);
}
private void onFileSelected(Uri inputFile) {
Uri outputFile = Uri.fromFile(new File(getCacheDir(), "cropped"));
if (inputFile == null) {
@@ -232,13 +225,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
this.reveal = ViewUtil.findById(this, R.id.reveal);
this.statusView = ViewUtil.findById(this, R.id.status_text);
this.avatar.setImageDrawable(new ResourceContactPhoto(R.drawable.ic_camera_alt_white_24dp).asDrawable(this, getResources().getColor(R.color.grey_400)));
this.avatar.setOnClickListener(view ->
new AvatarSelector(this, LoaderManager.getInstance(this), new AvatarSelectedListener(), avatarBytes != null)
.show(this, avatar)
);
passwordAccountSettings.setOnClickListener(view -> {
Intent intent = new Intent(this, RegistrationActivity.class);
startActivity(intent);
@@ -264,32 +250,21 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
}
private void initializeProfileAvatar() {
String address = DcHelper.get(this, DcHelper.CONFIG_ADDRESS);
if (AvatarHelper.getSelfAvatarFile(this).exists() && AvatarHelper.getSelfAvatarFile(this).length() > 0) {
new AsyncTask<Void, Void, byte[]>() {
@Override
protected byte[] doInBackground(Void... params) {
try {
return Util.readFully(new FileInputStream(AvatarHelper.getSelfAvatarFile(CreateProfileActivity.this)));
} catch (IOException e) {
Log.w(TAG, e);
return null;
}
}
@Override
protected void onPostExecute(byte[] result) {
if (result != null) {
avatarBytes = result;
GlideApp.with(CreateProfileActivity.this)
.load(result)
.circleCrop()
.into(avatar);
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
File avatarFile = AvatarHelper.getSelfAvatarFile(this);
if (avatarFile.exists() && avatarFile.length() > 0) {
imageLoaded = true;
GlideApp.with(this)
.load(avatarFile)
.circleCrop()
.into(avatar);
} else {
imageLoaded = false;
avatar.setImageDrawable(new ResourceContactPhoto(R.drawable.ic_camera_alt_white_24dp).asDrawable(this, getResources().getColor(R.color.grey_400)));
}
avatar.setOnClickListener(view ->
new AvatarSelector(this, LoaderManager.getInstance(this), new AvatarSelectedListener(), imageLoaded)
.show(this, avatar)
);
}
@@ -337,12 +312,14 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
DcHelper.set(context, DcHelper.CONFIG_DISPLAY_NAME, name);
setStatusText();
try {
AvatarHelper.setSelfAvatar(CreateProfileActivity.this, avatarBytes);
Prefs.setProfileAvatarId(CreateProfileActivity.this, new SecureRandom().nextInt());
} catch (IOException e) {
Log.w(TAG, e);
return false;
if (avatarChanged) {
try {
AvatarHelper.setSelfAvatar(CreateProfileActivity.this, avatarBmp);
Prefs.setProfileAvatarId(CreateProfileActivity.this, new SecureRandom().nextInt());
} catch (IOException e) {
Log.w(TAG, e);
return false;
}
}
return true;
@@ -378,7 +355,9 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
AttachmentManager.selectImage(CreateProfileActivity.this, REQUEST_CODE_AVATAR);
break;
case AvatarSelector.REMOVE_PHOTO:
avatarBytes = null;
avatarBmp = null;
imageLoaded = false;
avatarChanged = true;
avatar.setImageDrawable(new ResourceContactPhoto(R.drawable.ic_camera_alt_white_24dp).asDrawable(CreateProfileActivity.this, getResources().getColor(R.color.grey_400)));
break;
case AvatarSelector.TAKE_PHOTO:
@@ -17,7 +17,6 @@
package org.thoughtcrime.securesms;
import static org.thoughtcrime.securesms.util.RelayUtil.REQUEST_RELAY;
import static org.thoughtcrime.securesms.util.RelayUtil.setSharedText;
import android.Manifest;
@@ -263,11 +262,13 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
if (chatId != -1) {
composeIntent = getBaseShareIntent(ConversationActivity.class);
composeIntent.putExtra(EXTRA_CHAT_ID, chatId);
RelayUtil.setSharedUris(composeIntent, resolvedExtras);
startActivity(composeIntent);
} else {
composeIntent = getBaseShareIntent(ConversationListActivity.class);
composeIntent = getBaseShareIntent(ConversationListRelayingActivity.class);
RelayUtil.setSharedUris(composeIntent, resolvedExtras);
ConversationListRelayingActivity.start(this, composeIntent);
}
RelayUtil.setSharedUris(composeIntent, resolvedExtras);
startActivityForResult(composeIntent, REQUEST_RELAY);
// We use startActivityForResult() here so that the conversations list is correctly updated. (hide "Device messages", ...)a
// With startActivity() the list was not always updated before and after sharing and incorrectly showed or did not show the device talk.
finish();
@@ -70,13 +70,15 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
webSettings.setGeolocationEnabled(false);
webSettings.setAllowFileAccessFromFileURLs(false);
webSettings.setAllowUniversalAccessFromFileURLs(false);
webSettings.setDatabaseEnabled(true);
webSettings.setDomStorageEnabled(true);
webView.addJavascriptInterface(new InternalJSApi(), "InternalJSApi");
// `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,
// also a random-id is not that useful for debugging)
webView.loadUrl("webxdc://msg" + appMessageId + ".localhost/index.html");
webView.loadUrl("https://acc" + dcContext.getAccountId() + "-msg" + appMessageId + ".localhost/index.html");
Util.runOnAnyBackgroundThread(() -> {
JSONObject info = this.dcAppMsg.getWebxdcInfo();
@@ -147,7 +149,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
int eventId = event.getId();
if ((eventId == DcContext.DC_EVENT_WEBXDC_STATUS_UPDATE && event.getData1Int() == dcAppMsg.getId())) {
Log.i(TAG, "handleEvent");
webView.loadUrl("javascript:window.__webxdcUpdate(" + event.getData2Int() + ");");
webView.loadUrl("javascript:window.__webxdcUpdate();");
}
}
@@ -182,9 +184,9 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
}
@JavascriptInterface
public String getStatusUpdates(int statusUpdateId) {
public String getStatusUpdates(int lastKnownSerial) {
Log.i(TAG, "getStatusUpdates");
return WebxdcActivity.this.dcContext.getWebxdcStatusUpdates(WebxdcActivity.this.dcAppMsg.getId(), statusUpdateId);
return WebxdcActivity.this.dcContext.getWebxdcStatusUpdates(WebxdcActivity.this.dcAppMsg.getId(), lastKnownSerial );
}
}
}
@@ -55,7 +55,7 @@ public class WebxdcView extends FrameLayout {
this.viewListener = listener;
}
public void setWebxdc(final @NonNull DcMsg dcMsg)
public void setWebxdc(final @NonNull DcMsg dcMsg, String defaultSummary)
{
try {
JSONObject info = dcMsg.getWebxdcInfo();
@@ -76,7 +76,7 @@ public class WebxdcView extends FrameLayout {
// subtitle
String summary = info.optString("summary");
if (summary.isEmpty()) {
summary = Util.getPrettyFileSize(dcMsg.getFilebytes()) + " Webxdc";
summary = defaultSummary;
}
appSubtitle.setText(summary);
} catch (Exception e) {
@@ -7,7 +7,6 @@ import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatEditText;
import android.text.InputFilter;
import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.emoji.EmojiProvider.EmojiDrawable;
@@ -30,7 +29,6 @@ public class EmojiEditText extends AppCompatEditText {
if (!Prefs.isSystemEmojiPreferred(getContext())) {
setFilters(appendEmojiFilter(this.getFilters()));
}
setImeOptions(getImeOptions() | EditorInfo.IME_FLAG_NO_FULLSCREEN);
}
public void insertEmoji(String emoji) {
@@ -58,6 +58,7 @@ public class DcHelper {
public static final String CONFIG_SENTBOX_WATCH = "sentbox_watch";
public static final String CONFIG_MVBOX_WATCH = "mvbox_watch";
public static final String CONFIG_MVBOX_MOVE = "mvbox_move";
public static final String CONFIG_ONLY_FETCH_MVBOX = "only_fetch_mvbox";
public static final String CONFIG_BCC_SELF = "bcc_self";
public static final String CONFIG_SHOW_EMAILS = "show_emails";
public static final String CONFIG_MEDIA_QUALITY = "media_quality";
@@ -200,7 +201,11 @@ public class DcHelper {
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));
// HACK: svg does not handle entities correctly and shows `&quot;` as the text `quot;`.
// until that is fixed, we fix the most obvious errors (core uses encode_minimal, so this does not affect so many characters)
// cmp. https://github.com/deltachat/deltachat-android/issues/2187
dcContext.setStockTranslation(120, context.getString(R.string.qrshow_join_group_hint).replace("\"", ""));
}
public static File getImexDir() {
@@ -309,7 +309,7 @@ public class AttachmentManager {
} else if (slide.hasDocument()) {
if (slide.isWebxdcDocument()) {
DcMsg instance = msg != null ? msg : DcHelper.getContext(context).getMsg(slide.dcMsgId);
webxdcView.setWebxdc(instance);
webxdcView.setWebxdc(instance, context.getString(R.string.videochat_tap_to_open));
webxdcView.setWebxdcClickListener((v, s) -> {
WebxdcActivity.openWebxdcActivity(context, instance);
});
@@ -399,6 +399,18 @@ public class AttachmentManager {
return result;
}
// should be called when the attachement manager comes into view again.
// if the attachment manager contains a webxdc, its summary is updated.
public void onResume() {
if (slide.isPresent()) {
if (slide.get().isWebxdcDocument()) {
if (webxdcView != null) {
webxdcView.setWebxdc(DcHelper.getContext(context).getMsg(slide.get().dcMsgId), context.getString(R.string.videochat_tap_to_open));
}
}
}
}
public boolean isAttachmentPresent() {
return attachmentViewStub.resolved() && attachmentViewStub.get().getVisibility() == View.VISIBLE;
}
@@ -1,5 +1,13 @@
package org.thoughtcrime.securesms.preferences;
import static android.app.Activity.RESULT_OK;
import static android.text.InputType.TYPE_TEXT_VARIATION_URI;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_BCC_SELF;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_E2EE_ENABLED;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_MVBOX_MOVE;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_ONLY_FETCH_MVBOX;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SENTBOX_WATCH;
import android.Manifest;
import android.content.Context;
import android.content.DialogInterface;
@@ -32,13 +40,6 @@ import org.thoughtcrime.securesms.util.ScreenLockUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.views.ProgressDialog;
import static android.app.Activity.RESULT_OK;
import static android.text.InputType.TYPE_TEXT_VARIATION_URI;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_BCC_SELF;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_E2EE_ENABLED;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_MVBOX_MOVE;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SENTBOX_WATCH;
public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
implements DcEventCenter.DcEventDelegate
@@ -52,6 +53,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
CheckBoxPreference sentboxWatchCheckbox;
CheckBoxPreference bccSelfCheckbox;
CheckBoxPreference mvboxMoveCheckbox;
CheckBoxPreference onlyFetchMvboxCheckbox;
@Override
public void onCreate(Bundle paramBundle) {
@@ -82,10 +84,21 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
mvboxMoveCheckbox = (CheckBoxPreference) this.findPreference("pref_mvbox_move");
mvboxMoveCheckbox.setOnPreferenceChangeListener((preference, newValue) -> {
boolean enabled = (Boolean) newValue;
DcHelper.getAccounts(getContext()).stopIo();
dcContext.setConfigInt(CONFIG_MVBOX_MOVE, enabled? 1 : 0);
DcHelper.getAccounts(getContext()).startIo();
return true;
});
onlyFetchMvboxCheckbox = this.findPreference("pref_only_fetch_mvbox");
onlyFetchMvboxCheckbox.setOnPreferenceChangeListener(((preference, newValue) -> {
boolean enabled = (Boolean) newValue;
DcHelper.getAccounts(getContext()).stopIo();
dcContext.setConfigInt(CONFIG_ONLY_FETCH_MVBOX, enabled? 1 : 0);
DcHelper.getAccounts(getContext()).startIo();
return true;
}));
Preference manageKeys = this.findPreference("pref_manage_keys");
manageKeys.setOnPreferenceClickListener(new ManageKeysListener());
@@ -137,6 +150,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
sentboxWatchCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_SENTBOX_WATCH));
bccSelfCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_BCC_SELF));
mvboxMoveCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_MVBOX_MOVE));
onlyFetchMvboxCheckbox.setChecked(0!=dcContext.getConfigInt(CONFIG_ONLY_FETCH_MVBOX));
}
@Override
@@ -42,13 +42,13 @@ public class AvatarHelper {
return new File(dirString);
}
public static void setSelfAvatar(@NonNull Context context, @Nullable byte[] data) throws IOException {
if (data == null) {
public static void setSelfAvatar(@NonNull Context context, @Nullable Bitmap bitmap) throws IOException {
if (bitmap == null) {
DcHelper.set(context, DcHelper.CONFIG_SELF_AVATAR, null);
} else {
File avatar = File.createTempFile("selfavatar", ".jpg", context.getCacheDir());
FileOutputStream out = new FileOutputStream(avatar);
out.write(data);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.close();
DcHelper.set(context, DcHelper.CONFIG_SELF_AVATAR, avatar.getPath()); // The avatar is copied to the blobs directory here...
//noinspection ResultOfMethodCallIgnored
@@ -163,9 +163,7 @@ public class SearchFragment extends Fragment implements SearchListAdapter.EventL
if (conversationList != null) {
DcContext dcContext = DcHelper.getContext(getContext());
int chatId = message.getChatId();
int msgId = message.getId();
int startingPosition = DcMsg.getMessagePosition(message, dcContext);
int msgs[] = dcContext.getChatMsgs(chatId, 0, 0);
conversationList.openConversation(chatId, startingPosition);
}
}
@@ -82,6 +82,9 @@ public class MediaUtil {
if (type == null) {
final String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
if (type == null) {
type = "application/octet-stream";
}
}
return getCorrectedMimeType(type);
}