Change summary
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 4
src/main/java/eu/siacs/conversations/xmpp/jingle/RtpCapability.java | 58
src/main/res/drawable-hdpi/ic_call_white_24dp.png | 0
src/main/res/drawable-mdpi/ic_call_white_24dp.png | 0
src/main/res/drawable-xhdpi/ic_call_white_24dp.png | 0
src/main/res/drawable-xxhdpi/ic_call_white_24dp.png | 0
src/main/res/drawable-xxxhdpi/ic_call_white_24dp.png | 0
src/main/res/menu/fragment_conversation.xml | 76
src/main/res/values/attrs.xml | 1
src/main/res/values/strings.xml | 1
src/main/res/values/themes.xml | 2
11 files changed, 107 insertions(+), 35 deletions(-)
Detailed changes
@@ -116,6 +116,7 @@ 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.JingleFileTransferConnection;
+import eu.siacs.conversations.xmpp.jingle.RtpCapability;
import rocks.xmpp.addr.Jid;
import static eu.siacs.conversations.ui.XmppActivity.EXTRA_ACCOUNT;
@@ -950,6 +951,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
final MenuItem menuInviteContact = menu.findItem(R.id.action_invite);
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);
if (conversation != null) {
@@ -957,7 +959,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
menuContactDetails.setVisible(false);
menuInviteContact.setVisible(conversation.getMucOptions().canInvite());
menuMucDetails.setTitle(conversation.getMucOptions().isPrivateAndNonAnonymous() ? R.string.action_muc_details : R.string.channel_details);
+ menuCall.setVisible(false);
} else {
+ menuCall.setVisible(RtpCapability.check(conversation.getContact()) != RtpCapability.Capability.NONE);
menuContactDetails.setVisible(!this.conversation.withSelf());
menuMucDetails.setVisible(false);
final XmppConnectionService service = activity.xmppConnectionService;
@@ -0,0 +1,58 @@
+package eu.siacs.conversations.xmpp.jingle;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import eu.siacs.conversations.entities.Contact;
+import eu.siacs.conversations.entities.Presence;
+import eu.siacs.conversations.entities.Presences;
+import eu.siacs.conversations.entities.ServiceDiscoveryResult;
+import eu.siacs.conversations.xml.Namespace;
+
+public class RtpCapability {
+
+ private static List<String> BASIC_RTP_REQUIREMENTS = Arrays.asList(
+ Namespace.JINGLE,
+ Namespace.JINGLE_TRANSPORT_ICE_UDP,
+ Namespace.JINGLE_APPS_RTP,
+ Namespace.JINGLE_APPS_DTLS
+ );
+ private static List<String> VIDEO_REQUIREMENTS = Arrays.asList(
+ Namespace.JINGLE_FEATURE_AUDIO,
+ Namespace.JINGLE_FEATURE_VIDEO
+ );
+
+ public static Capability check(final Presence presence) {
+ final ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult();
+ final List<String> features = disco == null ? Collections.emptyList() : disco.getFeatures();
+ if (features.containsAll(BASIC_RTP_REQUIREMENTS)) {
+ if (features.containsAll(VIDEO_REQUIREMENTS)) {
+ return Capability.VIDEO;
+ }
+ if (features.contains(Namespace.JINGLE_FEATURE_AUDIO)) {
+ return Capability.AUDIO;
+ }
+ }
+ return Capability.NONE;
+ }
+
+ public static Capability check(final Contact contact) {
+ final Presences presences = contact.getPresences();
+ Capability result = Capability.NONE;
+ for(Presence presence : presences.getPresences().values()) {
+ Capability capability = check(presence);
+ if (capability == Capability.VIDEO) {
+ result = capability;
+ } else if (capability == Capability.AUDIO && result == Capability.NONE) {
+ result = capability;
+ }
+ }
+ return result;
+ }
+
+ public enum Capability {
+ NONE, AUDIO, VIDEO
+ }
+
+}
@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+ xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_security"
android:icon="?attr/icon_not_secure"
android:orderInCategory="20"
- app:showAsAction="always"
- android:title="@string/action_secure">
+ android:title="@string/action_secure"
+ app:showAsAction="always">
<menu>
- <group android:checkableBehavior="single" >
+ <group android:checkableBehavior="single">
<item
android:id="@+id/encryption_choice_none"
- android:title="@string/encryption_choice_unencrypted"/>
+ android:title="@string/encryption_choice_unencrypted" />
<item
android:id="@+id/encryption_choice_axolotl"
- android:title="@string/encryption_choice_omemo"/>
+ android:title="@string/encryption_choice_omemo" />
<item
android:id="@+id/encryption_choice_pgp"
- android:title="@string/encryption_choice_pgp"/>
+ android:title="@string/encryption_choice_pgp" />
</group>
</menu>
</item>
@@ -25,76 +25,82 @@
android:id="@+id/action_attach_file"
android:icon="?attr/icon_new_attachment"
android:orderInCategory="30"
- app:showAsAction="always"
- android:title="@string/attach_file">
+ android:title="@string/attach_file"
+ app:showAsAction="always">
<menu>
<item
android:id="@+id/attach_choose_file"
- android:title="@string/choose_file"
- android:icon="?attr/ic_attach_document"/>
+ android:icon="?attr/ic_attach_document"
+ android:title="@string/choose_file" />
<item
android:id="@+id/attach_choose_picture"
- android:title="@string/attach_choose_picture"
- android:icon="?attr/ic_attach_photo"/>
+ android:icon="?attr/ic_attach_photo"
+ android:title="@string/attach_choose_picture" />
<item
android:id="@+id/attach_take_picture"
- android:title="@string/attach_take_picture"
- android:icon="?attr/ic_attach_camera"/>
+ android:icon="?attr/ic_attach_camera"
+ android:title="@string/attach_take_picture" />
<item
android:id="@+id/attach_record_video"
- android:title="@string/attach_record_video"
- android:icon="?attr/ic_attach_videocam"/>
+ android:icon="?attr/ic_attach_videocam"
+ android:title="@string/attach_record_video" />
<item
android:id="@+id/attach_record_voice"
- android:title="@string/attach_record_voice"
- android:icon="?attr/ic_attach_record"/>
+ android:icon="?attr/ic_attach_record"
+ android:title="@string/attach_record_voice" />
<item
android:id="@+id/attach_location"
- android:title="@string/send_location"
- android:icon="?attr/ic_attach_location"/>
+ android:icon="?attr/ic_attach_location"
+ android:title="@string/send_location" />
</menu>
</item>
+ <item
+ android:id="@+id/action_call"
+ android:icon="?attr/icon_call"
+ android:orderInCategory="35"
+ android:title="@string/make_call"
+ app:showAsAction="always" />
<item
android:id="@+id/action_contact_details"
android:orderInCategory="40"
- app:showAsAction="never"
- android:title="@string/action_contact_details"/>
+ android:title="@string/action_contact_details"
+ app:showAsAction="never" />
<item
android:id="@+id/action_muc_details"
android:icon="?attr/icon_group"
android:orderInCategory="40"
- app:showAsAction="never"
- android:title="@string/action_muc_details"/>
+ android:title="@string/action_muc_details"
+ app:showAsAction="never" />
<item
android:id="@+id/action_invite"
android:orderInCategory="45"
- app:showAsAction="never"
- android:title="@string/invite_contact"/>
+ android:title="@string/invite_contact"
+ app:showAsAction="never" />
<item
android:id="@+id/action_clear_history"
android:orderInCategory="50"
- app:showAsAction="never"
- android:title="@string/action_clear_history"/>
+ android:title="@string/action_clear_history"
+ app:showAsAction="never" />
<item
android:id="@+id/action_archive"
android:orderInCategory="60"
- app:showAsAction="never"
- android:title="@string/action_end_conversation"/>
+ android:title="@string/action_end_conversation"
+ app:showAsAction="never" />
<item
android:id="@+id/action_mute"
android:orderInCategory="70"
- app:showAsAction="never"
- android:title="@string/disable_notifications"/>
+ android:title="@string/disable_notifications"
+ app:showAsAction="never" />
<item
android:id="@+id/action_unmute"
android:orderInCategory="71"
- app:showAsAction="never"
- android:title="@string/enable_notifications"/>
+ android:title="@string/enable_notifications"
+ app:showAsAction="never" />
</menu>
@@ -85,6 +85,7 @@
<attr name="icon_new" format="reference"/>
<attr name="icon_new_attachment" format="reference"/>
<attr name="icon_not_secure" format="reference"/>
+ <attr name="icon_call" format="reference"/>
<attr name="icon_quote" format="reference"/>
<attr name="icon_refresh" format="reference"/>
<attr name="icon_remove" format="reference"/>
@@ -884,6 +884,7 @@
<string name="backup">Backup</string>
<string name="category_about">About</string>
<string name="please_enable_an_account">Please enable an account</string>
+ <string name="make_call">Make call</string>
<plurals name="view_users">
<item quantity="one">View %1$d Participant</item>
<item quantity="other">View %1$d Participants</item>
@@ -93,6 +93,7 @@
<item type="reference" name="icon_refresh">@drawable/ic_refresh_black_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_call">@drawable/ic_call_white_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_secure">@drawable/ic_lock_open_white_24dp</item>
@@ -207,6 +208,7 @@
<item type="reference" name="icon_refresh">@drawable/ic_refresh_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_call">@drawable/ic_call_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_secure">@drawable/ic_lock_open_white_24dp</item>