support parsing mailto links

i mean, why not - if github decided every @username@example.social is actually
an email address, might as well support sharing that mailto link to megalodon
This commit is contained in:
sk 2023-06-03 23:39:43 +02:00
parent 37622ba9ce
commit 7859f4cd05
3 changed files with 28 additions and 20 deletions

View File

@ -29,35 +29,40 @@ public class UiUtilsTest {
} }
@Test @Test
public void looksLikeFediverseHandle() { public void parseFediverseHandle() {
assertEquals( assertEquals(
Optional.of(Pair.create("megalodon", Optional.of("floss.social"))), Optional.of(Pair.create("megalodon", Optional.of("floss.social"))),
UiUtils.looksLikeFediverseHandle("megalodon@floss.social") UiUtils.parseFediverseHandle("megalodon@floss.social")
); );
assertEquals( assertEquals(
Optional.of(Pair.create("megalodon", Optional.of("floss.social"))), Optional.of(Pair.create("megalodon", Optional.of("floss.social"))),
UiUtils.looksLikeFediverseHandle("@megalodon@floss.social") UiUtils.parseFediverseHandle("@megalodon@floss.social")
); );
assertEquals( assertEquals(
Optional.of(Pair.create("megalodon", Optional.empty())), Optional.of(Pair.create("megalodon", Optional.empty())),
UiUtils.looksLikeFediverseHandle("@megalodon") UiUtils.parseFediverseHandle("@megalodon")
);
assertEquals(
Optional.of(Pair.create("megalodon", Optional.of("floss.social"))),
UiUtils.parseFediverseHandle("mailto:megalodon@floss.social")
); );
assertEquals( assertEquals(
Optional.empty(), Optional.empty(),
UiUtils.looksLikeFediverseHandle("megalodon") UiUtils.parseFediverseHandle("megalodon")
); );
assertEquals( assertEquals(
Optional.empty(), Optional.empty(),
UiUtils.looksLikeFediverseHandle("this is not a fedi handle") UiUtils.parseFediverseHandle("this is not a fedi handle")
); );
assertEquals( assertEquals(
Optional.empty(), Optional.empty(),
UiUtils.looksLikeFediverseHandle("not@a-domain") UiUtils.parseFediverseHandle("not@a-domain")
); );
} }

View File

@ -33,7 +33,7 @@ public class ExternalShareActivity extends FragmentStackActivity{
if(savedInstanceState==null){ if(savedInstanceState==null){
Optional<String> text = Optional.ofNullable(getIntent().getStringExtra(Intent.EXTRA_TEXT)); Optional<String> text = Optional.ofNullable(getIntent().getStringExtra(Intent.EXTRA_TEXT));
Optional<Pair<String, Optional<String>>> fediHandle = text.flatMap(UiUtils::looksLikeFediverseHandle); Optional<Pair<String, Optional<String>>> fediHandle = text.flatMap(UiUtils::parseFediverseHandle);
boolean isFediUrl = text.map(UiUtils::looksLikeFediverseUrl).orElse(false); boolean isFediUrl = text.map(UiUtils::looksLikeFediverseUrl).orElse(false);
boolean isOpenable = isFediUrl || fediHandle.isPresent(); boolean isOpenable = isFediUrl || fediHandle.isPresent();

View File

@ -907,27 +907,30 @@ public class UiUtils {
return theme == GlobalUserPreferences.ThemePreference.DARK; return theme == GlobalUserPreferences.ThemePreference.DARK;
} }
public static Optional<Pair<String, Optional<String>>> looksLikeFediverseHandle(String maybeFediHandle) { public static Optional<Pair<String, Optional<String>>> parseFediverseHandle(String maybeFediHandle) {
// https://stackoverflow.com/a/26987741, except i put a + here ... v // https://stackoverflow.com/a/26987741, except i put a + here ... v
String domainRegex = "^(((?!-))(xn--|_)?[a-z0-9-]{0,61}[a-z0-9]\\.)+(xn--)?([a-z0-9][a-z0-9\\-]{0,60}|[a-z0-9-]{1,30}\\.[a-z]{2,})$"; String domainRegex = "^(((?!-))(xn--|_)?[a-z0-9-]{0,61}[a-z0-9]\\.)+(xn--)?([a-z0-9][a-z0-9\\-]{0,60}|[a-z0-9-]{1,30}\\.[a-z]{2,})$";
try { if (maybeFediHandle.toLowerCase().startsWith("mailto:")) {
maybeFediHandle = maybeFediHandle.substring("mailto:".length());
}
List<String> parts = Arrays.stream(maybeFediHandle.split("@")) List<String> parts = Arrays.stream(maybeFediHandle.split("@"))
.filter(part -> !part.isEmpty()) .filter(part -> !part.isEmpty())
.collect(Collectors.toList()); .collect(Collectors.toList());
if (parts.size() == 0 || !parts.get(0).matches("^[^/\\s]+$")) { if (parts.size() == 0 || !parts.get(0).matches("^[^/\\s]+$")) {
return Optional.empty(); return Optional.empty();
} else if (parts.size() == 2) { } else if (parts.size() == 2) {
try {
String domain = IDN.toASCII(parts.get(1)); String domain = IDN.toASCII(parts.get(1));
if (!domain.matches(domainRegex)) return Optional.empty(); if (!domain.matches(domainRegex)) return Optional.empty();
return Optional.of(Pair.create(parts.get(0), Optional.of(parts.get(1)))); return Optional.of(Pair.create(parts.get(0), Optional.of(parts.get(1))));
} catch (IllegalArgumentException ignored) {
return Optional.empty();
}
} else if (maybeFediHandle.startsWith("@")) { } else if (maybeFediHandle.startsWith("@")) {
return Optional.of(Pair.create(parts.get(0), Optional.empty())); return Optional.of(Pair.create(parts.get(0), Optional.empty()));
} else { } else {
return Optional.empty(); return Optional.empty();
} }
} catch (IllegalArgumentException ignored) {
return Optional.empty();
}
} }
// https://mastodon.foo.bar/@User // https://mastodon.foo.bar/@User