diff options
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/java/de/pixart/messenger/OmemoActivity.java | 237 | ||||
-rw-r--r-- | src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java | 48 | ||||
-rw-r--r-- | src/main/java/de/pixart/messenger/ui/EditAccountActivity.java | 176 | ||||
-rw-r--r-- | src/main/java/de/pixart/messenger/ui/TrustKeysActivity.java | 16 | ||||
-rw-r--r-- | src/main/java/de/pixart/messenger/ui/XmppActivity.java | 130 | ||||
-rw-r--r-- | src/main/res/drawable-hdpi/ic_verified_fingerprint.png | bin | 0 -> 1336 bytes | |||
-rw-r--r-- | src/main/res/drawable-mdpi/ic_verified_fingerprint.png | bin | 0 -> 1032 bytes | |||
-rw-r--r-- | src/main/res/drawable-xhdpi/ic_verified_fingerprint.png | bin | 0 -> 1557 bytes | |||
-rw-r--r-- | src/main/res/drawable-xxhdpi/ic_verified_fingerprint.png | bin | 0 -> 2305 bytes | |||
-rw-r--r-- | src/main/res/drawable-xxxhdpi/ic_verified_fingerprint.png | bin | 0 -> 2794 bytes | |||
-rw-r--r-- | src/main/res/layout/contact_key.xml | 73 | ||||
-rw-r--r-- | src/main/res/menu/omemo_key_context.xml | 9 | ||||
-rw-r--r-- | src/main/res/values/ids.xml | 2 | ||||
-rw-r--r-- | src/main/res/values/strings.xml | 80 |
14 files changed, 429 insertions, 342 deletions
diff --git a/src/main/java/de/pixart/messenger/OmemoActivity.java b/src/main/java/de/pixart/messenger/OmemoActivity.java new file mode 100644 index 000000000..c71e306df --- /dev/null +++ b/src/main/java/de/pixart/messenger/OmemoActivity.java @@ -0,0 +1,237 @@ +package de.pixart.messenger; + + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.ContextMenu; +import android.view.MenuItem; +import android.view.View; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import java.security.cert.X509Certificate; + +import de.pixart.messenger.crypto.axolotl.FingerprintStatus; +import de.pixart.messenger.entities.Account; +import de.pixart.messenger.ui.XmppActivity; +import de.pixart.messenger.ui.widget.Switch; +import de.pixart.messenger.utils.CryptoHelper; + +public abstract class OmemoActivity extends XmppActivity { + + private Account mSelectedAccount; + private String mSelectedFingerprint; + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu,v,menuInfo); + Object account = v.getTag(R.id.TAG_ACCOUNT); + Object fingerprint = v.getTag(R.id.TAG_FINGERPRINT); + if (account != null && fingerprint != null && account instanceof Account && fingerprint instanceof String) { + getMenuInflater().inflate(R.menu.omemo_key_context, menu); + this.mSelectedAccount = (Account) account; + this.mSelectedFingerprint = (String) fingerprint; + } + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.purge_omemo_key: + showPurgeKeyDialog(mSelectedAccount,mSelectedFingerprint); + break; + case R.id.copy_omemo_key: + copyOmemoFingerprint(mSelectedFingerprint); + break; + } + return true; + } + + protected void copyOmemoFingerprint(String fingerprint) { + if (copyTextToClipboard(CryptoHelper.prettifyFingerprint(fingerprint.substring(2)), R.string.omemo_fingerprint)) { + Toast.makeText( + this, + R.string.toast_message_omemo_fingerprint, + Toast.LENGTH_SHORT).show(); + } + } + + protected boolean addFingerprintRow(LinearLayout keys, final Account account, final String fingerprint, boolean highlight) { + final FingerprintStatus status = account.getAxolotlService().getFingerprintTrust(fingerprint); + return status != null && addFingerprintRowWithListeners(keys, account, fingerprint, highlight, status, true, true, new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + account.getAxolotlService().setFingerprintTrust(fingerprint, FingerprintStatus.createActive(isChecked)); + } + }); + } + + protected boolean addFingerprintRowWithListeners(LinearLayout keys, final Account account, + final String fingerprint, + boolean highlight, + FingerprintStatus status, + boolean showTag, + boolean undecidedNeedEnablement, + CompoundButton.OnCheckedChangeListener + onCheckedChangeListener) { + if (status.isCompromised()) { + return false; + } + View view = getLayoutInflater().inflate(R.layout.contact_key, keys, false); + TextView key = (TextView) view.findViewById(R.id.key); + TextView keyType = (TextView) view.findViewById(R.id.key_type); + if (Config.X509_VERIFICATION && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509) { + View.OnClickListener listener = new View.OnClickListener() { + @Override + public void onClick(View v) { + showX509Certificate(account,fingerprint); + } + }; + key.setOnClickListener(listener); + keyType.setOnClickListener(listener); + } + Switch trustToggle = (Switch) view.findViewById(R.id.tgl_trust); + ImageView verifiedFingerprintSymbol = (ImageView) view.findViewById(R.id.verified_fingerprint); + trustToggle.setVisibility(View.VISIBLE); + registerForContextMenu(view); + view.setTag(R.id.TAG_ACCOUNT,account); + view.setTag(R.id.TAG_FINGERPRINT,fingerprint); + boolean x509 = Config.X509_VERIFICATION && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509; + final View.OnClickListener toast; + trustToggle.setChecked(status.isTrusted(), false); + + if (status.isActive()){ + key.setTextColor(getPrimaryTextColor()); + keyType.setTextColor(getSecondaryTextColor()); + if (status.isVerified()) { + verifiedFingerprintSymbol.setVisibility(View.VISIBLE); + trustToggle.setVisibility(View.GONE); + verifiedFingerprintSymbol.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + replaceToast(getString(R.string.this_device_has_been_verified), false); + } + }); + toast = null; + } else { + verifiedFingerprintSymbol.setVisibility(View.GONE); + trustToggle.setVisibility(View.VISIBLE); + trustToggle.setOnCheckedChangeListener(onCheckedChangeListener); + if (status.getTrust() == FingerprintStatus.Trust.UNDECIDED && undecidedNeedEnablement) { + trustToggle.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + account.getAxolotlService().setFingerprintTrust(fingerprint,FingerprintStatus.createActive(false)); + v.setEnabled(true); + v.setOnClickListener(null); + } + }); + trustToggle.setEnabled(false); + } else { + trustToggle.setOnClickListener(null); + trustToggle.setEnabled(true); + } + toast = new View.OnClickListener() { + @Override + public void onClick(View v) { + hideToast(); + } + }; + } + } else { + key.setTextColor(getTertiaryTextColor()); + keyType.setTextColor(getTertiaryTextColor()); + toast = new View.OnClickListener() { + @Override + public void onClick(View v) { + replaceToast(getString(R.string.this_device_is_no_longer_in_use), false); + } + }; + if (status.isVerified()) { + trustToggle.setVisibility(View.GONE); + verifiedFingerprintSymbol.setVisibility(View.VISIBLE); + verifiedFingerprintSymbol.setOnClickListener(toast); + } else { + trustToggle.setVisibility(View.VISIBLE); + verifiedFingerprintSymbol.setVisibility(View.GONE); + trustToggle.setOnClickListener(null); + trustToggle.setEnabled(false); + trustToggle.setOnClickListener(toast); + } + } + + view.setOnClickListener(toast); + key.setOnClickListener(toast); + keyType.setOnClickListener(toast); + if (showTag) { + keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint)); + } else { + keyType.setVisibility(View.GONE); + } + if (highlight) { + keyType.setTextColor(getResources().getColor(R.color.accent)); + keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509_selected_message : R.string.omemo_fingerprint_selected_message)); + } else { + keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint)); + } + + key.setText(CryptoHelper.prettifyFingerprint(fingerprint.substring(2))); + + keys.addView(view); + return true; + } + + public void showPurgeKeyDialog(final Account account, final String fingerprint) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(getString(R.string.purge_key)); + builder.setIconAttribute(android.R.attr.alertDialogIcon); + builder.setMessage(getString(R.string.purge_key_desc_part1) + + "\n\n" + CryptoHelper.prettifyFingerprint(fingerprint.substring(2)) + + "\n\n" + getString(R.string.purge_key_desc_part2)); + builder.setNegativeButton(getString(R.string.cancel), null); + builder.setPositiveButton(getString(R.string.purge_key), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + account.getAxolotlService().purgeKey(fingerprint); + refreshUi(); + } + }); + builder.create().show(); + } + + private void showX509Certificate(Account account, String fingerprint) { + X509Certificate x509Certificate = account.getAxolotlService().getFingerprintCertificate(fingerprint); + if (x509Certificate != null) { + showCertificateInformationDialog(CryptoHelper.extractCertificateInformation(x509Certificate)); + } else { + Toast.makeText(this,R.string.certificate_not_found, Toast.LENGTH_SHORT).show(); + } + } + + private void showCertificateInformationDialog(Bundle bundle) { + View view = getLayoutInflater().inflate(R.layout.certificate_information, null); + final String not_available = getString(R.string.certicate_info_not_available); + TextView subject_cn = (TextView) view.findViewById(R.id.subject_cn); + TextView subject_o = (TextView) view.findViewById(R.id.subject_o); + TextView issuer_cn = (TextView) view.findViewById(R.id.issuer_cn); + TextView issuer_o = (TextView) view.findViewById(R.id.issuer_o); + TextView sha1 = (TextView) view.findViewById(R.id.sha1); + + subject_cn.setText(bundle.getString("subject_cn", not_available)); + subject_o.setText(bundle.getString("subject_o", not_available)); + issuer_cn.setText(bundle.getString("issuer_cn", not_available)); + issuer_o.setText(bundle.getString("issuer_o", not_available)); + sha1.setText(bundle.getString("sha1", not_available)); + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.certificate_information); + builder.setView(view); + builder.setPositiveButton(R.string.ok, null); + builder.create().show(); + } +}
\ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java b/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java index c3992c179..51b9b33ec 100644 --- a/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java @@ -27,20 +27,18 @@ import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.QuickContactBadge; import android.widget.TextView; -import android.widget.Toast; import com.wefika.flowlayout.FlowLayout; import org.openintents.openpgp.util.OpenPgpUtils; -import java.security.cert.X509Certificate; import java.util.List; import de.pixart.messenger.Config; +import de.pixart.messenger.OmemoActivity; import de.pixart.messenger.R; import de.pixart.messenger.crypto.PgpEngine; import de.pixart.messenger.crypto.axolotl.AxolotlService; -import de.pixart.messenger.crypto.axolotl.FingerprintStatus; import de.pixart.messenger.entities.Account; import de.pixart.messenger.entities.Contact; import de.pixart.messenger.entities.Conversation; @@ -55,7 +53,7 @@ import de.pixart.messenger.xmpp.XmppConnection; import de.pixart.messenger.xmpp.jid.InvalidJidException; import de.pixart.messenger.xmpp.jid.Jid; -public class ContactDetailsActivity extends XmppActivity implements OnAccountUpdate, OnRosterUpdate, OnUpdateBlocklist, OnKeyStatusUpdated { +public class ContactDetailsActivity extends OmemoActivity implements OnAccountUpdate, OnRosterUpdate, OnUpdateBlocklist, OnKeyStatusUpdated { public static final String ACTION_VIEW_CONTACT = "view_contact"; private Conversation mConversation; @@ -462,12 +460,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd if (Config.supportOmemo()) { for (final String fingerprint : contact.getAccount().getAxolotlService().getFingerprintsForContact(contact)) { boolean highlight = fingerprint.equals(messageFingerprint); - hasKeys |= addFingerprintRow(keys, contact.getAccount(), fingerprint, highlight, new OnClickListener() { - @Override - public void onClick(View v) { - onOmemoKeyClicked(contact.getAccount(), fingerprint); - } - }); + hasKeys |= addFingerprintRow(keys, contact.getAccount(), fingerprint, highlight); } } if (Config.supportOpenPgp() && contact.getPgpKeyId() != 0) { @@ -523,40 +516,6 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd } } - private void onOmemoKeyClicked(Account account, String fingerprint) { - FingerprintStatus status = account.getAxolotlService().getFingerprintTrust(fingerprint); - if (Config.X509_VERIFICATION && status != null && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509) { - X509Certificate x509Certificate = account.getAxolotlService().getFingerprintCertificate(fingerprint); - if (x509Certificate != null) { - showCertificateInformationDialog(CryptoHelper.extractCertificateInformation(x509Certificate)); - } else { - Toast.makeText(this,R.string.certificate_not_found, Toast.LENGTH_SHORT).show(); - } - } - } - - private void showCertificateInformationDialog(Bundle bundle) { - View view = getLayoutInflater().inflate(R.layout.certificate_information, null); - final String not_available = getString(R.string.certicate_info_not_available); - TextView subject_cn = (TextView) view.findViewById(R.id.subject_cn); - TextView subject_o = (TextView) view.findViewById(R.id.subject_o); - TextView issuer_cn = (TextView) view.findViewById(R.id.issuer_cn); - TextView issuer_o = (TextView) view.findViewById(R.id.issuer_o); - TextView sha1 = (TextView) view.findViewById(R.id.sha1); - - subject_cn.setText(bundle.getString("subject_cn", not_available)); - subject_o.setText(bundle.getString("subject_o", not_available)); - issuer_cn.setText(bundle.getString("issuer_cn", not_available)); - issuer_o.setText(bundle.getString("issuer_o", not_available)); - sha1.setText(bundle.getString("sha1", not_available)); - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.certificate_information); - builder.setView(view); - builder.setPositiveButton(R.string.ok, null); - builder.create().show(); - } - protected void confirmToDeleteFingerprint(final String fingerprint) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.delete_fingerprint); @@ -577,7 +536,6 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd builder.create().show(); } - @Override public void onBackendConnected() { if ((accountJid != null) && (contactJid != null)) { Account account = xmppConnectionService diff --git a/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java b/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java index e82bc0c5c..b5e3c8a1c 100644 --- a/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java +++ b/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java @@ -41,6 +41,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import de.pixart.messenger.Config; +import de.pixart.messenger.OmemoActivity; import de.pixart.messenger.R; import de.pixart.messenger.crypto.axolotl.AxolotlService; import de.pixart.messenger.entities.Account; @@ -59,19 +60,19 @@ import de.pixart.messenger.xmpp.jid.InvalidJidException; import de.pixart.messenger.xmpp.jid.Jid; import de.pixart.messenger.xmpp.pep.Avatar; -public class EditAccountActivity extends XmppActivity implements OnAccountUpdate, +public class EditAccountActivity extends OmemoActivity implements OnAccountUpdate, OnKeyStatusUpdated, OnCaptchaRequested, KeyChainAliasCallback, XmppConnectionService.OnShowErrorToast, XmppConnectionService.OnMamPreferencesFetched { - private static final int REQUEST_DATA_SAVER = 0x37af244; - private AutoCompleteTextView mAccountJid; + private static final int REQUEST_DATA_SAVER = 0x37af244; + private AutoCompleteTextView mAccountJid; private EditText mPassword; private EditText mPasswordConfirm; private CheckBox mRegisterNew; private Button mCancelButton; private Button mSaveButton; - private Button mDisableOsOptimizationsButton; - private TextView mDisableOsOptimizationsHeadline; - private TextView getmDisableOsOptimizationsBody; + private Button mDisableOsOptimizationsButton; + private TextView mDisableOsOptimizationsHeadline; + private TextView getmDisableOsOptimizationsBody; private TableLayout mMoreTable; private LinearLayout mStats; @@ -190,9 +191,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate return; } if (registerNewAccount) { - if (XmppConnection.errorMessage != null) { - Toast.makeText(EditAccountActivity.this,XmppConnection.errorMessage,Toast.LENGTH_LONG).show(); - } + if (XmppConnection.errorMessage != null) { + Toast.makeText(EditAccountActivity.this,XmppConnection.errorMessage,Toast.LENGTH_LONG).show(); + } if (!password.equals(passwordConfirm)) { mPasswordConfirm.setError(getString(R.string.passwords_do_not_match)); mPasswordConfirm.requestFocus(); @@ -206,11 +207,11 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate mAccount.setJid(jid); mAccount.setPort(numericPort); mAccount.setHostname(hostname); - if (XmppConnection.errorMessage != null) { - mAccountJid.setError(XmppConnection.errorMessage); - } else { - mAccountJid.setError(null); - } + if (XmppConnection.errorMessage != null) { + mAccountJid.setError(XmppConnection.errorMessage); + } else { + mAccountJid.setError(null); + } mPasswordConfirm.setError(null); mAccount.setPassword(password); mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount); @@ -480,10 +481,10 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate this.mAvatar.setOnClickListener(this.mAvatarClickListener); this.mRegisterNew = (CheckBox) findViewById(R.id.account_register_new); this.mStats = (LinearLayout) findViewById(R.id.stats); - this.mOsOptimizations = (RelativeLayout) findViewById(R.id.os_optimization); - this.mDisableOsOptimizationsButton = (Button) findViewById(R.id.os_optimization_disable); - this.mDisableOsOptimizationsHeadline = (TextView) findViewById(R.id.os_optimization_headline); - this.getmDisableOsOptimizationsBody = (TextView) findViewById(R.id.os_optimization_body); + this.mOsOptimizations = (RelativeLayout) findViewById(R.id.os_optimization); + this.mDisableOsOptimizationsButton = (Button) findViewById(R.id.os_optimization_disable); + this.mDisableOsOptimizationsHeadline = (TextView) findViewById(R.id.os_optimization_headline); + this.getmDisableOsOptimizationsBody = (TextView) findViewById(R.id.os_optimization_body); this.mSessionEst = (TextView) findViewById(R.id.session_est); this.mServerInfoRosterVersion = (TextView) findViewById(R.id.server_info_roster_version); this.mServerInfoCarbons = (TextView) findViewById(R.id.server_info_carbons); @@ -516,9 +517,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate this.mSaveButton.setOnClickListener(this.mSaveButtonClickListener); this.mCancelButton.setOnClickListener(this.mCancelButtonClickListener); this.mMoreTable = (TableLayout) findViewById(R.id.server_info_more); - if (savedInstanceState != null && savedInstanceState.getBoolean("showMoreTable")) { - changeMoreTableVisibility(true); - } + if (savedInstanceState != null && savedInstanceState.getBoolean("showMoreTable")) { + changeMoreTableVisibility(true); + } final OnCheckedChangeListener OnCheckedShowConfirmPassword = new OnCheckedChangeListener() { @Override public void onCheckedChanged(final CompoundButton buttonView, @@ -584,22 +585,22 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate return super.onCreateOptionsMenu(menu); } - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - final MenuItem showMoreInfo = menu.findItem(R.id.action_server_info_show_more); - if (showMoreInfo.isVisible()) { - showMoreInfo.setChecked(mMoreTable.getVisibility() == View.VISIBLE); - } - return super.onPrepareOptionsMenu(menu); - } + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + final MenuItem showMoreInfo = menu.findItem(R.id.action_server_info_show_more); + if (showMoreInfo.isVisible()) { + showMoreInfo.setChecked(mMoreTable.getVisibility() == View.VISIBLE); + } + return super.onPrepareOptionsMenu(menu); + } @Override protected void onStart() { super.onStart(); - final int theme = findTheme(); - if (this.mTheme != theme) { - recreate(); - } else if (getIntent() != null) { + final int theme = findTheme(); + if (this.mTheme != theme) { + recreate(); + } else if (getIntent() != null) { try { this.jidToEdit = Jid.fromString(getIntent().getStringExtra("jid")); } catch (final InvalidJidException | NullPointerException ignored) { @@ -637,12 +638,11 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate if (mAccount != null) { savedInstanceState.putString("account", mAccount.getJid().toBareJid().toString()); savedInstanceState.putBoolean("initMode", mInitMode); - savedInstanceState.putBoolean("showMoreTable", mMoreTable.getVisibility() == View.VISIBLE); + savedInstanceState.putBoolean("showMoreTable", mMoreTable.getVisibility() == View.VISIBLE); } super.onSaveInstanceState(savedInstanceState); } - @Override protected void onBackendConnected() { boolean init = true; if (mSavedInstanceAccount != null) { @@ -714,7 +714,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate startActivity(showBlocklistIntent); break; case R.id.action_server_info_show_more: - changeMoreTableVisibility(!item.isChecked()); + changeMoreTableVisibility(!item.isChecked()); break; case R.id.action_change_password_on_server: gotoChangePassword(null); @@ -738,9 +738,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate return super.onOptionsItemSelected(item); } - private void changeMoreTableVisibility(boolean visible) { - mMoreTable.setVisibility(visible ? View.VISIBLE : View.GONE); - } + private void changeMoreTableVisibility(boolean visible) { + mMoreTable.setVisibility(visible ? View.VISIBLE : View.GONE); + } private void gotoChangePassword(String newPassword) { final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class); @@ -803,9 +803,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate if (this.mAccount.isOnlineAndConnected() && !this.mFetchingAvatar) { Features features = this.mAccount.getXmppConnection().getFeatures(); this.mStats.setVisibility(View.VISIBLE); - boolean showBatteryWarning = !xmppConnectionService.getPushManagementService().available(mAccount) && isOptimizingBattery(); - boolean showDataSaverWarning = isAffectedByDataSaver(); - showOsOptimizationWarning(showBatteryWarning,showDataSaverWarning); + boolean showBatteryWarning = !xmppConnectionService.getPushManagementService().available(mAccount) && isOptimizingBattery(); + boolean showDataSaverWarning = isAffectedByDataSaver(); + showOsOptimizationWarning(showBatteryWarning,showDataSaverWarning); this.mSessionEst.setText(UIHelper.readableTimeDifferenceFull(this, this.mAccount.getXmppConnection() .getLastSessionEstablished())); if (features.rosterVersioning()) { @@ -901,13 +901,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate @Override public void onClick(final View v) { - - if (copyTextToClipboard(ownAxolotlFingerprint.substring(2), R.string.omemo_fingerprint)) { - Toast.makeText( - EditAccountActivity.this, - R.string.toast_message_omemo_fingerprint, - Toast.LENGTH_SHORT).show(); - } + copyOmemoFingerprint(ownAxolotlFingerprint); } }); if (Config.SHOW_REGENERATE_AXOLOTL_KEYS_BUTTON) { @@ -932,7 +926,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate continue; } boolean highlight = fingerprint.equals(messageFingerprint); - hasKeys |= addFingerprintRow(keys, mAccount, fingerprint, highlight, null); + hasKeys |= addFingerprintRow(keys, mAccount, fingerprint, highlight); } if (hasKeys && Config.supportOmemo()) { keysCard.setVisibility(View.VISIBLE); @@ -964,47 +958,47 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate } } - private void showOsOptimizationWarning(boolean showBatteryWarning, boolean showDataSaverWarning) { - this.mOsOptimizations.setVisibility(showBatteryWarning || showDataSaverWarning ? View.VISIBLE : View.GONE); - if (showDataSaverWarning) { - this.mDisableOsOptimizationsHeadline.setText(R.string.data_saver_enabled); - this.getmDisableOsOptimizationsBody.setText(R.string.data_saver_enabled_explained); - this.mDisableOsOptimizationsButton.setText(R.string.allow); - this.mDisableOsOptimizationsButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS); - Uri uri = Uri.parse("package:" + getPackageName()); - intent.setData(uri); - try { - startActivityForResult(intent, REQUEST_DATA_SAVER); - } catch (ActivityNotFoundException e) { - Toast.makeText(EditAccountActivity.this, R.string.device_does_not_support_data_saver, Toast.LENGTH_SHORT).show(); - } - } - }); - } else if (showBatteryWarning) { - this.mDisableOsOptimizationsButton.setText(R.string.disable); - this.mDisableOsOptimizationsHeadline.setText(R.string.battery_optimizations_enabled); - this.getmDisableOsOptimizationsBody.setText(R.string.battery_optimizations_enabled_explained); - this.mDisableOsOptimizationsButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); - Uri uri = Uri.parse("package:" + getPackageName()); - intent.setData(uri); - try { - startActivityForResult(intent, REQUEST_BATTERY_OP); - } catch (ActivityNotFoundException e) { - Toast.makeText(EditAccountActivity.this, R.string.device_does_not_support_battery_op, Toast.LENGTH_SHORT).show(); - } - } - }); - } - } - - - public void showRegenerateAxolotlKeyDialog() { + private void showOsOptimizationWarning(boolean showBatteryWarning, boolean showDataSaverWarning) { + this.mOsOptimizations.setVisibility(showBatteryWarning || showDataSaverWarning ? View.VISIBLE : View.GONE); + if (showDataSaverWarning) { + this.mDisableOsOptimizationsHeadline.setText(R.string.data_saver_enabled); + this.getmDisableOsOptimizationsBody.setText(R.string.data_saver_enabled_explained); + this.mDisableOsOptimizationsButton.setText(R.string.allow); + this.mDisableOsOptimizationsButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS); + Uri uri = Uri.parse("package:" + getPackageName()); + intent.setData(uri); + try { + startActivityForResult(intent, REQUEST_DATA_SAVER); + } catch (ActivityNotFoundException e) { + Toast.makeText(EditAccountActivity.this, R.string.device_does_not_support_data_saver, Toast.LENGTH_SHORT).show(); + } + } + }); + } else if (showBatteryWarning) { + this.mDisableOsOptimizationsButton.setText(R.string.disable); + this.mDisableOsOptimizationsHeadline.setText(R.string.battery_optimizations_enabled); + this.getmDisableOsOptimizationsBody.setText(R.string.battery_optimizations_enabled_explained); + this.mDisableOsOptimizationsButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + Uri uri = Uri.parse("package:" + getPackageName()); + intent.setData(uri); + try { + startActivityForResult(intent, REQUEST_BATTERY_OP); + } catch (ActivityNotFoundException e) { + Toast.makeText(EditAccountActivity.this, R.string.device_does_not_support_battery_op, Toast.LENGTH_SHORT).show(); + } + } + }); + } + } + + + public void showRegenerateAxolotlKeyDialog() { Builder builder = new Builder(this); builder.setTitle("Regenerate Key"); builder.setIconAttribute(android.R.attr.alertDialogIcon); diff --git a/src/main/java/de/pixart/messenger/ui/TrustKeysActivity.java b/src/main/java/de/pixart/messenger/ui/TrustKeysActivity.java index b737e17f1..dd499433a 100644 --- a/src/main/java/de/pixart/messenger/ui/TrustKeysActivity.java +++ b/src/main/java/de/pixart/messenger/ui/TrustKeysActivity.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import de.pixart.messenger.OmemoActivity; import de.pixart.messenger.R; import de.pixart.messenger.crypto.axolotl.AxolotlService; import de.pixart.messenger.crypto.axolotl.FingerprintStatus; @@ -27,7 +28,7 @@ import de.pixart.messenger.xmpp.OnKeyStatusUpdated; import de.pixart.messenger.xmpp.jid.InvalidJidException; import de.pixart.messenger.xmpp.jid.Jid; -public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdated { +public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdated { private List<Jid> contactJids; private Account mAccount; @@ -108,16 +109,14 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate for(final String fingerprint : ownKeysToTrust.keySet()) { hasOwnKeys = true; addFingerprintRowWithListeners(ownKeys, mAccount, fingerprint, false, - FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)), false, + FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)), false, false, new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { ownKeysToTrust.put(fingerprint, isChecked); // own fingerprints have no impact on locked status. } - }, - null, - null + } ); } @@ -133,16 +132,14 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate final Map<String, Boolean> fingerprints = entry.getValue(); for (final String fingerprint : fingerprints.keySet()) { addFingerprintRowWithListeners(keysContainer, mAccount, fingerprint, false, - FingerprintStatus.createActive(fingerprints.get(fingerprint)), false, + FingerprintStatus.createActive(fingerprints.get(fingerprint)), false, false, new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { fingerprints.put(fingerprint, isChecked); lockOrUnlockAsNeeded(); } - }, - null, - null + } ); } if (fingerprints.size() == 0) { @@ -211,7 +208,6 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate return ownKeysSet.size() + foreignKeysToTrust.size() > 0; } - @Override public void onBackendConnected() { Intent intent = getIntent(); this.mAccount = extractAccount(intent); diff --git a/src/main/java/de/pixart/messenger/ui/XmppActivity.java b/src/main/java/de/pixart/messenger/ui/XmppActivity.java index 95dc62d7d..b9c62e516 100644 --- a/src/main/java/de/pixart/messenger/ui/XmppActivity.java +++ b/src/main/java/de/pixart/messenger/ui/XmppActivity.java @@ -48,11 +48,8 @@ import android.util.Pair; import android.view.MenuItem; import android.view.View; import android.view.inputmethod.InputMethodManager; -import android.widget.CompoundButton; import android.widget.EditText; import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; import android.widget.Toast; import com.google.zxing.BarcodeFormat; @@ -76,7 +73,6 @@ import java.util.concurrent.atomic.AtomicInteger; import de.pixart.messenger.Config; import de.pixart.messenger.R; -import de.pixart.messenger.crypto.axolotl.FingerprintStatus; import de.pixart.messenger.entities.Account; import de.pixart.messenger.entities.Contact; import de.pixart.messenger.entities.Conversation; @@ -86,7 +82,6 @@ import de.pixart.messenger.entities.Presences; import de.pixart.messenger.services.AvatarService; import de.pixart.messenger.services.XmppConnectionService; import de.pixart.messenger.services.XmppConnectionService.XmppConnectionBinder; -import de.pixart.messenger.ui.widget.Switch; import de.pixart.messenger.utils.CryptoHelper; import de.pixart.messenger.utils.ExceptionHelper; import de.pixart.messenger.utils.UIHelper; @@ -775,131 +770,6 @@ public abstract class XmppActivity extends Activity { builder.create().show(); } - protected boolean addFingerprintRow(LinearLayout keys, final Account account, final String fingerprint, boolean highlight, View.OnClickListener onKeyClickedListener) { - final FingerprintStatus status = account.getAxolotlService().getFingerprintTrust(fingerprint); - if (status == null) { - return false; - } - return addFingerprintRowWithListeners(keys, account, fingerprint, highlight, status, true, - new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - account.getAxolotlService().setFingerprintTrust(fingerprint,FingerprintStatus.createActive(isChecked)); - } - }, - new View.OnClickListener() { - @Override - public void onClick(View v) { - account.getAxolotlService().setFingerprintTrust(fingerprint,FingerprintStatus.createActive(false)); - v.setEnabled(true); - } - }, - onKeyClickedListener - - ); - } - - protected boolean addFingerprintRowWithListeners(LinearLayout keys, final Account account, - final String fingerprint, - boolean highlight, - FingerprintStatus status, - boolean showTag, - CompoundButton.OnCheckedChangeListener - onCheckedChangeListener, - View.OnClickListener onClickListener, - View.OnClickListener onKeyClickedListener) { - if (status.isCompromised()) { - return false; - } - View view = getLayoutInflater().inflate(R.layout.contact_key, keys, false); - TextView key = (TextView) view.findViewById(R.id.key); - key.setOnClickListener(onKeyClickedListener); - TextView keyType = (TextView) view.findViewById(R.id.key_type); - keyType.setOnClickListener(onKeyClickedListener); - Switch trustToggle = (Switch) view.findViewById(R.id.tgl_trust); - trustToggle.setVisibility(View.VISIBLE); - final View.OnLongClickListener purge = new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - showPurgeKeyDialog(account, fingerprint); - return true; - } - }; - view.setOnLongClickListener(purge); - key.setOnLongClickListener(purge); - keyType.setOnLongClickListener(purge); - boolean x509 = Config.X509_VERIFICATION && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509; - final View.OnClickListener toast; - trustToggle.setChecked(status.isTrusted(), false); - if (status.isActive()) { - key.setTextColor(getPrimaryTextColor()); - keyType.setTextColor(getSecondaryTextColor()); - trustToggle.setOnCheckedChangeListener(onCheckedChangeListener); - if (status.getTrust() == FingerprintStatus.Trust.UNDECIDED) { - trustToggle.setOnClickListener(onClickListener); - trustToggle.setEnabled(false); - } else { - trustToggle.setOnClickListener(null); - trustToggle.setEnabled(true); - } - toast = new View.OnClickListener() { - @Override - public void onClick(View v) { - hideToast(); - } - }; - } else { - key.setTextColor(getTertiaryTextColor()); - keyType.setTextColor(getTertiaryTextColor()); - trustToggle.setOnClickListener(null); - trustToggle.setEnabled(false); - toast = new View.OnClickListener() { - @Override - public void onClick(View v) { - replaceToast(getString(R.string.this_device_is_no_longer_in_use), false); - } - }; - trustToggle.setOnClickListener(toast); - } - view.setOnClickListener(toast); - key.setOnClickListener(toast); - keyType.setOnClickListener(toast); - if (showTag) { - keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint)); - } else { - keyType.setVisibility(View.GONE); - } - if (highlight) { - keyType.setTextColor(getResources().getColor(R.color.accent)); - keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509_selected_message : R.string.omemo_fingerprint_selected_message)); - } else { - keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint)); - } - - key.setText(CryptoHelper.prettifyFingerprint(fingerprint.substring(2))); - keys.addView(view); - return true; - } - - public void showPurgeKeyDialog(final Account account, final String fingerprint) { - Builder builder = new Builder(this); - builder.setTitle(getString(R.string.purge_key)); - builder.setIconAttribute(android.R.attr.alertDialogIcon); - builder.setMessage(getString(R.string.purge_key_desc_part1) - + "\n\n" + CryptoHelper.prettifyFingerprint(fingerprint.substring(2)) - + "\n\n" + getString(R.string.purge_key_desc_part2)); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.setPositiveButton(getString(R.string.purge_key), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - account.getAxolotlService().purgeKey(fingerprint); - refreshUi(); - } - }); - builder.create().show(); - } - public boolean hasStoragePermission(int requestCode) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { diff --git a/src/main/res/drawable-hdpi/ic_verified_fingerprint.png b/src/main/res/drawable-hdpi/ic_verified_fingerprint.png Binary files differnew file mode 100644 index 000000000..297dea0d0 --- /dev/null +++ b/src/main/res/drawable-hdpi/ic_verified_fingerprint.png diff --git a/src/main/res/drawable-mdpi/ic_verified_fingerprint.png b/src/main/res/drawable-mdpi/ic_verified_fingerprint.png Binary files differnew file mode 100644 index 000000000..250ea4cd4 --- /dev/null +++ b/src/main/res/drawable-mdpi/ic_verified_fingerprint.png diff --git a/src/main/res/drawable-xhdpi/ic_verified_fingerprint.png b/src/main/res/drawable-xhdpi/ic_verified_fingerprint.png Binary files differnew file mode 100644 index 000000000..ba8162601 --- /dev/null +++ b/src/main/res/drawable-xhdpi/ic_verified_fingerprint.png diff --git a/src/main/res/drawable-xxhdpi/ic_verified_fingerprint.png b/src/main/res/drawable-xxhdpi/ic_verified_fingerprint.png Binary files differnew file mode 100644 index 000000000..e86e8efcc --- /dev/null +++ b/src/main/res/drawable-xxhdpi/ic_verified_fingerprint.png diff --git a/src/main/res/drawable-xxxhdpi/ic_verified_fingerprint.png b/src/main/res/drawable-xxxhdpi/ic_verified_fingerprint.png Binary files differnew file mode 100644 index 000000000..5c78ac272 --- /dev/null +++ b/src/main/res/drawable-xxxhdpi/ic_verified_fingerprint.png diff --git a/src/main/res/layout/contact_key.xml b/src/main/res/layout/contact_key.xml index 53a599fd3..ec8ca1996 100644 --- a/src/main/res/layout/contact_key.xml +++ b/src/main/res/layout/contact_key.xml @@ -1,16 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" - android:layout_height="match_parent" > + android:layout_height="match_parent" + android:longClickable="true"> <RelativeLayout android:id="@+id/key_data" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" - android:paddingTop="8dp" + android:paddingBottom="8dp" android:paddingLeft="8dp" - android:paddingBottom="8dp"> + android:paddingTop="8dp"> <TextView android:id="@+id/key" @@ -18,10 +19,11 @@ android:layout_height="wrap_content" android:textColor="@color/black87" android:layout_alignParentLeft="true" - android:layout_toLeftOf="@+id/tgl_trust" + android:layout_toLeftOf="@+id/action_container" android:textSize="?attr/TextSizeBody" android:typeface="monospace" - android:fontFamily="monospace"/> + android:fontFamily="monospace" + android:longClickable="true"/> <TextView android:id="@+id/key_type" @@ -31,7 +33,8 @@ android:layout_alignParentLeft="true" android:layout_below="@+id/key" android:maxLines="1" - android:textSize="?attr/TextSizeInfo"/> + android:textSize="?attr/TextSizeInfo" + android:longClickable="true"/> <TextView android:id="@+id/key_trust" @@ -41,29 +44,45 @@ android:layout_below="@+id/key" android:visibility="gone" android:textColor="@color/black54" - android:textSize="?attr/TextSizeInfo"/> - - <ImageButton - android:id="@+id/button_remove" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:layout_toRightOf="@+id/key" - android:layout_centerVertical="true" - android:background="?android:selectableItemBackground" - android:padding="@dimen/image_button_padding" - android:src="?attr/icon_remove" - android:visibility="gone" /> + android:textSize="?attr/TextSizeInfo" + android:longClickable="true"/> + <LinearLayout + android:id="@+id/action_container" + android:layout_width="96dp" + android:layout_marginRight="-32dp" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_alignParentRight="true" + android:layout_centerVertical="true"> + <ImageButton + android:layout_gravity="center_horizontal" + android:id="@+id/button_remove" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="?android:selectableItemBackground" + android:padding="@dimen/image_button_padding" + android:src="?attr/icon_remove" + android:layout_marginRight="16dp" + android:visibility="gone" /> - <de.pixart.messenger.ui.widget.Switch - android:id="@+id/tgl_trust" - android:visibility="invisible" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:layout_centerVertical="true" - style="@style/MD"/> + <ImageView + android:visibility="gone" + android:id="@+id/verified_fingerprint" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginRight="16dp" + android:src="@drawable/ic_verified_fingerprint" /> + <de.pixart.messenger.ui.widget.Switch + android:id="@+id/tgl_trust" + android:visibility="gone" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" + style="@style/MD"/> + </LinearLayout> </RelativeLayout> </RelativeLayout>
\ No newline at end of file diff --git a/src/main/res/menu/omemo_key_context.xml b/src/main/res/menu/omemo_key_context.xml new file mode 100644 index 000000000..2e2fc5dac --- /dev/null +++ b/src/main/res/menu/omemo_key_context.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:id="@+id/purge_omemo_key" + android:title="@string/purge_key"/> + <item + android:id="@+id/copy_omemo_key" + android:title="@string/copy_fingerprint"/> +</menu>
\ No newline at end of file diff --git a/src/main/res/values/ids.xml b/src/main/res/values/ids.xml index 0786006cf..84f9ac69e 100644 --- a/src/main/res/values/ids.xml +++ b/src/main/res/values/ids.xml @@ -4,4 +4,6 @@ <item name="message_image_view" type="id" /> <item name="message_video_view" type="id" /> <item name="import_text" type="id" /> + <item type="id" name="TAG_ACCOUNT"/> + <item type="id" name="TAG_FINGERPRINT"/> </resources>
\ No newline at end of file diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 6e2c31120..75df2af53 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -101,13 +101,13 @@ <string name="pref_xmpp_resource">XMPP resource</string> <string name="pref_xmpp_resource_summary">The name this client identifies itself with</string> <string name="pref_accept_files_wifi">Accept files in WiFi connections</string> - <string name="pref_accept_files_summary_wifi">When connected to wifi automatically accept files smaller than…</string> - <string name="pref_accept_files_mobile">Accept files in mobile connections</string> - <string name="pref_accept_files_summary_mobile">When connected with mobile data automatically accept files smaller than…</string> - <string name="pref_accept_files_mobileroaming">Accept files in mobile roaming connections</string> - <string name="pref_accept_files_summary_mobileroaming">When connected with mobile data in roaming automatically accept files smaller than…</string> + <string name="pref_accept_files_summary_wifi">When connected to wifi automatically accept files smaller than…</string> + <string name="pref_accept_files_mobile">Accept files in mobile connections</string> + <string name="pref_accept_files_summary_mobile">When connected with mobile data automatically accept files smaller than…</string> + <string name="pref_accept_files_mobileroaming">Accept files in mobile roaming connections</string> + <string name="pref_accept_files_summary_mobileroaming">When connected with mobile data in roaming automatically accept files smaller than…</string> <string name="pref_attachments">Attachments</string> - <string name="pref_notification_settings">Notification</string> + <string name="pref_notification_settings">Notification</string> <string name="pref_notifications">Notifications</string> <string name="pref_notifications_summary">Notify when a new message arrives</string> <string name="pref_vibrate">Vibrate</string> @@ -116,13 +116,13 @@ <string name="pref_led_summary">Blink notification light when a new message arrives</string> <string name="pref_sound">Ringtone</string> <string name="pref_sound_summary">Play sound when a new message arrives</string> - <string name="pref_send_crash">Send crash reports</string> + <string name="pref_send_crash">Send crash reports</string> <string name="pref_send_crash_summary">By sending in stack traces you are helping the ongoing development of Pix-Art Messenger</string> <string name="pref_confirm_messages">Confirm Messages</string> <string name="pref_confirm_messages_summary">Let your contact know when you have received and read a message</string> <string name="pref_ui_options">UI</string> <string name="openpgp_error">OpenKeychain reported an error</string> - <string name="accept">Accept</string> + <string name="accept">Accept</string> <string name="error">An error has occurred</string> <string name="pref_grant_presence_updates">Grant presence updates</string> <string name="pref_grant_presence_updates_summary">Preemptively grant and ask for presence subscription for contacts you created</string> @@ -197,7 +197,7 @@ <string name="last_seen_hours">%d hours ago</string> <string name="last_seen_day">1 day ago</string> <string name="last_seen_days">%d days ago</string> - <string name="install_openkeychain">Encrypted message. Please install OpenKeychain to decrypt.</string> + <string name="install_openkeychain">Encrypted message. Please install OpenKeychain to decrypt.</string> <string name="unknown_otr_fingerprint">Unknown OTR fingerprint</string> <string name="openpgp_messages_found">OpenPGP encrypted messages found</string> <string name="your_fingerprint">Your fingerprint</string> @@ -273,7 +273,7 @@ <string name="pref_dont_save_encrypted">Don’t save encrypted messages</string> <string name="pref_dont_save_encrypted_summary">Warning: This could lead to message loss</string> <string name="pref_expert_options">Expert settings</string> - <string name="title_activity_about">About Pix-Art Messenger</string> + <string name="title_activity_about">About Pix-Art Messenger</string> <string name="pref_about_conversations_summary">Build and licensing information</string> <string name="pref_about_message" translatable="false">Pix-Art Messenger \n\nCopyright © 2014-2016 Christian Schneppe @@ -330,7 +330,7 @@ <string name="pref_use_indicate_received_summary">Received messages will be marked with a green tick if supported</string> <string name="pref_use_send_button_to_indicate_status_summary">Colorize send button to indicate contact status</string> <string name="pref_expert_options_other">Other</string> - <string name="pref_autojoin">Automatically join conferences</string> + <string name="pref_autojoin">Automatically join conferences</string> <string name="pref_autojoin_summary">Respect the autojoin flag in conference bookmarks</string> <string name="toast_message_otr_fingerprint">OTR fingerprint copied to clipboard!</string> <string name="toast_message_omemo_fingerprint">OMEMO fingerprint copied to clipboard!</string> @@ -338,7 +338,7 @@ <string name="conference_members_only">This conference is members only</string> <string name="conference_kicked">You have been kicked from this conference</string> <string name="conference_shutdown">The conference was shut down</string> - <string name="using_account">using account %s</string> + <string name="using_account">using account %s</string> <string name="checking_x">Checking %s on HTTP host</string> <string name="not_connected_try_again">You are not connected. Try again later</string> <string name="check_x_filesize">Check %s size</string> @@ -394,7 +394,7 @@ <string name="enable_notifications">Enable notifications</string> <string name="no_conference_server_found">No conference server found</string> <string name="conference_creation_failed">Conference creation failed!</string>s - <string name="account_image_description">Account avatar</string> + <string name="account_image_description">Account avatar</string> <string name="copy_otr_clipboard_description">Copy OTR fingerprint to clipboard</string> <string name="copy_omemo_clipboard_description">Copy OMEMO fingerprint to clipboard</string> <string name="regenerate_omemo_key">Regenerate OMEMO key</string> @@ -471,7 +471,7 @@ <string name="sending_x_file">Sending %s</string> <string name="offering_x_file">Offering %s</string> <string name="hide_offline">Hide offline</string> - <string name="is_typing">is typing…</string> + <string name="is_typing">is typing…</string> <string name="pref_chat_states">Typing notifications</string> <string name="pref_chat_states_summary">Let your contact know when you are writing a new message</string> <string name="send_location">Send location</string> @@ -552,7 +552,7 @@ <string name="verified_omemo_key_with_certificate">Verified OMEMO key with certificate!</string> <string name="device_does_not_support_certificates">Your device does not support the selection of client certificates!</string> <string name="changelog">Changes</string> - <string name="account_settings_hostname">Hostname</string> + <string name="account_settings_hostname">Hostname</string> <string name="account_settings_port">Port</string> <string name="hostname_or_onion">Server- or .onion-Address</string> <string name="not_a_valid_port">This is not a valid port number</string> @@ -644,13 +644,13 @@ <string name="creating_conference">Creating conference…</string> <string name="import_text">There is a backup on your device which can be imported.\nPossibly you will be asked to uninstall the old version or Conversations and your Messenger will be restarted during backup process. Shall the backup be imported? </string> <string name="import_database">Import backup</string> - <string name="invite_again">Invite again</string> + <string name="invite_again">Invite again</string> <string name="inviteUser_Subject">has invited you via</string> <string name="InviteText">Hello,\n\nthe user %s has invited you to Pix-Art Messenger. If you are using Android, give it a try and click the following link to start over...</string> - <string name="pref_broadcast_last_activity">Broadcast Last User Interaction</string> + <string name="pref_broadcast_last_activity">Broadcast Last User Interaction</string> <string name="pref_broadcast_last_activity_summary">Let all your contacts know when use Pix-Art Messenger</string> - <string name="invite_user">Invite to Pix-Art Messenger</string> - <string name="request_permissions_message">Pix-Art Messenger will ask you to allow a few permissions. It is important that you allow all these permissions to use all features of this messenger. If you deny any of these permissions the app will close itself.</string> + <string name="invite_user">Invite to Pix-Art Messenger</string> + <string name="request_permissions_message">Pix-Art Messenger will ask you to allow a few permissions. It is important that you allow all these permissions to use all features of this messenger. If you deny any of these permissions the app will close itself.</string> <string name="request_permissions_message_again">You have denied some or all permissions needed for Pix-Art Messenger. Would you like to jump to the settings and allow these permissions? If you denie any of these permissions, the app will close itself.</string> <string name="unable_to_connect_to_keychain">Unable to connect to OpenKeychain</string> <string name="no_permission">Pix-Art Messenger has no permissions</string> @@ -678,7 +678,7 @@ <string name="preparing_video">Prepare video for transmission. Please wait…</string> <string name="compressing_video">Compressing video, please wait…</string> <string name="shared_video_with_x">Shared video with %s</string> - <string name="no_permission_to_access_x">No permission to access %s</string> + <string name="no_permission_to_access_x">No permission to access %s</string> <string name="remote_server_not_found">Remote server not found</string> <string name="error_file_corrupt">This file seems to be corrupt.</string> <string name="unable_to_update_account">Unable to update account</string> @@ -687,23 +687,25 @@ <string name="wrong_conference_configuration">This is not a private, non-anonymous conference.</string> <string name="this_conference_has_no_members">There are no members in this conference.</string> <string name="report_jid_as_spammer">Report this JID as sending unwanted messages.</string> - <string name="create_issue">Report an issue</string> - <string name="pref_delete_omemo_identities">Delete OMEMO identities</string> - <string name="pref_delete_omemo_identities_summary">Regenerate your OMEMO keys. All your contacts will have to verify you again. Use this only as a last resort.</string> - <string name="delete_selected_keys">Delete selected keys</string> - <string name="missing_presence_subscription">Missing presence subscription</string> - <string name="missing_omemo_keys">Missing OMEMO keys</string> - <string name="error_publish_avatar_offline">You need to be connected to publish your avatar.</string> - <string name="select_text">Select text</string> - <string name="show_error_message">Show error message</string> - <string name="error_message">Error Message</string> - <string name="data_saver_enabled">Data saver enabled</string> - <string name="data_saver_enabled_explained">Your operating system is restricting Pix-Art Messenger from accessing the Internet when in background. To receive notifications of new messages you should allow Pix-Art Messenger unrestricted access when Data saver is on.\\nPix-Art Messenger will still make an effort to save data when possible.</string> - <string name="device_does_not_support_data_saver">Your device does not supporting disabling Data saver for Pix-Art Messenger.</string> - <string name="navigate">Navigate to location</string> - <string name="add_to_contact_list">Add to contact list</string> - <string name="received_contact">Received contact</string> - <string name="contact">Contact</string> - <string name="unable_to_start_recording">Unable to start recording</string> - <string name="error_unable_to_create_temporary_file">Error: unable to create temporary file</string> + <string name="create_issue">Report an issue</string> + <string name="pref_delete_omemo_identities">Delete OMEMO identities</string> + <string name="pref_delete_omemo_identities_summary">Regenerate your OMEMO keys. All your contacts will have to verify you again. Use this only as a last resort.</string> + <string name="delete_selected_keys">Delete selected keys</string> + <string name="missing_presence_subscription">Missing presence subscription</string> + <string name="missing_omemo_keys">Missing OMEMO keys</string> + <string name="error_publish_avatar_offline">You need to be connected to publish your avatar.</string> + <string name="select_text">Select text</string> + <string name="show_error_message">Show error message</string> + <string name="error_message">Error Message</string> + <string name="data_saver_enabled">Data saver enabled</string> + <string name="data_saver_enabled_explained">Your operating system is restricting Pix-Art Messenger from accessing the Internet when in background. To receive notifications of new messages you should allow Pix-Art Messenger unrestricted access when Data saver is on.\\nPix-Art Messenger will still make an effort to save data when possible.</string> + <string name="device_does_not_support_data_saver">Your device does not supporting disabling Data saver for Pix-Art Messenger.</string> + <string name="navigate">Navigate to location</string> + <string name="add_to_contact_list">Add to contact list</string> + <string name="received_contact">Received contact</string> + <string name="contact">Contact</string> + <string name="unable_to_start_recording">Unable to start recording</string> + <string name="error_unable_to_create_temporary_file">Unable to create temporary file</string> + <string name="this_device_has_been_verified">This device has been verified</string> + <string name="copy_fingerprint">Copy fingerprint</string> </resources> |