show call log messages in conversation stream
|
@ -57,6 +57,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
||||||
public static final int TYPE_STATUS = 3;
|
public static final int TYPE_STATUS = 3;
|
||||||
public static final int TYPE_PRIVATE = 4;
|
public static final int TYPE_PRIVATE = 4;
|
||||||
public static final int TYPE_PRIVATE_FILE = 5;
|
public static final int TYPE_PRIVATE_FILE = 5;
|
||||||
|
public static final int TYPE_RTP_SESSION = 6;
|
||||||
|
|
||||||
public static final String CONVERSATION = "conversationUuid";
|
public static final String CONVERSATION = "conversationUuid";
|
||||||
public static final String COUNTERPART = "counterpart";
|
public static final String COUNTERPART = "counterpart";
|
||||||
|
@ -151,6 +152,31 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Message(Conversation conversation, int status, int type, final String remoteMsgId) {
|
||||||
|
this(conversation, java.util.UUID.randomUUID().toString(),
|
||||||
|
conversation.getUuid(),
|
||||||
|
conversation.getJid() == null ? null : conversation.getJid().asBareJid(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
Message.ENCRYPTION_NONE,
|
||||||
|
status,
|
||||||
|
type,
|
||||||
|
false,
|
||||||
|
remoteMsgId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
protected Message(final Conversational conversation, final String uuid, final String conversationUUid, final Jid counterpart,
|
protected Message(final Conversational conversation, final String uuid, final String conversationUUid, final Jid counterpart,
|
||||||
final Jid trueCounterpart, final String body, final long timeSent,
|
final Jid trueCounterpart, final String body, final long timeSent,
|
||||||
final int encryption, final int status, final int type, final boolean carbon,
|
final int encryption, final int status, final int type, final boolean carbon,
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package eu.siacs.conversations.entities;
|
||||||
|
|
||||||
|
import android.support.annotation.DrawableRes;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.R;
|
||||||
|
|
||||||
|
public class RtpSessionStatus {
|
||||||
|
|
||||||
|
public final boolean successful;
|
||||||
|
public final long duration;
|
||||||
|
|
||||||
|
|
||||||
|
public RtpSessionStatus(boolean successful, long duration) {
|
||||||
|
this.successful = successful;
|
||||||
|
this.duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return successful + ":" + duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RtpSessionStatus of(final String body) {
|
||||||
|
final String[] parts = Strings.nullToEmpty(body).split(":", 2);
|
||||||
|
long duration = 0;
|
||||||
|
if (parts.length == 2) {
|
||||||
|
try {
|
||||||
|
duration = Long.parseLong(parts[1]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean made;
|
||||||
|
try {
|
||||||
|
made = Boolean.parseBoolean(parts[0]);
|
||||||
|
} catch (Exception e) {
|
||||||
|
made = false;
|
||||||
|
}
|
||||||
|
return new RtpSessionStatus(made, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @DrawableRes int getDrawable(final boolean received, final boolean successful, final boolean darkTheme) {
|
||||||
|
if (received) {
|
||||||
|
if (successful) {
|
||||||
|
return darkTheme ? R.drawable.ic_call_received_white_18dp : R.drawable.ic_call_received_black_18dp;
|
||||||
|
} else {
|
||||||
|
return darkTheme ? R.drawable.ic_call_missed_white_18dp : R.drawable.ic_call_missed_black_18dp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (successful) {
|
||||||
|
return darkTheme ? R.drawable.ic_call_made_white_18dp : R.drawable.ic_call_made_black_18dp;
|
||||||
|
} else {
|
||||||
|
return darkTheme ? R.drawable.ic_call_missed_outgoing_white_18dp : R.drawable.ic_call_missed_outgoing_black_18dp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,6 +49,7 @@ import eu.siacs.conversations.entities.Conversational;
|
||||||
import eu.siacs.conversations.entities.DownloadableFile;
|
import eu.siacs.conversations.entities.DownloadableFile;
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.entities.Message.FileParams;
|
import eu.siacs.conversations.entities.Message.FileParams;
|
||||||
|
import eu.siacs.conversations.entities.RtpSessionStatus;
|
||||||
import eu.siacs.conversations.entities.Transferable;
|
import eu.siacs.conversations.entities.Transferable;
|
||||||
import eu.siacs.conversations.http.P1S3UrlStreamHandler;
|
import eu.siacs.conversations.http.P1S3UrlStreamHandler;
|
||||||
import eu.siacs.conversations.persistance.FileBackend;
|
import eu.siacs.conversations.persistance.FileBackend;
|
||||||
|
@ -72,6 +73,7 @@ import eu.siacs.conversations.utils.Emoticons;
|
||||||
import eu.siacs.conversations.utils.GeoHelper;
|
import eu.siacs.conversations.utils.GeoHelper;
|
||||||
import eu.siacs.conversations.utils.MessageUtils;
|
import eu.siacs.conversations.utils.MessageUtils;
|
||||||
import eu.siacs.conversations.utils.StylingHelper;
|
import eu.siacs.conversations.utils.StylingHelper;
|
||||||
|
import eu.siacs.conversations.utils.TimeframeUtils;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xmpp.mam.MamReference;
|
import eu.siacs.conversations.xmpp.mam.MamReference;
|
||||||
import rocks.xmpp.addr.Jid;
|
import rocks.xmpp.addr.Jid;
|
||||||
|
@ -83,6 +85,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
private static final int RECEIVED = 1;
|
private static final int RECEIVED = 1;
|
||||||
private static final int STATUS = 2;
|
private static final int STATUS = 2;
|
||||||
private static final int DATE_SEPARATOR = 3;
|
private static final int DATE_SEPARATOR = 3;
|
||||||
|
private static final int RTP_SESSION = 4;
|
||||||
private final XmppActivity activity;
|
private final XmppActivity activity;
|
||||||
private final ListSelectionManager listSelectionManager = new ListSelectionManager();
|
private final ListSelectionManager listSelectionManager = new ListSelectionManager();
|
||||||
private final AudioPlayer audioPlayer;
|
private final AudioPlayer audioPlayer;
|
||||||
|
@ -92,6 +95,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
private OnContactPictureLongClicked mOnContactPictureLongClickedListener;
|
private OnContactPictureLongClicked mOnContactPictureLongClickedListener;
|
||||||
private boolean mUseGreenBackground = false;
|
private boolean mUseGreenBackground = false;
|
||||||
private OnQuoteListener onQuoteListener;
|
private OnQuoteListener onQuoteListener;
|
||||||
|
|
||||||
public MessageAdapter(XmppActivity activity, List<Message> messages) {
|
public MessageAdapter(XmppActivity activity, List<Message> messages) {
|
||||||
super(activity, 0, messages);
|
super(activity, 0, messages);
|
||||||
this.audioPlayer = new AudioPlayer(this);
|
this.audioPlayer = new AudioPlayer(this);
|
||||||
|
@ -101,7 +105,6 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static void resetClickListener(View... views) {
|
private static void resetClickListener(View... views) {
|
||||||
for (View view : views) {
|
for (View view : views) {
|
||||||
view.setOnClickListener(null);
|
view.setOnClickListener(null);
|
||||||
|
@ -135,7 +138,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getViewTypeCount() {
|
public int getViewTypeCount() {
|
||||||
return 4;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getItemViewType(Message message) {
|
private int getItemViewType(Message message) {
|
||||||
|
@ -145,12 +148,14 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
} else {
|
} else {
|
||||||
return STATUS;
|
return STATUS;
|
||||||
}
|
}
|
||||||
|
} else if (message.getType() == Message.TYPE_RTP_SESSION) {
|
||||||
|
return RTP_SESSION;
|
||||||
} else if (message.getStatus() <= Message.STATUS_RECEIVED) {
|
} else if (message.getStatus() <= Message.STATUS_RECEIVED) {
|
||||||
return RECEIVED;
|
return RECEIVED;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
return SENT;
|
return SENT;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
|
@ -283,7 +288,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
final String formattedTime = UIHelper.readableTimeDifferenceFull(getContext(), message.getMergedTimeSent());
|
final String formattedTime = UIHelper.readableTimeDifferenceFull(getContext(), message.getMergedTimeSent());
|
||||||
final String bodyLanguage = message.getBodyLanguage();
|
final String bodyLanguage = message.getBodyLanguage();
|
||||||
final String bodyLanguageInfo = bodyLanguage == null ? "" : String.format(" \u00B7 %s", bodyLanguage.toUpperCase(Locale.US));
|
final String bodyLanguageInfo = bodyLanguage == null ? "" : String.format(" \u00B7 %s", bodyLanguage.toUpperCase(Locale.US));
|
||||||
if (message.getStatus() <= Message.STATUS_RECEIVED) { ;
|
if (message.getStatus() <= Message.STATUS_RECEIVED) {
|
||||||
if ((filesize != null) && (info != null)) {
|
if ((filesize != null) && (info != null)) {
|
||||||
viewHolder.time.setText(formattedTime + " \u00B7 " + filesize + " \u00B7 " + info + bodyLanguageInfo);
|
viewHolder.time.setText(formattedTime + " \u00B7 " + filesize + " \u00B7 " + info + bodyLanguageInfo);
|
||||||
} else if ((filesize == null) && (info != null)) {
|
} else if ((filesize == null) && (info != null)) {
|
||||||
|
@ -622,6 +627,13 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
view = activity.getLayoutInflater().inflate(R.layout.message_date_bubble, parent, false);
|
view = activity.getLayoutInflater().inflate(R.layout.message_date_bubble, parent, false);
|
||||||
viewHolder.status_message = view.findViewById(R.id.message_body);
|
viewHolder.status_message = view.findViewById(R.id.message_body);
|
||||||
viewHolder.message_box = view.findViewById(R.id.message_box);
|
viewHolder.message_box = view.findViewById(R.id.message_box);
|
||||||
|
viewHolder.indicatorReceived = view.findViewById(R.id.indicator_received);
|
||||||
|
break;
|
||||||
|
case RTP_SESSION:
|
||||||
|
view = activity.getLayoutInflater().inflate(R.layout.message_rtp_session, parent, false);
|
||||||
|
viewHolder.status_message = view.findViewById(R.id.message_body);
|
||||||
|
viewHolder.message_box = view.findViewById(R.id.message_box);
|
||||||
|
viewHolder.indicatorReceived = view.findViewById(R.id.indicator_received);
|
||||||
break;
|
break;
|
||||||
case SENT:
|
case SENT:
|
||||||
view = activity.getLayoutInflater().inflate(R.layout.message_sent, parent, false);
|
view = activity.getLayoutInflater().inflate(R.layout.message_sent, parent, false);
|
||||||
|
@ -684,6 +696,28 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
}
|
}
|
||||||
viewHolder.message_box.setBackgroundResource(activity.isDarkTheme() ? R.drawable.date_bubble_grey : R.drawable.date_bubble_white);
|
viewHolder.message_box.setBackgroundResource(activity.isDarkTheme() ? R.drawable.date_bubble_grey : R.drawable.date_bubble_white);
|
||||||
return view;
|
return view;
|
||||||
|
} else if (type == RTP_SESSION) {
|
||||||
|
final boolean isDarkTheme = activity.isDarkTheme();
|
||||||
|
final boolean received = message.getStatus() <= Message.STATUS_RECEIVED;
|
||||||
|
final RtpSessionStatus rtpSessionStatus = RtpSessionStatus.of(message.getBody());
|
||||||
|
final long duration = rtpSessionStatus.duration;
|
||||||
|
if (received) {
|
||||||
|
if (duration > 0) {
|
||||||
|
viewHolder.status_message.setText(activity.getString(R.string.incoming_call_duration, TimeframeUtils.resolve(activity,duration)));
|
||||||
|
} else {
|
||||||
|
viewHolder.status_message.setText(R.string.incoming_call);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (duration > 0) {
|
||||||
|
viewHolder.status_message.setText(activity.getString(R.string.outgoing_call_duration, TimeframeUtils.resolve(activity,duration)));
|
||||||
|
} else {
|
||||||
|
viewHolder.status_message.setText(R.string.outgoing_call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewHolder.indicatorReceived.setImageResource(RtpSessionStatus.getDrawable(received,rtpSessionStatus.successful,isDarkTheme));
|
||||||
|
viewHolder.indicatorReceived.setAlpha(isDarkTheme ? 0.7f : 0.57f);
|
||||||
|
viewHolder.message_box.setBackgroundResource(isDarkTheme ? R.drawable.date_bubble_grey : R.drawable.date_bubble_white);
|
||||||
|
return view;
|
||||||
} else if (type == STATUS) {
|
} else if (type == STATUS) {
|
||||||
if ("LOAD_MORE".equals(message.getBody())) {
|
if ("LOAD_MORE".equals(message.getBody())) {
|
||||||
viewHolder.status_message.setVisibility(View.GONE);
|
viewHolder.status_message.setVisibility(View.GONE);
|
||||||
|
|
|
@ -299,6 +299,8 @@ public class UIHelper {
|
||||||
return new Pair<>(context.getString(R.string.omemo_decryption_failed), true);
|
return new Pair<>(context.getString(R.string.omemo_decryption_failed), true);
|
||||||
} else if (message.isFileOrImage()) {
|
} else if (message.isFileOrImage()) {
|
||||||
return new Pair<>(getFileDescriptionString(context, message), true);
|
return new Pair<>(getFileDescriptionString(context, message), true);
|
||||||
|
} else if (message.getType() == Message.TYPE_RTP_SESSION) {
|
||||||
|
return new Pair<>(context.getString(message.getStatus() == Message.STATUS_RECEIVED ? R.string.incoming_call : R.string.outgoing_call), true);
|
||||||
} else {
|
} else {
|
||||||
final String body = MessageUtils.filterLtrRtl(message.getBody());
|
final String body = MessageUtils.filterLtrRtl(message.getBody());
|
||||||
if (body.startsWith(Message.ME_COMMAND)) {
|
if (body.startsWith(Message.ME_COMMAND)) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package eu.siacs.conversations.xmpp.jingle;
|
package eu.siacs.conversations.xmpp.jingle;
|
||||||
|
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
@ -18,6 +19,10 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
|
import eu.siacs.conversations.entities.Conversational;
|
||||||
|
import eu.siacs.conversations.entities.Message;
|
||||||
|
import eu.siacs.conversations.entities.RtpSessionStatus;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
import eu.siacs.conversations.xml.Namespace;
|
||||||
import eu.siacs.conversations.xmpp.jingle.stanzas.Group;
|
import eu.siacs.conversations.xmpp.jingle.stanzas.Group;
|
||||||
|
@ -94,13 +99,27 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
|
|
||||||
private final WebRTCWrapper webRTCWrapper = new WebRTCWrapper(this);
|
private final WebRTCWrapper webRTCWrapper = new WebRTCWrapper(this);
|
||||||
private final ArrayDeque<IceCandidate> pendingIceCandidates = new ArrayDeque<>();
|
private final ArrayDeque<IceCandidate> pendingIceCandidates = new ArrayDeque<>();
|
||||||
|
private final Message message;
|
||||||
private State state = State.NULL;
|
private State state = State.NULL;
|
||||||
private RtpContentMap initiatorRtpContentMap;
|
private RtpContentMap initiatorRtpContentMap;
|
||||||
private RtpContentMap responderRtpContentMap;
|
private RtpContentMap responderRtpContentMap;
|
||||||
|
private long rtpConnectionStarted = 0; //time of 'connected'
|
||||||
|
|
||||||
|
|
||||||
JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) {
|
JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) {
|
||||||
super(jingleConnectionManager, id, initiator);
|
super(jingleConnectionManager, id, initiator);
|
||||||
|
final Conversation conversation = jingleConnectionManager.getXmppConnectionService().findOrCreateConversation(
|
||||||
|
id.account,
|
||||||
|
id.with.asBareJid(),
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
this.message = new Message(
|
||||||
|
conversation,
|
||||||
|
isInitiator() ? Message.STATUS_SEND : Message.STATUS_RECEIVED,
|
||||||
|
Message.TYPE_RTP_SESSION,
|
||||||
|
id.sessionId
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static State reasonToState(Reason reason) {
|
private static State reasonToState(Reason reason) {
|
||||||
|
@ -153,7 +172,9 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
webRTCWrapper.close();
|
webRTCWrapper.close();
|
||||||
transitionOrThrow(reasonToState(wrapper.reason));
|
final State target = reasonToState(wrapper.reason);
|
||||||
|
transitionOrThrow(target);
|
||||||
|
writeLogMessage(target);
|
||||||
if (previous == State.PROPOSED || previous == State.SESSION_INITIALIZED) {
|
if (previous == State.PROPOSED || previous == State.SESSION_INITIALIZED) {
|
||||||
xmppConnectionService.getNotificationService().cancelIncomingCallNotification();
|
xmppConnectionService.getNotificationService().cancelIncomingCallNotification();
|
||||||
}
|
}
|
||||||
|
@ -455,7 +476,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
if (transition(State.RETRACTED)) {
|
if (transition(State.RETRACTED)) {
|
||||||
xmppConnectionService.getNotificationService().cancelIncomingCallNotification();
|
xmppConnectionService.getNotificationService().cancelIncomingCallNotification();
|
||||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": session with " + id.with + " has been retracted");
|
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": session with " + id.with + " has been retracted");
|
||||||
//TODO create missed call notification/message
|
writeLogMessageMissed();
|
||||||
jingleConnectionManager.finishConnection(this);
|
jingleConnectionManager.finishConnection(this);
|
||||||
} else {
|
} else {
|
||||||
Log.d(Config.LOGTAG, "ignoring retract because already in " + this.state);
|
Log.d(Config.LOGTAG, "ignoring retract because already in " + this.state);
|
||||||
|
@ -509,6 +530,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
private void sendSessionTerminate(final Reason reason, final String text) {
|
private void sendSessionTerminate(final Reason reason, final String text) {
|
||||||
final State target = reasonToState(reason);
|
final State target = reasonToState(reason);
|
||||||
transitionOrThrow(target);
|
transitionOrThrow(target);
|
||||||
|
writeLogMessage(target);
|
||||||
final JinglePacket jinglePacket = new JinglePacket(JinglePacket.Action.SESSION_TERMINATE, id.sessionId);
|
final JinglePacket jinglePacket = new JinglePacket(JinglePacket.Action.SESSION_TERMINATE, id.sessionId);
|
||||||
jinglePacket.setReason(reason, text);
|
jinglePacket.setReason(reason, text);
|
||||||
send(jinglePacket);
|
send(jinglePacket);
|
||||||
|
@ -773,6 +795,9 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
public void onConnectionChange(final PeerConnection.PeerConnectionState newState) {
|
public void onConnectionChange(final PeerConnection.PeerConnectionState newState) {
|
||||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": PeerConnectionState changed to " + newState);
|
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": PeerConnectionState changed to " + newState);
|
||||||
updateEndUserState();
|
updateEndUserState();
|
||||||
|
if (newState == PeerConnection.PeerConnectionState.CONNECTED && this.rtpConnectionStarted == 0) {
|
||||||
|
this.rtpConnectionStarted = SystemClock.elapsedRealtime();
|
||||||
|
}
|
||||||
if (newState == PeerConnection.PeerConnectionState.FAILED) {
|
if (newState == PeerConnection.PeerConnectionState.FAILED) {
|
||||||
if (TERMINATED.contains(this.state)) {
|
if (TERMINATED.contains(this.state)) {
|
||||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": not sending session-terminate after connectivity error because session is already in state " + this.state);
|
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": not sending session-terminate after connectivity error because session is already in state " + this.state);
|
||||||
|
@ -850,6 +875,37 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeLogMessage(final State state) {
|
||||||
|
final long started = this.rtpConnectionStarted;
|
||||||
|
long duration = started <= 0 ? 0 : SystemClock.elapsedRealtime() - started;
|
||||||
|
if (state == State.TERMINATED_SUCCESS || (state == State.TERMINATED_CONNECTIVITY_ERROR && duration > 0)) {
|
||||||
|
writeLogMessageSuccess(duration);
|
||||||
|
} else {
|
||||||
|
writeLogMessageMissed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeLogMessageSuccess(final long duration) {
|
||||||
|
this.message.setBody(new RtpSessionStatus(true, duration).toString());
|
||||||
|
this.writeMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeLogMessageMissed() {
|
||||||
|
this.message.setBody(new RtpSessionStatus(false,0).toString());
|
||||||
|
this.writeMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeMessage() {
|
||||||
|
final Conversational conversational = message.getConversation();
|
||||||
|
if (conversational instanceof Conversation) {
|
||||||
|
((Conversation) conversational).add(this.message);
|
||||||
|
xmppConnectionService.databaseBackend.createMessage(message);
|
||||||
|
xmppConnectionService.updateConversationUi();
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Somehow the conversation in a message was a stub");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public State getState() {
|
public State getState() {
|
||||||
return this.state;
|
return this.state;
|
||||||
}
|
}
|
||||||
|
|
BIN
src/main/res/drawable-hdpi/ic_call_made_black_18dp.png
Normal file
After Width: | Height: | Size: 159 B |
BIN
src/main/res/drawable-hdpi/ic_call_made_white_18dp.png
Normal file
After Width: | Height: | Size: 174 B |
BIN
src/main/res/drawable-hdpi/ic_call_missed_black_18dp.png
Normal file
After Width: | Height: | Size: 179 B |
After Width: | Height: | Size: 180 B |
After Width: | Height: | Size: 180 B |
BIN
src/main/res/drawable-hdpi/ic_call_missed_white_18dp.png
Normal file
After Width: | Height: | Size: 191 B |
BIN
src/main/res/drawable-hdpi/ic_call_received_black_18dp.png
Normal file
After Width: | Height: | Size: 159 B |
BIN
src/main/res/drawable-hdpi/ic_call_received_white_18dp.png
Normal file
After Width: | Height: | Size: 169 B |
BIN
src/main/res/drawable-mdpi/ic_call_made_black_18dp.png
Normal file
After Width: | Height: | Size: 132 B |
BIN
src/main/res/drawable-mdpi/ic_call_made_white_18dp.png
Normal file
After Width: | Height: | Size: 135 B |
BIN
src/main/res/drawable-mdpi/ic_call_missed_black_18dp.png
Normal file
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 134 B |
After Width: | Height: | Size: 136 B |
BIN
src/main/res/drawable-mdpi/ic_call_missed_white_18dp.png
Normal file
After Width: | Height: | Size: 147 B |
BIN
src/main/res/drawable-mdpi/ic_call_received_black_18dp.png
Normal file
After Width: | Height: | Size: 133 B |
BIN
src/main/res/drawable-mdpi/ic_call_received_white_18dp.png
Normal file
After Width: | Height: | Size: 140 B |
BIN
src/main/res/drawable-xhdpi/ic_call_made_black_18dp.png
Normal file
After Width: | Height: | Size: 174 B |
BIN
src/main/res/drawable-xhdpi/ic_call_made_white_18dp.png
Normal file
After Width: | Height: | Size: 189 B |
BIN
src/main/res/drawable-xhdpi/ic_call_missed_black_18dp.png
Normal file
After Width: | Height: | Size: 201 B |
After Width: | Height: | Size: 188 B |
After Width: | Height: | Size: 193 B |
BIN
src/main/res/drawable-xhdpi/ic_call_missed_white_18dp.png
Normal file
After Width: | Height: | Size: 215 B |
BIN
src/main/res/drawable-xhdpi/ic_call_received_black_18dp.png
Normal file
After Width: | Height: | Size: 175 B |
BIN
src/main/res/drawable-xhdpi/ic_call_received_white_18dp.png
Normal file
After Width: | Height: | Size: 189 B |
BIN
src/main/res/drawable-xxhdpi/ic_call_made_black_18dp.png
Normal file
After Width: | Height: | Size: 202 B |
BIN
src/main/res/drawable-xxhdpi/ic_call_made_white_18dp.png
Normal file
After Width: | Height: | Size: 225 B |
BIN
src/main/res/drawable-xxhdpi/ic_call_missed_black_18dp.png
Normal file
After Width: | Height: | Size: 247 B |
After Width: | Height: | Size: 235 B |
After Width: | Height: | Size: 235 B |
BIN
src/main/res/drawable-xxhdpi/ic_call_missed_white_18dp.png
Normal file
After Width: | Height: | Size: 263 B |
BIN
src/main/res/drawable-xxhdpi/ic_call_received_black_18dp.png
Normal file
After Width: | Height: | Size: 202 B |
BIN
src/main/res/drawable-xxhdpi/ic_call_received_white_18dp.png
Normal file
After Width: | Height: | Size: 228 B |
BIN
src/main/res/drawable-xxxhdpi/ic_call_made_black_18dp.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
src/main/res/drawable-xxxhdpi/ic_call_made_white_18dp.png
Normal file
After Width: | Height: | Size: 247 B |
BIN
src/main/res/drawable-xxxhdpi/ic_call_missed_black_18dp.png
Normal file
After Width: | Height: | Size: 267 B |
After Width: | Height: | Size: 257 B |
After Width: | Height: | Size: 248 B |
BIN
src/main/res/drawable-xxxhdpi/ic_call_missed_white_18dp.png
Normal file
After Width: | Height: | Size: 291 B |
BIN
src/main/res/drawable-xxxhdpi/ic_call_received_black_18dp.png
Normal file
After Width: | Height: | Size: 214 B |
BIN
src/main/res/drawable-xxxhdpi/ic_call_received_white_18dp.png
Normal file
After Width: | Height: | Size: 257 B |
|
@ -1,24 +1,27 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="5dp"
|
|
||||||
android:paddingLeft="8dp"
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingTop="5dp"
|
||||||
android:paddingRight="8dp"
|
android:paddingRight="8dp"
|
||||||
android:paddingTop="5dp">
|
android:paddingBottom="5dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/message_box"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/date_bubble_white"
|
android:layout_centerHorizontal="true"
|
||||||
android:id="@+id/message_box"
|
android:background="@drawable/date_bubble_white">
|
||||||
android:layout_centerHorizontal="true">
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/message_body"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@style/TextAppearance.Conversations.Body1.Secondary"
|
android:textAppearance="@style/TextAppearance.Conversations.Body1.Secondary"
|
||||||
android:id="@+id/message_body" />
|
tools:text="Yesterday" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
38
src/main/res/layout/message_rtp_session.xml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingTop="5dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:paddingBottom="5dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/message_box"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:background="@drawable/date_bubble_white"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/indicator_received"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="4sp"
|
||||||
|
android:layout_marginLeft="0sp"
|
||||||
|
tools:alpha="0.57"
|
||||||
|
tools:src="@drawable/ic_call_received_black_18dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/message_body"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="@string/incoming_call"
|
||||||
|
android:textAppearance="@style/TextAppearance.Conversations.Body1.Secondary" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -903,6 +903,10 @@
|
||||||
<string name="hang_up">Hang up</string>
|
<string name="hang_up">Hang up</string>
|
||||||
<string name="ongoing_call">Ongoing call</string>
|
<string name="ongoing_call">Ongoing call</string>
|
||||||
<string name="disable_tor_to_make_call">Disable Tor to make calls</string>
|
<string name="disable_tor_to_make_call">Disable Tor to make calls</string>
|
||||||
|
<string name="incoming_call">Incoming call</string>
|
||||||
|
<string name="incoming_call_duration">Incoming call · %s</string>
|
||||||
|
<string name="outgoing_call">Outgoing call</string>
|
||||||
|
<string name="outgoing_call_duration">Outgoing call · %s</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>
|
||||||
|
|