diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/AppComponent.java b/app/src/main/java/eu/toldi/infinityforlemmy/AppComponent.java index 3c53b06b..e459968f 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/AppComponent.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/AppComponent.java @@ -82,6 +82,7 @@ import eu.toldi.infinityforlemmy.fragments.ViewImgurVideoFragment; import eu.toldi.infinityforlemmy.fragments.ViewPostDetailFragment; import eu.toldi.infinityforlemmy.fragments.ViewRedditGalleryImageOrGifFragment; import eu.toldi.infinityforlemmy.fragments.ViewRedditGalleryVideoFragment; +import eu.toldi.infinityforlemmy.post.ObjectResolver; import eu.toldi.infinityforlemmy.services.DownloadMediaService; import eu.toldi.infinityforlemmy.services.DownloadRedditVideoService; import eu.toldi.infinityforlemmy.services.EditProfileService; @@ -307,6 +308,9 @@ public interface AppComponent { void inject(MorePostsInfoFragment morePostsInfoFragment); + void inject(ObjectResolver mObjectResolver); + + @Component.Factory interface Factory { AppComponent create(@BindsInstance Application application); diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/AppModule.java b/app/src/main/java/eu/toldi/infinityforlemmy/AppModule.java index 2da13ece..22924ba8 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/AppModule.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/AppModule.java @@ -22,6 +22,7 @@ import dagger.Module; import dagger.Provides; import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper; import eu.toldi.infinityforlemmy.customviews.LoopAvailableExoCreator; +import eu.toldi.infinityforlemmy.post.ObjectResolver; import eu.toldi.infinityforlemmy.utils.CustomThemeSharedPreferencesUtils; import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils; import eu.toldi.infinityforlemmy.videoautoplay.Config; @@ -192,8 +193,8 @@ abstract class AppModule { @Provides @Singleton static ExoCreator provideExoCreator(Config config, - ToroExo toroExo, - @Named("default") SharedPreferences sharedPreferences) { + ToroExo toroExo, + @Named("default") SharedPreferences sharedPreferences) { return new LoopAvailableExoCreator(toroExo, config, sharedPreferences); } @@ -202,4 +203,10 @@ abstract class AppModule { static Executor provideExecutor() { return Executors.newFixedThreadPool(4); } + + @Provides + @Singleton + static ObjectResolver provideObjectResolver() { + return new ObjectResolver(); + } } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/activities/LinkResolverActivity.java b/app/src/main/java/eu/toldi/infinityforlemmy/activities/LinkResolverActivity.java index 7c4a7d92..78c82e16 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/activities/LinkResolverActivity.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/activities/LinkResolverActivity.java @@ -25,7 +25,10 @@ import javax.inject.Named; import eu.toldi.infinityforlemmy.Infinity; import eu.toldi.infinityforlemmy.R; +import eu.toldi.infinityforlemmy.RetrofitHolder; import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper; +import eu.toldi.infinityforlemmy.post.ObjectResolver; +import eu.toldi.infinityforlemmy.post.Post; import eu.toldi.infinityforlemmy.utils.LemmyUtils; import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils; @@ -35,8 +38,7 @@ public class LinkResolverActivity extends AppCompatActivity { public static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; public static final String EXTRA_IS_NSFW = "EIN"; - private static final String POST_PATTERN = "/r/[\\w-]+/comments/\\w+/?\\w+/?"; - private static final String POST_PATTERN_2 = "/(u|U|user)/[\\w-]+/comments/\\w+/?\\w+/?"; + private static final String POST_PATTERN = "https?:\\/\\/\\S+\\/post\\/\\d+"; private static final String POST_PATTERN_3 = "/[\\w-]+$"; private static final String COMMENT_PATTERN = "/(r|u|U|user)/[\\w-]+/comments/\\w+/?[\\w-]+/\\w+/?"; private static final String SUBREDDIT_PATTERN = "(?:https?://[\\w.-]+)?/c/[\\w-]+(@[\\w.-]+)?"; @@ -60,6 +62,19 @@ public class LinkResolverActivity extends AppCompatActivity { @Inject CustomThemeWrapper mCustomThemeWrapper; + @Inject + ObjectResolver mObjectResolver; + + @Inject + @Named("current_account") + SharedPreferences mCurrentAccountSharedPreferences; + + @Inject + @Named("no_oauth") + RetrofitHolder mRetrofit; + + private String mAccessToken; + private Uri getRedditUriByPath(String path) { if (path.charAt(0) != '/') { return Uri.parse("https://www.reddit.com/" + path); @@ -73,6 +88,7 @@ public class LinkResolverActivity extends AppCompatActivity { super.onCreate(savedInstanceState); ((Infinity) getApplication()).getAppComponent().inject(this); + mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null); Uri uri = getIntent().getData(); if (uri == null) { @@ -169,6 +185,35 @@ public class LinkResolverActivity extends AppCompatActivity { intent.putExtra(ViewUserDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); intent.putExtra(ViewUserDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); startActivity(intent); + } else if (uri.toString().matches(POST_PATTERN)) { + if (mAccessToken == null) { + // switch retrofit to use the current instance for anonymous requests + mRetrofit.setBaseURL(uri.getScheme() + "://" + uri.getHost() + "/"); + Intent intent = new Intent(LinkResolverActivity.this, ViewPostDetailActivity.class); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, Integer.parseInt(segments.get(segments.size() - 1))); + intent.putExtra(ViewPostDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); + intent.putExtra(ViewPostDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); + startActivity(intent); + } else { + ((Infinity) getApplication()).getAppComponent().inject(mObjectResolver); + mObjectResolver.resolvePost(uri.toString(), mAccessToken, new ObjectResolver.ObjectResolverListener() { + @Override + public void onResolveObjectSuccess(Object p) { + Post post = (Post) p; + Intent intent = new Intent(LinkResolverActivity.this, ViewPostDetailActivity.class); + intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, post.getId()); + intent.putExtra(ViewPostDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); + intent.putExtra(ViewPostDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); + startActivity(intent); + } + + @Override + public void onResolveObjectFailed() { + Toast.makeText(LinkResolverActivity.this, R.string.could_not_resolve_link, Toast.LENGTH_SHORT).show(); + finish(); + } + }); + } } else if (authority.equals("v.redd.it")) { Intent intent = new Intent(this, ViewVideoActivity.class); intent.putExtra(ViewVideoActivity.EXTRA_VIDEO_TYPE, ViewVideoActivity.VIDEO_TYPE_V_REDD_IT); @@ -187,17 +232,6 @@ public class LinkResolverActivity extends AppCompatActivity { startActivity(intent); } else if (path.equals("/report")) { openInWebView(uri); - } else if (path.matches(POST_PATTERN) || path.matches(POST_PATTERN_2)) { - int commentsIndex = segments.lastIndexOf("comments"); - if (commentsIndex >= 0 && commentsIndex < segments.size() - 1) { - Intent intent = new Intent(this, ViewPostDetailActivity.class); - intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, segments.get(commentsIndex + 1)); - intent.putExtra(ViewPostDetailActivity.EXTRA_MESSAGE_FULLNAME, messageFullname); - intent.putExtra(ViewPostDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); - startActivity(intent); - } else { - deepLinkError(uri); - } } else if (path.matches(POST_PATTERN_3)) { Intent intent = new Intent(this, ViewPostDetailActivity.class); intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, path.substring(1)); diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/apis/LemmyAPI.java b/app/src/main/java/eu/toldi/infinityforlemmy/apis/LemmyAPI.java index 9fec1b63..e72ec511 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/apis/LemmyAPI.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/apis/LemmyAPI.java @@ -159,4 +159,10 @@ public interface LemmyAPI { @Header("Cookie") String token, @Part MultipartBody.Part filePart ); + + @GET("api/v3/resolve_object") + Call resolveObject( + @Query("q") String query, + @Query("auth") String auth + ); } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/fragments/ViewPostDetailFragment.java b/app/src/main/java/eu/toldi/infinityforlemmy/fragments/ViewPostDetailFragment.java index a0df5d15..1ffcb479 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/fragments/ViewPostDetailFragment.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/fragments/ViewPostDetailFragment.java @@ -1258,7 +1258,7 @@ public class ViewPostDetailFragment extends Fragment implements FragmentCommunic mPostDetailsSharedPreferences, mExoCreator, post1 -> EventBus.getDefault().post(new PostUpdateEventToPostList(mPost, postListPosition))); mSwipeRefreshLayout.setRefreshing(false); - FetchComment.fetchComments(mExecutor, new Handler(), mRetrofit.getRetrofit(), mAccessToken, subredditId, mSingleCommentId, sortType, mExpandChildren, 1, new FetchComment.FetchCommentListener() { + FetchComment.fetchComments(mExecutor, new Handler(), mRetrofit.getRetrofit(), mAccessToken, post.getId(), mSingleCommentId == 0 ? null : mSingleCommentId, sortType, mExpandChildren, 1, new FetchComment.FetchCommentListener() { @Override public void onFetchCommentSuccess(ArrayList expandedComments, Integer parentId, ArrayList children) { pages_loaded++; diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/post/ObjectResolver.java b/app/src/main/java/eu/toldi/infinityforlemmy/post/ObjectResolver.java new file mode 100644 index 00000000..20c44786 --- /dev/null +++ b/app/src/main/java/eu/toldi/infinityforlemmy/post/ObjectResolver.java @@ -0,0 +1,91 @@ +package eu.toldi.infinityforlemmy.post; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Objects; + +import javax.inject.Inject; +import javax.inject.Named; + +import eu.toldi.infinityforlemmy.RetrofitHolder; +import eu.toldi.infinityforlemmy.apis.LemmyAPI; +import eu.toldi.infinityforlemmy.comment.Comment; +import eu.toldi.infinityforlemmy.comment.ParseComment; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +public class ObjectResolver { + + @Inject + @Named("no_oauth") + RetrofitHolder retrofitHolder; + + public void resolvePost(String query, String auth, ObjectResolverListener objectResolverListener) { + LemmyAPI lemmyAPI = retrofitHolder.getRetrofit().create(LemmyAPI.class); + + Call response = lemmyAPI.resolveObject(query, auth); + response.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful() + && response.body() != null) { + try { + JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body())).getJSONObject("post"); + Post p = ParsePost.parseBasicData(jsonObject); + objectResolverListener.onResolveObjectSuccess(p); + } catch (JSONException e) { + objectResolverListener.onResolveObjectFailed(); + } + + } else { + objectResolverListener.onResolveObjectFailed(); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + objectResolverListener.onResolveObjectFailed(); + } + }); + + } + + public void resolveComment(String query, String auth, ObjectResolverListener objectResolverListener) { + LemmyAPI lemmyAPI = retrofitHolder.getRetrofit().create(LemmyAPI.class); + + Call response = lemmyAPI.resolveObject(query, auth); + response.enqueue( + new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful() + && response.body() != null) { + try { + JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body())).getJSONObject("comment"); + Comment c = ParseComment.parseSingleComment(jsonObject); + objectResolverListener.onResolveObjectSuccess(c); + } catch (JSONException e) { + objectResolverListener.onResolveObjectFailed(); + } + + } else { + objectResolverListener.onResolveObjectFailed(); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + objectResolverListener.onResolveObjectFailed(); + } + } + ); + } + + public interface ObjectResolverListener { + void onResolveObjectSuccess(Object resolvedObject); + + void onResolveObjectFailed(); + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e6f5f53c..4e440272 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1341,4 +1341,5 @@ 9 Months Anonymous Account Instance URL cannot be null or empty + Could not resolve URL :(