add suggested users feature
This commit is contained in:
parent
3242fdc7ef
commit
975654961f
@ -53,18 +53,22 @@ public final class NotificationViewHolder extends RecyclerView.ViewHolder {
|
||||
case RESPONDED_STORY:
|
||||
subtext = model.getText();
|
||||
break;
|
||||
case AYML:
|
||||
subtext = model.getPostId();
|
||||
break;
|
||||
}
|
||||
binding.tvSubComment.setText(model.getType() == NotificationType.AYML ? model.getText() : subtext);
|
||||
if (text == -1 && subtext != null) {
|
||||
binding.tvComment.setText(subtext);
|
||||
binding.tvSubComment.setVisibility(View.GONE);
|
||||
binding.tvComment.setVisibility(TextUtils.isEmpty(subtext) ? View.GONE : View.VISIBLE);
|
||||
binding.tvSubComment.setVisibility(model.getType() == NotificationType.AYML ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
else if (text != -1) {
|
||||
binding.tvComment.setText(text);
|
||||
binding.tvSubComment.setText(subtext);
|
||||
binding.tvSubComment.setVisibility(subtext == null ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
if (model.getType() != NotificationType.REQUEST) {
|
||||
if (model.getType() != NotificationType.REQUEST && model.getType() != NotificationType.AYML) {
|
||||
binding.tvDate.setText(model.getDateTime());
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@ import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.NotificationsAdapter;
|
||||
import awais.instagrabber.adapters.NotificationsAdapter.OnNotificationClickListener;
|
||||
@ -46,6 +48,7 @@ import awais.instagrabber.utils.Utils;
|
||||
import awais.instagrabber.viewmodels.NotificationViewModel;
|
||||
import awais.instagrabber.webservices.FriendshipService;
|
||||
import awais.instagrabber.webservices.MediaService;
|
||||
import awais.instagrabber.webservices.NewsService;
|
||||
import awais.instagrabber.webservices.ServiceCallback;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
@ -59,8 +62,8 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
||||
private NotificationViewModel notificationViewModel;
|
||||
private FriendshipService friendshipService;
|
||||
private MediaService mediaService;
|
||||
private String userId;
|
||||
private String csrfToken;
|
||||
private NewsService newsService;
|
||||
private String userId, csrfToken, type;
|
||||
private Context context;
|
||||
|
||||
private final OnNotificationClickListener clickListener = new OnNotificationClickListener() {
|
||||
@ -96,7 +99,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
||||
public void onNotificationClick(final NotificationModel model) {
|
||||
if (model == null) return;
|
||||
final String username = model.getUsername();
|
||||
if (model.getType() == NotificationType.FOLLOW) {
|
||||
if (model.getType() == NotificationType.FOLLOW || model.getType() == NotificationType.AYML) {
|
||||
openProfile(username);
|
||||
}
|
||||
else {
|
||||
@ -242,6 +245,8 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
||||
}
|
||||
|
||||
private void init() {
|
||||
final NotificationsViewerFragmentArgs fragmentArgs = NotificationsViewerFragmentArgs.fromBundle(getArguments());
|
||||
type = fragmentArgs.getType();
|
||||
final Context context = getContext();
|
||||
CookieUtils.setupCookies(settingsHelper.getString(Constants.COOKIE));
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
@ -256,10 +261,30 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
new NotificationsFetcher(true, notificationModels -> {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
notificationViewModel.getList().postValue(notificationModels);
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
switch (type) {
|
||||
case "notif":
|
||||
new NotificationsFetcher(true, notificationModels -> {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
notificationViewModel.getList().postValue(notificationModels);
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
break;
|
||||
case "ayml":
|
||||
newsService = NewsService.getInstance();
|
||||
newsService.fetchSuggestions(csrfToken, new ServiceCallback<List<NotificationModel>>() {
|
||||
@Override
|
||||
public void onSuccess(final List<NotificationModel> notificationModels) {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
notificationViewModel.getList().postValue(notificationModels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void openProfile(final String username) {
|
||||
|
@ -134,7 +134,13 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
|
||||
screen.addPreference(getDivider(context));
|
||||
if (isLoggedIn) {
|
||||
screen.addPreference(getPreference(R.string.action_notif, R.drawable.ic_not_liked, preference -> {
|
||||
NavHostFragment.findNavController(this).navigate(R.id.action_global_notificationsViewerFragment);
|
||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("notif");
|
||||
NavHostFragment.findNavController(this).navigate(navDirections);
|
||||
return true;
|
||||
}));
|
||||
screen.addPreference(getPreference(R.string.action_ayml, R.drawable.ic_suggested_users, preference -> {
|
||||
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("ayml");
|
||||
NavHostFragment.findNavController(this).navigate(navDirections);
|
||||
return true;
|
||||
}));
|
||||
screen.addPreference(getPreference(R.string.action_archive, R.drawable.ic_archive, preference -> {
|
||||
|
@ -15,8 +15,10 @@ public enum NotificationType implements Serializable {
|
||||
COMMENT_LIKE("13"),
|
||||
TAGGED_COMMENT("14"),
|
||||
RESPONDED_STORY("213"),
|
||||
// efr
|
||||
REQUEST("REQUEST");
|
||||
// efr - random value
|
||||
REQUEST("REQUEST"),
|
||||
// ayml - random value
|
||||
AYML("AYML");
|
||||
|
||||
private final String itemType;
|
||||
private static final Map<String, NotificationType> map = new HashMap<>();
|
||||
|
@ -21,4 +21,9 @@ public interface NewsRepository {
|
||||
@Headers("User-Agent: " + Constants.I_USER_AGENT)
|
||||
@GET("/api/v1/news/inbox/")
|
||||
Call<String> appInbox(@Query(value = "mark_as_seen", encoded = true) boolean markAsSeen);
|
||||
|
||||
@FormUrlEncoded
|
||||
@Headers("User-Agent: " + Constants.I_USER_AGENT)
|
||||
@POST("/api/v1/discover/ayml/")
|
||||
Call<String> getAyml(@FieldMap final Map<String, String> form);
|
||||
}
|
||||
|
@ -12,14 +12,15 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.models.NotificationModel;
|
||||
import awais.instagrabber.models.enums.NotificationType;
|
||||
import awais.instagrabber.repositories.NewsRepository;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.NetworkUtils;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
@ -89,7 +90,6 @@ public class NewsService extends BaseService {
|
||||
|
||||
public void fetchWebInbox(final boolean markAsSeen,
|
||||
final ServiceCallback<List<NotificationModel>> callback) {
|
||||
final List<NotificationModel> result = new ArrayList<>();
|
||||
final Call<String> request = repository.webInbox();
|
||||
request.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
@ -100,6 +100,7 @@ public class NewsService extends BaseService {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final List<NotificationModel> result = new ArrayList<>();
|
||||
final JSONObject page = new JSONObject(body)
|
||||
.getJSONObject("graphql")
|
||||
.getJSONObject("user");
|
||||
@ -168,7 +169,7 @@ public class NewsService extends BaseService {
|
||||
final String type = itemJson.getString("story_type");
|
||||
final NotificationType notificationType = NotificationType.valueOfType(type);
|
||||
if (notificationType == null) {
|
||||
Log.d("austin_debug", "unhandled news type: "+itemJson);
|
||||
if (BuildConfig.DEBUG) Log.d("austin_debug", "unhandled news type: "+itemJson);
|
||||
return null;
|
||||
}
|
||||
final JSONObject data = itemJson.getJSONObject("args");
|
||||
@ -194,4 +195,67 @@ public class NewsService extends BaseService {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void fetchSuggestions(final String csrfToken,
|
||||
final ServiceCallback<List<NotificationModel>> callback) {
|
||||
final Map<String, String> form = new HashMap<>();
|
||||
form.put("_uuid", UUID.randomUUID().toString());
|
||||
form.put("_csrftoken", csrfToken);
|
||||
form.put("phone_id", UUID.randomUUID().toString());
|
||||
form.put("device_id", UUID.randomUUID().toString());
|
||||
form.put("module", "discover_people");
|
||||
form.put("paginate", "false");
|
||||
final Call<String> request = repository.getAyml(form);
|
||||
request.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
final String body = response.body();
|
||||
if (body == null) {
|
||||
callback.onSuccess(null);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final List<NotificationModel> result = new ArrayList<>();
|
||||
final JSONObject jsonObject = new JSONObject(body);
|
||||
final JSONArray oldStories = jsonObject.getJSONObject("suggested_users").getJSONArray("suggestions"),
|
||||
newStories = jsonObject.getJSONObject("new_suggested_users").getJSONArray("suggestions");
|
||||
|
||||
for (int j = 0; j < newStories.length(); ++j) {
|
||||
final NotificationModel newsItem = parseAymlItem(newStories.getJSONObject(j));
|
||||
if (newsItem != null) result.add(newsItem);
|
||||
}
|
||||
|
||||
for (int i = 0; i < oldStories.length(); ++i) {
|
||||
final NotificationModel newsItem = parseAymlItem(oldStories.getJSONObject(i));
|
||||
if (newsItem != null) result.add(newsItem);
|
||||
}
|
||||
|
||||
callback.onSuccess(result);
|
||||
} catch (JSONException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
||||
callback.onFailure(t);
|
||||
// Log.e(TAG, "onFailure: ", t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private NotificationModel parseAymlItem(final JSONObject itemJson) throws JSONException {
|
||||
if (itemJson == null) return null;
|
||||
final JSONObject data = itemJson.getJSONObject("user");
|
||||
return new NotificationModel(
|
||||
itemJson.getString("uuid"),
|
||||
itemJson.getString("social_context"),
|
||||
0L,
|
||||
data.getString("pk"),
|
||||
data.getString("username"),
|
||||
data.getString("profile_pic_url"),
|
||||
data.getString("full_name"), // just borrowing this field
|
||||
null,
|
||||
NotificationType.AYML);
|
||||
}
|
||||
}
|
||||
|
10
app/src/main/res/drawable/ic_suggested_users.xml
Normal file
10
app/src/main/res/drawable/ic_suggested_users.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11,14H9c0,-4.97 4.03,-9 9,-9v2C14.13,7 11,10.13 11,14zM18,11V9c-2.76,0 -5,2.24 -5,5h2C15,12.34 16.34,11 18,11zM7,4c0,-1.11 -0.89,-2 -2,-2S3,2.89 3,4s0.89,2 2,2S7,5.11 7,4zM11.45,4.5h-2C9.21,5.92 7.99,7 6.5,7h-3C2.67,7 2,7.67 2,8.5V11h6V8.74C9.86,8.15 11.25,6.51 11.45,4.5zM19,17c1.11,0 2,-0.89 2,-2s-0.89,-2 -2,-2s-2,0.89 -2,2S17.89,17 19,17zM20.5,18h-3c-1.49,0 -2.71,-1.08 -2.95,-2.5h-2c0.2,2.01 1.59,3.65 3.45,4.24V22h6v-2.5C22,18.67 21.33,18 20.5,18z"/>
|
||||
</vector>
|
@ -42,7 +42,12 @@
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_notificationsViewerFragment"
|
||||
app:destination="@id/notification_viewer_nav_graph" />
|
||||
app:destination="@id/notification_viewer_nav_graph">
|
||||
<argument
|
||||
android:name="type"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
</action>
|
||||
|
||||
<include app:graph="@navigation/comments_nav_graph" />
|
||||
|
||||
|
@ -76,7 +76,12 @@
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_notificationsViewerFragment"
|
||||
app:destination="@id/notification_viewer_nav_graph" />
|
||||
app:destination="@id/notification_viewer_nav_graph">
|
||||
<argument
|
||||
android:name="type"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
</action>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/discoverFragment"
|
||||
|
@ -76,7 +76,12 @@
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_notificationsViewerFragment"
|
||||
app:destination="@id/notification_viewer_nav_graph" />
|
||||
app:destination="@id/notification_viewer_nav_graph">
|
||||
<argument
|
||||
android:name="type"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
</action>
|
||||
|
||||
<include app:graph="@navigation/story_list_nav_graph" />
|
||||
|
||||
|
@ -50,7 +50,12 @@
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_notificationsViewerFragment"
|
||||
app:destination="@id/notification_viewer_nav_graph" />
|
||||
app:destination="@id/notification_viewer_nav_graph">
|
||||
<argument
|
||||
android:name="type"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
</action>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/morePreferencesFragment"
|
||||
|
@ -9,11 +9,21 @@
|
||||
android:id="@+id/notificationsViewer"
|
||||
android:name="awais.instagrabber.fragments.NotificationsViewerFragment"
|
||||
android:label="@string/title_notifications"
|
||||
tools:layout="@layout/fragment_notifications_viewer" />
|
||||
tools:layout="@layout/fragment_notifications_viewer">
|
||||
<argument
|
||||
android:name="type"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
</fragment>
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_notificationsViewerFragment"
|
||||
app:destination="@id/notificationsViewer" />
|
||||
app:destination="@id/notificationsViewer">
|
||||
<argument
|
||||
android:name="type"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
</action>
|
||||
|
||||
<include app:graph="@navigation/comments_nav_graph" />
|
||||
|
||||
|
@ -77,7 +77,12 @@
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_notificationsViewerFragment"
|
||||
app:destination="@id/notification_viewer_nav_graph" />
|
||||
app:destination="@id/notification_viewer_nav_graph">
|
||||
<argument
|
||||
android:name="type"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
</action>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/profileFragment"
|
||||
|
@ -232,7 +232,8 @@
|
||||
<string name="crash_descr">Oops.. the app crashed, but don\'t worry you can send error report to the developer to help him fix the issue. (:</string>
|
||||
<string name="action_notif">Activity</string>
|
||||
<string name="action_archive">Story archive</string>
|
||||
<string name="license" translatable="false">Copyright (C) 2019 AWAiS\nCopyright (C) 2020 Austin Huang, Ammar Githam\nThis program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See https://www.gnu.org/licenses/.</string>
|
||||
<string name="action_ayml">Suggested users</string>
|
||||
<string name="license" translatable="false">Copyright (C) 2019-2020 AWAiS\nCopyright (C) 2020-2021 Austin Huang & Ammar Githam\nThis program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See https://www.gnu.org/licenses/.</string>
|
||||
<string name="liability" translatable="false">This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.</string>
|
||||
<string name="select_picture">Select Picture</string>
|
||||
<string name="uploading">Uploading…</string>
|
||||
|
Loading…
Reference in New Issue
Block a user