Implement new video call experience.
Before Width: | Height: | Size: 140 B |
Before Width: | Height: | Size: 176 B |
Before Width: | Height: | Size: 104 B |
Before Width: | Height: | Size: 118 B |
Before Width: | Height: | Size: 118 B |
Before Width: | Height: | Size: 192 B |
Before Width: | Height: | Size: 524 B |
Before Width: | Height: | Size: 176 B |
Before Width: | Height: | Size: 270 B |
Before Width: | Height: | Size: 192 B |
Before Width: | Height: | Size: 334 B |
9
res/drawable/ic_phone_right_solid_24.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M21.11,16.608a26.24,26.24 0,0 1,-4.513 -2.5,1.384 1.384,0 0,0 -1.918,0.284 9.116,9.116 0,0 0,-0.866 1.465,4.5 4.5,0 0,0 -0.357,1.242A13.113,13.113 0,0 1,6.9 10.542a4.474,4.474 0,0 0,1.243 -0.355,9.019 9.019,0 0,0 1.343,-0.779 1.444,1.444 0,0 0,0.4 -2A26.2,26.2 0,0 1,7.357 2.9a1.42,1.42 0,0 0,-1.71 -0.825,8.63 8.63,0 0,0 -1.1,0.421 4.284,4.284 0,0 0,-2.5 4.392l-0.014,0A16.948,16.948 0,0 0,17.073 21.953l0,-0.016a4.308,4.308 0,0 0,4.441 -2.492,8.732 8.732,0 0,0 0.431,-1.13A1.42,1.42 0,0 0,21.11 16.608Z"/>
|
||||
</vector>
|
9
res/drawable/ic_phone_right_unlock_solid_24.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M21.94,18.315a8.732,8.732 0,0 1,-0.431 1.13,4.308 4.308,0 0,1 -4.441,2.492l0,0.016A16.948,16.948 0,0 1,2.035 6.878l0.014,0a4.284,4.284 0,0 1,2.5 -4.392,8.63 8.63,0 0,1 1.1,-0.421 1.42,1.42 0,0 1,1.71 0.825A26.2,26.2 0,0 0,9.877 7.41a1.444,1.444 0,0 1,-0.4 2,9.019 9.019,0 0,1 -1.343,0.779 4.474,4.474 0,0 1,-1.243 0.355,13.113 13.113,0 0,0 6.56,6.557 4.5,4.5 0,0 1,0.357 -1.242,9.116 9.116,0 0,1 0.866,-1.465 1.384,1.384 0,0 1,1.918 -0.284,26.24 26.24,0 0,0 4.513,2.5A1.42,1.42 0,0 1,21.94 18.315ZM19.75,1A2.75,2.75 0,0 0,17 3.75V5H14.5A1.5,1.5 0,0 0,13 6.5v3A1.5,1.5 0,0 0,14.5 11h3.75a1.5,1.5 0,0 0,1.5 -1.5v-3A1.5,1.5 0,0 0,18.5 5.026V3.75a1.25,1.25 0,0 1,2.5 0V5h1.5V3.75A2.751,2.751 0,0 0,19.75 1Z"/>
|
||||
</vector>
|
9
res/drawable/ic_video_solid_24.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M23,8.563v6.874a1,1 0,0 1,-1.419 0.908L18.5,14.923V9.077l3.081,-1.422A1,1 0,0 1,23 8.563ZM2.535,4.876A2.639,2.639 0,0 0,1.4 5.939,3.854 3.854,0 0,0 1,8.105V15.9a3.854,3.854 0,0 0,0.4 2.166,2.639 2.639,0 0,0 1.134,1.063 4.6,4.6 0,0 0,2.311 0.376h8.308a4.6,4.6 0,0 0,2.311 -0.376A2.639,2.639 0,0 0,16.6 18.061,3.854 3.854,0 0,0 17,15.9V8.105a3.854,3.854 0,0 0,-0.4 -2.166,2.639 2.639,0 0,0 -1.134,-1.063A4.6,4.6 0,0 0,13.154 4.5H4.846A4.6,4.6 0,0 0,2.535 4.876Z"/>
|
||||
</vector>
|
9
res/drawable/ic_video_solid_24_tinted.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?icon_tint"
|
||||
android:pathData="M23,8.563v6.874a1,1 0,0 1,-1.419 0.908L18.5,14.923V9.077l3.081,-1.422A1,1 0,0 1,23 8.563ZM2.535,4.876A2.639,2.639 0,0 0,1.4 5.939,3.854 3.854,0 0,0 1,8.105V15.9a3.854,3.854 0,0 0,0.4 2.166,2.639 2.639,0 0,0 1.134,1.063 4.6,4.6 0,0 0,2.311 0.376h8.308a4.6,4.6 0,0 0,2.311 -0.376A2.639,2.639 0,0 0,16.6 18.061,3.854 3.854,0 0,0 17,15.9V8.105a3.854,3.854 0,0 0,-0.4 -2.166,2.639 2.639,0 0,0 -1.134,-1.063A4.6,4.6 0,0 0,13.154 4.5H4.846A4.6,4.6 0,0 0,2.535 4.876Z"/>
|
||||
</vector>
|
@ -5,5 +5,5 @@
|
||||
android:left="5dp"
|
||||
android:right="5dp"
|
||||
android:bottom="5dp"
|
||||
android:drawable="@drawable/ic_videocam_white_24dp"/>
|
||||
android:drawable="@drawable/ic_video_solid_24"/>
|
||||
</layer-list>
|
@ -53,14 +53,15 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<include layout="@layout/expiration_timer_badge" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/verified_indicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="3dp"
|
||||
android:alpha="0.7"
|
||||
android:src="@drawable/ic_check_circle_white_18dp"
|
||||
android:tint="?conversation_subtitle_color"
|
||||
app:srcCompat="@drawable/ic_check_24"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
@ -74,6 +75,7 @@
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:textColor="?conversation_subtitle_color"
|
||||
android:text="@string/ConversationTitleView_verified"
|
||||
android:textDirection="ltr" />
|
||||
|
||||
@ -85,6 +87,7 @@
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="?conversation_subtitle_color"
|
||||
android:maxLines="1"
|
||||
android:textDirection="ltr"
|
||||
tools:text="(123) 123-1234" />
|
||||
|
34
res/layout/expiration_timer_badge.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/expiration_badge_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="11dp"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/menu_badge_icon"
|
||||
android:layout_width="14dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginEnd="3dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:tint="?conversation_subtitle_color"
|
||||
app:srcCompat="@drawable/ic_timer_60_12" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/expiration_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:gravity="center_horizontal|bottom"
|
||||
android:paddingTop="1dp"
|
||||
android:paddingBottom="3dp"
|
||||
android:textColor="?conversation_subtitle_color"
|
||||
android:textSize="14sp"
|
||||
tools:text="1w" />
|
||||
</LinearLayout>
|
@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
style="?android:attr/actionButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/menu_badge_icon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="center"
|
||||
app:srcCompat="@drawable/ic_timer_conversation_24"
|
||||
android:scaleType="fitCenter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/expiration_badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:gravity="center_horizontal|bottom"
|
||||
android:paddingBottom="3dp"
|
||||
android:paddingTop="1dp"
|
||||
android:textColor="?conversation_subtitle_color"
|
||||
android:textSize="10sp" />
|
||||
</FrameLayout>
|
@ -15,7 +15,7 @@
|
||||
android:layout_height="24dp"
|
||||
android:layout_margin="16dp"
|
||||
android:tint="@color/grey_600"
|
||||
tools:src="@drawable/ic_call_white_24dp" />
|
||||
tools:src="@drawable/ic_phone_right_unlock_solid_24" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/contact_field_avatar"
|
||||
|
@ -6,20 +6,30 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView android:id="@+id/message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="?attr/message_icon"
|
||||
android:layout_marginEnd="20dp"/>
|
||||
<ImageView
|
||||
android:id="@+id/message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="20dp"
|
||||
app:srcCompat="?attr/message_icon" />
|
||||
|
||||
<ImageView android:id="@+id/call"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_call_white_24dp"/>
|
||||
<ImageView
|
||||
android:id="@+id/call"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_phone_right_unlock_solid_24" />
|
||||
|
||||
<ImageView android:id="@+id/secure_call"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_call_secure_white_24dp"/>
|
||||
<ImageView
|
||||
android:id="@+id/secure_video"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="20dp"
|
||||
app:srcCompat="@drawable/ic_video_solid_24" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/secure_call"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_phone_right_solid_24" />
|
||||
|
||||
</LinearLayout>
|
@ -26,6 +26,12 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:visibility="invisible" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.webrtc.PercentFrameLayout
|
||||
android:id="@+id/local_large_render_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:visibility="invisible" />
|
||||
|
||||
<!-- "Call info" block #1, for the foreground call. -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/call_info_1"
|
||||
|
@ -2,9 +2,14 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:title="@string/conversation_callable_secure__menu_video"
|
||||
android:id="@+id/menu_video_secure"
|
||||
android:icon="@drawable/ic_video_solid_24"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item android:title="@string/conversation_callable_secure__menu_call"
|
||||
android:id="@+id/menu_call_secure"
|
||||
android:icon="@drawable/ic_call_secure_white_24dp"
|
||||
android:icon="@drawable/ic_phone_right_solid_24"
|
||||
app:showAsAction="always" />
|
||||
|
||||
</menu>
|
@ -3,8 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:id="@+id/menu_expiring_messages"
|
||||
app:actionLayout="@layout/expiration_timer_menu"
|
||||
app:showAsAction="always"
|
||||
android:title="@string/menu_conversation_expiring_on__messages_expiring"/>
|
||||
app:showAsAction="never"
|
||||
android:title="@string/conversation_expiring_off__disappearing_messages"/>
|
||||
|
||||
</menu>
|
@ -120,6 +120,10 @@
|
||||
<!-- CommunicationActions -->
|
||||
<string name="CommunicationActions_no_browser_found">No web browser found.</string>
|
||||
<string name="CommunicationActions_a_cellular_call_is_already_in_progress">A cellular call is already in progress.</string>
|
||||
<string name="CommunicationActions_start_video_call">Start video call?</string>
|
||||
<string name="CommunicationActions_start_voice_call">Start voice call?</string>
|
||||
<string name="CommunicationActions_cancel">Cancel</string>
|
||||
<string name="CommunicationActions_call">Call</string>
|
||||
|
||||
<!-- ConfirmIdentityDialog -->
|
||||
<string name="ConfirmIdentityDialog_your_safety_number_with_s_has_changed">Your safety number with %1$s has changed. This could either mean that someone is trying to intercept your communication, or that %2$s simply reinstalled Signal.</string>
|
||||
@ -1453,6 +1457,7 @@
|
||||
|
||||
<!-- conversation_callable_secure -->
|
||||
<string name="conversation_callable_secure__menu_call">Signal call</string>
|
||||
<string name="conversation_callable_secure__menu_video">Signal video call</string>
|
||||
|
||||
<!-- conversation_context -->
|
||||
<string name="conversation_context__menu_message_details">Message details</string>
|
||||
|
@ -302,7 +302,7 @@
|
||||
<item name="menu_new_conversation_icon">@drawable/ic_add_white_24dp</item>
|
||||
<item name="menu_group_icon">@drawable/ic_group_solid_24</item>
|
||||
<item name="menu_search_icon">@drawable/ic_search_24</item>
|
||||
<item name="menu_call_icon">@drawable/ic_call_white_24dp</item>
|
||||
<item name="menu_call_icon">@drawable/ic_phone_right_unlock_solid_24</item>
|
||||
<item name="menu_popup_expand">@drawable/ic_launch_white_24dp</item>
|
||||
<item name="menu_unlock_icon">@drawable/ic_unlocked_white_24dp</item>
|
||||
<item name="menu_lock_icon">@drawable/ic_lock_white_24dp</item>
|
||||
@ -532,7 +532,7 @@
|
||||
<item name="menu_new_conversation_icon">@drawable/ic_add_white_24dp</item>
|
||||
<item name="menu_group_icon">@drawable/ic_group_solid_24</item>
|
||||
<item name="menu_search_icon">@drawable/ic_search_24</item>
|
||||
<item name="menu_call_icon">@drawable/ic_call_white_24dp</item>
|
||||
<item name="menu_call_icon">@drawable/ic_phone_right_unlock_solid_24</item>
|
||||
<item name="menu_popup_expand">@drawable/ic_launch_white_24dp</item>
|
||||
<item name="menu_unlock_icon">@drawable/ic_unlocked_white_24dp</item>
|
||||
<item name="menu_lock_icon">@drawable/ic_lock_white_24dp</item>
|
||||
|
@ -769,6 +769,11 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
CommunicationActions.startVoiceCall(getActivity(), recipient.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSecureVideoClicked() {
|
||||
CommunicationActions.startVideoCall(getActivity(), recipient.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInSecureCallClicked() {
|
||||
try {
|
||||
|
@ -49,6 +49,7 @@ import org.thoughtcrime.securesms.service.WebRtcCallService;
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.webrtc.SurfaceViewRenderer;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||
|
||||
@ -65,7 +66,10 @@ public class WebRtcCallActivity extends Activity {
|
||||
public static final String DENY_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".DENY_ACTION";
|
||||
public static final String END_CALL_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".END_CALL_ACTION";
|
||||
|
||||
private WebRtcCallScreen callScreen;
|
||||
public static final String EXTRA_ENABLE_VIDEO_IF_AVAILABLE = WebRtcCallActivity.class.getCanonicalName() + ".ENABLE_VIDEO_IF_AVAILABLE";
|
||||
|
||||
private WebRtcCallScreen callScreen;
|
||||
private boolean enableVideoIfAvailable;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@ -82,6 +86,9 @@ public class WebRtcCallActivity extends Activity {
|
||||
initializeResources();
|
||||
|
||||
processIntent(getIntent());
|
||||
|
||||
enableVideoIfAvailable = getIntent().getBooleanExtra(EXTRA_ENABLE_VIDEO_IF_AVAILABLE, false);
|
||||
getIntent().removeExtra(EXTRA_ENABLE_VIDEO_IF_AVAILABLE);
|
||||
}
|
||||
|
||||
|
||||
@ -173,10 +180,10 @@ public class WebRtcCallActivity extends Activity {
|
||||
.request(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(getString(R.string.WebRtcCallActivity_to_answer_the_call_from_s_give_signal_access_to_your_microphone, event.getRecipient().toShortString(this)),
|
||||
R.drawable.ic_mic_solid_24, R.drawable.ic_videocam_white_48dp)
|
||||
R.drawable.ic_mic_solid_24, R.drawable.ic_video_solid_24_tinted)
|
||||
.withPermanentDenialDialog(getString(R.string.WebRtcCallActivity_signal_requires_microphone_and_camera_permissions_in_order_to_make_or_receive_calls))
|
||||
.onAllGranted(() -> {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_answering));
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_answering), event.getLocalRenderer());
|
||||
|
||||
Intent intent = new Intent(this, WebRtcCallService.class);
|
||||
intent.setAction(WebRtcCallService.ACTION_ANSWER_CALL);
|
||||
@ -195,7 +202,7 @@ public class WebRtcCallActivity extends Activity {
|
||||
intent.setAction(WebRtcCallService.ACTION_DENY_CALL);
|
||||
startService(intent);
|
||||
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_ending_call));
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_ending_call), event.getLocalRenderer());
|
||||
delayedFinish();
|
||||
}
|
||||
}
|
||||
@ -212,24 +219,24 @@ public class WebRtcCallActivity extends Activity {
|
||||
}
|
||||
|
||||
private void handleOutgoingCall(@NonNull WebRtcViewModel event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_dialing));
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_dialing), event.getLocalRenderer());
|
||||
}
|
||||
|
||||
private void handleTerminate(@NonNull Recipient recipient /*, int terminationType */) {
|
||||
private void handleTerminate(@NonNull Recipient recipient, @NonNull SurfaceViewRenderer localRenderer /*, int terminationType */) {
|
||||
Log.i(TAG, "handleTerminate called");
|
||||
|
||||
callScreen.setActiveCall(recipient, getString(R.string.RedPhone_ending_call));
|
||||
callScreen.setActiveCall(recipient, getString(R.string.RedPhone_ending_call), localRenderer);
|
||||
EventBus.getDefault().removeStickyEvent(WebRtcViewModel.class);
|
||||
|
||||
delayedFinish();
|
||||
}
|
||||
|
||||
private void handleCallRinging(@NonNull WebRtcViewModel event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_ringing));
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_ringing), event.getLocalRenderer());
|
||||
}
|
||||
|
||||
private void handleCallBusy(@NonNull WebRtcViewModel event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_busy));
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_busy), event.getLocalRenderer());
|
||||
|
||||
delayedFinish(BUSY_SIGNAL_DELAY_FINISH);
|
||||
}
|
||||
@ -240,12 +247,12 @@ public class WebRtcCallActivity extends Activity {
|
||||
}
|
||||
|
||||
private void handleRecipientUnavailable(@NonNull WebRtcViewModel event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_recipient_unavailable));
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_recipient_unavailable), event.getLocalRenderer());
|
||||
delayedFinish();
|
||||
}
|
||||
|
||||
private void handleServerFailure(@NonNull WebRtcViewModel event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_network_failed));
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_network_failed), event.getLocalRenderer());
|
||||
delayedFinish();
|
||||
}
|
||||
|
||||
@ -259,13 +266,13 @@ public class WebRtcCallActivity extends Activity {
|
||||
dialog.setPositiveButton(R.string.RedPhone_got_it, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
WebRtcCallActivity.this.handleTerminate(event.getRecipient());
|
||||
WebRtcCallActivity.this.handleTerminate(event.getRecipient(), event.getLocalRenderer());
|
||||
}
|
||||
});
|
||||
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
WebRtcCallActivity.this.handleTerminate(event.getRecipient());
|
||||
WebRtcCallActivity.this.handleTerminate(event.getRecipient(), event.getLocalRenderer());
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
@ -294,7 +301,7 @@ public class WebRtcCallActivity extends Activity {
|
||||
callScreen.setCancelIdentityButton(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
handleTerminate(recipient);
|
||||
handleTerminate(recipient, event.getLocalRenderer());
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -316,22 +323,27 @@ public class WebRtcCallActivity extends Activity {
|
||||
Log.i(TAG, "Got message from service: " + event);
|
||||
|
||||
switch (event.getState()) {
|
||||
case CALL_CONNECTED: handleCallConnected(event); break;
|
||||
case NETWORK_FAILURE: handleServerFailure(event); break;
|
||||
case CALL_RINGING: handleCallRinging(event); break;
|
||||
case CALL_DISCONNECTED: handleTerminate(event.getRecipient()); break;
|
||||
case NO_SUCH_USER: handleNoSuchUser(event); break;
|
||||
case RECIPIENT_UNAVAILABLE: handleRecipientUnavailable(event); break;
|
||||
case CALL_INCOMING: handleIncomingCall(event); break;
|
||||
case CALL_OUTGOING: handleOutgoingCall(event); break;
|
||||
case CALL_BUSY: handleCallBusy(event); break;
|
||||
case UNTRUSTED_IDENTITY: handleUntrustedIdentity(event); break;
|
||||
case CALL_CONNECTED: handleCallConnected(event); break;
|
||||
case NETWORK_FAILURE: handleServerFailure(event); break;
|
||||
case CALL_RINGING: handleCallRinging(event); break;
|
||||
case CALL_DISCONNECTED: handleTerminate(event.getRecipient(), event.getLocalRenderer()); break;
|
||||
case NO_SUCH_USER: handleNoSuchUser(event); break;
|
||||
case RECIPIENT_UNAVAILABLE: handleRecipientUnavailable(event); break;
|
||||
case CALL_INCOMING: handleIncomingCall(event); break;
|
||||
case CALL_OUTGOING: handleOutgoingCall(event); break;
|
||||
case CALL_BUSY: handleCallBusy(event); break;
|
||||
case UNTRUSTED_IDENTITY: handleUntrustedIdentity(event); break;
|
||||
}
|
||||
|
||||
callScreen.setRemoteVideoEnabled(event.isRemoteVideoEnabled());
|
||||
callScreen.updateAudioState(event.isBluetoothAvailable(), event.isMicrophoneEnabled());
|
||||
callScreen.setControlsEnabled(event.getState() != WebRtcViewModel.State.CALL_INCOMING);
|
||||
callScreen.setLocalVideoState(event.getLocalCameraState());
|
||||
callScreen.setLocalVideoState(event.getLocalCameraState(), event.getLocalRenderer());
|
||||
|
||||
if (event.getLocalCameraState().getCameraCount() > 0 && enableVideoIfAvailable) {
|
||||
enableVideoIfAvailable = false;
|
||||
handleSetMuteVideo(false);
|
||||
}
|
||||
}
|
||||
|
||||
private class HangupButtonListener implements WebRtcCallScreen.HangupButtonListener {
|
||||
|
@ -40,6 +40,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
@ -67,6 +68,7 @@ public class WebRtcCallScreen extends FrameLayout implements RecipientForeverObs
|
||||
private SurfaceViewRenderer localRenderer;
|
||||
private PercentFrameLayout localRenderLayout;
|
||||
private PercentFrameLayout remoteRenderLayout;
|
||||
private PercentFrameLayout localLargeRenderLayout;
|
||||
private TextView name;
|
||||
private TextView phoneNumber;
|
||||
private TextView label;
|
||||
@ -83,9 +85,8 @@ public class WebRtcCallScreen extends FrameLayout implements RecipientForeverObs
|
||||
|
||||
private WebRtcAnswerDeclineButton incomingCallButton;
|
||||
|
||||
private LiveRecipient recipient;
|
||||
private boolean minimized;
|
||||
|
||||
private LiveRecipient recipient;
|
||||
private boolean minimized;
|
||||
|
||||
public WebRtcCallScreen(Context context) {
|
||||
super(context);
|
||||
@ -110,8 +111,9 @@ public class WebRtcCallScreen extends FrameLayout implements RecipientForeverObs
|
||||
endCallButton.show();
|
||||
}
|
||||
|
||||
public void setActiveCall(@NonNull Recipient personInfo, @NonNull String message) {
|
||||
public void setActiveCall(@NonNull Recipient personInfo, @NonNull String message, @NonNull SurfaceViewRenderer localRenderer) {
|
||||
setCard(personInfo, message);
|
||||
setRinging(localRenderer);
|
||||
incomingCallButton.stopRingingAnimation();
|
||||
incomingCallButton.setVisibility(View.GONE);
|
||||
endCallButton.show();
|
||||
@ -194,22 +196,22 @@ public class WebRtcCallScreen extends FrameLayout implements RecipientForeverObs
|
||||
this.controls.setControlsEnabled(enabled);
|
||||
}
|
||||
|
||||
public void setLocalVideoState(@NonNull CameraState cameraState) {
|
||||
public void setLocalVideoState(@NonNull CameraState cameraState, @NonNull SurfaceViewRenderer localRenderer) {
|
||||
this.controls.setVideoAvailable(cameraState.getCameraCount() > 0);
|
||||
this.controls.setVideoEnabled(cameraState.isEnabled());
|
||||
this.controls.setCameraFlipAvailable(cameraState.getCameraCount() > 1);
|
||||
this.controls.setCameraFlipClickable(cameraState.getActiveDirection() != CameraState.Direction.PENDING);
|
||||
this.controls.setCameraFlipButtonEnabled(cameraState.getActiveDirection() == CameraState.Direction.BACK);
|
||||
|
||||
if (this.localRenderer != null) {
|
||||
this.localRenderer.setMirror(cameraState.getActiveDirection() == CameraState.Direction.FRONT);
|
||||
localRenderer.setMirror(cameraState.getActiveDirection() == CameraState.Direction.FRONT);
|
||||
|
||||
if (localRenderLayout.getChildCount() != 0) {
|
||||
displayLocalRendererInSmallLayout(!cameraState.isEnabled());
|
||||
} else {
|
||||
displayLocalRendererInLargeLayout(!cameraState.isEnabled());
|
||||
}
|
||||
|
||||
if (this.localRenderLayout.isHidden() == cameraState.isEnabled()) {
|
||||
this.localRenderLayout.setHidden(!cameraState.isEnabled());
|
||||
this.localRenderLayout.requestLayout();
|
||||
this.localRenderer.setVisibility(cameraState.isEnabled() ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
localRenderer.setVisibility(cameraState.isEnabled() ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
public void setRemoteVideoEnabled(boolean enabled) {
|
||||
@ -233,6 +235,42 @@ public class WebRtcCallScreen extends FrameLayout implements RecipientForeverObs
|
||||
return controls.isVideoEnabled();
|
||||
}
|
||||
|
||||
private void displayLocalRendererInLargeLayout(boolean hide) {
|
||||
if (localLargeRenderLayout.getChildCount() == 0) {
|
||||
localRenderLayout.removeAllViews();
|
||||
localLargeRenderLayout.addView(localRenderer);
|
||||
}
|
||||
|
||||
localRenderLayout.setHidden(true);
|
||||
localRenderLayout.requestLayout();
|
||||
|
||||
localLargeRenderLayout.setHidden(hide);
|
||||
localLargeRenderLayout.requestLayout();
|
||||
|
||||
if (hide) {
|
||||
photo.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
photo.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void displayLocalRendererInSmallLayout(boolean hide) {
|
||||
if (localRenderLayout.getChildCount() == 0) {
|
||||
localLargeRenderLayout.removeAllViews();
|
||||
localRenderLayout.addView(localRenderer);
|
||||
}
|
||||
|
||||
localLargeRenderLayout.setHidden(true);
|
||||
localLargeRenderLayout.requestLayout();
|
||||
|
||||
localRenderLayout.setHidden(hide);
|
||||
localRenderLayout.requestLayout();
|
||||
|
||||
if (remoteRenderLayout.isHidden()) {
|
||||
photo.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
inflater.inflate(R.layout.webrtc_call_screen, this, true);
|
||||
@ -241,6 +279,7 @@ public class WebRtcCallScreen extends FrameLayout implements RecipientForeverObs
|
||||
this.photo = findViewById(R.id.photo);
|
||||
this.localRenderLayout = findViewById(R.id.local_render_layout);
|
||||
this.remoteRenderLayout = findViewById(R.id.remote_render_layout);
|
||||
this.localLargeRenderLayout = findViewById(R.id.local_large_render_layout);
|
||||
this.phoneNumber = findViewById(R.id.phoneNumber);
|
||||
this.name = findViewById(R.id.name);
|
||||
this.label = findViewById(R.id.label);
|
||||
@ -266,10 +305,28 @@ public class WebRtcCallScreen extends FrameLayout implements RecipientForeverObs
|
||||
});
|
||||
}
|
||||
|
||||
private void setConnected(SurfaceViewRenderer localRenderer,
|
||||
SurfaceViewRenderer remoteRenderer)
|
||||
{
|
||||
if (localRenderLayout.getChildCount() == 0 && remoteRenderLayout.getChildCount() == 0) {
|
||||
private void setRinging(SurfaceViewRenderer localRenderer) {
|
||||
if (localLargeRenderLayout.getChildCount() == 0) {
|
||||
if (localRenderer.getParent() != null) {
|
||||
((ViewGroup)localRenderer.getParent()).removeView(localRenderer);
|
||||
}
|
||||
|
||||
localLargeRenderLayout.setPosition(0, 0, 100, 100);
|
||||
|
||||
localRenderer.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
localRenderer.setMirror(true);
|
||||
localRenderer.setZOrderMediaOverlay(true);
|
||||
|
||||
localLargeRenderLayout.addView(localRenderer);
|
||||
|
||||
this.localRenderer = localRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
private void setConnected(SurfaceViewRenderer localRenderer, SurfaceViewRenderer remoteRenderer) {
|
||||
if (localRenderLayout.getChildCount() == 0) {
|
||||
if (localRenderer.getParent() != null) {
|
||||
((ViewGroup)localRenderer.getParent()).removeView(localRenderer);
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.Conta
|
||||
|
||||
Field(@NonNull Context context, @NonNull Phone phoneNumber, @NonNull Locale locale) {
|
||||
this.value = ContactUtil.getPrettyPhoneNumber(phoneNumber, locale);
|
||||
this.iconResId = R.drawable.ic_call_white_24dp;
|
||||
this.iconResId = R.drawable.ic_phone_right_unlock_solid_24;
|
||||
this.iconUri = null;
|
||||
this.maxLines = 1;
|
||||
this.selectable = phoneNumber;
|
||||
|
@ -683,15 +683,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
if (isSecureText) {
|
||||
if (recipient.get().getExpireMessages() > 0) {
|
||||
inflater.inflate(R.menu.conversation_expiring_on, menu);
|
||||
|
||||
final MenuItem item = menu.findItem(R.id.menu_expiring_messages);
|
||||
final View actionView = MenuItemCompat.getActionView(item);
|
||||
final TextView badgeView = actionView.findViewById(R.id.expiration_badge);
|
||||
|
||||
badgeView.setText(ExpirationUtil.getExpirationAbbreviatedDisplayValue(this, recipient.get().getExpireMessages()));
|
||||
actionView.setOnClickListener(v -> onOptionsItemSelected(item));
|
||||
titleView.showExpiring(recipient);
|
||||
} else {
|
||||
inflater.inflate(R.menu.conversation_expiring_off, menu);
|
||||
titleView.clearExpiring();
|
||||
}
|
||||
}
|
||||
|
||||
@ -729,8 +724,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
if (recipient != null && recipient.get().isLocalNumber()) {
|
||||
if (isSecureText) menu.findItem(R.id.menu_call_secure).setVisible(false);
|
||||
else menu.findItem(R.id.menu_call_insecure).setVisible(false);
|
||||
if (isSecureText) {
|
||||
menu.findItem(R.id.menu_call_secure).setVisible(false);
|
||||
menu.findItem(R.id.menu_video_secure).setVisible(false);
|
||||
} else {
|
||||
menu.findItem(R.id.menu_call_insecure).setVisible(false);
|
||||
}
|
||||
|
||||
MenuItem muteItem = menu.findItem(R.id.menu_mute_notifications);
|
||||
|
||||
@ -798,6 +797,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
super.onOptionsItemSelected(item);
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_call_secure: handleDial(getRecipient(), true); return true;
|
||||
case R.id.menu_video_secure: handleVideo(getRecipient()); return true;
|
||||
case R.id.menu_call_insecure: handleDial(getRecipient(), false); return true;
|
||||
case R.id.menu_view_media: handleViewMedia(); return true;
|
||||
case R.id.menu_add_shortcut: handleAddShortcut(); return true;
|
||||
@ -1135,6 +1135,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
|
||||
private void handleVideo(final Recipient recipient) {
|
||||
if (recipient == null) return;
|
||||
|
||||
CommunicationActions.startVideoCall(this, recipient);
|
||||
}
|
||||
|
||||
private void handleDisplayGroupRecipients() {
|
||||
new GroupMembersDialog(this, getRecipient()).display();
|
||||
}
|
||||
|
@ -18,7 +18,9 @@ import com.annimon.stream.Stream;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
@ -38,6 +40,8 @@ public class ConversationTitleView extends RelativeLayout {
|
||||
private ImageView verified;
|
||||
private View subtitleContainer;
|
||||
private View verifiedSubtitle;
|
||||
private View expirationBadgeContainer;
|
||||
private TextView expirationBadgeTime;
|
||||
|
||||
public ConversationTitleView(Context context) {
|
||||
this(context, null);
|
||||
@ -45,25 +49,37 @@ public class ConversationTitleView extends RelativeLayout {
|
||||
|
||||
public ConversationTitleView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
this.content = ViewUtil.findById(this, R.id.content);
|
||||
this.title = ViewUtil.findById(this, R.id.title);
|
||||
this.subtitle = ViewUtil.findById(this, R.id.subtitle);
|
||||
this.verified = ViewUtil.findById(this, R.id.verified_indicator);
|
||||
this.subtitleContainer = ViewUtil.findById(this, R.id.subtitle_container);
|
||||
this.verifiedSubtitle = ViewUtil.findById(this, R.id.verified_subtitle);
|
||||
this.avatar = ViewUtil.findById(this, R.id.contact_photo_image);
|
||||
this.content = ViewUtil.findById(this, R.id.content);
|
||||
this.title = ViewUtil.findById(this, R.id.title);
|
||||
this.subtitle = ViewUtil.findById(this, R.id.subtitle);
|
||||
this.verified = ViewUtil.findById(this, R.id.verified_indicator);
|
||||
this.subtitleContainer = ViewUtil.findById(this, R.id.subtitle_container);
|
||||
this.verifiedSubtitle = ViewUtil.findById(this, R.id.verified_subtitle);
|
||||
this.avatar = ViewUtil.findById(this, R.id.contact_photo_image);
|
||||
this.expirationBadgeContainer = ViewUtil.findById(this, R.id.expiration_badge_container);
|
||||
this.expirationBadgeTime = ViewUtil.findById(this, R.id.expiration_badge);
|
||||
|
||||
ViewUtil.setTextViewGravityStart(this.title, getContext());
|
||||
ViewUtil.setTextViewGravityStart(this.subtitle, getContext());
|
||||
}
|
||||
|
||||
public void showExpiring(@NonNull LiveRecipient recipient) {
|
||||
expirationBadgeTime.setText(ExpirationUtil.getExpirationAbbreviatedDisplayValue(getContext(), recipient.get().getExpireMessages()));
|
||||
expirationBadgeContainer.setVisibility(View.VISIBLE);
|
||||
updateSubtitleVisibility();
|
||||
}
|
||||
|
||||
public void clearExpiring() {
|
||||
expirationBadgeContainer.setVisibility(View.GONE);
|
||||
updateSubtitleVisibility();
|
||||
}
|
||||
|
||||
public void setTitle(@NonNull GlideRequests glideRequests, @Nullable Recipient recipient) {
|
||||
this.subtitleContainer.setVisibility(View.VISIBLE);
|
||||
|
||||
@ -106,7 +122,7 @@ public class ConversationTitleView extends RelativeLayout {
|
||||
private void setComposeTitle() {
|
||||
this.title.setText(R.string.ConversationActivity_compose_message);
|
||||
this.subtitle.setText(null);
|
||||
this.subtitle.setVisibility(View.GONE);
|
||||
updateSubtitleVisibility();
|
||||
}
|
||||
|
||||
private void setRecipientTitle(Recipient recipient) {
|
||||
@ -128,11 +144,11 @@ public class ConversationTitleView extends RelativeLayout {
|
||||
|
||||
if (TextUtils.isEmpty(recipient.getProfileName())) {
|
||||
this.subtitle.setText(null);
|
||||
this.subtitle.setVisibility(View.GONE);
|
||||
} else {
|
||||
this.subtitle.setText("~" + recipient.getProfileName());
|
||||
this.subtitle.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
updateSubtitleVisibility();
|
||||
}
|
||||
|
||||
private void setContactRecipientTitle(Recipient recipient) {
|
||||
@ -140,11 +156,11 @@ public class ConversationTitleView extends RelativeLayout {
|
||||
|
||||
if (TextUtils.isEmpty(recipient.getCustomLabel())) {
|
||||
this.subtitle.setText(null);
|
||||
this.subtitle.setVisibility(View.GONE);
|
||||
} else {
|
||||
this.subtitle.setText(recipient.getCustomLabel());
|
||||
this.subtitle.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
updateSubtitleVisibility();
|
||||
}
|
||||
|
||||
private void setGroupRecipientTitle(Recipient recipient) {
|
||||
@ -161,7 +177,7 @@ public class ConversationTitleView extends RelativeLayout {
|
||||
.map(r -> r.toShortString(getContext()))
|
||||
.collect(Collectors.joining(", ")));
|
||||
|
||||
this.subtitle.setVisibility(View.VISIBLE);
|
||||
updateSubtitleVisibility();
|
||||
}
|
||||
|
||||
private void setSelfTitle() {
|
||||
@ -173,10 +189,15 @@ public class ConversationTitleView extends RelativeLayout {
|
||||
final String displayName = recipient.getDisplayName(getContext());
|
||||
this.title.setText(displayName);
|
||||
this.subtitle.setText(null);
|
||||
this.subtitle.setVisibility(View.GONE);
|
||||
updateVerifiedSubtitleVisibility();
|
||||
}
|
||||
|
||||
private void updateVerifiedSubtitleVisibility() {
|
||||
verifiedSubtitle.setVisibility(subtitle.getVisibility() != VISIBLE && verified.getVisibility() == VISIBLE ? VISIBLE : GONE);
|
||||
}
|
||||
|
||||
private void updateSubtitleVisibility() {
|
||||
subtitle.setVisibility(expirationBadgeContainer.getVisibility() != VISIBLE && !TextUtils.isEmpty(subtitle.getText()) ? VISIBLE : GONE);
|
||||
updateVerifiedSubtitleVisibility();
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ public class ContactPreference extends Preference {
|
||||
private ImageView messageButton;
|
||||
private ImageView callButton;
|
||||
private ImageView secureCallButton;
|
||||
private ImageView secureVideoButton;
|
||||
|
||||
private Listener listener;
|
||||
private boolean secure;
|
||||
@ -48,9 +49,10 @@ public class ContactPreference extends Preference {
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
super.onBindViewHolder(view);
|
||||
|
||||
this.messageButton = (ImageView) view.findViewById(R.id.message);
|
||||
this.callButton = (ImageView) view.findViewById(R.id.call);
|
||||
this.secureCallButton = (ImageView) view.findViewById(R.id.secure_call);
|
||||
this.messageButton = (ImageView) view.findViewById(R.id.message);
|
||||
this.callButton = (ImageView) view.findViewById(R.id.call);
|
||||
this.secureCallButton = (ImageView) view.findViewById(R.id.secure_call);
|
||||
this.secureVideoButton = (ImageView) view.findViewById(R.id.secure_video);
|
||||
|
||||
if (listener != null) setListener(listener);
|
||||
setSecure(secure);
|
||||
@ -59,8 +61,9 @@ public class ContactPreference extends Preference {
|
||||
public void setSecure(boolean secure) {
|
||||
this.secure = secure;
|
||||
|
||||
if (secureCallButton != null) secureCallButton.setVisibility(secure ? View.VISIBLE : View.GONE);
|
||||
if (callButton != null) callButton.setVisibility(secure ? View.GONE : View.VISIBLE);
|
||||
if (secureCallButton != null) secureCallButton.setVisibility(secure ? View.VISIBLE : View.GONE);
|
||||
if (secureVideoButton != null) secureVideoButton.setVisibility(secure ? View.VISIBLE : View.GONE);
|
||||
if (callButton != null) callButton.setVisibility(secure ? View.GONE : View.VISIBLE);
|
||||
|
||||
int color;
|
||||
|
||||
@ -70,22 +73,25 @@ public class ContactPreference extends Preference {
|
||||
color = getContext().getResources().getColor(R.color.grey_600);
|
||||
}
|
||||
|
||||
if (messageButton != null) messageButton.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
if (secureCallButton != null) secureCallButton.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
if (callButton != null) callButton.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
if (messageButton != null) messageButton.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
if (secureCallButton != null) secureCallButton.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
if (secureVideoButton != null) secureVideoButton.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
if (callButton != null) callButton.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
this.listener = listener;
|
||||
|
||||
if (this.messageButton != null) this.messageButton.setOnClickListener(v -> listener.onMessageClicked());
|
||||
if (this.secureCallButton != null) this.secureCallButton.setOnClickListener(v -> listener.onSecureCallClicked());
|
||||
if (this.callButton != null) this.callButton.setOnClickListener(v -> listener.onInSecureCallClicked());
|
||||
if (this.messageButton != null) this.messageButton.setOnClickListener(v -> listener.onMessageClicked());
|
||||
if (this.secureCallButton != null) this.secureCallButton.setOnClickListener(v -> listener.onSecureCallClicked());
|
||||
if (this.secureVideoButton != null) this.secureVideoButton.setOnClickListener(v -> listener.onSecureVideoClicked());
|
||||
if (this.callButton != null) this.callButton.setOnClickListener(v -> listener.onInSecureCallClicked());
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
public void onMessageClicked();
|
||||
public void onSecureCallClicked();
|
||||
public void onSecureVideoClicked();
|
||||
public void onInSecureCallClicked();
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
@ -27,29 +28,34 @@ public class CommunicationActions {
|
||||
if (TelephonyUtil.isAnyPstnLineBusy(activity)) {
|
||||
Toast.makeText(activity,
|
||||
R.string.CommunicationActions_a_cellular_call_is_already_in_progress,
|
||||
Toast.LENGTH_SHORT
|
||||
).show();
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
|
||||
Permissions.with(activity)
|
||||
.request(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(activity.getString(R.string.ConversationActivity_to_call_s_signal_needs_access_to_your_microphone_and_camera, recipient.toShortString(activity)),
|
||||
R.drawable.ic_mic_solid_24,
|
||||
R.drawable.ic_videocam_white_48dp)
|
||||
.withPermanentDenialDialog(activity.getString(R.string.ConversationActivity_signal_needs_the_microphone_and_camera_permissions_in_order_to_call_s, recipient.toShortString(activity)))
|
||||
.onAllGranted(() -> {
|
||||
Intent intent = new Intent(activity, WebRtcCallService.class);
|
||||
intent.setAction(WebRtcCallService.ACTION_OUTGOING_CALL);
|
||||
intent.putExtra(WebRtcCallService.EXTRA_REMOTE_RECIPIENT, recipient.getId());
|
||||
activity.startService(intent);
|
||||
new AlertDialog.Builder(activity)
|
||||
.setMessage(R.string.CommunicationActions_start_voice_call)
|
||||
.setPositiveButton(R.string.CommunicationActions_call, (d, w) -> startCallInternal(activity, recipient, false))
|
||||
.setNegativeButton(R.string.CommunicationActions_cancel, (d, w) -> d.dismiss())
|
||||
.setCancelable(true)
|
||||
.show();
|
||||
}
|
||||
|
||||
Intent activityIntent = new Intent(activity, WebRtcCallActivity.class);
|
||||
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
activity.startActivity(activityIntent);
|
||||
})
|
||||
.execute();
|
||||
public static void startVideoCall(@NonNull Activity activity, @NonNull Recipient recipient) {
|
||||
if (TelephonyUtil.isAnyPstnLineBusy(activity)) {
|
||||
Toast.makeText(activity,
|
||||
R.string.CommunicationActions_a_cellular_call_is_already_in_progress,
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(activity)
|
||||
.setMessage(R.string.CommunicationActions_start_video_call)
|
||||
.setPositiveButton(R.string.CommunicationActions_call, (d, w) -> startCallInternal(activity, recipient, true))
|
||||
.setNegativeButton(R.string.CommunicationActions_cancel, (d, w) -> d.dismiss())
|
||||
.setCancelable(true)
|
||||
.show();
|
||||
}
|
||||
|
||||
public static void startConversation(@NonNull Context context, @NonNull Recipient recipient, @Nullable String text) {
|
||||
@ -103,4 +109,31 @@ public class CommunicationActions {
|
||||
Toast.makeText(context, R.string.CommunicationActions_no_browser_found, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void startCallInternal(@NonNull Activity activity, @NonNull Recipient recipient, boolean isVideo) {
|
||||
Permissions.with(activity)
|
||||
.request(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(activity.getString(R.string.ConversationActivity_to_call_s_signal_needs_access_to_your_microphone_and_camera, recipient.getDisplayName(activity)),
|
||||
R.drawable.ic_mic_solid_24,
|
||||
R.drawable.ic_video_solid_24_tinted)
|
||||
.withPermanentDenialDialog(activity.getString(R.string.ConversationActivity_signal_needs_the_microphone_and_camera_permissions_in_order_to_call_s, recipient.getDisplayName(activity)))
|
||||
.onAllGranted(() -> {
|
||||
Intent intent = new Intent(activity, WebRtcCallService.class);
|
||||
intent.setAction(WebRtcCallService.ACTION_OUTGOING_CALL);
|
||||
intent.putExtra(WebRtcCallService.EXTRA_REMOTE_RECIPIENT, recipient.getId());
|
||||
activity.startService(intent);
|
||||
|
||||
Intent activityIntent = new Intent(activity, WebRtcCallActivity.class);
|
||||
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
if (isVideo) {
|
||||
activityIntent.putExtra(WebRtcCallActivity.EXTRA_ENABLE_VIDEO_IF_AVAILABLE, true);
|
||||
}
|
||||
|
||||
activity.startActivity(activityIntent);
|
||||
})
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
|