mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 03:25:34 +00:00 
			
		
		
		
	discovery topics are messed up tbh
This commit is contained in:
		
							parent
							
								
									f827874b3a
								
							
						
					
					
						commit
						440f6e2339
					
				| @ -20,6 +20,8 @@ import android.util.Log; | |||||||
| import android.util.TypedValue; | import android.util.TypedValue; | ||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.view.ViewGroup; | import android.view.ViewGroup; | ||||||
|  | import android.widget.AdapterView; | ||||||
|  | import android.widget.ArrayAdapter; | ||||||
| import android.widget.ImageView; | import android.widget.ImageView; | ||||||
| import android.widget.LinearLayout; | import android.widget.LinearLayout; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
| @ -61,6 +63,7 @@ import awais.instagrabber.asyncs.LocationFetcher; | |||||||
| import awais.instagrabber.asyncs.PostsFetcher; | import awais.instagrabber.asyncs.PostsFetcher; | ||||||
| import awais.instagrabber.asyncs.ProfileFetcher; | import awais.instagrabber.asyncs.ProfileFetcher; | ||||||
| import awais.instagrabber.asyncs.i.iStoryStatusFetcher; | import awais.instagrabber.asyncs.i.iStoryStatusFetcher; | ||||||
|  | import awais.instagrabber.asyncs.i.iTopicFetcher; | ||||||
| import awais.instagrabber.customviews.MouseDrawer; | import awais.instagrabber.customviews.MouseDrawer; | ||||||
| import awais.instagrabber.customviews.RamboTextView; | import awais.instagrabber.customviews.RamboTextView; | ||||||
| import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager; | import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager; | ||||||
| @ -71,6 +74,7 @@ import awais.instagrabber.interfaces.FetchListener; | |||||||
| import awais.instagrabber.interfaces.MentionClickListener; | import awais.instagrabber.interfaces.MentionClickListener; | ||||||
| import awais.instagrabber.models.BasePostModel; | import awais.instagrabber.models.BasePostModel; | ||||||
| import awais.instagrabber.models.DiscoverItemModel; | import awais.instagrabber.models.DiscoverItemModel; | ||||||
|  | import awais.instagrabber.models.DiscoverTopicModel; | ||||||
| import awais.instagrabber.models.FeedModel; | import awais.instagrabber.models.FeedModel; | ||||||
| import awais.instagrabber.models.FeedStoryModel; | import awais.instagrabber.models.FeedStoryModel; | ||||||
| import awais.instagrabber.models.HashtagModel; | import awais.instagrabber.models.HashtagModel; | ||||||
| @ -94,7 +98,8 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { | |||||||
|     private final boolean autoloadPosts; |     private final boolean autoloadPosts; | ||||||
|     private FeedStoryModel[] stories; |     private FeedStoryModel[] stories; | ||||||
|     private boolean hasNextPage = false, feedHasNextPage = false, discoverHasMore = false; |     private boolean hasNextPage = false, feedHasNextPage = false, discoverHasMore = false; | ||||||
|     private String endCursor = null, feedEndCursor = null, discoverEndMaxId = null; |     private String endCursor = null, feedEndCursor = null, discoverEndMaxId = null, topic = null; | ||||||
|  |     private String[] topicIds = null; | ||||||
|     private final FetchListener<PostModel[]> postsFetchListener = new FetchListener<PostModel[]>() { |     private final FetchListener<PostModel[]> postsFetchListener = new FetchListener<PostModel[]>() { | ||||||
|         @Override |         @Override | ||||||
|         public void onResult(final PostModel[] result) { |         public void onResult(final PostModel[] result) { | ||||||
| @ -194,7 +199,10 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { | |||||||
| 
 | 
 | ||||||
|         @Override |         @Override | ||||||
|         public void onResult(final DiscoverItemModel[] result) { |         public void onResult(final DiscoverItemModel[] result) { | ||||||
|             if (result != null) { |             if (result.length == 0) { | ||||||
|  |                 Toast.makeText(main, R.string.discover_empty, Toast.LENGTH_SHORT).show(); | ||||||
|  |             } | ||||||
|  |             else if (result != null) { | ||||||
|                 final int oldSize = main.discoverItems.size(); |                 final int oldSize = main.discoverItems.size(); | ||||||
|                 main.discoverItems.addAll(Arrays.asList(result)); |                 main.discoverItems.addAll(Arrays.asList(result)); | ||||||
|                 discoverAdapter.notifyItemRangeInserted(oldSize, result.length); |                 discoverAdapter.notifyItemRangeInserted(oldSize, result.length); | ||||||
| @ -210,6 +218,20 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { | |||||||
|             main.mainBinding.discoverSwipeRefreshLayout.setRefreshing(false); |             main.mainBinding.discoverSwipeRefreshLayout.setRefreshing(false); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |     private final FetchListener<DiscoverTopicModel> topicFetchListener = new FetchListener<DiscoverTopicModel>() { | ||||||
|  |         @Override | ||||||
|  |         public void doBefore() {} | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void onResult(final DiscoverTopicModel result) { | ||||||
|  |             if (result != null) { | ||||||
|  |                 topicIds = result.getIds(); | ||||||
|  |                 ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>( | ||||||
|  |                         main, android.R.layout.simple_spinner_dropdown_item, result.getNames() ); | ||||||
|  |                 main.mainBinding.discoverType.setAdapter(spinnerArrayAdapter); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|     private final FetchListener<FeedStoryModel[]> feedStoriesListener = new FetchListener<FeedStoryModel[]>() { |     private final FetchListener<FeedStoryModel[]> feedStoriesListener = new FetchListener<FeedStoryModel[]>() { | ||||||
|         @Override |         @Override | ||||||
|         public void doBefore() { |         public void doBefore() { | ||||||
| @ -533,11 +555,30 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { | |||||||
|         main.mainBinding.discoverPosts.setLayoutManager(layoutManager); |         main.mainBinding.discoverPosts.setLayoutManager(layoutManager); | ||||||
|         main.mainBinding.discoverPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4))); |         main.mainBinding.discoverPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4))); | ||||||
| 
 | 
 | ||||||
|  |         new iTopicFetcher(topicFetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | ||||||
|  |         main.mainBinding.discoverType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { | ||||||
|  |             @Override | ||||||
|  |             public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { | ||||||
|  |                 if (topicIds != null) { | ||||||
|  |                     topic = topicIds[pos]; | ||||||
|  |                     main.mainBinding.discoverSwipeRefreshLayout.setRefreshing(true); | ||||||
|  |                     if (discoverLazyLoader != null) discoverLazyLoader.resetState(); | ||||||
|  |                     main.discoverItems.clear(); | ||||||
|  |                     if (discoverAdapter != null) discoverAdapter.notifyDataSetChanged(); | ||||||
|  |                     new DiscoverFetcher(topic, null, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             @Override | ||||||
|  |             public void onNothingSelected(AdapterView<?> parent) { | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|         main.mainBinding.discoverSwipeRefreshLayout.setOnRefreshListener(() -> { |         main.mainBinding.discoverSwipeRefreshLayout.setOnRefreshListener(() -> { | ||||||
|             if (discoverLazyLoader != null) discoverLazyLoader.resetState(); |             if (discoverLazyLoader != null) discoverLazyLoader.resetState(); | ||||||
|             main.discoverItems.clear(); |             main.discoverItems.clear(); | ||||||
|             if (discoverAdapter != null) discoverAdapter.notifyDataSetChanged(); |             if (discoverAdapter != null) discoverAdapter.notifyDataSetChanged(); | ||||||
|             new DiscoverFetcher(null, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |             new DiscoverFetcher(topic, null, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         main.mainBinding.discoverPosts.setAdapter(discoverAdapter = new DiscoverAdapter(main.discoverItems, v -> { |         main.mainBinding.discoverPosts.setAdapter(discoverAdapter = new DiscoverAdapter(main.discoverItems, v -> { | ||||||
| @ -563,12 +604,12 @@ public final class MainHelper implements SwipeRefreshLayout.OnRefreshListener { | |||||||
|         main.mainBinding.discoverPosts.addOnScrollListener(discoverLazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { |         main.mainBinding.discoverPosts.addOnScrollListener(discoverLazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { | ||||||
|             if (discoverHasMore) { |             if (discoverHasMore) { | ||||||
|                 main.mainBinding.discoverSwipeRefreshLayout.setRefreshing(true); |                 main.mainBinding.discoverSwipeRefreshLayout.setRefreshing(true); | ||||||
|                 new DiscoverFetcher(discoverEndMaxId, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |                 new DiscoverFetcher(topic, discoverEndMaxId, discoverFetchListener, false).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | ||||||
|                 discoverEndMaxId = null; |                 discoverEndMaxId = null; | ||||||
|             } |             } | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         new DiscoverFetcher(null, discoverFetchListener, true).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |         new DiscoverFetcher(topic, null, discoverFetchListener, true).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void onIntent(final Intent intent) { |     public void onIntent(final Intent intent) { | ||||||
|  | |||||||
| @ -43,7 +43,7 @@ public final class DirectMessagesUserInbox extends AppCompatActivity { | |||||||
|     private DirectItemModel directItemModel; |     private DirectItemModel directItemModel; | ||||||
|     private final ProfileModel myProfileHolder = |     private final ProfileModel myProfileHolder = | ||||||
|             new ProfileModel(false, false, false, null, null, null, null, null, null, null, 0, 0, 0, false, false, false, false); |             new ProfileModel(false, false, false, null, null, null, null, null, null, null, 0, 0, 0, false, false, false, false); | ||||||
|     private final ArrayList<ProfileModel> users = new ArrayList<>(); |     private final ArrayList<ProfileModel> users = new ArrayList<>(), leftusers = new ArrayList<>(); | ||||||
|     private final ArrayList<DirectItemModel> directItemModels = new ArrayList<>(); |     private final ArrayList<DirectItemModel> directItemModels = new ArrayList<>(); | ||||||
|     private final FetchListener<InboxThreadModel> fetchListener = new FetchListener<InboxThreadModel>() { |     private final FetchListener<InboxThreadModel> fetchListener = new FetchListener<InboxThreadModel>() { | ||||||
|         @Override |         @Override | ||||||
| @ -63,6 +63,9 @@ public final class DirectMessagesUserInbox extends AppCompatActivity { | |||||||
|                 users.clear(); |                 users.clear(); | ||||||
|                 users.addAll(Arrays.asList(result.getUsers())); |                 users.addAll(Arrays.asList(result.getUsers())); | ||||||
| 
 | 
 | ||||||
|  |                 leftusers.clear(); | ||||||
|  |                 leftusers.addAll(Arrays.asList(result.getLeftUsers())); | ||||||
|  | 
 | ||||||
|                 final int oldSize = directItemModels.size(); |                 final int oldSize = directItemModels.size(); | ||||||
|                 final List<DirectItemModel> itemModels = Arrays.asList(result.getItems()); |                 final List<DirectItemModel> itemModels = Arrays.asList(result.getItems()); | ||||||
|                 directItemModels.addAll(itemModels); |                 directItemModels.addAll(itemModels); | ||||||
| @ -102,7 +105,7 @@ public final class DirectMessagesUserInbox extends AppCompatActivity { | |||||||
|             } |             } | ||||||
|         })); |         })); | ||||||
| 
 | 
 | ||||||
|         messageItemsAdapter = new MessageItemsAdapter(directItemModels, users, v -> { |         messageItemsAdapter = new MessageItemsAdapter(directItemModels, users, leftusers, v -> { | ||||||
|             Object tag = v.getTag(); |             Object tag = v.getTag(); | ||||||
|             if (tag instanceof DirectItemModel) { |             if (tag instanceof DirectItemModel) { | ||||||
|                 directItemModel = (DirectItemModel) tag; |                 directItemModel = (DirectItemModel) tag; | ||||||
| @ -129,21 +132,28 @@ public final class DirectMessagesUserInbox extends AppCompatActivity { | |||||||
|                         Toast.makeText(v.getContext(), R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show(); |                         Toast.makeText(v.getContext(), R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show(); | ||||||
|                         break; |                         break; | ||||||
|                     case STORY_SHARE: |                     case STORY_SHARE: | ||||||
|                         StoryModel sm = new StoryModel( |                         if (directItemModel.getReelShare() != null) { | ||||||
|                                 directItemModel.getReelShare().getReelId(), |                             StoryModel sm = new StoryModel( | ||||||
|                                 directItemModel.getReelShare().getMedia().getVideoUrl(), |                                     directItemModel.getReelShare().getReelId(), | ||||||
|                                 directItemModel.getReelShare().getMedia().getMediaType(), |                                     directItemModel.getReelShare().getMedia().getVideoUrl(), | ||||||
|                                 directItemModel.getTimestamp(), |                                     directItemModel.getReelShare().getMedia().getMediaType(), | ||||||
|                                 directItemModel.getReelShare().getReelOwnerName() |                                     directItemModel.getTimestamp(), | ||||||
| 
 |                                     directItemModel.getReelShare().getReelOwnerName() | ||||||
|                         ); |                             ); | ||||||
|                         sm.setVideoUrl(directItemModel.getReelShare().getMedia().getVideoUrl()); |                             sm.setVideoUrl(directItemModel.getReelShare().getMedia().getVideoUrl()); | ||||||
|                         StoryModel[] sms = {sm}; |                             StoryModel[] sms = {sm}; | ||||||
|                         if (directItemModel.getReelShare() != null) |  | ||||||
|                             startActivity(new Intent(this, StoryViewer.class) |                             startActivity(new Intent(this, StoryViewer.class) | ||||||
|                                     .putExtra(Constants.EXTRAS_USERNAME, directItemModel.getReelShare().getReelOwnerName()) |                                     .putExtra(Constants.EXTRAS_USERNAME, directItemModel.getReelShare().getReelOwnerName()) | ||||||
|                                     .putExtra(Constants.EXTRAS_STORIES, sms) |                                     .putExtra(Constants.EXTRAS_STORIES, sms) | ||||||
|                             ); |                             ); | ||||||
|  |                         } | ||||||
|  |                         else if (directItemModel.getText() != null) { | ||||||
|  |                             searchUsername(directItemModel.getText().toString().split("@")[1].split(" ")[0]); | ||||||
|  |                         } | ||||||
|  |                         break; | ||||||
|  |                     case PLACEHOLDER: | ||||||
|  |                         if (directItemModel.getText().toString().contains("@")) | ||||||
|  |                             searchUsername(directItemModel.getText().toString().split("@")[1].split(" ")[0]); | ||||||
|                         break; |                         break; | ||||||
|                     default: |                     default: | ||||||
|                         Log.d("austin_debug", "unsupported type "+itemType); |                         Log.d("austin_debug", "unsupported type "+itemType); | ||||||
| @ -163,10 +173,18 @@ public final class DirectMessagesUserInbox extends AppCompatActivity { | |||||||
| 
 | 
 | ||||||
|     @Nullable |     @Nullable | ||||||
|     private ProfileModel getUser(final long userId) { |     private ProfileModel getUser(final long userId) { | ||||||
|         for (final ProfileModel user : users) { |         if (users != null) { | ||||||
|             if (Long.toString(userId).equals(user.getId())) return user; |             ProfileModel result = myProfileHolder; | ||||||
|  |             for (final ProfileModel user : users) { | ||||||
|  |                 if (Long.toString(userId).equals(user.getId())) result = user; | ||||||
|  |             } | ||||||
|  |             if (leftusers != null) | ||||||
|  |                 for (final ProfileModel leftuser : leftusers) { | ||||||
|  |                     if (Long.toString(userId).equals(leftuser.getId())) result = leftuser; | ||||||
|  |                 } | ||||||
|  |             return result; | ||||||
|         } |         } | ||||||
|         return myProfileHolder; |         return null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void searchUsername(final String text) { |     private void searchUsername(final String text) { | ||||||
|  | |||||||
| @ -77,36 +77,45 @@ public final class DirectMessagesAdapter extends RecyclerView.Adapter<DirectMess | |||||||
|             final Context context = layoutInflater.getContext(); |             final Context context = layoutInflater.getContext(); | ||||||
| 
 | 
 | ||||||
|             final CharSequence messageText; |             final CharSequence messageText; | ||||||
|             if (itemType == DirectItemType.TEXT) |             switch (itemType) { | ||||||
|                 messageText = lastItemModel.getText(); |                 case TEXT: | ||||||
|             else if (itemType == DirectItemType.LINK) |                     messageText = lastItemModel.getText(); | ||||||
|                 messageText = context.getString(R.string.direct_messages_sent_link); |                     break; | ||||||
|             else if (itemType == DirectItemType.MEDIA || itemType == DirectItemType.MEDIA_SHARE) |                 case LINK: | ||||||
|                 messageText = context.getString(R.string.direct_messages_sent_media); |                     messageText = context.getString(R.string.direct_messages_sent_link); | ||||||
|             else if (itemType == DirectItemType.ACTION_LOG) { |                     break; | ||||||
|                 final DirectItemActionLogModel logModel = lastItemModel.getActionLogModel(); |                 case MEDIA: | ||||||
|                 messageText = logModel != null ? logModel.getDescription() : "..."; |                 case MEDIA_SHARE: | ||||||
|             } |  | ||||||
|             else if (itemType == DirectItemType.REEL_SHARE) { |  | ||||||
|                 final DirectItemReelShareModel reelShare = lastItemModel.getReelShare(); |  | ||||||
|                 if (reelShare == null) |  | ||||||
|                     messageText = context.getString(R.string.direct_messages_sent_media); |                     messageText = context.getString(R.string.direct_messages_sent_media); | ||||||
|                 else { |                     break; | ||||||
|                     final String reelType = reelShare.getType(); |                 case ACTION_LOG: | ||||||
|                     final int textRes; |                     final DirectItemActionLogModel logModel = lastItemModel.getActionLogModel(); | ||||||
|                     if ("reply".equals(reelType)) textRes = R.string.direct_messages_replied_story; |                     messageText = logModel != null ? logModel.getDescription() : "..."; | ||||||
|                     else if ("mention".equals(reelType)) |                     break; | ||||||
|                         textRes = R.string.direct_messages_mention_story; |                 case REEL_SHARE: | ||||||
|                     else if ("reaction".equals(reelType)) |                     final DirectItemReelShareModel reelShare = lastItemModel.getReelShare(); | ||||||
|                         textRes = R.string.direct_messages_reacted_story; |                     if (reelShare == null) | ||||||
|                     else textRes = R.string.direct_messages_sent_media; |                         messageText = context.getString(R.string.direct_messages_sent_media); | ||||||
|  |                     else { | ||||||
|  |                         final String reelType = reelShare.getType(); | ||||||
|  |                         final int textRes; | ||||||
|  |                         if ("reply".equals(reelType)) | ||||||
|  |                             textRes = R.string.direct_messages_replied_story; | ||||||
|  |                         else if ("mention".equals(reelType)) | ||||||
|  |                             textRes = R.string.direct_messages_mention_story; | ||||||
|  |                         else if ("reaction".equals(reelType)) | ||||||
|  |                             textRes = R.string.direct_messages_reacted_story; | ||||||
|  |                         else textRes = R.string.direct_messages_sent_media; | ||||||
| 
 | 
 | ||||||
|                     messageText = context.getString(textRes) + " : " + reelShare.getText(); |                         messageText = context.getString(textRes) + " : " + reelShare.getText(); | ||||||
|                 } |                     } | ||||||
|  |                     break; | ||||||
|  |                 case RAVEN_MEDIA: | ||||||
|  |                     messageText = context.getString(R.string.direct_messages_sent_media); | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     messageText = "<i>Unsupported message</i>"; | ||||||
|             } |             } | ||||||
|             else if (itemType == DirectItemType.RAVEN_MEDIA) { |  | ||||||
|                 messageText = context.getString(R.string.direct_messages_sent_media); |  | ||||||
|             } else messageText = "<i>Unsupported message</i>"; |  | ||||||
| 
 | 
 | ||||||
|             holder.tvMessage.setText(HtmlCompat.fromHtml(messageText.toString(), 63)); |             holder.tvMessage.setText(HtmlCompat.fromHtml(messageText.toString(), 63)); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -46,9 +46,11 @@ import static awais.instagrabber.models.direct_messages.DirectItemModel.RavenExp | |||||||
| public final class MessageItemsAdapter extends RecyclerView.Adapter<TextMessageViewHolder> { | public final class MessageItemsAdapter extends RecyclerView.Adapter<TextMessageViewHolder> { | ||||||
|     private static final int MESSAGE_INCOMING = 69, MESSAGE_OUTGOING = 420; |     private static final int MESSAGE_INCOMING = 69, MESSAGE_OUTGOING = 420; | ||||||
|     private final ProfileModel myProfileHolder = |     private final ProfileModel myProfileHolder = | ||||||
|             new ProfileModel(false, false, false, null, null, null, null, null, null, null, 0, 0, 0, false, false, false, false); |             new ProfileModel(false, false, false, | ||||||
|  |                     Utils.getUserIdFromCookie(Utils.settingsHelper.getString(Constants.COOKIE)), | ||||||
|  |                     null, null, null, null, null, null, 0, 0, 0, false, false, false, false); | ||||||
|     private final ArrayList<DirectItemModel> directItemModels; |     private final ArrayList<DirectItemModel> directItemModels; | ||||||
|     private final ArrayList<ProfileModel> users; |     private final ArrayList<ProfileModel> users, leftusers; | ||||||
|     private final View.OnClickListener onClickListener; |     private final View.OnClickListener onClickListener; | ||||||
|     private final MentionClickListener mentionClickListener; |     private final MentionClickListener mentionClickListener; | ||||||
|     private final View.OnClickListener openProfileClickListener = v -> { |     private final View.OnClickListener openProfileClickListener = v -> { | ||||||
| @ -93,8 +95,10 @@ public final class MessageItemsAdapter extends RecyclerView.Adapter<TextMessageV | |||||||
|     private String strDmYou; |     private String strDmYou; | ||||||
| 
 | 
 | ||||||
|     public MessageItemsAdapter(final ArrayList<DirectItemModel> directItemModels, final ArrayList<ProfileModel> users, |     public MessageItemsAdapter(final ArrayList<DirectItemModel> directItemModels, final ArrayList<ProfileModel> users, | ||||||
|                                final View.OnClickListener onClickListener, final MentionClickListener mentionClickListener) { |                                final ArrayList<ProfileModel> leftusers, final View.OnClickListener onClickListener, | ||||||
|  |                                final MentionClickListener mentionClickListener) { | ||||||
|         this.users = users; |         this.users = users; | ||||||
|  |         this.leftusers = leftusers; | ||||||
|         this.directItemModels = directItemModels; |         this.directItemModels = directItemModels; | ||||||
|         this.onClickListener = onClickListener; |         this.onClickListener = onClickListener; | ||||||
|         this.mentionClickListener = mentionClickListener; |         this.mentionClickListener = mentionClickListener; | ||||||
| @ -392,10 +396,15 @@ public final class MessageItemsAdapter extends RecyclerView.Adapter<TextMessageV | |||||||
|     @Nullable |     @Nullable | ||||||
|     private ProfileModel getUser(final long userId) { |     private ProfileModel getUser(final long userId) { | ||||||
|         if (users != null) { |         if (users != null) { | ||||||
|  |             ProfileModel result = myProfileHolder; | ||||||
|             for (final ProfileModel user : users) { |             for (final ProfileModel user : users) { | ||||||
|                 if (Long.toString(userId).equals(user.getId())) return user; |                 if (Long.toString(userId).equals(user.getId())) result = user; | ||||||
|                 return myProfileHolder; |  | ||||||
|             } |             } | ||||||
|  |             if (leftusers != null) | ||||||
|  |                 for (final ProfileModel leftuser : leftusers) { | ||||||
|  |                     if (Long.toString(userId).equals(leftuser.getId())) result = leftuser; | ||||||
|  |                 } | ||||||
|  |             return result; | ||||||
|         } |         } | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -31,13 +31,15 @@ import static awais.instagrabber.utils.Utils.logCollector; | |||||||
| import static awais.instagrabber.utils.Utils.settingsHelper; | import static awais.instagrabber.utils.Utils.settingsHelper; | ||||||
| 
 | 
 | ||||||
| public final class DiscoverFetcher extends AsyncTask<Void, Void, DiscoverItemModel[]> { | public final class DiscoverFetcher extends AsyncTask<Void, Void, DiscoverItemModel[]> { | ||||||
|     private final String maxId; |     private final String cluster, maxId; | ||||||
|     private final FetchListener<DiscoverItemModel[]> fetchListener; |     private final FetchListener<DiscoverItemModel[]> fetchListener; | ||||||
|     private int lastId = 0; |     private int lastId = 0; | ||||||
|     private boolean isFirst, moreAvailable; |     private boolean isFirst, moreAvailable; | ||||||
|     private String nextMaxId; |     private String nextMaxId; | ||||||
| 
 | 
 | ||||||
|     public DiscoverFetcher(final String maxId, final FetchListener<DiscoverItemModel[]> fetchListener, final boolean isFirst) { |     public DiscoverFetcher(final String cluster, final String maxId, | ||||||
|  |                            final FetchListener<DiscoverItemModel[]> fetchListener, final boolean isFirst) { | ||||||
|  |         this.cluster = cluster == null ? "explore_all%3A0" : cluster.replace(":", "%3A"); | ||||||
|         this.maxId = maxId == null ? "" : "&max_id=" + maxId; |         this.maxId = maxId == null ? "" : "&max_id=" + maxId; | ||||||
|         this.fetchListener = fetchListener; |         this.fetchListener = fetchListener; | ||||||
|         this.isFirst = isFirst; |         this.isFirst = isFirst; | ||||||
| @ -54,7 +56,7 @@ public final class DiscoverFetcher extends AsyncTask<Void, Void, DiscoverItemMod | |||||||
|             result = discoverItemModels.toArray(new DiscoverItemModel[0]); |             result = discoverItemModels.toArray(new DiscoverItemModel[0]); | ||||||
|             if (result.length > 0) { |             if (result.length > 0) { | ||||||
|                 final DiscoverItemModel lastModel = result[result.length - 1]; |                 final DiscoverItemModel lastModel = result[result.length - 1]; | ||||||
|                 if (lastModel != null) lastModel.setMore(moreAvailable, nextMaxId); |                 if (lastModel != null && nextMaxId != null) lastModel.setMore(moreAvailable, nextMaxId); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -64,7 +66,7 @@ public final class DiscoverFetcher extends AsyncTask<Void, Void, DiscoverItemMod | |||||||
|     private ArrayList<DiscoverItemModel> fetchItems(ArrayList<DiscoverItemModel> discoverItemModels, final String maxId) { |     private ArrayList<DiscoverItemModel> fetchItems(ArrayList<DiscoverItemModel> discoverItemModels, final String maxId) { | ||||||
|         try { |         try { | ||||||
|             final String url = "https://www.instagram.com/explore/grid/?is_prefetch=false&omit_cover_media=true&module=explore_popular" + |             final String url = "https://www.instagram.com/explore/grid/?is_prefetch=false&omit_cover_media=true&module=explore_popular" + | ||||||
|                     "&use_sectional_payload=false&cluster_id=explore_all%3A0&include_fixed_destinations=true" + maxId; |                     "&use_sectional_payload=false&cluster_id="+cluster+"&include_fixed_destinations=true" + maxId; | ||||||
| 
 | 
 | ||||||
|             final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); |             final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); | ||||||
| 
 | 
 | ||||||
| @ -75,7 +77,7 @@ public final class DiscoverFetcher extends AsyncTask<Void, Void, DiscoverItemMod | |||||||
|                 final JSONObject discoverResponse = new JSONObject(Utils.readFromConnection(urlConnection)); |                 final JSONObject discoverResponse = new JSONObject(Utils.readFromConnection(urlConnection)); | ||||||
| 
 | 
 | ||||||
|                 moreAvailable = discoverResponse.getBoolean("more_available"); |                 moreAvailable = discoverResponse.getBoolean("more_available"); | ||||||
|                 nextMaxId = discoverResponse.getString("next_max_id"); |                 nextMaxId = discoverResponse.optString("next_max_id"); | ||||||
| 
 | 
 | ||||||
|                 final JSONArray sectionalItems = discoverResponse.getJSONArray("sectional_items"); |                 final JSONArray sectionalItems = discoverResponse.getJSONArray("sectional_items"); | ||||||
|                 if (discoverItemModels == null) discoverItemModels = new ArrayList<>(sectionalItems.length() * 2); |                 if (discoverItemModels == null) discoverItemModels = new ArrayList<>(sectionalItems.length() * 2); | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ public final class InboxFetcher extends AsyncTask<Void, Void, InboxModel> { | |||||||
|         final String url = "https://i.instagram.com/api/v1/direct_v2/inbox/" + endCursor; |         final String url = "https://i.instagram.com/api/v1/direct_v2/inbox/" + endCursor; | ||||||
|         try { |         try { | ||||||
|             final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); |             final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); | ||||||
|             conn.setRequestProperty("User-Agent", Constants.USER_AGENT); |             conn.setRequestProperty("User-Agent", Constants.I_USER_AGENT); | ||||||
|             conn.setRequestProperty("Accept-Language", LocaleUtils.getCurrentLocale().getLanguage() + ",en-US;q=0.8"); |             conn.setRequestProperty("Accept-Language", LocaleUtils.getCurrentLocale().getLanguage() + ",en-US;q=0.8"); | ||||||
|             conn.setUseCaches(false); |             conn.setUseCaches(false); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ import awais.instagrabber.interfaces.FetchListener; | |||||||
| import awais.instagrabber.models.direct_messages.InboxThreadModel; | import awais.instagrabber.models.direct_messages.InboxThreadModel; | ||||||
| import awais.instagrabber.models.enums.UserInboxDirection; | import awais.instagrabber.models.enums.UserInboxDirection; | ||||||
| import awais.instagrabber.utils.Constants; | import awais.instagrabber.utils.Constants; | ||||||
|  | import awais.instagrabber.utils.LocaleUtils; | ||||||
| import awais.instagrabber.utils.Utils; | import awais.instagrabber.utils.Utils; | ||||||
| 
 | 
 | ||||||
| import static awais.instagrabber.utils.Utils.logCollector; | import static awais.instagrabber.utils.Utils.logCollector; | ||||||
| @ -45,7 +46,8 @@ public final class UserInboxFetcher extends AsyncTask<Void, Void, InboxThreadMod | |||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); |             final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); | ||||||
|             conn.setRequestProperty("User-Agent", Constants.USER_AGENT); |             conn.setRequestProperty("User-Agent", Constants.I_USER_AGENT); | ||||||
|  |             conn.setRequestProperty("Accept-Language", LocaleUtils.getCurrentLocale().getLanguage() + ",en-US;q=0.8"); | ||||||
|             conn.setUseCaches(false); |             conn.setUseCaches(false); | ||||||
| 
 | 
 | ||||||
|             if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { |             if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { | ||||||
|  | |||||||
							
								
								
									
										71
									
								
								app/src/main/java/awais/instagrabber/asyncs/i/iTopicFetcher.java
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										71
									
								
								app/src/main/java/awais/instagrabber/asyncs/i/iTopicFetcher.java
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,71 @@ | |||||||
|  | package awais.instagrabber.asyncs.i; | ||||||
|  | 
 | ||||||
|  | import android.os.AsyncTask; | ||||||
|  | import android.os.Environment; | ||||||
|  | import android.util.Log; | ||||||
|  | 
 | ||||||
|  | import org.json.JSONArray; | ||||||
|  | import org.json.JSONObject; | ||||||
|  | 
 | ||||||
|  | import java.io.File; | ||||||
|  | import java.net.HttpURLConnection; | ||||||
|  | import java.net.URL; | ||||||
|  | 
 | ||||||
|  | import awais.instagrabber.BuildConfig; | ||||||
|  | import awais.instagrabber.interfaces.FetchListener; | ||||||
|  | import awais.instagrabber.models.DiscoverTopicModel; | ||||||
|  | import awais.instagrabber.utils.Constants; | ||||||
|  | import awais.instagrabber.utils.LocaleUtils; | ||||||
|  | import awais.instagrabber.utils.Utils; | ||||||
|  | import awaisomereport.LogCollector; | ||||||
|  | 
 | ||||||
|  | import static awais.instagrabber.utils.Utils.logCollector; | ||||||
|  | 
 | ||||||
|  | public final class iTopicFetcher extends AsyncTask<Void, Void, DiscoverTopicModel> { | ||||||
|  |     private final FetchListener<DiscoverTopicModel> fetchListener; | ||||||
|  | 
 | ||||||
|  |     public iTopicFetcher(final FetchListener<DiscoverTopicModel> fetchListener) { | ||||||
|  |         this.fetchListener = fetchListener; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     protected DiscoverTopicModel doInBackground(final Void... voids) { | ||||||
|  |         final String url = "https://i.instagram.com/api/v1/discover/topical_explore/"; | ||||||
|  | 
 | ||||||
|  |         DiscoverTopicModel result = null; | ||||||
|  |         try { | ||||||
|  |             final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); | ||||||
|  |             conn.setUseCaches(false); | ||||||
|  |             conn.setRequestProperty("User-Agent", Constants.I_USER_AGENT); | ||||||
|  |             conn.setRequestProperty("Accept-Language", LocaleUtils.getCurrentLocale().getLanguage() + ",en-US;q=0.8"); | ||||||
|  |             conn.connect(); | ||||||
|  | 
 | ||||||
|  |             if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { | ||||||
|  |                 final JSONObject body = new JSONObject(Utils.readFromConnection(conn)); | ||||||
|  | 
 | ||||||
|  |                 final JSONArray edges = body.getJSONArray("clusters"); | ||||||
|  |                 String[] names = new String[edges.length()], ids = new String[edges.length()]; | ||||||
|  |                 for (int i = 0; i < names.length; ++i) { | ||||||
|  |                     final JSONObject mediaNode = edges.getJSONObject(i); | ||||||
|  |                     ids[i] = mediaNode.getString("id"); | ||||||
|  |                     names[i] = mediaNode.getString("title"); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 result = new DiscoverTopicModel(ids, names); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             conn.disconnect(); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             if (logCollector != null) | ||||||
|  |                 logCollector.appendException(e, LogCollector.LogFile.ASYNC_DISCOVER_TOPICS_FETCHER, "doInBackground"); | ||||||
|  |             if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     protected void onPostExecute(final DiscoverTopicModel discoverTopicModel) { | ||||||
|  |         if (fetchListener != null) fetchListener.onResult(discoverTopicModel); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								app/src/main/java/awais/instagrabber/models/DiscoverTopicModel.java
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										20
									
								
								app/src/main/java/awais/instagrabber/models/DiscoverTopicModel.java
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | package awais.instagrabber.models; | ||||||
|  | 
 | ||||||
|  | import java.io.Serializable; | ||||||
|  | 
 | ||||||
|  | public final class DiscoverTopicModel implements Serializable { | ||||||
|  |     private final String[] id, name; | ||||||
|  | 
 | ||||||
|  |     public DiscoverTopicModel(final String[] id, final String[] name) { | ||||||
|  |         this.id = id; | ||||||
|  |         this.name = name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String[] getIds() { | ||||||
|  |         return id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String[] getNames() { | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -487,6 +487,8 @@ public final class Utils { | |||||||
| 
 | 
 | ||||||
|         final JSONArray users = data.getJSONArray("users"); |         final JSONArray users = data.getJSONArray("users"); | ||||||
|         final int usersLen = users.length(); |         final int usersLen = users.length(); | ||||||
|  |         final JSONArray leftusers = data.getJSONArray("left_users"); | ||||||
|  |         final int leftusersLen = leftusers.length(); | ||||||
| 
 | 
 | ||||||
|         final ProfileModel[] userModels = new ProfileModel[usersLen]; |         final ProfileModel[] userModels = new ProfileModel[usersLen]; | ||||||
|         for (int j = 0; j < usersLen; ++j) { |         for (int j = 0; j < usersLen; ++j) { | ||||||
| @ -502,6 +504,20 @@ public final class Utils { | |||||||
|                     null, 0, 0, 0, false, false, false, false); |                     null, 0, 0, 0, false, false, false, false); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         final ProfileModel[] leftuserModels = new ProfileModel[leftusersLen]; | ||||||
|  |         for (int j = 0; j < leftusersLen; ++j) { | ||||||
|  |             final JSONObject userObject = leftusers.getJSONObject(j); | ||||||
|  |             leftuserModels[j] = new ProfileModel(userObject.getBoolean("is_private"), | ||||||
|  |                     false, | ||||||
|  |                     userObject.optBoolean("is_verified"), | ||||||
|  |                     String.valueOf(userObject.get("pk")), | ||||||
|  |                     userObject.getString("username"), | ||||||
|  |                     userObject.getString("full_name"), | ||||||
|  |                     null, null, | ||||||
|  |                     userObject.getString("profile_pic_url"), | ||||||
|  |                     null, 0, 0, 0, false, false, false, false); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         final JSONArray items = data.getJSONArray("items"); |         final JSONArray items = data.getJSONArray("items"); | ||||||
|         final int itemsLen = items.length(); |         final int itemsLen = items.length(); | ||||||
| 
 | 
 | ||||||
| @ -737,8 +753,7 @@ public final class Utils { | |||||||
|         return new InboxThreadModel(readState, threadId, threadV2Id, threadType, threadTitle, |         return new InboxThreadModel(readState, threadId, threadV2Id, threadType, threadTitle, | ||||||
|                 threadNewestCursor, threadOldestCursor, threadNextCursor, threadPrevCursor, |                 threadNewestCursor, threadOldestCursor, threadNextCursor, threadPrevCursor, | ||||||
|                 null, // todo |                 null, // todo | ||||||
|                 userModels, |                 userModels, leftuserModels, | ||||||
|                 null, // todo |  | ||||||
|                 itemModels.toArray(new DirectItemModel[0]), |                 itemModels.toArray(new DirectItemModel[0]), | ||||||
|                 muted, isPin, named, canonical, |                 muted, isPin, named, canonical, | ||||||
|                 pending, threadHasOlder, threadHasNewer, isSpam, isGroup, archived, lastActivityAt); |                 pending, threadHasOlder, threadHasNewer, isSpam, isGroup, archived, lastActivityAt); | ||||||
|  | |||||||
| @ -104,6 +104,7 @@ public final class LogCollector { | |||||||
|         //////////////////////// |         //////////////////////// | ||||||
|         ASYNC_DOWNLOADER("async-download.txt"), |         ASYNC_DOWNLOADER("async-download.txt"), | ||||||
|         ASYNC_MAIN_POSTS_FETCHER("async-main-posts-fetcher.txt"), |         ASYNC_MAIN_POSTS_FETCHER("async-main-posts-fetcher.txt"), | ||||||
|  |         ASYNC_DISCOVER_TOPICS_FETCHER("async-discover-topics-fetcher.txt"), | ||||||
|         ASYNC_POST_FETCHER("async-single-post-fetcher.txt"), |         ASYNC_POST_FETCHER("async-single-post-fetcher.txt"), | ||||||
|         ASYNC_FEED_FETCHER("async-feed-fetcher.txt"), |         ASYNC_FEED_FETCHER("async-feed-fetcher.txt"), | ||||||
|         ASYNC_HASHTAG_FETCHER("async-hashtag-fetcher.txt"), |         ASYNC_HASHTAG_FETCHER("async-hashtag-fetcher.txt"), | ||||||
|  | |||||||
| @ -525,21 +525,39 @@ | |||||||
|             </LinearLayout> |             </LinearLayout> | ||||||
| 
 | 
 | ||||||
|             <!-- Discover View --> |             <!-- Discover View --> | ||||||
|             <androidx.swiperefreshlayout.widget.SwipeRefreshLayout |             <LinearLayout | ||||||
|                 android:id="@+id/discoverSwipeRefreshLayout" |                 android:id="@+id/discoverLayout" | ||||||
|                 android:layout_width="match_parent" |                 android:layout_width="match_parent" | ||||||
|                 android:layout_height="match_parent" |                 android:layout_height="match_parent" | ||||||
|                 android:layout_gravity="end" |                 android:layout_gravity="end" | ||||||
|  |                 android:paddingTop="24dp" | ||||||
|  |                 android:animateLayoutChanges="true" | ||||||
|  |                 android:orientation="vertical" | ||||||
|                 android:tag="@android:string/yes"> |                 android:tag="@android:string/yes"> | ||||||
| 
 | 
 | ||||||
|                 <androidx.recyclerview.widget.RecyclerView |                 <androidx.appcompat.widget.AppCompatSpinner | ||||||
|                     android:id="@+id/discoverPosts" |                     android:id="@+id/discoverType" | ||||||
|                     android:layout_width="match_parent" |                     android:layout_width="match_parent" | ||||||
|                     android:layout_height="match_parent" |                     android:layout_height="wrap_content" | ||||||
|                     android:clipToPadding="false" |                     android:entries="@array/discover_placeholder" | ||||||
|                     android:paddingTop="24dp" |                     android:paddingTop="4dp" | ||||||
|                     tools:listitem="@layout/item_feed" /> |                     android:paddingBottom="4dp" /> | ||||||
|             </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> | 
 | ||||||
|  |                 <androidx.swiperefreshlayout.widget.SwipeRefreshLayout | ||||||
|  |                     android:id="@+id/discoverSwipeRefreshLayout" | ||||||
|  |                     android:layout_width="match_parent" | ||||||
|  |                     android:layout_height="wrap_content" | ||||||
|  |                     android:layout_gravity="end" | ||||||
|  |                     android:tag="@android:string/yes"> | ||||||
|  | 
 | ||||||
|  |                     <androidx.recyclerview.widget.RecyclerView | ||||||
|  |                         android:id="@+id/discoverPosts" | ||||||
|  |                         android:layout_width="match_parent" | ||||||
|  |                         android:layout_height="match_parent" | ||||||
|  |                         android:clipToPadding="false" | ||||||
|  |                         tools:listitem="@layout/item_feed" /> | ||||||
|  |                     </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> | ||||||
|  |             </LinearLayout> | ||||||
|         </awais.instagrabber.customviews.RemixDrawerLayout> |         </awais.instagrabber.customviews.RemixDrawerLayout> | ||||||
|     </LinearLayout> |     </LinearLayout> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -26,6 +26,9 @@ | |||||||
|         <item>\|</item> |         <item>\|</item> | ||||||
|         <item>-</item> |         <item>-</item> | ||||||
|     </string-array> |     </string-array> | ||||||
|  |     <string-array name="discover_placeholder"> | ||||||
|  |         <item>Loading...</item> | ||||||
|  |     </string-array> | ||||||
|     <string-array name="date_presets"> |     <string-array name="date_presets"> | ||||||
|         <item>dd-MM-yyyy</item> |         <item>dd-MM-yyyy</item> | ||||||
|         <item>dd/MM/yyyy</item> |         <item>dd/MM/yyyy</item> | ||||||
|  | |||||||
| @ -201,6 +201,8 @@ | |||||||
|     <string name="share_public_post">Share this public post to...</string> |     <string name="share_public_post">Share this public post to...</string> | ||||||
|     <string name="share_private_post">This is a private post! Share to those who can view them!</string> |     <string name="share_private_post">This is a private post! Share to those who can view them!</string> | ||||||
| 
 | 
 | ||||||
|  |     <string name="discover_empty">This category is somehow empty...</string> | ||||||
|  | 
 | ||||||
|     <string name="update_available">An update is available! (%s)</string> |     <string name="update_available">An update is available! (%s)</string> | ||||||
|     <string name="update_notice">Reminder: If you downloaded from F-Droid, you must update from it! Same applies for GitHub.</string> |     <string name="update_notice">Reminder: If you downloaded from F-Droid, you must update from it! Same applies for GitHub.</string> | ||||||
|     <string name="updated">Thank you for updating InstaGrabber!</string> |     <string name="updated">Thank you for updating InstaGrabber!</string> | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user