diff --git a/jni/deltachat-core-rust b/jni/deltachat-core-rust index 1ba448fe1..ba2e573c2 160000 --- a/jni/deltachat-core-rust +++ b/jni/deltachat-core-rust @@ -1 +1 @@ -Subproject commit 1ba448fe199751e0854fccccde8c768229a5f44e +Subproject commit ba2e573c2358f7c29bf3ad3bb082dd74da167261 diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index eba9a14cf..702cdadbd 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -371,7 +371,7 @@ android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"> - diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java b/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java index c6c3578ae..1574c599f 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java @@ -117,7 +117,7 @@ import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener; import org.thoughtcrime.securesms.util.guava.Optional; import org.thoughtcrime.securesms.util.views.ProgressDialog; import org.thoughtcrime.securesms.video.recode.VideoRecoder; -import org.thoughtcrime.securesms.videochat.VideochatUtil; +import org.thoughtcrime.securesms.calls.CallUtil; import java.io.File; import java.util.ArrayList; @@ -543,7 +543,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity WebxdcActivity.openMaps(this, chatId); return true; } else if (itemId == R.id.menu_start_call) { - VideochatUtil.startCall(this, chatId); + CallUtil.startCall(this, chatId); return true; } else if (itemId == R.id.menu_all_media) { handleAllMedia(); diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java b/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java index c67484595..4c63ebc7b 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java @@ -65,7 +65,7 @@ import org.thoughtcrime.securesms.util.StickyHeaderDecoration; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.views.ConversationAdaptiveActionsToolbar; -import org.thoughtcrime.securesms.videochat.VideochatUtil; +import org.thoughtcrime.securesms.calls.CallUtil; import java.util.Collections; import java.util.LinkedList; diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationItem.java b/src/main/java/org/thoughtcrime/securesms/ConversationItem.java index bb9fc5e64..d388cc226 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationItem.java @@ -70,7 +70,7 @@ import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.views.Stub; -import org.thoughtcrime.securesms.videochat.VideochatUtil; +import org.thoughtcrime.securesms.calls.CallUtil; import java.util.List; import java.util.Set; @@ -412,7 +412,7 @@ public class ConversationItem extends BaseConversationItem String text = messageRecord.getText(); - if (messageRecord.getType()==DcMsg.DC_MSG_CALL || text.isEmpty()) { + if (messageRecord.getType() == DcMsg.DC_MSG_CALL || text.isEmpty()) { bodyText.setVisibility(View.GONE); } else { @@ -578,7 +578,7 @@ public class ConversationItem extends BaseConversationItem ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); footer.setVisibility(VISIBLE); } - else if (messageRecord.getType()==DcMsg.DC_MSG_CALL) { + else if (messageRecord.getType() == DcMsg.DC_MSG_CALL) { callViewStub.get().setVisibility(View.VISIBLE); if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); @@ -821,7 +821,7 @@ public class ConversationItem extends BaseConversationItem return stickerStub.get().getFooter(); } else if (hasOnlyThumbnail(messageRecord) && TextUtils.isEmpty(messageRecord.getText())) { return mediaThumbnailStub.get().getFooter(); - } else if (messageRecord.getType()==DcMsg.DC_MSG_CALL) { + } else if (messageRecord.getType() == DcMsg.DC_MSG_CALL) { return callViewStub.get().getFooter(); } else { return footer; @@ -996,9 +996,9 @@ public class ConversationItem extends BaseConversationItem int chatId = messageRecord.getChatId(); if (!messageRecord.isOutgoing() && callInfo.state instanceof CallState.Alerting) { int callId = messageRecord.getId(); - VideochatUtil.openCall(getContext(), accId, chatId, callId, callInfo.sdpOffer); + CallUtil.openCall(getContext(), accId, chatId, callId, callInfo.sdpOffer); } else { - VideochatUtil.startCall(getContext(), accId, chatId); + CallUtil.startCall(getContext(), accId, chatId); } } } diff --git a/src/main/java/org/thoughtcrime/securesms/videochat/VideochatActivity.java b/src/main/java/org/thoughtcrime/securesms/calls/CallActivity.java similarity index 95% rename from src/main/java/org/thoughtcrime/securesms/videochat/VideochatActivity.java rename to src/main/java/org/thoughtcrime/securesms/calls/CallActivity.java index 92735d09b..d20eb88a7 100644 --- a/src/main/java/org/thoughtcrime/securesms/videochat/VideochatActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/calls/CallActivity.java @@ -1,4 +1,4 @@ -package org.thoughtcrime.securesms.videochat; +package org.thoughtcrime.securesms.calls; import android.Manifest; import android.annotation.SuppressLint; @@ -36,8 +36,8 @@ import java.util.Objects; import chat.delta.rpc.Rpc; import chat.delta.rpc.RpcException; -public class VideochatActivity extends WebViewActivity implements DcEventCenter.DcEventDelegate { - private static final String TAG = VideochatActivity.class.getSimpleName(); +public class CallActivity extends WebViewActivity implements DcEventCenter.DcEventDelegate { + private static final String TAG = CallActivity.class.getSimpleName(); public static final String EXTRA_ACCOUNT_ID = "acc_id"; public static final String EXTRA_CHAT_ID = "chat_id"; @@ -190,7 +190,7 @@ public class VideochatActivity extends WebViewActivity implements DcEventCenter. @JavascriptInterface public String getAvatar() { - final Context context = VideochatActivity.this; + final Context context = CallActivity.this; final DcChat dcChat = dcContext.getChat(chatId); if (!TextUtils.isEmpty(dcChat.getProfileImage())) { return AvatarUtil.asDataUri(dcChat.getProfileImage()); diff --git a/src/main/java/org/thoughtcrime/securesms/videochat/VideochatUtil.java b/src/main/java/org/thoughtcrime/securesms/calls/CallUtil.java similarity index 68% rename from src/main/java/org/thoughtcrime/securesms/videochat/VideochatUtil.java rename to src/main/java/org/thoughtcrime/securesms/calls/CallUtil.java index 209e22896..f84e2385b 100644 --- a/src/main/java/org/thoughtcrime/securesms/videochat/VideochatUtil.java +++ b/src/main/java/org/thoughtcrime/securesms/calls/CallUtil.java @@ -1,4 +1,4 @@ -package org.thoughtcrime.securesms.videochat; +package org.thoughtcrime.securesms.calls; import android.Manifest; import android.app.Activity; @@ -15,8 +15,8 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -public class VideochatUtil { - private static final String TAG = VideochatUtil.class.getSimpleName(); +public class CallUtil { + private static final String TAG = CallUtil.class.getSimpleName(); public static void startCall(Activity activity, int chatId) { Permissions.with(activity) @@ -31,11 +31,11 @@ public class VideochatUtil { } public static void startCall(Context context, int accId, int chatId) { - Intent intent = new Intent(context, VideochatActivity.class); + Intent intent = new Intent(context, CallActivity.class); intent.setAction(Intent.ACTION_VIEW); - intent.putExtra(VideochatActivity.EXTRA_ACCOUNT_ID, accId); - intent.putExtra(VideochatActivity.EXTRA_CHAT_ID, chatId); - intent.putExtra(VideochatActivity.EXTRA_HASH, "#startCall"); + intent.putExtra(CallActivity.EXTRA_ACCOUNT_ID, accId); + intent.putExtra(CallActivity.EXTRA_CHAT_ID, chatId); + intent.putExtra(CallActivity.EXTRA_HASH, "#startCall"); context.startActivity(intent); } @@ -48,12 +48,12 @@ public class VideochatUtil { Log.e(TAG, "Error", e); } - Intent intent = new Intent(context, VideochatActivity.class); + Intent intent = new Intent(context, CallActivity.class); intent.setAction(Intent.ACTION_VIEW); - intent.putExtra(VideochatActivity.EXTRA_ACCOUNT_ID, accId); - intent.putExtra(VideochatActivity.EXTRA_CHAT_ID, chatId); - intent.putExtra(VideochatActivity.EXTRA_CALL_ID, callId); - intent.putExtra(VideochatActivity.EXTRA_HASH, hash); + intent.putExtra(CallActivity.EXTRA_ACCOUNT_ID, accId); + intent.putExtra(CallActivity.EXTRA_CHAT_ID, chatId); + intent.putExtra(CallActivity.EXTRA_CALL_ID, callId); + intent.putExtra(CallActivity.EXTRA_HASH, hash); context.startActivity(intent); } diff --git a/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java b/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java index 4d829b2bd..fe6dcdbad 100644 --- a/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java +++ b/src/main/java/org/thoughtcrime/securesms/components/CallItemView.java @@ -55,6 +55,12 @@ public class CallItemView extends FrameLayout { public void setCallItem(boolean isOutgoing, CallInfo callInfo) { this.callInfo = callInfo; + if (callInfo.state instanceof CallState.Completed) { + footer.setCallDuration(((CallState.Completed) callInfo.state).duration); + } else { + footer.setCallDuration(0); // reset + } + if (callInfo.state instanceof CallState.Missed) { title.setText(R.string.missed_call); } else if (callInfo.state instanceof CallState.Cancelled) { diff --git a/src/main/java/org/thoughtcrime/securesms/components/ConversationItemFooter.java b/src/main/java/org/thoughtcrime/securesms/components/ConversationItemFooter.java index f74c0ce6b..11b1b281f 100644 --- a/src/main/java/org/thoughtcrime/securesms/components/ConversationItemFooter.java +++ b/src/main/java/org/thoughtcrime/securesms/components/ConversationItemFooter.java @@ -26,6 +26,7 @@ public class ConversationItemFooter extends LinearLayout { private ImageView locationIndicatorView; private DeliveryStatusView deliveryStatusView; private Integer textColor = null; + private int callDuration = 0; public ConversationItemFooter(Context context) { super(context); @@ -59,6 +60,11 @@ public class ConversationItemFooter extends LinearLayout { } } + /* Call duration in seconds. Only >0 if this is a call message */ + public void setCallDuration(int duration) { + callDuration = duration; + } + public void setMessageRecord(@NonNull DcMsg messageRecord) { presentDate(messageRecord); boolean bookmark = messageRecord.getOriginalMsgId() != 0 || messageRecord.getSavedMsgId() != 0; @@ -86,18 +92,29 @@ public class ConversationItemFooter extends LinearLayout { deliveryStatusView.setTint(color); } - private void presentDate(@NonNull DcMsg messageRecord) { + private void presentDate(@NonNull DcMsg dcMsg) { dateView.forceLayout(); - dateView.setText(DateUtils.getExtendedRelativeTimeSpanString(getContext(), messageRecord.getTimestamp())); + Context context = getContext(); + String date = dcMsg.getType() == DcMsg.DC_MSG_CALL? + DateUtils.getFormattedCallTime(context, dcMsg.getTimestamp()) + : DateUtils.getExtendedRelativeTimeSpanString(context, dcMsg.getTimestamp()); + if (callDuration > 0) { + String duration = DateUtils.getFormattedCallDuration(context, callDuration); + dateView.setText(context.getString(R.string.call_date_and_duration, date, duration)); + } else { + dateView.setText(date); + } } private void presentDeliveryStatus(@NonNull DcMsg messageRecord) { // isDownloading is temporary and should be checked first. boolean isDownloading = messageRecord.getDownloadState() == DcMsg.DC_DOWNLOAD_IN_PROGRESS; + boolean isCall = messageRecord.getType() == DcMsg.DC_MSG_CALL; if (isDownloading) deliveryStatusView.setDownloading(); + else if (messageRecord.isPending()) deliveryStatusView.setPending(); else if (messageRecord.isFailed()) deliveryStatusView.setFailed(); - else if (!messageRecord.isOutgoing()) deliveryStatusView.setNone(); + else if (!messageRecord.isOutgoing() || isCall) deliveryStatusView.setNone(); else if (messageRecord.isRemoteRead()) deliveryStatusView.setRead(); else if (messageRecord.isDelivered()) deliveryStatusView.setSent(); else if (messageRecord.isPreparing()) deliveryStatusView.setPreparing(); diff --git a/src/main/java/org/thoughtcrime/securesms/notifications/NotificationCenter.java b/src/main/java/org/thoughtcrime/securesms/notifications/NotificationCenter.java index be7d0fa0f..4c96c1c2b 100644 --- a/src/main/java/org/thoughtcrime/securesms/notifications/NotificationCenter.java +++ b/src/main/java/org/thoughtcrime/securesms/notifications/NotificationCenter.java @@ -49,7 +49,7 @@ import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.Pair; import org.thoughtcrime.securesms.util.Prefs; import org.thoughtcrime.securesms.util.Util; -import org.thoughtcrime.securesms.videochat.VideochatActivity; +import org.thoughtcrime.securesms.calls.CallActivity; import java.io.UnsupportedEncodingException; import java.math.BigInteger; @@ -178,12 +178,12 @@ public class NotificationCenter { Log.e(TAG, "Error", e); } - Intent intent = new Intent(context, VideochatActivity.class); + Intent intent = new Intent(context, CallActivity.class); intent.setAction(autoAccept? Intent.ACTION_ANSWER : Intent.ACTION_VIEW); - intent.putExtra(VideochatActivity.EXTRA_ACCOUNT_ID, chatData.accountId); - intent.putExtra(VideochatActivity.EXTRA_CHAT_ID, chatData.chatId); - intent.putExtra(VideochatActivity.EXTRA_CALL_ID, callId); - intent.putExtra(VideochatActivity.EXTRA_HASH, hash); + intent.putExtra(CallActivity.EXTRA_ACCOUNT_ID, chatData.accountId); + intent.putExtra(CallActivity.EXTRA_CHAT_ID, chatData.chatId); + intent.putExtra(CallActivity.EXTRA_CALL_ID, callId); + intent.putExtra(CallActivity.EXTRA_HASH, hash); intent.setPackage(context.getPackageName()); return TaskStackBuilder.create(context) .addNextIntentWithParentStack(chatIntent) diff --git a/src/main/java/org/thoughtcrime/securesms/util/DateUtils.java b/src/main/java/org/thoughtcrime/securesms/util/DateUtils.java index 14c6cdf33..ed1345792 100644 --- a/src/main/java/org/thoughtcrime/securesms/util/DateUtils.java +++ b/src/main/java/org/thoughtcrime/securesms/util/DateUtils.java @@ -119,6 +119,19 @@ public class DateUtils extends android.text.format.DateUtils { TimeUnit.MILLISECONDS.toSeconds(millis-(TimeUnit.MILLISECONDS.toMinutes(millis)*60000))); } + public static String getFormattedCallDuration(Context c, int seconds) { + if (seconds < 60) { + return c.getResources().getQuantityString(R.plurals.n_seconds_ext, seconds, seconds); + } + + int mins = seconds / 60; + return c.getResources().getQuantityString(R.plurals.n_minutes_ext, mins, mins); + } + + public static String getFormattedCallTime(final Context c, final long timestamp) { + return getFormattedDateTime(timestamp, DateFormat.is24HourFormat(c)? "HH:mm" : "hh:mm a"); + } + public static String getFormattedTimespan(Context c, int timestamp) { int mins = timestamp / (1000 * 60); if (mins / 60 == 0) { diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index a83e8af2c..2f98f699d 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -118,11 +118,22 @@ Last seen %1$s Last seen: Unknown + + + %d second + %d seconds + + + + %d minute + %d minutes + %d min %d min + %d hour @@ -377,6 +388,7 @@ Declined Call Canceled Call Missed Call + %1$s, %2$s Video Chat