diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 0f47f6936..e8016fc01 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -52,6 +52,8 @@ import android.widget.PopupMenu; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; +import com.google.common.base.Optional; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -117,6 +119,7 @@ import eu.siacs.conversations.utils.TimeframeUtils; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.chatstate.ChatState; +import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection; import eu.siacs.conversations.xmpp.jingle.JingleFileTransferConnection; import eu.siacs.conversations.xmpp.jingle.RtpCapability; import rocks.xmpp.addr.Jid; @@ -956,6 +959,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke final MenuItem menuMute = menu.findItem(R.id.action_mute); final MenuItem menuUnmute = menu.findItem(R.id.action_unmute); final MenuItem menuCall = menu.findItem(R.id.action_call); + final MenuItem menuOngoingCall = menu.findItem(R.id.action_ongoing_call); final MenuItem menuVideoCall = menu.findItem(R.id.action_video_call); @@ -965,10 +969,18 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke menuInviteContact.setVisible(conversation.getMucOptions().canInvite()); menuMucDetails.setTitle(conversation.getMucOptions().isPrivateAndNonAnonymous() ? R.string.action_muc_details : R.string.channel_details); menuCall.setVisible(false); + menuOngoingCall.setVisible(false); } else { - final RtpCapability.Capability rtpCapability = RtpCapability.check(conversation.getContact()); - menuCall.setVisible(rtpCapability != RtpCapability.Capability.NONE); - menuVideoCall.setVisible(rtpCapability == RtpCapability.Capability.VIDEO); + final Optional ongoingRtpSession = activity.xmppConnectionService.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact()); + if (ongoingRtpSession.isPresent()) { + menuOngoingCall.setVisible(true); + menuCall.setVisible(false); + } else { + menuOngoingCall.setVisible(false); + final RtpCapability.Capability rtpCapability = RtpCapability.check(conversation.getContact()); + menuCall.setVisible(rtpCapability != RtpCapability.Capability.NONE); + menuVideoCall.setVisible(rtpCapability == RtpCapability.Capability.VIDEO); + } menuContactDetails.setVisible(!this.conversation.withSelf()); menuMucDetails.setVisible(false); final XmppConnectionService service = activity.xmppConnectionService; @@ -1245,12 +1257,28 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke case R.id.action_video_call: checkPermissionAndTriggerVideoCall(); break; + case R.id.action_ongoing_call: + returnToOngoingCall(); + break; default: break; } return super.onOptionsItemSelected(item); } + private void returnToOngoingCall() { + final Optional ongoingRtpSession = activity.xmppConnectionService.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact()); + if (ongoingRtpSession.isPresent()) { + final AbstractJingleConnection.Id id = ongoingRtpSession.get(); + final Intent intent = new Intent(getActivity(), RtpSessionActivity.class); + intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().asBareJid().toEscapedString()); + intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toEscapedString()); + intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId); + startActivity(intent); + } + + } + private void checkPermissionAndTriggerAudioCall() { if (activity.mUseTor || conversation.getAccount().isOnion()) { Toast.makeText(activity, R.string.disable_tor_to_make_call, Toast.LENGTH_SHORT).show(); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 3ea451653..dacfc8df0 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -9,11 +9,14 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.google.common.base.Optional; + import java.util.List; import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.ConversationListRowBinding; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Conversational; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.ConversationFragment; import eu.siacs.conversations.ui.XmppActivity; @@ -22,6 +25,7 @@ import eu.siacs.conversations.ui.util.StyledAttributes; import eu.siacs.conversations.utils.EmojiWrapper; import eu.siacs.conversations.utils.IrregularUnicodeDetector; import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection; import rocks.xmpp.addr.Jid; public class ConversationAdapter extends RecyclerView.Adapter { @@ -160,21 +164,35 @@ public class ConversationAdapter extends RecyclerView.Adapter= System.currentTimeMillis()) { - viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE); - int ic_notifications_paused = activity.getThemeResource(R.attr.icon_notifications_paused, R.drawable.ic_notifications_paused_black_24dp); - viewHolder.binding.notificationStatus.setImageResource(ic_notifications_paused); - } else if (conversation.alwaysNotify()) { - viewHolder.binding.notificationStatus.setVisibility(View.GONE); + + final Optional ongoingCall; + if (conversation.getMode() == Conversational.MODE_MULTI) { + ongoingCall = Optional.absent(); } else { + ongoingCall = activity.xmppConnectionService.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact()); + } + + if (ongoingCall.isPresent()) { viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE); - int ic_notifications_none = activity.getThemeResource(R.attr.icon_notifications_none, R.drawable.ic_notifications_none_black_24dp); - viewHolder.binding.notificationStatus.setImageResource(ic_notifications_none); + final int ic_ongoing_call = activity.getThemeResource(R.attr.ic_ongoing_call_hint, R.drawable.ic_phone_in_talk_black_18dp); + viewHolder.binding.notificationStatus.setImageResource(ic_ongoing_call); + } else { + final long muted_till = conversation.getLongAttribute(Conversation.ATTRIBUTE_MUTED_TILL, 0); + if (muted_till == Long.MAX_VALUE) { + viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE); + int ic_notifications_off = activity.getThemeResource(R.attr.icon_notifications_off, R.drawable.ic_notifications_off_black_24dp); + viewHolder.binding.notificationStatus.setImageResource(ic_notifications_off); + } else if (muted_till >= System.currentTimeMillis()) { + viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE); + int ic_notifications_paused = activity.getThemeResource(R.attr.icon_notifications_paused, R.drawable.ic_notifications_paused_black_24dp); + viewHolder.binding.notificationStatus.setImageResource(ic_notifications_paused); + } else if (conversation.alwaysNotify()) { + viewHolder.binding.notificationStatus.setVisibility(View.GONE); + } else { + viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE); + int ic_notifications_none = activity.getThemeResource(R.attr.icon_notifications_none, R.drawable.ic_notifications_none_black_24dp); + viewHolder.binding.notificationStatus.setImageResource(ic_notifications_none); + } } long timestamp; diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 4c410a5be..a6c14a384 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -1,19 +1,16 @@ package eu.siacs.conversations.xmpp.jingle; -import android.os.SystemClock; import android.util.Base64; import android.util.Log; -import com.google.common.base.Function; import com.google.common.base.Objects; +import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableSet; -import org.checkerframework.checker.nullness.compatqual.NullableDecl; - import java.lang.ref.WeakReference; import java.security.SecureRandom; import java.util.Collection; @@ -108,6 +105,7 @@ public class JingleConnectionManager extends AbstractConnectionManager { return; } connections.put(id, connection); + mXmppConnectionService.updateConversationUi(); connection.deliverPacket(packet); } else { Log.d(Config.LOGTAG, "unable to route jingle packet: " + packet); @@ -353,6 +351,18 @@ public class JingleConnectionManager extends AbstractConnectionManager { connection.init(message); } + public Optional getOngoingRtpConnection(final Contact contact) { + for(final Map.Entry entry : this.connections.entrySet()) { + if (entry.getValue() instanceof JingleRtpConnection) { + final AbstractJingleConnection.Id id = entry.getKey(); + if (id.account == contact.getAccount() && id.with.asBareJid().equals(contact.getJid().asBareJid())) { + return Optional.of(id); + } + } + } + return Optional.absent(); + } + void finishConnection(final AbstractJingleConnection connection) { this.connections.remove(connection.getId()); } diff --git a/src/main/res/drawable-hdpi/ic_phone_in_talk_black_18dp.png b/src/main/res/drawable-hdpi/ic_phone_in_talk_black_18dp.png new file mode 100644 index 000000000..37bf2abc3 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_phone_in_talk_black_18dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_phone_in_talk_white_18dp.png b/src/main/res/drawable-hdpi/ic_phone_in_talk_white_18dp.png new file mode 100644 index 000000000..ecb24eb76 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_phone_in_talk_white_18dp.png differ diff --git a/src/main/res/drawable-hdpi/ic_phone_in_talk_white_24dp.png b/src/main/res/drawable-hdpi/ic_phone_in_talk_white_24dp.png new file mode 100644 index 000000000..f2c89424e Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_phone_in_talk_white_24dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_phone_in_talk_black_18dp.png b/src/main/res/drawable-mdpi/ic_phone_in_talk_black_18dp.png new file mode 100644 index 000000000..ee4526853 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_phone_in_talk_black_18dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_phone_in_talk_white_18dp.png b/src/main/res/drawable-mdpi/ic_phone_in_talk_white_18dp.png new file mode 100644 index 000000000..833386bbc Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_phone_in_talk_white_18dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_phone_in_talk_white_24dp.png b/src/main/res/drawable-mdpi/ic_phone_in_talk_white_24dp.png new file mode 100644 index 000000000..e6f98af95 Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_phone_in_talk_white_24dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_phone_in_talk_black_18dp.png b/src/main/res/drawable-xhdpi/ic_phone_in_talk_black_18dp.png new file mode 100644 index 000000000..0eea8bcb7 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_phone_in_talk_black_18dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_phone_in_talk_white_18dp.png b/src/main/res/drawable-xhdpi/ic_phone_in_talk_white_18dp.png new file mode 100644 index 000000000..f2c89424e Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_phone_in_talk_white_18dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_phone_in_talk_white_24dp.png b/src/main/res/drawable-xhdpi/ic_phone_in_talk_white_24dp.png new file mode 100644 index 000000000..a2d78b221 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_phone_in_talk_white_24dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_phone_in_talk_black_18dp.png b/src/main/res/drawable-xxhdpi/ic_phone_in_talk_black_18dp.png new file mode 100644 index 000000000..ed36763d8 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_phone_in_talk_black_18dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_18dp.png b/src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_18dp.png new file mode 100644 index 000000000..ec67c6ef9 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_18dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_24dp.png new file mode 100644 index 000000000..9c002da0a Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_24dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_phone_in_talk_black_18dp.png b/src/main/res/drawable-xxxhdpi/ic_phone_in_talk_black_18dp.png new file mode 100644 index 000000000..64b912bca Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_phone_in_talk_black_18dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_phone_in_talk_white_18dp.png b/src/main/res/drawable-xxxhdpi/ic_phone_in_talk_white_18dp.png new file mode 100644 index 000000000..9c002da0a Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_phone_in_talk_white_18dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_phone_in_talk_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_phone_in_talk_white_24dp.png new file mode 100644 index 000000000..36be1da99 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_phone_in_talk_white_24dp.png differ diff --git a/src/main/res/menu/fragment_conversation.xml b/src/main/res/menu/fragment_conversation.xml index b01e8cfa5..77306486a 100644 --- a/src/main/res/menu/fragment_conversation.xml +++ b/src/main/res/menu/fragment_conversation.xml @@ -60,6 +60,12 @@ android:title="@string/send_location" /> + + + diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 48ca72cea..f7445bf86 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -919,6 +919,7 @@ Video call Your microphone is unavailable You can only have one call at a time. + Return to ongoing call View %1$d Participant View %1$d Participants diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml index 2f8ecc434..b9e971cf1 100644 --- a/src/main/res/values/themes.xml +++ b/src/main/res/values/themes.xml @@ -99,6 +99,8 @@ @drawable/ic_attach_file_white_24dp @drawable/ic_lock_open_white_24dp @drawable/ic_call_white_24dp + @drawable/ic_phone_in_talk_white_24dp + @drawable/ic_phone_in_talk_black_18dp @drawable/ic_delete_black_24dp @drawable/ic_search_white_24dp @drawable/ic_lock_open_white_24dp @@ -219,6 +221,8 @@ @drawable/ic_attach_file_white_24dp @drawable/ic_lock_open_white_24dp @drawable/ic_call_white_24dp + @drawable/ic_phone_in_talk_white_24dp + @drawable/ic_phone_in_talk_white_18dp @drawable/ic_delete_white_24dp @drawable/ic_search_white_24dp @drawable/ic_lock_open_white_24dp