1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-22 14:47:29 +00:00

Convert FriendshipRepository and FriendshipService to kotlin

This commit is contained in:
Ammar Githam 2021-06-06 14:18:27 +09:00
parent 7769aa220f
commit cf65ed0fc5
6 changed files with 433 additions and 383 deletions

View File

@ -30,9 +30,12 @@ import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
import awais.instagrabber.databinding.FragmentFollowersViewerBinding; import awais.instagrabber.databinding.FragmentFollowersViewerBinding;
import awais.instagrabber.models.FollowModel; import awais.instagrabber.models.FollowModel;
import awais.instagrabber.repositories.responses.FriendshipListFetchResponse; import awais.instagrabber.repositories.responses.FriendshipListFetchResponse;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.CoroutineUtilsKt;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.webservices.FriendshipService; import awais.instagrabber.webservices.FriendshipService;
import awais.instagrabber.webservices.ServiceCallback; import awais.instagrabber.webservices.ServiceCallback;
import kotlinx.coroutines.Dispatchers;
import thoughtbot.expandableadapter.ExpandableGroup; import thoughtbot.expandableadapter.ExpandableGroup;
public final class FollowViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { public final class FollowViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
@ -68,10 +71,32 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
if (!isFollowersList) followModels.addAll(result.getItems()); if (!isFollowersList) followModels.addAll(result.getItems());
if (result.isMoreAvailable()) { if (result.isMoreAvailable()) {
endCursor = result.getNextMaxId(); endCursor = result.getNextMaxId();
friendshipService.getList(false, profileId, endCursor, this); friendshipService.getList(
false,
profileId,
endCursor,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
onFailure(throwable);
return;
}
onSuccess(response);
}), Dispatchers.getIO())
);
} else if (followersModels.size() == 0) { } else if (followersModels.size() == 0) {
if (!isFollowersList) moreAvailable = false; if (!isFollowersList) moreAvailable = false;
friendshipService.getList(true, profileId, null, followingFetchCb); friendshipService.getList(
true,
profileId,
null,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
followingFetchCb.onFailure(throwable);
return;
}
followingFetchCb.onSuccess(response);
}), Dispatchers.getIO())
);
} else { } else {
if (!isFollowersList) moreAvailable = false; if (!isFollowersList) moreAvailable = false;
showCompare(); showCompare();
@ -84,8 +109,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
try { try {
binding.swipeRefreshLayout.setRefreshing(false); binding.swipeRefreshLayout.setRefreshing(false);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
} } catch (Throwable ignored) {}
catch(Throwable e) {}
Log.e(TAG, "Error fetching list (double, following)", t); Log.e(TAG, "Error fetching list (double, following)", t);
} }
}; };
@ -97,10 +121,32 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
if (isFollowersList) followModels.addAll(result.getItems()); if (isFollowersList) followModels.addAll(result.getItems());
if (result.isMoreAvailable()) { if (result.isMoreAvailable()) {
endCursor = result.getNextMaxId(); endCursor = result.getNextMaxId();
friendshipService.getList(true, profileId, endCursor, this); friendshipService.getList(
true,
profileId,
endCursor,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
onFailure(throwable);
return;
}
onSuccess(response);
}), Dispatchers.getIO())
);
} else if (followingModels.size() == 0) { } else if (followingModels.size() == 0) {
if (isFollowersList) moreAvailable = false; if (isFollowersList) moreAvailable = false;
friendshipService.getList(false, profileId, null, followingFetchCb); friendshipService.getList(
false,
profileId,
null,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
followingFetchCb.onFailure(throwable);
return;
}
followingFetchCb.onSuccess(response);
}), Dispatchers.getIO())
);
} else { } else {
if (isFollowersList) moreAvailable = false; if (isFollowersList) moreAvailable = false;
showCompare(); showCompare();
@ -113,8 +159,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
try { try {
binding.swipeRefreshLayout.setRefreshing(false); binding.swipeRefreshLayout.setRefreshing(false);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
} } catch (Throwable ignored) {}
catch(Throwable e) {}
Log.e(TAG, "Error fetching list (double, follower)", t); Log.e(TAG, "Error fetching list (double, follower)", t);
} }
}; };
@ -122,7 +167,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
@Override @Override
public void onCreate(@Nullable final Bundle savedInstanceState) { public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
friendshipService = FriendshipService.getInstance(null, null, 0); friendshipService = FriendshipService.INSTANCE;
fragmentActivity = (AppCompatActivity) getActivity(); fragmentActivity = (AppCompatActivity) getActivity();
setHasOptionsMenu(true); setHasOptionsMenu(true);
} }
@ -235,8 +280,7 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
try { try {
binding.swipeRefreshLayout.setRefreshing(false); binding.swipeRefreshLayout.setRefreshing(false);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
} } catch (Throwable ignored) {}
catch(Throwable e) {}
Log.e(TAG, "Error fetching list (single)", t); Log.e(TAG, "Error fetching list (single)", t);
} }
}; };
@ -245,7 +289,18 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
if (!TextUtils.isEmpty(endCursor) && !searching) { if (!TextUtils.isEmpty(endCursor) && !searching) {
binding.swipeRefreshLayout.setRefreshing(true); binding.swipeRefreshLayout.setRefreshing(true);
layoutManager.setStackFromEnd(true); layoutManager.setStackFromEnd(true);
friendshipService.getList(isFollowersList, profileId, endCursor, cb); friendshipService.getList(
isFollowersList,
profileId,
endCursor,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
cb.onFailure(throwable);
return;
}
cb.onSuccess(response);
}), Dispatchers.getIO())
);
endCursor = null; endCursor = null;
} }
}); });
@ -253,7 +308,18 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
binding.rvFollow.setLayoutManager(layoutManager); binding.rvFollow.setLayoutManager(layoutManager);
if (moreAvailable) { if (moreAvailable) {
binding.swipeRefreshLayout.setRefreshing(true); binding.swipeRefreshLayout.setRefreshing(true);
friendshipService.getList(isFollowersList, profileId, endCursor, cb); friendshipService.getList(
isFollowersList,
profileId,
endCursor,
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
cb.onFailure(throwable);
return;
}
cb.onSuccess(response);
}), Dispatchers.getIO())
);
} else { } else {
refreshAdapter(followModels, null, null, null); refreshAdapter(followModels, null, null, null);
layoutManager.scrollToPosition(0); layoutManager.scrollToPosition(0);
@ -269,17 +335,34 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
if (moreAvailable) { if (moreAvailable) {
binding.swipeRefreshLayout.setRefreshing(true); binding.swipeRefreshLayout.setRefreshing(true);
Toast.makeText(getContext(), R.string.follower_start_compare, Toast.LENGTH_LONG).show(); Toast.makeText(getContext(), R.string.follower_start_compare, Toast.LENGTH_LONG).show();
friendshipService.getList(isFollowersList, friendshipService.getList(
isFollowersList,
profileId, profileId,
endCursor, endCursor,
isFollowersList ? followersFetchCb : followingFetchCb); CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
final ServiceCallback<FriendshipListFetchResponse> callback = isFollowersList ? followersFetchCb : followingFetchCb;
if (throwable != null) {
callback.onFailure(throwable);
return;
}
callback.onSuccess(response);
}), Dispatchers.getIO())
);
} else if (followersModels.size() == 0 || followingModels.size() == 0) { } else if (followersModels.size() == 0 || followingModels.size() == 0) {
binding.swipeRefreshLayout.setRefreshing(true); binding.swipeRefreshLayout.setRefreshing(true);
Toast.makeText(getContext(), R.string.follower_start_compare, Toast.LENGTH_LONG).show(); Toast.makeText(getContext(), R.string.follower_start_compare, Toast.LENGTH_LONG).show();
friendshipService.getList(!isFollowersList, friendshipService.getList(
!isFollowersList,
profileId, profileId,
null, null,
isFollowersList ? followingFetchCb : followersFetchCb); CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
final ServiceCallback<FriendshipListFetchResponse> callback = isFollowersList ? followingFetchCb : followersFetchCb;
if (throwable != null) {
callback.onFailure(throwable);
return;
}
callback.onSuccess(response);
}), Dispatchers.getIO()));
} else showCompare(); } else showCompare();
} }
@ -337,10 +420,10 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
final Context context = getContext(); final Context context = getContext();
if (loading) Toast.makeText(context, R.string.follower_wait_to_load, Toast.LENGTH_LONG).show(); if (loading) Toast.makeText(context, R.string.follower_wait_to_load, Toast.LENGTH_LONG).show();
else if (isCompare) { else if (isCompare) {
isCompare = !isCompare; isCompare = false;
listFollows(); listFollows();
} else { } else {
isCompare = !isCompare; isCompare = true;
listCompare(); listCompare();
} }
return true; return true;
@ -354,16 +437,15 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
final ArrayList<ExpandableGroup> groups = new ArrayList<>(1); final ArrayList<ExpandableGroup> groups = new ArrayList<>(1);
if (isCompare && followingModels != null && followersModels != null && allFollowing != null) { if (isCompare && followingModels != null && followersModels != null && allFollowing != null) {
if (followingModels != null && followingModels.size() > 0) if (followingModels.size() > 0)
groups.add(new ExpandableGroup(resources.getString(R.string.followers_not_following, username), followingModels)); groups.add(new ExpandableGroup(resources.getString(R.string.followers_not_following, username), followingModels));
if (followersModels != null && followersModels.size() > 0) if (followersModels.size() > 0)
groups.add(new ExpandableGroup(resources.getString(R.string.followers_not_follower, namePost), followersModels)); groups.add(new ExpandableGroup(resources.getString(R.string.followers_not_follower, namePost), followersModels));
if (allFollowing != null && allFollowing.size() > 0) if (allFollowing.size() > 0)
groups.add(new ExpandableGroup(resources.getString(R.string.followers_both_following), allFollowing)); groups.add(new ExpandableGroup(resources.getString(R.string.followers_both_following), allFollowing));
} else if (followModels != null) { } else if (followModels != null) {
groups.add(new ExpandableGroup(type, followModels)); groups.add(new ExpandableGroup(type, followModels));
} } else return;
else return;
adapter = new FollowAdapter(clickListener, groups); adapter = new FollowAdapter(clickListener, groups);
adapter.toggleGroup(0); adapter.toggleGroup(0);
binding.rvFollow.setAdapter(adapter); binding.rvFollow.setAdapter(adapter);

View File

@ -34,7 +34,6 @@ import awais.instagrabber.adapters.NotificationsAdapter.OnNotificationClickListe
import awais.instagrabber.databinding.FragmentNotificationsViewerBinding; import awais.instagrabber.databinding.FragmentNotificationsViewerBinding;
import awais.instagrabber.models.enums.NotificationType; import awais.instagrabber.models.enums.NotificationType;
import awais.instagrabber.repositories.requests.StoryViewerOptions; import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.responses.FriendshipChangeResponse;
import awais.instagrabber.repositories.responses.notification.Notification; import awais.instagrabber.repositories.responses.notification.Notification;
import awais.instagrabber.repositories.responses.notification.NotificationArgs; import awais.instagrabber.repositories.responses.notification.NotificationArgs;
import awais.instagrabber.repositories.responses.notification.NotificationImage; import awais.instagrabber.repositories.responses.notification.NotificationImage;
@ -68,6 +67,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
private String type; private String type;
private long targetId; private long targetId;
private Context context; private Context context;
private long userId;
private final ServiceCallback<List<Notification>> cb = new ServiceCallback<List<Notification>>() { private final ServiceCallback<List<Notification>> cb = new ServiceCallback<List<Notification>>() {
@Override @Override
@ -168,34 +168,40 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
break; break;
case 1: case 1:
if (model.getType() == NotificationType.REQUEST) { if (model.getType() == NotificationType.REQUEST) {
friendshipService.approve(args.getUserId(), new ServiceCallback<FriendshipChangeResponse>() { friendshipService.approve(
@Override csrfToken,
public void onSuccess(final FriendshipChangeResponse result) { userId,
deviceUuid,
args.getUserId(),
CoroutineUtilsKt.getContinuation(
(response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
Log.e(TAG, "approve: onFailure: ", throwable);
return;
}
onRefresh(); onRefresh();
Log.e(TAG, "approve: status was not ok!"); }),
} Dispatchers.getIO()
)
@Override );
public void onFailure(final Throwable t) {
Log.e(TAG, "approve: onFailure: ", t);
}
});
return; return;
} }
clickListener.onPreviewClick(model); clickListener.onPreviewClick(model);
break; break;
case 2: case 2:
friendshipService.ignore(args.getUserId(), new ServiceCallback<FriendshipChangeResponse>() { friendshipService.ignore(
@Override csrfToken,
public void onSuccess(final FriendshipChangeResponse result) { userId,
deviceUuid,
args.getUserId(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
Log.e(TAG, "approve: onFailure: ", throwable);
return;
}
onRefresh(); onRefresh();
} }), Dispatchers.getIO())
);
@Override
public void onFailure(final Throwable t) {
Log.e(TAG, "ignore: onFailure: ", t);
}
});
break; break;
} }
}; };
@ -219,10 +225,10 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
if (TextUtils.isEmpty(cookie)) { if (TextUtils.isEmpty(cookie)) {
Toast.makeText(context, R.string.activity_notloggedin, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.activity_notloggedin, Toast.LENGTH_SHORT).show();
} }
final long userId = CookieUtils.getUserIdFromCookie(cookie); userId = CookieUtils.getUserIdFromCookie(cookie);
deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID);
csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, userId); friendshipService = FriendshipService.INSTANCE;
mediaService = MediaService.INSTANCE; mediaService = MediaService.INSTANCE;
newsService = NewsService.getInstance(); newsService = NewsService.getInstance();
} }

View File

@ -79,7 +79,6 @@ import awais.instagrabber.models.enums.FavoriteType;
import awais.instagrabber.models.enums.PostItemType; import awais.instagrabber.models.enums.PostItemType;
import awais.instagrabber.repositories.requests.StoryViewerOptions; import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.responses.FriendshipChangeResponse; import awais.instagrabber.repositories.responses.FriendshipChangeResponse;
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse;
import awais.instagrabber.repositories.responses.FriendshipStatus; import awais.instagrabber.repositories.responses.FriendshipStatus;
import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.User;
@ -146,6 +145,8 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
private AppStateViewModel appStateViewModel; private AppStateViewModel appStateViewModel;
private boolean disableDm = false; private boolean disableDm = false;
private ProfileFragmentViewModel viewModel; private ProfileFragmentViewModel viewModel;
private String csrfToken;
private String deviceUuid;
private final ServiceCallback<FriendshipChangeResponse> changeCb = new ServiceCallback<FriendshipChangeResponse>() { private final ServiceCallback<FriendshipChangeResponse> changeCb = new ServiceCallback<FriendshipChangeResponse>() {
@Override @Override
@ -331,10 +332,10 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
cookie = Utils.settingsHelper.getString(Constants.COOKIE); cookie = Utils.settingsHelper.getString(Constants.COOKIE);
isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0;
myId = CookieUtils.getUserIdFromCookie(cookie); myId = CookieUtils.getUserIdFromCookie(cookie);
final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID);
final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
fragmentActivity = (MainActivity) requireActivity(); fragmentActivity = (MainActivity) requireActivity();
friendshipService = isLoggedIn ? FriendshipService.getInstance(deviceUuid, csrfToken, myId) : null; friendshipService = isLoggedIn ? FriendshipService.INSTANCE : null;
directMessagesService = isLoggedIn ? DirectMessagesService.getInstance(csrfToken, myId, deviceUuid) : null; directMessagesService = isLoggedIn ? DirectMessagesService.getInstance(csrfToken, myId, deviceUuid) : null;
storiesService = isLoggedIn ? StoriesService.getInstance(null, 0L, null) : null; storiesService = isLoggedIn ? StoriesService.getInstance(null, 0L, null) : null;
mediaService = isLoggedIn ? MediaService.INSTANCE : null; mediaService = isLoggedIn ? MediaService.INSTANCE : null;
@ -451,25 +452,38 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
final String action = profileModel.getFriendshipStatus().isRestricted() ? "Unrestrict" : "Restrict"; final String action = profileModel.getFriendshipStatus().isRestricted() ? "Unrestrict" : "Restrict";
friendshipService.toggleRestrict( friendshipService.toggleRestrict(
csrfToken,
deviceUuid,
profileModel.getPk(), profileModel.getPk(),
!profileModel.getFriendshipStatus().isRestricted(), !profileModel.getFriendshipStatus().isRestricted(),
new ServiceCallback<FriendshipRestrictResponse>() { CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
@Override if (throwable != null) {
public void onSuccess(final FriendshipRestrictResponse result) { Log.e(TAG, "Error while performing " + action, throwable);
Log.d(TAG, action + " success: " + result); return;
}
// Log.d(TAG, action + " success: " + response);
fetchProfileDetails(); fetchProfileDetails();
} }), Dispatchers.getIO())
);
@Override
public void onFailure(final Throwable t) {
Log.e(TAG, "Error while performing " + action, t);
}
});
return true; return true;
} }
if (item.getItemId() == R.id.block) { if (item.getItemId() == R.id.block) {
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
friendshipService.changeBlock(profileModel.getFriendshipStatus().getBlocking(), profileModel.getPk(), changeCb); // changeCb
friendshipService.changeBlock(
csrfToken,
myId,
deviceUuid,
profileModel.getFriendshipStatus().getBlocking(),
profileModel.getPk(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
return true; return true;
} }
if (item.getItemId() == R.id.chaining) { if (item.getItemId() == R.id.chaining) {
@ -484,25 +498,57 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
final String action = profileModel.getFriendshipStatus().isMutingReel() ? "Unmute stories" : "Mute stories"; final String action = profileModel.getFriendshipStatus().isMutingReel() ? "Unmute stories" : "Mute stories";
friendshipService.changeMute( friendshipService.changeMute(
csrfToken,
myId,
deviceUuid,
profileModel.getFriendshipStatus().isMutingReel(), profileModel.getFriendshipStatus().isMutingReel(),
profileModel.getPk(), profileModel.getPk(),
true, true,
changeCb); CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
return true; return true;
} }
if (item.getItemId() == R.id.mute_posts) { if (item.getItemId() == R.id.mute_posts) {
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
final String action = profileModel.getFriendshipStatus().getMuting() ? "Unmute stories" : "Mute stories"; final String action = profileModel.getFriendshipStatus().getMuting() ? "Unmute stories" : "Mute stories";
friendshipService.changeMute( friendshipService.changeMute(
csrfToken,
myId,
deviceUuid,
profileModel.getFriendshipStatus().getMuting(), profileModel.getFriendshipStatus().getMuting(),
profileModel.getPk(), profileModel.getPk(),
false, false,
changeCb); CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
return true; return true;
} }
if (item.getItemId() == R.id.remove_follower) { if (item.getItemId() == R.id.remove_follower) {
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
friendshipService.removeFollower(profileModel.getPk(), changeCb); friendshipService.removeFollower(
csrfToken,
myId,
deviceUuid,
profileModel.getPk(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
return true; return true;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
@ -1032,19 +1078,55 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
private void setupCommonListeners() { private void setupCommonListeners() {
final Context context = getContext(); final Context context = getContext();
if (context == null) return;
profileDetailsBinding.btnFollow.setOnClickListener(v -> { profileDetailsBinding.btnFollow.setOnClickListener(v -> {
if (profileModel.getFriendshipStatus().getFollowing() && profileModel.isPrivate()) { if (profileModel.getFriendshipStatus().getFollowing() && profileModel.isPrivate()) {
new AlertDialog.Builder(context) new AlertDialog.Builder(context)
.setTitle(R.string.priv_acc) .setTitle(R.string.priv_acc)
.setMessage(R.string.priv_acc_confirm) .setMessage(R.string.priv_acc_confirm)
.setPositiveButton(R.string.confirm, (d, w) -> .setPositiveButton(R.string.confirm, (d, w) -> friendshipService.unfollow(
friendshipService.unfollow(profileModel.getPk(), changeCb)) csrfToken,
myId,
deviceUuid,
profileModel.getPk(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
))
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.show(); .show();
} else if (profileModel.getFriendshipStatus().getFollowing() || profileModel.getFriendshipStatus().getOutgoingRequest()) { } else if (profileModel.getFriendshipStatus().getFollowing() || profileModel.getFriendshipStatus().getOutgoingRequest()) {
friendshipService.unfollow(profileModel.getPk(), changeCb); friendshipService.unfollow(
csrfToken,
myId,
deviceUuid,
profileModel.getPk(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
} else { } else {
friendshipService.follow(profileModel.getPk(), changeCb); friendshipService.follow(
csrfToken,
myId,
deviceUuid,
profileModel.getPk(),
CoroutineUtilsKt.getContinuation((response, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
changeCb.onFailure(throwable);
return;
}
changeCb.onSuccess(response);
}), Dispatchers.getIO())
);
} }
}); });
profileDetailsBinding.btnSaved.setOnClickListener(v -> { profileDetailsBinding.btnSaved.setOnClickListener(v -> {
@ -1109,7 +1191,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
} }
showProfilePicDialog(); showProfilePicDialog();
}; };
if (context == null) return;
new AlertDialog.Builder(context) new AlertDialog.Builder(context)
.setItems(options, profileDialogListener) .setItems(options, profileDialogListener)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)

View File

@ -19,8 +19,6 @@ import awais.instagrabber.repositories.requests.UploadFinishOptions
import awais.instagrabber.repositories.requests.VideoOptions import awais.instagrabber.repositories.requests.VideoOptions
import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds
import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds.Companion.of import awais.instagrabber.repositories.requests.directmessages.ThreadIdOrUserIds.Companion.of
import awais.instagrabber.repositories.responses.FriendshipChangeResponse
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse
import awais.instagrabber.repositories.responses.User import awais.instagrabber.repositories.responses.User
import awais.instagrabber.repositories.responses.directmessages.* import awais.instagrabber.repositories.responses.directmessages.*
import awais.instagrabber.repositories.responses.giphy.GiphyGif import awais.instagrabber.repositories.responses.giphy.GiphyGif
@ -34,7 +32,6 @@ import awais.instagrabber.utils.TextUtils.isEmpty
import awais.instagrabber.webservices.DirectMessagesService import awais.instagrabber.webservices.DirectMessagesService
import awais.instagrabber.webservices.FriendshipService import awais.instagrabber.webservices.FriendshipService
import awais.instagrabber.webservices.MediaService import awais.instagrabber.webservices.MediaService
import awais.instagrabber.webservices.ServiceCallback
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import com.google.common.collect.Iterables import com.google.common.collect.Iterables
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -69,7 +66,6 @@ class ThreadManager private constructor(
private val currentUser: User? private val currentUser: User?
private val contentResolver: ContentResolver private val contentResolver: ContentResolver
private val service: DirectMessagesService private val service: DirectMessagesService
private val friendshipService: FriendshipService
val thread: LiveData<DirectThread?> by lazy { val thread: LiveData<DirectThread?> by lazy {
distinctUntilChanged(map(inboxManager.getInbox()) { inboxResource: Resource<DirectInbox?>? -> distinctUntilChanged(map(inboxManager.getInbox()) { inboxResource: Resource<DirectInbox?>? ->
@ -1132,61 +1128,57 @@ class ThreadManager private constructor(
fun blockUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> { fun blockUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> {
val data = MutableLiveData<Resource<Any?>>() val data = MutableLiveData<Resource<Any?>>()
friendshipService.changeBlock(false, user.pk, object : ServiceCallback<FriendshipChangeResponse?> { scope.launch(Dispatchers.IO) {
override fun onSuccess(result: FriendshipChangeResponse?) { try {
FriendshipService.changeBlock(csrfToken, viewerId, deviceUuid, false, user.pk)
refreshChats(scope) refreshChats(scope)
} catch (e: Exception) {
Log.e(TAG, "onFailure: ", e)
data.postValue(error(e.message, null))
} }
override fun onFailure(t: Throwable) {
Log.e(TAG, "onFailure: ", t)
data.postValue(error(t.message, null))
} }
})
return data return data
} }
fun unblockUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> { fun unblockUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> {
val data = MutableLiveData<Resource<Any?>>() val data = MutableLiveData<Resource<Any?>>()
friendshipService.changeBlock(true, user.pk, object : ServiceCallback<FriendshipChangeResponse?> { scope.launch(Dispatchers.IO) {
override fun onSuccess(result: FriendshipChangeResponse?) { try {
FriendshipService.changeBlock(csrfToken, viewerId, deviceUuid, true, user.pk)
refreshChats(scope) refreshChats(scope)
} catch (e: Exception) {
Log.e(TAG, "onFailure: ", e)
data.postValue(error(e.message, null))
} }
override fun onFailure(t: Throwable) {
Log.e(TAG, "onFailure: ", t)
data.postValue(error(t.message, null))
} }
})
return data return data
} }
fun restrictUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> { fun restrictUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> {
val data = MutableLiveData<Resource<Any?>>() val data = MutableLiveData<Resource<Any?>>()
friendshipService.toggleRestrict(user.pk, true, object : ServiceCallback<FriendshipRestrictResponse?> { scope.launch(Dispatchers.IO) {
override fun onSuccess(result: FriendshipRestrictResponse?) { try {
FriendshipService.toggleRestrict(csrfToken, deviceUuid, user.pk, true)
refreshChats(scope) refreshChats(scope)
} catch (e: Exception) {
Log.e(TAG, "onFailure: ", e)
data.postValue(error(e.message, null))
} }
override fun onFailure(t: Throwable) {
Log.e(TAG, "onFailure: ", t)
data.postValue(error(t.message, null))
} }
})
return data return data
} }
fun unRestrictUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> { fun unRestrictUser(user: User, scope: CoroutineScope): LiveData<Resource<Any?>> {
val data = MutableLiveData<Resource<Any?>>() val data = MutableLiveData<Resource<Any?>>()
friendshipService.toggleRestrict(user.pk, false, object : ServiceCallback<FriendshipRestrictResponse?> { scope.launch(Dispatchers.IO) {
override fun onSuccess(result: FriendshipRestrictResponse?) { try {
FriendshipService.toggleRestrict(csrfToken, deviceUuid, user.pk, false)
refreshChats(scope) refreshChats(scope)
} catch (e: Exception) {
Log.e(TAG, "onFailure: ", e)
data.postValue(error(e.message, null))
} }
override fun onFailure(t: Throwable) {
Log.e(TAG, "onFailure: ", t)
data.postValue(error(t.message, null))
} }
})
return data return data
} }
@ -1415,7 +1407,6 @@ class ThreadManager private constructor(
this.contentResolver = contentResolver this.contentResolver = contentResolver
this.viewerId = viewerId this.viewerId = viewerId
service = DirectMessagesService.getInstance(csrfToken, viewerId, deviceUuid) service = DirectMessagesService.getInstance(csrfToken, viewerId, deviceUuid)
friendshipService = FriendshipService.getInstance(deviceUuid, csrfToken, viewerId)
// fetchChats(); // fetchChats();
} }
} }

View File

@ -1,37 +1,36 @@
package awais.instagrabber.repositories; package awais.instagrabber.repositories
import java.util.Map; import awais.instagrabber.repositories.responses.FriendshipChangeResponse
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse
import awais.instagrabber.repositories.responses.FriendshipChangeResponse; import retrofit2.http.*
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse;
import retrofit2.Call;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.QueryMap;
public interface FriendshipRepository {
interface FriendshipRepository {
@FormUrlEncoded @FormUrlEncoded
@POST("/api/v1/friendships/{action}/{id}/") @POST("/api/v1/friendships/{action}/{id}/")
Call<FriendshipChangeResponse> change(@Path("action") String action, suspend fun change(
@Path("id") long id, @Path("action") action: String,
@FieldMap Map<String, String> form); @Path("id") id: Long,
@FieldMap form: Map<String, String>,
): FriendshipChangeResponse
@FormUrlEncoded @FormUrlEncoded
@POST("/api/v1/restrict_action/{action}/") @POST("/api/v1/restrict_action/{action}/")
Call<FriendshipRestrictResponse> toggleRestrict(@Path("action") String action, suspend fun toggleRestrict(
@FieldMap Map<String, String> form); @Path("action") action: String,
@FieldMap form: Map<String, String>,
): FriendshipRestrictResponse
@GET("/api/v1/friendships/{userId}/{type}/") @GET("/api/v1/friendships/{userId}/{type}/")
Call<String> getList(@Path("userId") long userId, suspend fun getList(
@Path("type") String type, // following or followers @Path("userId") userId: Long,
@QueryMap(encoded = true) Map<String, String> queryParams); @Path("type") type: String, // following or followers
@QueryMap(encoded = true) queryParams: Map<String, String>,
): String
@FormUrlEncoded @FormUrlEncoded
@POST("/api/v1/friendships/{action}/") @POST("/api/v1/friendships/{action}/")
Call<FriendshipChangeResponse> changeMute(@Path("action") String action, suspend fun changeMute(
@FieldMap Map<String, String> form); @Path("action") action: String,
@FieldMap form: Map<String, String>,
): FriendshipChangeResponse
} }

View File

@ -1,264 +1,155 @@
package awais.instagrabber.webservices; package awais.instagrabber.webservices
import android.util.Log; import awais.instagrabber.models.FollowModel
import awais.instagrabber.repositories.FriendshipRepository
import awais.instagrabber.repositories.responses.FriendshipChangeResponse
import awais.instagrabber.repositories.responses.FriendshipListFetchResponse
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse
import awais.instagrabber.utils.Utils
import awais.instagrabber.webservices.RetrofitFactory.retrofit
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import androidx.annotation.NonNull; object FriendshipService : BaseService() {
private val repository: FriendshipRepository = retrofit.create(FriendshipRepository::class.java)
import org.json.JSONArray; suspend fun follow(
import org.json.JSONException; csrfToken: String,
import org.json.JSONObject; userId: Long,
deviceUuid: String,
targetUserId: Long,
): FriendshipChangeResponse = change(csrfToken, userId, deviceUuid, "create", targetUserId)
import java.util.ArrayList; suspend fun unfollow(
import java.util.Collections; csrfToken: String,
import java.util.HashMap; userId: Long,
import java.util.List; deviceUuid: String,
import java.util.Map; targetUserId: Long,
import java.util.Objects; ): FriendshipChangeResponse = change(csrfToken, userId, deviceUuid, "destroy", targetUserId)
import awais.instagrabber.models.FollowModel; suspend fun changeBlock(
import awais.instagrabber.repositories.FriendshipRepository; csrfToken: String,
import awais.instagrabber.repositories.responses.FriendshipChangeResponse; userId: Long,
import awais.instagrabber.repositories.responses.FriendshipListFetchResponse; deviceUuid: String,
import awais.instagrabber.repositories.responses.FriendshipRestrictResponse; unblock: Boolean,
import awais.instagrabber.utils.TextUtils; targetUserId: Long,
import awais.instagrabber.utils.Utils; ): FriendshipChangeResponse {
import retrofit2.Call; return change(csrfToken, userId, deviceUuid, if (unblock) "unblock" else "block", targetUserId)
import retrofit2.Callback;
import retrofit2.Response;
public class FriendshipService extends BaseService {
private static final String TAG = "FriendshipService";
private final FriendshipRepository repository;
private final String deviceUuid, csrfToken;
private final long userId;
private static FriendshipService instance;
private FriendshipService(final String deviceUuid,
final String csrfToken,
final long userId) {
this.deviceUuid = deviceUuid;
this.csrfToken = csrfToken;
this.userId = userId;
repository = RetrofitFactory.INSTANCE
.getRetrofit()
.create(FriendshipRepository.class);
} }
public String getCsrfToken() { suspend fun toggleRestrict(
return csrfToken; csrfToken: String,
deviceUuid: String,
targetUserId: Long,
restrict: Boolean,
): FriendshipRestrictResponse {
val form = mapOf(
"_csrftoken" to csrfToken,
"_uuid" to deviceUuid,
"target_user_id" to targetUserId.toString(),
)
val action = if (restrict) "restrict" else "unrestrict"
return repository.toggleRestrict(action, form)
} }
public String getDeviceUuid() { suspend fun approve(
return deviceUuid; csrfToken: String,
userId: Long,
deviceUuid: String,
targetUserId: Long,
): FriendshipChangeResponse = change(csrfToken, userId, deviceUuid, "approve", targetUserId)
suspend fun ignore(
csrfToken: String,
userId: Long,
deviceUuid: String,
targetUserId: Long,
): FriendshipChangeResponse = change(csrfToken, userId, deviceUuid, "ignore", targetUserId)
suspend fun removeFollower(
csrfToken: String,
userId: Long,
deviceUuid: String,
targetUserId: Long,
): FriendshipChangeResponse = change(csrfToken, userId, deviceUuid, "remove_follower", targetUserId)
private suspend fun change(
csrfToken: String,
userId: Long,
deviceUuid: String,
action: String,
targetUserId: Long,
): FriendshipChangeResponse {
val form = mapOf(
"_csrftoken" to csrfToken,
"_uid" to userId,
"_uuid" to deviceUuid,
"radio_type" to "wifi-none",
"user_id" to targetUserId,
)
val signedForm = Utils.sign(form)
return repository.change(action, targetUserId, signedForm)
} }
public long getUserId() { suspend fun changeMute(
return userId; csrfToken: String,
userId: Long,
deviceUuid: String,
unmute: Boolean,
targetUserId: Long,
story: Boolean, // true for story, false for posts
): FriendshipChangeResponse {
val form = mapOf(
"_csrftoken" to csrfToken,
"_uid" to userId.toString(),
"_uuid" to deviceUuid,
(if (story) "target_reel_author_id" else "target_posts_author_id") to targetUserId.toString(),
)
return repository.changeMute(
if (unmute) "unmute_posts_or_story_from_follow" else "mute_posts_or_story_from_follow",
form
)
} }
public static FriendshipService getInstance(final String deviceUuid, final String csrfToken, final long userId) { suspend fun getList(
if (instance == null follower: Boolean,
|| !Objects.equals(instance.getCsrfToken(), csrfToken) targetUserId: Long,
|| !Objects.equals(instance.getDeviceUuid(), deviceUuid) maxId: String?,
|| !Objects.equals(instance.getUserId(), userId)) { ): FriendshipListFetchResponse {
instance = new FriendshipService(deviceUuid, csrfToken, userId); val queryMap = if (maxId != null) mapOf("max_id" to maxId) else emptyMap()
} val response = repository.getList(targetUserId, if (follower) "followers" else "following", queryMap)
return instance; return parseListResponse(response)
} }
public void follow(final long targetUserId, @Throws(JSONException::class)
final ServiceCallback<FriendshipChangeResponse> callback) { private fun parseListResponse(body: String): FriendshipListFetchResponse {
change("create", targetUserId, callback); val root = JSONObject(body)
} val nextMaxId = root.optString("next_max_id")
val status = root.optString("status")
public void unfollow(final long targetUserId, val itemsJson = root.optJSONArray("users")
final ServiceCallback<FriendshipChangeResponse> callback) { val items = parseItems(itemsJson)
change("destroy", targetUserId, callback); return FriendshipListFetchResponse(
}
public void changeBlock(final boolean unblock,
final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
change(unblock ? "unblock" : "block", targetUserId, callback);
}
public void toggleRestrict(final long targetUserId,
final boolean restrict,
final ServiceCallback<FriendshipRestrictResponse> callback) {
final Map<String, String> form = new HashMap<>(3);
form.put("_csrftoken", csrfToken);
form.put("_uuid", deviceUuid);
form.put("target_user_id", String.valueOf(targetUserId));
final String action = restrict ? "restrict" : "unrestrict";
final Call<FriendshipRestrictResponse> request = repository.toggleRestrict(action, form);
request.enqueue(new Callback<FriendshipRestrictResponse>() {
@Override
public void onResponse(@NonNull final Call<FriendshipRestrictResponse> call,
@NonNull final Response<FriendshipRestrictResponse> response) {
if (callback != null) {
callback.onSuccess(response.body());
}
}
@Override
public void onFailure(@NonNull final Call<FriendshipRestrictResponse> call,
@NonNull final Throwable t) {
if (callback != null) {
callback.onFailure(t);
}
}
});
}
public void approve(final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
change("approve", targetUserId, callback);
}
public void ignore(final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
change("ignore", targetUserId, callback);
}
public void removeFollower(final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
change("remove_follower", targetUserId, callback);
}
private void change(final String action,
final long targetUserId,
final ServiceCallback<FriendshipChangeResponse> callback) {
final Map<String, Object> form = new HashMap<>(5);
form.put("_csrftoken", csrfToken);
form.put("_uid", userId);
form.put("_uuid", deviceUuid);
form.put("radio_type", "wifi-none");
form.put("user_id", targetUserId);
final Map<String, String> signedForm = Utils.sign(form);
final Call<FriendshipChangeResponse> request = repository.change(action, targetUserId, signedForm);
request.enqueue(new Callback<FriendshipChangeResponse>() {
@Override
public void onResponse(@NonNull final Call<FriendshipChangeResponse> call,
@NonNull final Response<FriendshipChangeResponse> response) {
if (callback != null) {
callback.onSuccess(response.body());
}
}
@Override
public void onFailure(@NonNull final Call<FriendshipChangeResponse> call,
@NonNull final Throwable t) {
if (callback != null) {
callback.onFailure(t);
}
}
});
}
public void changeMute(final boolean unmute,
final long targetUserId,
final boolean story, // true for story, false for posts
final ServiceCallback<FriendshipChangeResponse> callback) {
final Map<String, String> form = new HashMap<>(4);
form.put("_csrftoken", csrfToken);
form.put("_uid", String.valueOf(userId));
form.put("_uuid", deviceUuid);
form.put(story ? "target_reel_author_id" : "target_posts_author_id", String.valueOf(targetUserId));
final Call<FriendshipChangeResponse> request = repository.changeMute(unmute ?
"unmute_posts_or_story_from_follow" :
"mute_posts_or_story_from_follow",
form);
request.enqueue(new Callback<FriendshipChangeResponse>() {
@Override
public void onResponse(@NonNull final Call<FriendshipChangeResponse> call,
@NonNull final Response<FriendshipChangeResponse> response) {
if (callback != null) {
callback.onSuccess(response.body());
}
}
@Override
public void onFailure(@NonNull final Call<FriendshipChangeResponse> call,
@NonNull final Throwable t) {
if (callback != null) {
callback.onFailure(t);
}
}
});
}
public void getList(final boolean follower,
final long targetUserId,
final String maxId,
final ServiceCallback<FriendshipListFetchResponse> callback) {
final Map<String, String> queryMap = new HashMap<>();
if (maxId != null) queryMap.put("max_id", maxId);
final Call<String> request = repository.getList(
targetUserId,
follower ? "followers" : "following",
queryMap);
request.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
try {
if (callback == null) {
return;
}
final String body = response.body();
if (TextUtils.isEmpty(body)) {
callback.onSuccess(null);
return;
}
final FriendshipListFetchResponse friendshipListFetchResponse = parseListResponse(body);
callback.onSuccess(friendshipListFetchResponse);
} catch (JSONException e) {
Log.e(TAG, "onResponse", e);
callback.onFailure(e);
}
}
@Override
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
if (callback != null) {
callback.onFailure(t);
}
}
});
}
private FriendshipListFetchResponse parseListResponse(@NonNull final String body) throws JSONException {
final JSONObject root = new JSONObject(body);
final String nextMaxId = root.optString("next_max_id");
final String status = root.optString("status");
final JSONArray itemsJson = root.optJSONArray("users");
final List<FollowModel> items = parseItems(itemsJson);
return new FriendshipListFetchResponse(
nextMaxId, nextMaxId,
status, status,
items items
); )
} }
private List<FollowModel> parseItems(final JSONArray items) throws JSONException { @Throws(JSONException::class)
private fun parseItems(items: JSONArray?): List<FollowModel> {
if (items == null) { if (items == null) {
return Collections.emptyList(); return emptyList()
} }
final List<FollowModel> followModels = new ArrayList<>(); val followModels = mutableListOf<FollowModel>()
for (int i = 0; i < items.length(); i++) { for (i in 0 until items.length()) {
final JSONObject itemJson = items.optJSONObject(i); val itemJson = items.optJSONObject(i) ?: continue
if (itemJson == null) { val followModel = FollowModel(itemJson.getString("pk"),
continue;
}
final FollowModel followModel = new FollowModel(itemJson.getString("pk"),
itemJson.getString("username"), itemJson.getString("username"),
itemJson.optString("full_name"), itemJson.optString("full_name"),
itemJson.getString("profile_pic_url")); itemJson.getString("profile_pic_url"))
if (followModel != null) { followModels.add(followModel)
followModels.add(followModel); }
} return followModels
}
return followModels;
} }
} }