WIP - dialpad and dtmf sending

This commit is contained in:
Ketroc 2021-07-03 11:20:38 -04:00 committed by Stephen Paul Weber
parent 6bd552f6a3
commit 358271b767
No known key found for this signature in database
GPG key ID: D11C2911CE519CDE
11 changed files with 589 additions and 7 deletions

View file

@ -38,6 +38,7 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import org.jetbrains.annotations.NotNull;
import org.webrtc.RendererCommon;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoTrack;
@ -149,6 +150,35 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
this.binding = DataBindingUtil.setContentView(this, R.layout.activity_rtp_session);
setSupportActionBar(binding.toolbar);
//TODO: remove this - for testing dialpad input
//((DialpadView)findViewById(R.id.action_dialpad)).
findViewById(R.id.dialpad_1_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_2_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_3_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_4_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_5_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_6_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_7_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_8_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_9_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_0_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_asterisk_holder).setOnClickListener(view -> dialpadPressed(view));
findViewById(R.id.dialpad_pound_holder).setOnClickListener(view -> dialpadPressed(view));
if (savedInstanceState != null) {
int dialpad_visibility = savedInstanceState.getInt("dialpad_visibility");
System.out.println("dialpad_visibility onCreate = " + dialpad_visibility);
findViewById(R.id.dialpad).setVisibility(dialpad_visibility);
}
}
private void dialpadPressed(View dialpadKeyHolderView) {
JingleRtpConnection rtpConnection = requireRtpConnection();
rtpConnection.applyDtmfTone(dialpadKeyHolderView.getTag().toString());
}
@Override
@ -156,8 +186,10 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
getMenuInflater().inflate(R.menu.activity_rtp_session, menu);
final MenuItem help = menu.findItem(R.id.action_help);
final MenuItem gotoChat = menu.findItem(R.id.action_goto_chat);
final MenuItem dialpad = menu.findItem(R.id.action_dialpad);
help.setVisible(isHelpButtonVisible());
gotoChat.setVisible(isSwitchToConversationVisible());
dialpad.setVisible(isAudioOnlyConversation());
return super.onCreateOptionsMenu(menu);
}
@ -192,12 +224,29 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
return connection != null && STATES_SHOWING_SWITCH_TO_CHAT.contains(connection.getEndUserState());
}
private boolean isAudioOnlyConversation() {
final JingleRtpConnection connection =
this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
return connection != null &&
connection.getEndUserState() == RtpEndUserState.CONNECTED &&
!connection.isVideoEnabled();
}
private void switchToConversation() {
final Contact contact = getWith();
final Conversation conversation = xmppConnectionService.findOrCreateConversation(contact.getAccount(), contact.getJid(), false, true);
switchToConversation(conversation);
}
private void toggleDialpadVisibility() {
if (binding.dialpad.getVisibility() == View.VISIBLE) {
binding.dialpad.setVisibility(View.GONE);
}
else {
binding.dialpad.setVisibility(View.VISIBLE);
}
}
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.action_help:
@ -206,6 +255,9 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
case R.id.action_goto_chat:
switchToConversation();
break;
case R.id.action_dialpad:
toggleDialpadVisibility();
break;
}
return super.onOptionsItemSelected(item);
}
@ -1187,6 +1239,14 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
}
}
@Override
protected void onSaveInstanceState(@NonNull @NotNull Bundle outState) {
super.onSaveInstanceState(outState);
int visibility = findViewById(R.id.action_dialpad).getVisibility();
System.out.println("visibility onSave = " + visibility);
outState.putInt("dialpad_visibility", visibility);
}
private void updateRtpSessionProposalState(final Account account, final Jid with, final RtpEndUserState state) {
final Intent currentIntent = getIntent();
final String withExtra = currentIntent == null ? null : currentIntent.getStringExtra(EXTRA_WITH);

View file

@ -0,0 +1,73 @@
/*
* Copyright 2012-2015 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.siacs.conversations.ui.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import androidx.constraintlayout.widget.ConstraintLayout;
import eu.siacs.conversations.R;
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
public class DialpadView extends ConstraintLayout implements View.OnClickListener {
public DialpadView(Context context) {
super(context);
init();
}
public DialpadView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DialpadView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
inflate(getContext(), R.layout.dialpad, this);
initViews();
}
private void initViews() {
findViewById(R.id.dialpad_1_holder).setOnClickListener(this);
findViewById(R.id.dialpad_2_holder).setOnClickListener(this);
findViewById(R.id.dialpad_3_holder).setOnClickListener(this);
findViewById(R.id.dialpad_4_holder).setOnClickListener(this);
findViewById(R.id.dialpad_5_holder).setOnClickListener(this);
findViewById(R.id.dialpad_6_holder).setOnClickListener(this);
findViewById(R.id.dialpad_7_holder).setOnClickListener(this);
findViewById(R.id.dialpad_8_holder).setOnClickListener(this);
findViewById(R.id.dialpad_9_holder).setOnClickListener(this);
findViewById(R.id.dialpad_0_holder).setOnClickListener(this);
findViewById(R.id.dialpad_asterisk_holder).setOnClickListener(this);
findViewById(R.id.dialpad_pound_holder).setOnClickListener(this);
}
@Override
public void onClick(View v) {
/* TODO: this widget doesn't know anything about the RTP Connection,
so how to make this widget generic but also able to send touch-tone sounds
*/
System.out.println("v.getTag() = " + v.getTag());
}
}

View file

@ -20,6 +20,7 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import org.webrtc.DtmfSender;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.PeerConnection;
@ -231,6 +232,17 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
}
}
//TODO: remove - hack to test dtmfSending
public DtmfSender getDtmfSender() {
return webRTCWrapper.getDtmfSender();
}
//FIXME: possible implementation
public boolean applyDtmfTone(String tone) {
return webRTCWrapper.applyDtmfTone(tone);
}
private void receiveSessionTerminate(final JinglePacket jinglePacket) {
respondOk(jinglePacket);
final JinglePacket.ReasonWrapper wrapper = jinglePacket.getReason();

View file

@ -148,7 +148,7 @@ class ToneManager {
}
}
private void startTone(final int toneType, final int durationMs) {
public void startTone(final int toneType, final int durationMs) {
if (toneGenerator != null) {
this.toneGenerator.startTone(toneType, durationMs);
} else {

View file

@ -1,6 +1,7 @@
package eu.siacs.conversations.xmpp.jingle;
import android.content.Context;
import android.media.ToneGenerator;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@ -8,6 +9,7 @@ import android.util.Log;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
@ -25,6 +27,7 @@ import org.webrtc.CandidatePairChangeEvent;
import org.webrtc.DataChannel;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.DtmfSender;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
@ -47,6 +50,7 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -83,6 +87,25 @@ public class WebRTCWrapper {
.add("GT-I9505") // Samsung Galaxy S4 (jfltexx)
.build();
private static final int TONE_DURATION = 200;
private static final Map<String,Integer> TONE_CODES;
static {
ImmutableMap.Builder<String,Integer> builder = new ImmutableMap.Builder<>();
builder.put("0", ToneGenerator.TONE_DTMF_0);
builder.put("1", ToneGenerator.TONE_DTMF_1);
builder.put("2", ToneGenerator.TONE_DTMF_2);
builder.put("3", ToneGenerator.TONE_DTMF_3);
builder.put("4", ToneGenerator.TONE_DTMF_4);
builder.put("5", ToneGenerator.TONE_DTMF_5);
builder.put("6", ToneGenerator.TONE_DTMF_6);
builder.put("7", ToneGenerator.TONE_DTMF_7);
builder.put("8", ToneGenerator.TONE_DTMF_8);
builder.put("9", ToneGenerator.TONE_DTMF_9);
builder.put("*", ToneGenerator.TONE_DTMF_S);
builder.put("#", ToneGenerator.TONE_DTMF_P);
TONE_CODES = builder.build();
}
private static final int CAPTURING_RESOLUTION = 1920;
private static final int CAPTURING_MAX_FRAME_RATE = 30;
@ -507,6 +530,20 @@ public class WebRTCWrapper {
return peerConnection;
}
//TODO: remove - hack to test dtmfSending
public DtmfSender getDtmfSender() {
return peerConnection.getSenders().get(0).dtmf();
}
public boolean applyDtmfTone(String tone) {
if (toneManager == null || peerConnection.getSenders().isEmpty()) {
return false;
}
peerConnection.getSenders().get(0).dtmf().insertDtmf(tone, TONE_DURATION, 100);
toneManager.startTone(TONE_CODES.get(tone), TONE_DURATION);
return true;
}
void addIceCandidate(IceCandidate iceCandidate) {
requirePeerConnection().addIceCandidate(iceCandidate);
}

View file

@ -77,6 +77,14 @@
android:textAppearance="@style/TextAppearance.Conversations.Title.Monospace"
tools:text="01:23" />
<eu.siacs.conversations.ui.widget.DialpadView
layout="@layout/dialpad"
android:id="@+id/dialpad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="gone" />
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/contact_photo"
android:layout_width="@dimen/publish_avatar_size"
@ -163,7 +171,7 @@
app:elevation="4dp"
app:fabCustomSize="72dp"
app:maxImageSize="36dp"
tools:visibility="visible" />
tools:visibility="gone" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/accept_call"
@ -178,7 +186,7 @@
app:elevation="4dp"
app:fabCustomSize="72dp"
app:maxImageSize="36dp"
tools:visibility="visible" />
tools:visibility="gone" />
</RelativeLayout>
@ -189,7 +197,7 @@
android:layout_centerVertical="true"
android:layout_margin="@dimen/in_call_fab_margin"
android:layout_toStartOf="@+id/end_call"
android:visibility="gone"
android:visibility="visible"
app:backgroundTint="?color_background_primary"
app:elevation="4dp"
app:fabSize="mini"
@ -215,7 +223,7 @@
android:layout_centerVertical="true"
android:layout_margin="@dimen/in_call_fab_margin"
android:layout_toEndOf="@+id/end_call"
android:visibility="gone"
android:visibility="visible"
app:backgroundTint="?color_background_primary"
app:elevation="4dp"
app:fabSize="mini"
@ -228,7 +236,7 @@
android:layout_centerVertical="true"
android:layout_margin="@dimen/in_call_fab_margin"
android:layout_toEndOf="@+id/in_call_action_right"
android:visibility="gone"
android:visibility="visible"
app:backgroundTint="?color_background_primary"
app:elevation="4dp"
app:fabSize="mini"

View file

@ -0,0 +1,368 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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/dialpad_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:focusableInTouchMode="true"
android:paddingTop="@dimen/medium_margin"
tools:ignore="HardcodedText">
<RelativeLayout
android:id="@+id/dialpad_1_holder"
android:tag="1"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="@dimen/activity_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="@+id/dialpad_2_holder"
app:layout_constraintEnd_toStartOf="@+id/dialpad_2_holder"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/dialpad_2_holder"
android:focusable="true" >
<TextView
android:id="@+id/dialpad_1"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="1" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_2_holder"
android:tag="2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/medium_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toTopOf="@+id/dialpad_5_holder"
app:layout_constraintEnd_toStartOf="@+id/dialpad_3_holder"
app:layout_constraintStart_toEndOf="@+id/dialpad_1_holder">
<TextView
android:id="@+id/dialpad_2"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="2" />
<TextView
android:id="@+id/dialpad_2_letters"
style="@style/DialpadLetterStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/dialpad_2"
android:layout_centerHorizontal="true"
android:layout_marginBottom="@dimen/medium_margin"
android:gravity="center_horizontal"
android:text="ABC" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_3_holder"
android:tag="3"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="@dimen/activity_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="@+id/dialpad_2_holder"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/dialpad_2_holder"
app:layout_constraintTop_toTopOf="@+id/dialpad_2_holder">
<TextView
android:id="@+id/dialpad_3"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="3" />
<TextView
android:id="@+id/dialpad_3_letters"
style="@style/DialpadLetterStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/dialpad_3"
android:layout_centerHorizontal="true"
android:layout_marginBottom="@dimen/medium_margin"
android:gravity="center_horizontal"
android:text="DEF" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_4_holder"
android:tag="4"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="@dimen/activity_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="@+id/dialpad_5_holder"
app:layout_constraintEnd_toStartOf="@+id/dialpad_5_holder"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/dialpad_5_holder">
<TextView
android:id="@+id/dialpad_4"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="4" />
<TextView
android:id="@+id/dialpad_4_letters"
style="@style/DialpadLetterStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/dialpad_4"
android:layout_centerHorizontal="true"
android:layout_marginBottom="@dimen/medium_margin"
android:gravity="center_horizontal"
android:text="GHI" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_5_holder"
android:tag="5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/medium_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toTopOf="@+id/dialpad_8_holder"
app:layout_constraintEnd_toStartOf="@+id/dialpad_6_holder"
app:layout_constraintStart_toEndOf="@+id/dialpad_4_holder">
<TextView
android:id="@+id/dialpad_5"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="5" />
<TextView
android:id="@+id/dialpad_5_letters"
style="@style/DialpadLetterStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/dialpad_5"
android:layout_centerHorizontal="true"
android:layout_marginBottom="@dimen/medium_margin"
android:gravity="center_horizontal"
android:text="JKL" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_6_holder"
android:tag="6"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="@dimen/activity_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="@+id/dialpad_5_holder"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/dialpad_5_holder"
app:layout_constraintTop_toTopOf="@+id/dialpad_5_holder">
<TextView
android:id="@+id/dialpad_6"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="6" />
<TextView
android:id="@+id/dialpad_6_letters"
style="@style/DialpadLetterStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/dialpad_6"
android:layout_centerHorizontal="true"
android:layout_marginBottom="@dimen/medium_margin"
android:gravity="center_horizontal"
android:text="MNO" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_7_holder"
android:tag="7"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="@dimen/activity_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="@+id/dialpad_8_holder"
app:layout_constraintEnd_toStartOf="@+id/dialpad_8_holder"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/dialpad_8_holder">
<TextView
android:id="@+id/dialpad_7"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="7" />
<TextView
android:id="@+id/dialpad_7_letters"
style="@style/DialpadLetterStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/dialpad_7"
android:layout_centerHorizontal="true"
android:layout_marginBottom="@dimen/medium_margin"
android:gravity="center_horizontal"
android:text="PQRS" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_8_holder"
android:tag="8"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/medium_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toTopOf="@+id/dialpad_0_holder"
app:layout_constraintEnd_toStartOf="@+id/dialpad_9_holder"
app:layout_constraintStart_toEndOf="@+id/dialpad_7_holder">
<TextView
android:id="@+id/dialpad_8"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="8" />
<TextView
android:id="@+id/dialpad_8_letters"
style="@style/DialpadLetterStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/dialpad_8"
android:layout_centerHorizontal="true"
android:layout_marginBottom="@dimen/medium_margin"
android:gravity="center_horizontal"
android:text="TUV" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_9_holder"
android:tag="9"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="@dimen/activity_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="@+id/dialpad_8_holder"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/dialpad_8_holder"
app:layout_constraintTop_toTopOf="@+id/dialpad_8_holder">
<TextView
android:id="@+id/dialpad_9"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="9" />
<TextView
android:id="@+id/dialpad_9_letters"
style="@style/DialpadLetterStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/dialpad_9"
android:layout_centerHorizontal="true"
android:layout_marginBottom="@dimen/medium_margin"
android:gravity="center_horizontal"
android:text="WXYZ" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_asterisk_holder"
android:tag="*"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="@dimen/activity_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="@+id/dialpad_0_holder"
app:layout_constraintEnd_toStartOf="@+id/dialpad_0_holder"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/dialpad_0_holder">
<TextView
android:id="@+id/dialpad_asterisk"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="*" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_0_holder"
android:tag="0"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/activity_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/dialpad_pound_holder"
app:layout_constraintStart_toEndOf="@+id/dialpad_asterisk_holder">
<TextView
android:id="@+id/dialpad_0"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="0" />
<TextView
android:id="@+id/dialpad_plus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/dialpad_0"
android:layout_alignBottom="@+id/dialpad_0"
android:layout_centerHorizontal="true"
android:layout_toEndOf="@+id/dialpad_0"
android:gravity="center"
android:paddingStart="@dimen/small_margin"
android:paddingTop="@dimen/small_margin"
android:text="+"
android:textSize="@dimen/actionbar_text_size" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/dialpad_pound_holder"
android:tag="#"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="@dimen/activity_margin"
android:background="?attr/selectableItemBackgroundBorderless"
app:layout_constraintBottom_toBottomOf="@+id/dialpad_0_holder"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/dialpad_0_holder"
app:layout_constraintTop_toTopOf="@+id/dialpad_0_holder">
<TextView
android:id="@+id/dialpad_pound"
style="@style/DialpadNumberStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginEnd="@dimen/activity_margin"
android:text="#" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -12,5 +12,11 @@
android:id="@+id/action_goto_chat"
android:icon="?attr/icon_goto_chat"
android:title="@string/switch_to_conversation"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_dialpad"
android:icon="?attr/icon_new"
android:title="@string/action_dialpad"
app:showAsAction="always" />
</menu>

View file

@ -44,4 +44,11 @@
<dimen name="local_video_preview_height">128dp</dimen>
<dimen name="local_video_preview_width">96dp</dimen>
<dimen name="rtp_session_duration_top_margin">24dp</dimen>
<dimen name="dialpad_text_size">30sp</dimen>
<dimen name="smaller_text_size">12sp</dimen>
<dimen name="medium_margin">8dp</dimen>
<dimen name="activity_margin">16dp</dimen>
<dimen name="small_margin">4dp</dimen>
<dimen name="actionbar_text_size">20sp</dimen>
</resources>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="action_settings">Settings</string>
<string name="action_dialpad">Dialpad</string>
<string name="action_add">New conversation</string>
<string name="action_accounts">Manage accounts</string>
<string name="action_account">Manage account</string>

View file

@ -159,4 +159,14 @@
<style name="TextAppearance.Conversations.Body1.Secondary.OnDark" parent="TextAppearance.Conversations.Body1">
<item name="android:textColor">@color/white70</item>
</style>
</resources>
<style name="DialpadNumberStyle">
<item name="android:includeFontPadding">false</item>
<item name="android:textSize">@dimen/dialpad_text_size</item>
</style>
<style name="DialpadLetterStyle">
<item name="android:textSize">@dimen/smaller_text_size</item>
<item name="android:alpha">0.8</item>
</style>
</resources>