diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 6dbb0cc777213aadd4831c18d9aeb63799b64a4d..9d9ddd5ac8defabf558e9d1cb06cc684a3c667ba 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -1385,15 +1385,17 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl if (oldConversation != null) { oldConversation.pagerAdapter.mPager = null; oldConversation.pagerAdapter.mTabs = null; + page1 = oldConversation.pagerAdapter.page1; + page2 = oldConversation.pagerAdapter.page2; + oldConversation.pagerAdapter.page1 = null; + oldConversation.pagerAdapter.page2 = null; } if (mPager == null) return; if (sessions != null) show(); - if (pager.getChildAt(0) != null) page1 = pager.getChildAt(0); - if (pager.getChildAt(1) != null) page2 = pager.getChildAt(1); - if (page1 == null) page1 = oldConversation.pagerAdapter.page1; - if (page2 == null) page2 = oldConversation.pagerAdapter.page2; + if (page1 == null) page1 = pager.getChildAt(0); + if (page2 == null) page2 = pager.getChildAt(1); if (page1 == null || page2 == null) { throw new IllegalStateException("page1 or page2 were not present as child or in model?"); } @@ -1798,16 +1800,16 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl if (field.getType().equals(Optional.of("jid-single")) || field.getType().equals(Optional.of("jid-multi"))) { binding.values.setOnItemClickListener((arg0, arg1, pos, id) -> { - new FixedURLSpan("xmpp:" + Jid.ofEscaped(values.getItem(pos).getValue()).toEscapedString()).onClick(binding.values); + new FixedURLSpan("xmpp:" + Jid.ofEscaped(values.getItem(pos).getValue()).toEscapedString(), account).onClick(binding.values); }); } else if ("xs:anyURI".equals(datatype)) { binding.values.setOnItemClickListener((arg0, arg1, pos, id) -> { - new FixedURLSpan(values.getItem(pos).getValue()).onClick(binding.values); + new FixedURLSpan(values.getItem(pos).getValue(), account).onClick(binding.values); }); } else if ("html:tel".equals(datatype)) { binding.values.setOnItemClickListener((arg0, arg1, pos, id) -> { try { - new FixedURLSpan("tel:" + PhoneNumberUtilWrapper.normalize(binding.getRoot().getContext(), values.getItem(pos).getValue())).onClick(binding.values); + new FixedURLSpan("tel:" + PhoneNumberUtilWrapper.normalize(binding.getRoot().getContext(), values.getItem(pos).getValue()), account).onClick(binding.values); } catch (final IllegalArgumentException | NumberParseException | NullPointerException e) { } }); } @@ -1837,12 +1839,12 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl String value = formatValue(datatype, cell.el.findChildContent("value", "jabber:x:data"), true); SpannableStringBuilder text = new SpannableStringBuilder(value == null ? "" : value); if (cell.reported.getType().equals(Optional.of("jid-single"))) { - text.setSpan(new FixedURLSpan("xmpp:" + Jid.ofEscaped(text.toString()).toEscapedString()), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new FixedURLSpan("xmpp:" + Jid.ofEscaped(text.toString()).toEscapedString(), account), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else if ("xs:anyURI".equals(datatype)) { - text.setSpan(new FixedURLSpan(text.toString()), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new FixedURLSpan(text.toString(), account), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else if ("html:tel".equals(datatype)) { try { - text.setSpan(new FixedURLSpan("tel:" + PhoneNumberUtilWrapper.normalize(binding.getRoot().getContext(), text.toString())), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new FixedURLSpan("tel:" + PhoneNumberUtilWrapper.normalize(binding.getRoot().getContext(), text.toString()), account), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } catch (final IllegalArgumentException | NumberParseException | NullPointerException e) { } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java index 6cf016714d6fd88f2b64879211037f21a884a17d..70039e5a04fcb9d15f713ed5aa9766f5fef81ea8 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationsActivity.java @@ -64,6 +64,8 @@ import com.cheogram.android.DownloadDefaultStickers; import com.google.common.collect.ImmutableList; +import io.michaelrocks.libphonenumber.android.NumberParseException; + import org.openintents.openpgp.util.OpenPgpApi; import java.util.Arrays; @@ -92,6 +94,7 @@ import eu.siacs.conversations.ui.util.ConversationMenuConfigurator; import eu.siacs.conversations.ui.util.MenuDoubleTabUtil; import eu.siacs.conversations.ui.util.PendingItem; import eu.siacs.conversations.utils.ExceptionHelper; +import eu.siacs.conversations.utils.PhoneNumberUtilWrapper; import eu.siacs.conversations.utils.SignupUtils; import eu.siacs.conversations.utils.ThemeHelper; import eu.siacs.conversations.utils.XmppUri; @@ -600,6 +603,36 @@ public class ConversationsActivity extends XmppActivity implements OnConversatio return false; } + public boolean onTelUriClicked(Uri uri, Account acct) { + final String tel; + try { + tel = PhoneNumberUtilWrapper.normalize(this, uri.getSchemeSpecificPart()); + } catch (final IllegalArgumentException | NumberParseException | NullPointerException e) { + return false; + } + + Set gateways = new HashSet<>(); + for (Account account : (acct == null ? xmppConnectionService.getAccounts() : List.of(acct))) { + for (Contact contact : account.getRoster().getContacts()) { + if (contact.getPresences().anyIdentity("gateway", "pstn") || contact.getPresences().anyIdentity("gateway", "sms")) { + if (acct == null) acct = account; + gateways.add(contact.getJid().asBareJid().toEscapedString()); + } + } + } + + for (String gateway : gateways) { + if (onXmppUriClicked(Uri.parse("xmpp:" + tel + "@" + gateway))) return true; + } + + if (gateways.size() == 1 && acct != null) { + openConversation(xmppConnectionService.findOrCreateConversation(acct, Jid.ofLocalAndDomain(tel, gateways.iterator().next()), false, true), null); + return true; + } + + return false; + } + @Override public boolean onOptionsItemSelected(MenuItem item) { if (MenuDoubleTabUtil.shouldIgnoreTap()) { diff --git a/src/main/java/eu/siacs/conversations/ui/text/FixedURLSpan.java b/src/main/java/eu/siacs/conversations/ui/text/FixedURLSpan.java index c76ba16c8e76bcc74b2858c8fea2c1b987fc1dbd..64debcf3e6be9a8d418118e15b7b2d9e029c53b1 100644 --- a/src/main/java/eu/siacs/conversations/ui/text/FixedURLSpan.java +++ b/src/main/java/eu/siacs/conversations/ui/text/FixedURLSpan.java @@ -44,14 +44,21 @@ import android.widget.Toast; import java.util.Arrays; import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.ui.ConversationsActivity; - @SuppressLint("ParcelCreator") public class FixedURLSpan extends URLSpan { + protected final Account account; + public FixedURLSpan(String url) { + this(url, null); + } + + public FixedURLSpan(String url, Account account) { super(url); + this.account = account; } public static void fix(final Editable editable) { @@ -74,6 +81,14 @@ public class FixedURLSpan extends URLSpan { return; } } + + if (("sms".equals(uri.getScheme()) || "tel".equals(uri.getScheme())) && context instanceof ConversationsActivity) { + if (((ConversationsActivity) context).onTelUriClicked(uri, account)) { + widget.playSoundEffect(0); + return; + } + } + final Intent intent = new Intent(Intent.ACTION_VIEW, uri); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);