indicate ongoing call. fixes #3675
|
@ -52,6 +52,8 @@ import android.widget.PopupMenu;
|
||||||
import android.widget.TextView.OnEditorActionListener;
|
import android.widget.TextView.OnEditorActionListener;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -117,6 +119,7 @@ import eu.siacs.conversations.utils.TimeframeUtils;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import eu.siacs.conversations.xmpp.chatstate.ChatState;
|
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.JingleFileTransferConnection;
|
||||||
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
|
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
|
||||||
import rocks.xmpp.addr.Jid;
|
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 menuMute = menu.findItem(R.id.action_mute);
|
||||||
final MenuItem menuUnmute = menu.findItem(R.id.action_unmute);
|
final MenuItem menuUnmute = menu.findItem(R.id.action_unmute);
|
||||||
final MenuItem menuCall = menu.findItem(R.id.action_call);
|
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);
|
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());
|
menuInviteContact.setVisible(conversation.getMucOptions().canInvite());
|
||||||
menuMucDetails.setTitle(conversation.getMucOptions().isPrivateAndNonAnonymous() ? R.string.action_muc_details : R.string.channel_details);
|
menuMucDetails.setTitle(conversation.getMucOptions().isPrivateAndNonAnonymous() ? R.string.action_muc_details : R.string.channel_details);
|
||||||
menuCall.setVisible(false);
|
menuCall.setVisible(false);
|
||||||
|
menuOngoingCall.setVisible(false);
|
||||||
} else {
|
} else {
|
||||||
|
final Optional<AbstractJingleConnection.Id> 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());
|
final RtpCapability.Capability rtpCapability = RtpCapability.check(conversation.getContact());
|
||||||
menuCall.setVisible(rtpCapability != RtpCapability.Capability.NONE);
|
menuCall.setVisible(rtpCapability != RtpCapability.Capability.NONE);
|
||||||
menuVideoCall.setVisible(rtpCapability == RtpCapability.Capability.VIDEO);
|
menuVideoCall.setVisible(rtpCapability == RtpCapability.Capability.VIDEO);
|
||||||
|
}
|
||||||
menuContactDetails.setVisible(!this.conversation.withSelf());
|
menuContactDetails.setVisible(!this.conversation.withSelf());
|
||||||
menuMucDetails.setVisible(false);
|
menuMucDetails.setVisible(false);
|
||||||
final XmppConnectionService service = activity.xmppConnectionService;
|
final XmppConnectionService service = activity.xmppConnectionService;
|
||||||
|
@ -1245,12 +1257,28 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
case R.id.action_video_call:
|
case R.id.action_video_call:
|
||||||
checkPermissionAndTriggerVideoCall();
|
checkPermissionAndTriggerVideoCall();
|
||||||
break;
|
break;
|
||||||
|
case R.id.action_ongoing_call:
|
||||||
|
returnToOngoingCall();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void returnToOngoingCall() {
|
||||||
|
final Optional<AbstractJingleConnection.Id> 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() {
|
private void checkPermissionAndTriggerAudioCall() {
|
||||||
if (activity.mUseTor || conversation.getAccount().isOnion()) {
|
if (activity.mUseTor || conversation.getAccount().isOnion()) {
|
||||||
Toast.makeText(activity, R.string.disable_tor_to_make_call, Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, R.string.disable_tor_to_make_call, Toast.LENGTH_SHORT).show();
|
||||||
|
|
|
@ -9,11 +9,14 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.databinding.ConversationListRowBinding;
|
import eu.siacs.conversations.databinding.ConversationListRowBinding;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
|
import eu.siacs.conversations.entities.Conversational;
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.ui.ConversationFragment;
|
import eu.siacs.conversations.ui.ConversationFragment;
|
||||||
import eu.siacs.conversations.ui.XmppActivity;
|
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.EmojiWrapper;
|
||||||
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
|
import eu.siacs.conversations.utils.IrregularUnicodeDetector;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
|
import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
|
||||||
import rocks.xmpp.addr.Jid;
|
import rocks.xmpp.addr.Jid;
|
||||||
|
|
||||||
public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapter.ConversationViewHolder> {
|
public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapter.ConversationViewHolder> {
|
||||||
|
@ -160,7 +164,20 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long muted_till = conversation.getLongAttribute(Conversation.ATTRIBUTE_MUTED_TILL, 0);
|
|
||||||
|
final Optional<AbstractJingleConnection.Id> 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);
|
||||||
|
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) {
|
if (muted_till == Long.MAX_VALUE) {
|
||||||
viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE);
|
viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE);
|
||||||
int ic_notifications_off = activity.getThemeResource(R.attr.icon_notifications_off, R.drawable.ic_notifications_off_black_24dp);
|
int ic_notifications_off = activity.getThemeResource(R.attr.icon_notifications_off, R.drawable.ic_notifications_off_black_24dp);
|
||||||
|
@ -176,6 +193,7 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapte
|
||||||
int ic_notifications_none = activity.getThemeResource(R.attr.icon_notifications_none, R.drawable.ic_notifications_none_black_24dp);
|
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);
|
viewHolder.binding.notificationStatus.setImageResource(ic_notifications_none);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
long timestamp;
|
long timestamp;
|
||||||
if (draft != null) {
|
if (draft != null) {
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
package eu.siacs.conversations.xmpp.jingle;
|
package eu.siacs.conversations.xmpp.jingle;
|
||||||
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.collect.Collections2;
|
import com.google.common.collect.Collections2;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -108,6 +105,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
connections.put(id, connection);
|
connections.put(id, connection);
|
||||||
|
mXmppConnectionService.updateConversationUi();
|
||||||
connection.deliverPacket(packet);
|
connection.deliverPacket(packet);
|
||||||
} else {
|
} else {
|
||||||
Log.d(Config.LOGTAG, "unable to route jingle packet: " + packet);
|
Log.d(Config.LOGTAG, "unable to route jingle packet: " + packet);
|
||||||
|
@ -353,6 +351,18 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
||||||
connection.init(message);
|
connection.init(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<AbstractJingleConnection.Id> getOngoingRtpConnection(final Contact contact) {
|
||||||
|
for(final Map.Entry<AbstractJingleConnection.Id,AbstractJingleConnection> 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) {
|
void finishConnection(final AbstractJingleConnection connection) {
|
||||||
this.connections.remove(connection.getId());
|
this.connections.remove(connection.getId());
|
||||||
}
|
}
|
||||||
|
|
BIN
src/main/res/drawable-hdpi/ic_phone_in_talk_black_18dp.png
Normal file
After Width: | Height: | Size: 374 B |
BIN
src/main/res/drawable-hdpi/ic_phone_in_talk_white_18dp.png
Normal file
After Width: | Height: | Size: 393 B |
BIN
src/main/res/drawable-hdpi/ic_phone_in_talk_white_24dp.png
Normal file
After Width: | Height: | Size: 483 B |
BIN
src/main/res/drawable-mdpi/ic_phone_in_talk_black_18dp.png
Normal file
After Width: | Height: | Size: 253 B |
BIN
src/main/res/drawable-mdpi/ic_phone_in_talk_white_18dp.png
Normal file
After Width: | Height: | Size: 261 B |
BIN
src/main/res/drawable-mdpi/ic_phone_in_talk_white_24dp.png
Normal file
After Width: | Height: | Size: 325 B |
BIN
src/main/res/drawable-xhdpi/ic_phone_in_talk_black_18dp.png
Normal file
After Width: | Height: | Size: 477 B |
BIN
src/main/res/drawable-xhdpi/ic_phone_in_talk_white_18dp.png
Normal file
After Width: | Height: | Size: 483 B |
BIN
src/main/res/drawable-xhdpi/ic_phone_in_talk_white_24dp.png
Normal file
After Width: | Height: | Size: 601 B |
BIN
src/main/res/drawable-xxhdpi/ic_phone_in_talk_black_18dp.png
Normal file
After Width: | Height: | Size: 685 B |
BIN
src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_18dp.png
Normal file
After Width: | Height: | Size: 704 B |
BIN
src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_24dp.png
Normal file
After Width: | Height: | Size: 882 B |
BIN
src/main/res/drawable-xxxhdpi/ic_phone_in_talk_black_18dp.png
Normal file
After Width: | Height: | Size: 868 B |
BIN
src/main/res/drawable-xxxhdpi/ic_phone_in_talk_white_18dp.png
Normal file
After Width: | Height: | Size: 882 B |
BIN
src/main/res/drawable-xxxhdpi/ic_phone_in_talk_white_24dp.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
|
@ -60,6 +60,12 @@
|
||||||
android:title="@string/send_location" />
|
android:title="@string/send_location" />
|
||||||
</menu>
|
</menu>
|
||||||
</item>
|
</item>
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_ongoing_call"
|
||||||
|
android:icon="?attr/icon_ongoing_call"
|
||||||
|
android:orderInCategory="34"
|
||||||
|
android:title="@string/return_to_ongoing_call"
|
||||||
|
app:showAsAction="always" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_call"
|
android:id="@+id/action_call"
|
||||||
android:icon="?attr/icon_call"
|
android:icon="?attr/icon_call"
|
||||||
|
|
|
@ -91,6 +91,8 @@
|
||||||
<attr name="icon_new_attachment" format="reference"/>
|
<attr name="icon_new_attachment" format="reference"/>
|
||||||
<attr name="icon_not_secure" format="reference"/>
|
<attr name="icon_not_secure" format="reference"/>
|
||||||
<attr name="icon_call" format="reference"/>
|
<attr name="icon_call" format="reference"/>
|
||||||
|
<attr name="icon_ongoing_call" format="reference"/>
|
||||||
|
<attr name="ic_ongoing_call_hint" format="reference"/>
|
||||||
<attr name="icon_quote" format="reference"/>
|
<attr name="icon_quote" format="reference"/>
|
||||||
<attr name="icon_refresh" format="reference"/>
|
<attr name="icon_refresh" format="reference"/>
|
||||||
<attr name="icon_remove" format="reference"/>
|
<attr name="icon_remove" format="reference"/>
|
||||||
|
|
|
@ -919,6 +919,7 @@
|
||||||
<string name="video_call">Video call</string>
|
<string name="video_call">Video call</string>
|
||||||
<string name="microphone_unavailable">Your microphone is unavailable</string>
|
<string name="microphone_unavailable">Your microphone is unavailable</string>
|
||||||
<string name="only_one_call_at_a_time">You can only have one call at a time.</string>
|
<string name="only_one_call_at_a_time">You can only have one call at a time.</string>
|
||||||
|
<string name="return_to_ongoing_call">Return to ongoing call</string>
|
||||||
<plurals name="view_users">
|
<plurals name="view_users">
|
||||||
<item quantity="one">View %1$d Participant</item>
|
<item quantity="one">View %1$d Participant</item>
|
||||||
<item quantity="other">View %1$d Participants</item>
|
<item quantity="other">View %1$d Participants</item>
|
||||||
|
|
|
@ -99,6 +99,8 @@
|
||||||
<item type="reference" name="icon_new_attachment">@drawable/ic_attach_file_white_24dp</item>
|
<item type="reference" name="icon_new_attachment">@drawable/ic_attach_file_white_24dp</item>
|
||||||
<item type="reference" name="icon_not_secure">@drawable/ic_lock_open_white_24dp</item>
|
<item type="reference" name="icon_not_secure">@drawable/ic_lock_open_white_24dp</item>
|
||||||
<item type="reference" name="icon_call">@drawable/ic_call_white_24dp</item>
|
<item type="reference" name="icon_call">@drawable/ic_call_white_24dp</item>
|
||||||
|
<item type="reference" name="icon_ongoing_call">@drawable/ic_phone_in_talk_white_24dp</item>
|
||||||
|
<item type="reference" name="ic_ongoing_call_hint">@drawable/ic_phone_in_talk_black_18dp</item>
|
||||||
<item type="reference" name="icon_remove">@drawable/ic_delete_black_24dp</item>
|
<item type="reference" name="icon_remove">@drawable/ic_delete_black_24dp</item>
|
||||||
<item type="reference" name="icon_search">@drawable/ic_search_white_24dp</item>
|
<item type="reference" name="icon_search">@drawable/ic_search_white_24dp</item>
|
||||||
<item type="reference" name="icon_secure">@drawable/ic_lock_open_white_24dp</item>
|
<item type="reference" name="icon_secure">@drawable/ic_lock_open_white_24dp</item>
|
||||||
|
@ -219,6 +221,8 @@
|
||||||
<item type="reference" name="icon_new_attachment">@drawable/ic_attach_file_white_24dp</item>
|
<item type="reference" name="icon_new_attachment">@drawable/ic_attach_file_white_24dp</item>
|
||||||
<item type="reference" name="icon_not_secure">@drawable/ic_lock_open_white_24dp</item>
|
<item type="reference" name="icon_not_secure">@drawable/ic_lock_open_white_24dp</item>
|
||||||
<item type="reference" name="icon_call">@drawable/ic_call_white_24dp</item>
|
<item type="reference" name="icon_call">@drawable/ic_call_white_24dp</item>
|
||||||
|
<item type="reference" name="icon_ongoing_call">@drawable/ic_phone_in_talk_white_24dp</item>
|
||||||
|
<item type="reference" name="ic_ongoing_call_hint">@drawable/ic_phone_in_talk_white_18dp</item>
|
||||||
<item type="reference" name="icon_remove">@drawable/ic_delete_white_24dp</item>
|
<item type="reference" name="icon_remove">@drawable/ic_delete_white_24dp</item>
|
||||||
<item type="reference" name="icon_search">@drawable/ic_search_white_24dp</item>
|
<item type="reference" name="icon_search">@drawable/ic_search_white_24dp</item>
|
||||||
<item type="reference" name="icon_secure">@drawable/ic_lock_open_white_24dp</item>
|
<item type="reference" name="icon_secure">@drawable/ic_lock_open_white_24dp</item>
|
||||||
|
|