let users confirm each member in a conference even if that contact is already trusted
This commit is contained in:
parent
134c75ae01
commit
198dc2c6b4
|
@ -284,7 +284,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
|
|
||||||
private Set<XmppAxolotlSession> findSessionsForConversation(Conversation conversation) {
|
private Set<XmppAxolotlSession> findSessionsForConversation(Conversation conversation) {
|
||||||
HashSet<XmppAxolotlSession> sessions = new HashSet<>();
|
HashSet<XmppAxolotlSession> sessions = new HashSet<>();
|
||||||
for(Jid jid : getCryptoTargets(conversation)) {
|
for(Jid jid : conversation.getAcceptedCryptoTargets()) {
|
||||||
sessions.addAll(this.sessions.getAll(getAddressForJid(jid)).values());
|
sessions.addAll(this.sessions.getAll(getAddressForJid(jid)).values());
|
||||||
}
|
}
|
||||||
return sessions;
|
return sessions;
|
||||||
|
|
|
@ -9,11 +9,13 @@ import net.java.otr4j.session.SessionID;
|
||||||
import net.java.otr4j.session.SessionImpl;
|
import net.java.otr4j.session.SessionImpl;
|
||||||
import net.java.otr4j.session.SessionStatus;
|
import net.java.otr4j.session.SessionStatus;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.security.interfaces.DSAPublicKey;
|
import java.security.interfaces.DSAPublicKey;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -48,6 +50,7 @@ public class Conversation extends AbstractEntity implements Blockable {
|
||||||
public static final String ATTRIBUTE_MUC_PASSWORD = "muc_password";
|
public static final String ATTRIBUTE_MUC_PASSWORD = "muc_password";
|
||||||
public static final String ATTRIBUTE_MUTED_TILL = "muted_till";
|
public static final String ATTRIBUTE_MUTED_TILL = "muted_till";
|
||||||
public static final String ATTRIBUTE_ALWAYS_NOTIFY = "always_notify";
|
public static final String ATTRIBUTE_ALWAYS_NOTIFY = "always_notify";
|
||||||
|
public static final String ATTRIBUTE_CRYPTO_TARGETS = "crypto_targets";
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private String contactUuid;
|
private String contactUuid;
|
||||||
|
@ -313,6 +316,18 @@ public class Conversation extends AbstractEntity implements Blockable {
|
||||||
return getLongAttribute("last_clear_history", 0);
|
return getLongAttribute("last_clear_history", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Jid> getAcceptedCryptoTargets() {
|
||||||
|
if (mode == MODE_SINGLE) {
|
||||||
|
return Arrays.asList(getJid().toBareJid());
|
||||||
|
} else {
|
||||||
|
return getJidListAttribute(ATTRIBUTE_CRYPTO_TARGETS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAcceptedCryptoTargets(List<Jid> acceptedTargets) {
|
||||||
|
setAttribute(ATTRIBUTE_CRYPTO_TARGETS, acceptedTargets);
|
||||||
|
}
|
||||||
|
|
||||||
public void setCorrectingMessage(Message correctingMessage) {
|
public void setCorrectingMessage(Message correctingMessage) {
|
||||||
this.correctingMessage = correctingMessage;
|
this.correctingMessage = correctingMessage;
|
||||||
}
|
}
|
||||||
|
@ -794,22 +809,61 @@ public class Conversation extends AbstractEntity implements Blockable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setAttribute(String key, String value) {
|
public boolean setAttribute(String key, String value) {
|
||||||
try {
|
synchronized (this.attributes) {
|
||||||
this.attributes.put(key, value);
|
try {
|
||||||
return true;
|
this.attributes.put(key, value);
|
||||||
} catch (JSONException e) {
|
return true;
|
||||||
return false;
|
} catch (JSONException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setAttribute(String key, List<Jid> jids) {
|
||||||
|
JSONArray array = new JSONArray();
|
||||||
|
for(Jid jid : jids) {
|
||||||
|
array.put(jid.toBareJid().toString());
|
||||||
|
}
|
||||||
|
synchronized (this.attributes) {
|
||||||
|
try {
|
||||||
|
this.attributes.put(key, array);
|
||||||
|
return true;
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAttribute(String key) {
|
public String getAttribute(String key) {
|
||||||
try {
|
synchronized (this.attributes) {
|
||||||
return this.attributes.getString(key);
|
try {
|
||||||
} catch (JSONException e) {
|
return this.attributes.getString(key);
|
||||||
return null;
|
} catch (JSONException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Jid> getJidListAttribute(String key) {
|
||||||
|
ArrayList<Jid> list = new ArrayList<>();
|
||||||
|
synchronized (this.attributes) {
|
||||||
|
try {
|
||||||
|
JSONArray array = this.attributes.getJSONArray(key);
|
||||||
|
for (int i = 0; i < array.length(); ++i) {
|
||||||
|
try {
|
||||||
|
list.add(Jid.fromString(array.getString(i)));
|
||||||
|
} catch (InvalidJidException e) {
|
||||||
|
//ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
//ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
public int getIntAttribute(String key, int defaultValue) {
|
public int getIntAttribute(String key, int defaultValue) {
|
||||||
String value = this.getAttribute(key);
|
String value = this.getAttribute(key);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
|
|
@ -1531,11 +1531,12 @@ public class ConversationActivity extends XmppActivity
|
||||||
protected boolean trustKeysIfNeeded(int requestCode, int attachmentChoice) {
|
protected boolean trustKeysIfNeeded(int requestCode, int attachmentChoice) {
|
||||||
AxolotlService axolotlService = mSelectedConversation.getAccount().getAxolotlService();
|
AxolotlService axolotlService = mSelectedConversation.getAccount().getAxolotlService();
|
||||||
final List<Jid> targets = axolotlService.getCryptoTargets(mSelectedConversation);
|
final List<Jid> targets = axolotlService.getCryptoTargets(mSelectedConversation);
|
||||||
|
boolean hasUnaccepted = !mSelectedConversation.getAcceptedCryptoTargets().containsAll(targets);
|
||||||
boolean hasUndecidedOwn = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED).isEmpty();
|
boolean hasUndecidedOwn = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED).isEmpty();
|
||||||
boolean hasUndecidedContacts = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, targets).isEmpty();
|
boolean hasUndecidedContacts = !axolotlService.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED, targets).isEmpty();
|
||||||
boolean hasPendingKeys = !axolotlService.findDevicesWithoutSession(mSelectedConversation).isEmpty();
|
boolean hasPendingKeys = !axolotlService.findDevicesWithoutSession(mSelectedConversation).isEmpty();
|
||||||
boolean hasNoTrustedKeys = axolotlService.anyTargetHasNoTrustedKeys(targets);
|
boolean hasNoTrustedKeys = axolotlService.anyTargetHasNoTrustedKeys(targets);
|
||||||
if(hasUndecidedOwn || hasUndecidedContacts || hasPendingKeys || hasNoTrustedKeys) {
|
if(hasUndecidedOwn || hasUndecidedContacts || hasPendingKeys || hasNoTrustedKeys || hasUnaccepted) {
|
||||||
axolotlService.createSessionsIfNeeded(mSelectedConversation);
|
axolotlService.createSessionsIfNeeded(mSelectedConversation);
|
||||||
Intent intent = new Intent(getApplicationContext(), TrustKeysActivity.class);
|
Intent intent = new Intent(getApplicationContext(), TrustKeysActivity.class);
|
||||||
String[] contacts = new String[targets.size()];
|
String[] contacts = new String[targets.size()];
|
||||||
|
@ -1545,6 +1546,7 @@ public class ConversationActivity extends XmppActivity
|
||||||
intent.putExtra("contacts", contacts);
|
intent.putExtra("contacts", contacts);
|
||||||
intent.putExtra(EXTRA_ACCOUNT, mSelectedConversation.getAccount().getJid().toBareJid().toString());
|
intent.putExtra(EXTRA_ACCOUNT, mSelectedConversation.getAccount().getJid().toBareJid().toString());
|
||||||
intent.putExtra("choice", attachmentChoice);
|
intent.putExtra("choice", attachmentChoice);
|
||||||
|
intent.putExtra("conversation",mSelectedConversation.getUuid());
|
||||||
startActivityForResult(intent, requestCode);
|
startActivityForResult(intent, requestCode);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -10,6 +10,8 @@ import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import org.whispersystems.libaxolotl.IdentityKey;
|
import org.whispersystems.libaxolotl.IdentityKey;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -18,19 +20,21 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
||||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||||
|
|
||||||
public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdated {
|
public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdated {
|
||||||
private Jid accountJid;
|
|
||||||
private List<Jid> contactJids;
|
private List<Jid> contactJids;
|
||||||
|
|
||||||
private Account mAccount;
|
private Account mAccount;
|
||||||
|
private Conversation mConversation;
|
||||||
private TextView keyErrorMessage;
|
private TextView keyErrorMessage;
|
||||||
private LinearLayout keyErrorMessageCard;
|
private LinearLayout keyErrorMessageCard;
|
||||||
private TextView ownKeysTitle;
|
private TextView ownKeysTitle;
|
||||||
|
@ -71,10 +75,6 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_trust_keys);
|
setContentView(R.layout.activity_trust_keys);
|
||||||
try {
|
|
||||||
this.accountJid = Jid.fromString(getIntent().getExtras().getString(EXTRA_ACCOUNT));
|
|
||||||
} catch (final InvalidJidException ignored) {
|
|
||||||
}
|
|
||||||
this.contactJids = new ArrayList<>();
|
this.contactJids = new ArrayList<>();
|
||||||
for(String jid : getIntent().getStringArrayExtra("contacts")) {
|
for(String jid : getIntent().getStringArrayExtra("contacts")) {
|
||||||
try {
|
try {
|
||||||
|
@ -126,13 +126,15 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
||||||
|
|
||||||
synchronized (this.foreignKeysToTrust) {
|
synchronized (this.foreignKeysToTrust) {
|
||||||
for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
|
for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
|
||||||
|
hasForeignKeys = true;
|
||||||
final LinearLayout layout = (LinearLayout) getLayoutInflater().inflate(R.layout.keys_card, foreignKeys, false);
|
final LinearLayout layout = (LinearLayout) getLayoutInflater().inflate(R.layout.keys_card, foreignKeys, false);
|
||||||
|
final Jid jid = entry.getKey();
|
||||||
final TextView header = (TextView) layout.findViewById(R.id.foreign_keys_title);
|
final TextView header = (TextView) layout.findViewById(R.id.foreign_keys_title);
|
||||||
final LinearLayout keysContainer = (LinearLayout) layout.findViewById(R.id.foreign_keys_details);
|
final LinearLayout keysContainer = (LinearLayout) layout.findViewById(R.id.foreign_keys_details);
|
||||||
header.setText(entry.getKey().toString());
|
final TextView informNoKeys = (TextView) layout.findViewById(R.id.no_keys_to_accept);
|
||||||
|
header.setText(jid.toString());
|
||||||
final Map<String, Boolean> fingerprints = entry.getValue();
|
final Map<String, Boolean> fingerprints = entry.getValue();
|
||||||
for (final String fingerprint : fingerprints.keySet()) {
|
for (final String fingerprint : fingerprints.keySet()) {
|
||||||
hasForeignKeys = true;
|
|
||||||
addFingerprintRowWithListeners(keysContainer, mAccount, fingerprint, false,
|
addFingerprintRowWithListeners(keysContainer, mAccount, fingerprint, false,
|
||||||
XmppAxolotlSession.Trust.fromBoolean(fingerprints.get(fingerprint)), false,
|
XmppAxolotlSession.Trust.fromBoolean(fingerprints.get(fingerprint)), false,
|
||||||
new CompoundButton.OnCheckedChangeListener() {
|
new CompoundButton.OnCheckedChangeListener() {
|
||||||
|
@ -146,11 +148,17 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (fingerprints.size() == 0) {
|
||||||
|
informNoKeys.setVisibility(View.VISIBLE);
|
||||||
|
informNoKeys.setText(getString(R.string.no_keys_just_confirm,mAccount.getRoster().getContact(jid).getDisplayName()));
|
||||||
|
} else {
|
||||||
|
informNoKeys.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
foreignKeys.addView(layout);
|
foreignKeys.addView(layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ownKeysTitle.setText(accountJid.toString());
|
ownKeysTitle.setText(mAccount.getJid().toBareJid().toString());
|
||||||
ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE);
|
ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE);
|
||||||
foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE);
|
foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE);
|
||||||
if(hasPendingKeyFetches()) {
|
if(hasPendingKeyFetches()) {
|
||||||
|
@ -176,6 +184,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean reloadFingerprints() {
|
private boolean reloadFingerprints() {
|
||||||
|
List<Jid> acceptedTargets = mConversation == null ? new ArrayList<Jid>() : mConversation.getAcceptedCryptoTargets();
|
||||||
ownKeysToTrust.clear();
|
ownKeysToTrust.clear();
|
||||||
AxolotlService service = this.mAccount.getAxolotlService();
|
AxolotlService service = this.mAccount.getAxolotlService();
|
||||||
Set<IdentityKey> ownKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED);
|
Set<IdentityKey> ownKeysSet = service.getKeysWithTrust(XmppAxolotlSession.Trust.UNDECIDED);
|
||||||
|
@ -197,7 +206,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
||||||
foreignFingerprints.put(identityKey.getFingerprint().replaceAll("\\s", ""), false);
|
foreignFingerprints.put(identityKey.getFingerprint().replaceAll("\\s", ""), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (foreignFingerprints.size() > 0) {
|
if (foreignFingerprints.size() > 0 || !acceptedTargets.contains(jid)) {
|
||||||
foreignKeysToTrust.put(jid, foreignFingerprints);
|
foreignKeysToTrust.put(jid, foreignFingerprints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,11 +216,11 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackendConnected() {
|
public void onBackendConnected() {
|
||||||
if (accountJid != null) {
|
Intent intent = getIntent();
|
||||||
this.mAccount = xmppConnectionService.findAccountByJid(accountJid);
|
this.mAccount = extractAccount(intent);
|
||||||
if (this.mAccount == null) {
|
if (this.mAccount != null && intent != null) {
|
||||||
return;
|
String uuid = intent.getStringExtra("conversation");
|
||||||
}
|
this.mConversation = xmppConnectionService.findConversationByUuid(uuid);
|
||||||
reloadFingerprints();
|
reloadFingerprints();
|
||||||
populateView();
|
populateView();
|
||||||
}
|
}
|
||||||
|
@ -276,8 +285,14 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
||||||
fingerprint,
|
fingerprint,
|
||||||
XmppAxolotlSession.Trust.fromBoolean(ownKeysToTrust.get(fingerprint)));
|
XmppAxolotlSession.Trust.fromBoolean(ownKeysToTrust.get(fingerprint)));
|
||||||
}
|
}
|
||||||
|
List<Jid> acceptedTargets = mConversation == null ? new ArrayList<Jid>() : mConversation.getAcceptedCryptoTargets();
|
||||||
synchronized (this.foreignKeysToTrust) {
|
synchronized (this.foreignKeysToTrust) {
|
||||||
for (Map<String, Boolean> value : foreignKeysToTrust.values()) {
|
for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
|
||||||
|
Jid jid = entry.getKey();
|
||||||
|
Map<String, Boolean> value = entry.getValue();
|
||||||
|
if (!acceptedTargets.contains(jid)) {
|
||||||
|
acceptedTargets.add(jid);
|
||||||
|
}
|
||||||
for (final String fingerprint : value.keySet()) {
|
for (final String fingerprint : value.keySet()) {
|
||||||
mAccount.getAxolotlService().setFingerprintTrust(
|
mAccount.getAxolotlService().setFingerprintTrust(
|
||||||
fingerprint,
|
fingerprint,
|
||||||
|
@ -285,6 +300,11 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mConversation != null && mConversation.getMode() == Conversation.MODE_MULTI) {
|
||||||
|
Log.d(Config.LOGTAG,"commiting accepted crypto targets: "+acceptedTargets);
|
||||||
|
mConversation.setAcceptedCryptoTargets(acceptedTargets);
|
||||||
|
//xmppConnectionService.updateConversation(mConversation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unlock() {
|
private void unlock() {
|
||||||
|
|
|
@ -1,31 +1,39 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout android:id="@+id/foreign_keys_card"
|
||||||
android:id="@+id/foreign_keys_card"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
android:layout_marginBottom="@dimen/activity_vertical_margin"
|
||||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||||
android:layout_marginTop="@dimen/activity_vertical_margin"
|
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||||
android:layout_marginBottom="@dimen/activity_vertical_margin"
|
android:layout_marginTop="@dimen/activity_vertical_margin"
|
||||||
android:background="@drawable/infocard_border"
|
android:background="@drawable/infocard_border"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="@dimen/infocard_padding">
|
android:padding="@dimen/infocard_padding">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/foreign_keys_title"
|
android:id="@+id/foreign_keys_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@color/black87"
|
android:textColor="@color/black87"
|
||||||
android:textSize="?attr/TextSizeHeadline"
|
android:textSize="?attr/TextSizeHeadline"
|
||||||
android:textStyle="bold"/>
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/foreign_keys_details"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:divider="?android:dividerHorizontal"
|
|
||||||
android:showDividers="middle"
|
|
||||||
android:orientation="vertical">
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/foreign_keys_details"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:divider="?android:dividerHorizontal"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:showDividers="middle">
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:id="@+id/no_keys_to_accept"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black87"
|
||||||
|
android:text="@string/no_keys_just_confirm"
|
||||||
|
android:textSize="?attr/TextSizeBody"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -599,4 +599,5 @@
|
||||||
<string name="this_field_is_required">This field is required</string>
|
<string name="this_field_is_required">This field is required</string>
|
||||||
<string name="correct_message">Correct message</string>
|
<string name="correct_message">Correct message</string>
|
||||||
<string name="send_corrected_message">Send corrected message</string>
|
<string name="send_corrected_message">Send corrected message</string>
|
||||||
|
<string name="no_keys_just_confirm">You already trust this contact. By selecting \'done\' you are just confirming that %s is part of this conference.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue