Skip to content

Commit

Permalink
Several improvements with links/sharing/opening externally (#1101)
Browse files Browse the repository at this point in the history
* Normalize URI schemes and hosts to lowercase (#1099); properly handle sharing/copying internal Reddit links

* Open mailto links properly (#771)

* Merge in upstream changes

* Add ability to open comment in external browser (#205)

* Preference for domain when sharing Reddit links (#947), use LinkHandler.shareText() to share post-comment links

* Share post title as subject if title should be included when sharing

* Use "Share Link" instead of "Share" to describe sharing post links, for clarity (#946)
  • Loading branch information
Cguy7777 authored Sep 23, 2023
1 parent 54d427f commit d724d4e
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,10 @@ private static void onSubredditActionMenuItemSelected(

switch(action) {
case SHARE: {
LinkHandler.shareText(activity, subredditCanonicalId.toString(), url);
LinkHandler.shareText(
activity,
subredditCanonicalId.toString(),
LinkHandler.getPreferredRedditUriString(url));
break;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ private enum FeatureFlag {
CONTROVERSIAL_DATE_SORTS_FEATURE("controversialDateSortsFeature"),
HIDE_STATUS_BAR_FOR_MEDIA_FEATURE("hideStatusBarForMediaFeature"),
REPLY_IN_POST_ACTION_MENU_FEATURE("replyInPostActionMenuFeature"),
MAIN_MENU_FIND_SUBREDDIT_FEATURE("mainMenuFindSubreddit");
MAIN_MENU_FIND_SUBREDDIT_FEATURE("mainMenuFindSubreddit"),
OPEN_COMMENT_EXTERNALLY_FEATURE("openCommentExternallyFeature");

@NonNull private final String id;

Expand Down Expand Up @@ -243,6 +244,26 @@ public static void handleUpgrade(@NonNull final Context context) {
context.getString(R.string.pref_menus_mainmenu_shortcutitems_key),
existingShortcutPreferences).apply();
}

if(getAndSetFeatureFlag(prefs, FeatureFlag.OPEN_COMMENT_EXTERNALLY_FEATURE)
== FeatureFlagStatus.UPGRADE_NEEDED) {

Log.i(TAG, "Upgrading, add external browser option to comment action menu.");

final Set<String> existingCommentActionMenuItems = getStringSet(
R.string.pref_menus_comment_context_items_key,
R.array.pref_menus_comment_context_items_return,
context,
prefs);

existingCommentActionMenuItems.add("external");

prefs.edit()
.putStringSet(
context.getString(R.string.pref_menus_comment_context_items_key),
existingCommentActionMenuItems)
.apply();
}
});
}

Expand Down
139 changes: 106 additions & 33 deletions src/main/java/org/quantumbadger/redreader/common/LinkHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import org.quantumbadger.redreader.image.StreamableAPI;
import org.quantumbadger.redreader.reddit.kthings.RedditPost;
import org.quantumbadger.redreader.reddit.url.ComposeMessageURL;
import org.quantumbadger.redreader.reddit.url.PostCommentListingURL;
import org.quantumbadger.redreader.reddit.url.RedditURLParser;

import java.util.ArrayList;
Expand Down Expand Up @@ -137,7 +138,7 @@ public static void onLinkClicked(

public static void onLinkClicked(
final AppCompatActivity activity,
String url,
final String url,
final boolean forceNoImage,
final RedditPost post,
final AlbumInfo albumInfo,
Expand Down Expand Up @@ -167,22 +168,13 @@ public static void onLinkClicked(
}
}

if(url.startsWith("r/") || url.startsWith("u/")) {
url = "/" + url;
}

if(url.startsWith("/")) {
url = "https://reddit.com" + url;
}

if(!url.contains("://")) {
url = "http://" + url;
}
final Uri normalUrl = convertAndNormalizeUri(url);
final String normalUrlString = normalUrl.toString();

if(!forceNoImage && isProbablyAnImage(url)) {
if(!forceNoImage && isProbablyAnImage(normalUrlString)) {

final Intent intent = new Intent(activity, ImageViewActivity.class);
intent.setData(Uri.parse(url));
intent.setData(normalUrl);
intent.putExtra("post", post);

if(albumInfo != null) {
Expand All @@ -194,8 +186,8 @@ public static void onLinkClicked(
return;
}

if(!forceNoImage && (imgurAlbumPattern.matcher(url).matches()
|| redditGalleryPattern.matcher(url).matches())) {
if(!forceNoImage && (imgurAlbumPattern.matcher(normalUrlString).matches()
|| redditGalleryPattern.matcher(normalUrlString).matches())) {

final PrefsUtility.AlbumViewMode albumViewMode
= PrefsUtility.pref_behaviour_albumview_mode();
Expand All @@ -206,7 +198,7 @@ public static void onLinkClicked(
final Intent intent = new Intent(
activity,
AlbumListingActivity.class);
intent.setData(Uri.parse(url));
intent.setData(normalUrl);
intent.putExtra("post", post);
activity.startActivity(intent);
return;
Expand All @@ -215,22 +207,22 @@ public static void onLinkClicked(
case INTERNAL_BROWSER: {
if(PrefsUtility.pref_behaviour_usecustomtabs()
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
openCustomTab(activity, Uri.parse(url), post);
openCustomTab(activity, normalUrl, post);

} else {
openInternalBrowser(activity, url, post);
openInternalBrowser(activity, normalUrlString, post);
}
return;
}

case EXTERNAL_BROWSER: {
openWebBrowser(activity, Uri.parse(url), fromExternalIntent);
openWebBrowser(activity, normalUrl, fromExternalIntent);
return;
}
}
}

final RedditURLParser.RedditURL redditURL = RedditURLParser.parse(Uri.parse(url));
final RedditURLParser.RedditURL redditURL = RedditURLParser.parse(normalUrl);
if(redditURL != null) {

switch(redditURL.pathType()) {
Expand Down Expand Up @@ -288,20 +280,21 @@ public static void onLinkClicked(
// Use a browser

if(!PrefsUtility.pref_behaviour_useinternalbrowser()) {
if(openWebBrowser(activity, Uri.parse(url), fromExternalIntent)) {
if(openWebBrowser(activity, normalUrl, fromExternalIntent)) {
return;
}
}

if(youtubeDotComPattern.matcher(url).matches()
|| vimeoPattern.matcher(url).matches()
|| googlePlayPattern.matcher(url).matches()) {
if(openWebBrowser(activity, Uri.parse(url), fromExternalIntent)) {
if(youtubeDotComPattern.matcher(normalUrlString).matches()
|| vimeoPattern.matcher(normalUrlString).matches()
|| googlePlayPattern.matcher(normalUrlString).matches()
|| normalUrlString.startsWith("mailto:")) {
if(openWebBrowser(activity, normalUrl, fromExternalIntent)) {
return;
}
}

final Matcher youtuDotBeMatcher = youtuDotBePattern.matcher(url);
final Matcher youtuDotBeMatcher = youtuDotBePattern.matcher(normalUrlString);

if(youtuDotBeMatcher.find() && youtuDotBeMatcher.group(1) != null) {
final String youtuBeUrl = "http://youtube.com/watch?v="
Expand All @@ -316,10 +309,10 @@ public static void onLinkClicked(

if(PrefsUtility.pref_behaviour_usecustomtabs()
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
openCustomTab(activity, Uri.parse(url), post);
openCustomTab(activity, normalUrl, post);

} else {
openInternalBrowser(activity, url, post);
openInternalBrowser(activity, normalUrlString, post);
}

}
Expand All @@ -336,6 +329,8 @@ public static void onLinkLongClicked(
return;
}

final String normalUriString = convertAndNormalizeUri(uri).toString();

final EnumSet<LinkHandler.LinkAction> itemPref
= PrefsUtility.pref_menus_link_context_items();

Expand All @@ -358,7 +353,7 @@ public static void onLinkLongClicked(
LinkAction.EXTERNAL));
}
if(itemPref.contains(LinkAction.SAVE_IMAGE)
&& isProbablyAnImage(uri)
&& isProbablyAnImage(normalUriString)
&& !forceNoImage) {
menu.add(new LinkMenuItem(
activity,
Expand All @@ -369,7 +364,7 @@ && isProbablyAnImage(uri)
menu.add(new LinkMenuItem(activity, R.string.action_share, LinkAction.SHARE));
}
if(itemPref.contains(LinkAction.SHARE_IMAGE)
&& isProbablyAnImage(uri)
&& isProbablyAnImage(normalUriString)
&& !forceNoImage) {
menu.add(new LinkMenuItem(
activity,
Expand All @@ -385,7 +380,10 @@ && isProbablyAnImage(uri)
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);

builder.setItems(menuText,
(dialog, which) -> onActionMenuItemSelected(uri, activity, menu.get(which).action));
(dialog, which) -> onActionMenuItemSelected(
normalUriString,
activity,
menu.get(which).action));

//builder.setNeutralButton(R.string.dialog_cancel, null);

Expand All @@ -400,7 +398,7 @@ public static void onActionMenuItemSelected(
final LinkAction action) {
switch(action) {
case SHARE:
shareText(activity, null, uri);
shareText(activity, null, getPreferredRedditUriString(uri));
break;
case COPY_URL:
final ClipboardManager clipboardManager
Expand Down Expand Up @@ -1302,4 +1300,79 @@ public static void shareText(
activity.getString(R.string.action_share)));
}
}

public static Uri convertAndNormalizeUri(@NonNull String uri) {
if(uri.startsWith("r/") || uri.startsWith("u/")) {
uri = "/" + uri;
}

if(uri.startsWith("/")) {
uri = "https://reddit.com" + uri;
}

if(!uri.contains("://") && !uri.startsWith("mailto:")) {
uri = "http://" + uri;
}

final Uri parsedUri = Uri.parse(uri).normalizeScheme();
final Uri.Builder uriBuilder = parsedUri.buildUpon();

final String authority = parsedUri.getEncodedAuthority();
if(authority != null) {
final String normalAuthority;

//Don't lowercase the rare userinfo component if present.
if(authority.contains("@")) {
final String[] authorityParts = authority.split("@", 2);
normalAuthority =
authorityParts[0] + "@" + StringUtils.asciiLowercase(authorityParts[1]);
} else {
normalAuthority = StringUtils.asciiLowercase(authority);
}

uriBuilder.encodedAuthority(normalAuthority);
}

return uriBuilder.build();
}

public static String getPreferredRedditUriString(final String uri) {
final Uri parsedUri = convertAndNormalizeUri(uri);

//Return non-Reddit links normalized but otherwise unaltered
if (RedditURLParser.parse(parsedUri) == null) {
return parsedUri.toString();
}

//Respect non-participation links
if(parsedUri.getHost().equals("np.reddit.com")) {
return parsedUri.toString();
}

final PostCommentListingURL potentialPostLink = PostCommentListingURL.parse(parsedUri);
final String postId;
if(potentialPostLink != null && potentialPostLink.commentId == null) {
//Direct link to a post, not to a comment or anything else
postId = potentialPostLink.postId;
} else {
postId = null;
}

final PrefsUtility.SharingDomain preferredDomain
= PrefsUtility.pref_behaviour_sharing_domain();

//Only direct links to posts will be converted to redd.it links
if(preferredDomain == PrefsUtility.SharingDomain.SHORT_REDDIT && postId == null) {
return parsedUri.toString();
}

final Uri.Builder uriBuilder = parsedUri.buildUpon();

uriBuilder.encodedAuthority(preferredDomain.domain);
if(preferredDomain == PrefsUtility.SharingDomain.SHORT_REDDIT) {
uriBuilder.encodedPath("/" + postId);
}

return uriBuilder.build().toString();
}
}
18 changes: 18 additions & 0 deletions src/main/java/org/quantumbadger/redreader/common/PrefsUtility.java
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,24 @@ public static boolean pref_behaviour_hide_read_posts() {
false);
}

public enum SharingDomain {
STANDARD_REDDIT("reddit.com"),
SHORT_REDDIT("redd.it"),
OLD_REDDIT("old.reddit.com"),
NEW_REDDIT("new.reddit.com"),
NP_REDDIT("np.reddit.com");

public final String domain;
SharingDomain(final String domain) {
this.domain = domain;
}
}

public static SharingDomain pref_behaviour_sharing_domain() {
return SharingDomain.valueOf(StringUtils.asciiUppercase(getString(
R.string.pref_behaviour_sharing_domain_key,
"standard_reddit")));
}
public static boolean pref_behaviour_share_permalink() {
return getBoolean(
R.string.pref_behaviour_share_permalink_key,
Expand Down
Loading

0 comments on commit d724d4e

Please sign in to comment.