Ammar Githam
4 years ago
23 changed files with 731 additions and 560 deletions
-
7app/src/main/AndroidManifest.xml
-
3app/src/main/java/awais/instagrabber/activities/MainActivity.java
-
189app/src/main/java/awais/instagrabber/activities/NotificationsViewer.java
-
90app/src/main/java/awais/instagrabber/adapters/NotificationsAdapter.java
-
105app/src/main/java/awais/instagrabber/adapters/viewholder/NotificationViewHolder.java
-
71app/src/main/java/awais/instagrabber/asyncs/NotificationsFetcher.java
-
215app/src/main/java/awais/instagrabber/fragments/NotificationsViewerFragment.java
-
1app/src/main/java/awais/instagrabber/fragments/PostViewFragment.java
-
6app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java
-
29app/src/main/java/awais/instagrabber/models/NotificationModel.java
-
21app/src/main/java/awais/instagrabber/repositories/NewsRepository.java
-
7app/src/main/java/awais/instagrabber/services/AddCookiesInterceptor.java
-
4app/src/main/java/awais/instagrabber/services/BaseService.java
-
14app/src/main/java/awais/instagrabber/services/FriendshipService.java
-
69app/src/main/java/awais/instagrabber/services/NewsService.java
-
1app/src/main/java/awais/instagrabber/utils/Constants.java
-
19app/src/main/java/awais/instagrabber/viewmodels/NotificationViewModel.java
-
30app/src/main/res/layout/activity_notification.xml
-
15app/src/main/res/layout/fragment_notifications_viewer.xml
-
203app/src/main/res/layout/item_notification.xml
-
152app/src/main/res/layout/layout_include_notif_item.xml
-
38app/src/main/res/navigation/more_nav_graph.xml
-
2app/src/main/res/values/dimens.xml
@ -1,189 +0,0 @@ |
|||||
package awais.instagrabber.activities; |
|
||||
|
|
||||
import android.content.DialogInterface; |
|
||||
import android.content.res.Resources; |
|
||||
import android.os.AsyncTask; |
|
||||
import android.os.Bundle; |
|
||||
import android.text.SpannableString; |
|
||||
import android.text.Spanned; |
|
||||
import android.text.style.RelativeSizeSpan; |
|
||||
import android.util.Log; |
|
||||
import android.view.View; |
|
||||
import android.widget.ArrayAdapter; |
|
||||
import android.widget.Toast; |
|
||||
|
|
||||
import androidx.annotation.Nullable; |
|
||||
import androidx.appcompat.app.AlertDialog; |
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; |
|
||||
|
|
||||
import java.io.DataOutputStream; |
|
||||
import java.net.HttpURLConnection; |
|
||||
import java.net.URL; |
|
||||
|
|
||||
import awais.instagrabber.R; |
|
||||
import awais.instagrabber.adapters.NotificationsAdapter; |
|
||||
import awais.instagrabber.asyncs.NotificationsFetcher; |
|
||||
import awais.instagrabber.databinding.ActivityNotificationBinding; |
|
||||
import awais.instagrabber.interfaces.FetchListener; |
|
||||
import awais.instagrabber.interfaces.MentionClickListener; |
|
||||
import awais.instagrabber.models.NotificationModel; |
|
||||
import awais.instagrabber.models.enums.NotificationType; |
|
||||
import awais.instagrabber.utils.Constants; |
|
||||
import awais.instagrabber.utils.TextUtils; |
|
||||
import awais.instagrabber.utils.Utils; |
|
||||
|
|
||||
import static awais.instagrabber.utils.Utils.notificationManager; |
|
||||
|
|
||||
public final class NotificationsViewer extends BaseLanguageActivity implements SwipeRefreshLayout.OnRefreshListener { |
|
||||
private NotificationModel notificationModel; |
|
||||
private ActivityNotificationBinding notificationsBinding; |
|
||||
private ArrayAdapter<String> commmentDialogAdapter; |
|
||||
private String shortCode, postId, userId; |
|
||||
private final String cookie = Utils.settingsHelper.getString(Constants.COOKIE); |
|
||||
private Resources resources; |
|
||||
String[] commentDialogList; |
|
||||
|
|
||||
@Override |
|
||||
protected void onCreate(@Nullable final Bundle savedInstanceState) { |
|
||||
notificationManager.cancel(1800000000); |
|
||||
if (TextUtils.isEmpty(cookie)) { |
|
||||
Toast.makeText(this, R.string.activity_notloggedin, Toast.LENGTH_SHORT).show(); |
|
||||
} |
|
||||
super.onCreate(savedInstanceState); |
|
||||
notificationsBinding = ActivityNotificationBinding.inflate(getLayoutInflater()); |
|
||||
setContentView(notificationsBinding.getRoot()); |
|
||||
notificationsBinding.swipeRefreshLayout.setOnRefreshListener(this); |
|
||||
resources = getResources(); |
|
||||
setSupportActionBar(notificationsBinding.toolbar.toolbar); |
|
||||
notificationsBinding.toolbar.toolbar.setTitle(R.string.action_notif); |
|
||||
onRefresh(); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void onRefresh() { |
|
||||
notificationsBinding.swipeRefreshLayout.setRefreshing(true); |
|
||||
new NotificationsFetcher(new FetchListener<NotificationModel[]>() { |
|
||||
@Override |
|
||||
public void onResult(final NotificationModel[] notificationModels) { |
|
||||
notificationsBinding.rvComments.setAdapter(new NotificationsAdapter(notificationModels, clickListener, mentionClickListener)); |
|
||||
notificationsBinding.swipeRefreshLayout.setRefreshing(false); |
|
||||
new SeenAction().execute(); |
|
||||
} |
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|
||||
} |
|
||||
|
|
||||
final DialogInterface.OnClickListener profileDialogListener = (dialog, which) -> { |
|
||||
if (which == 0) |
|
||||
searchUsername(notificationModel.getUsername()); |
|
||||
else if (which == 1 && commentDialogList.length == 2) { |
|
||||
// startActivity(new Intent(getApplicationContext(), PostViewer.class) |
|
||||
// .putExtra(Constants.EXTRAS_POST, new PostModel(notificationModel.getShortcode(), false))); |
|
||||
} |
|
||||
else if (which == 1) new ProfileAction().execute("/approve/"); |
|
||||
else if (which == 2) new ProfileAction().execute("/ignore/"); |
|
||||
}; |
|
||||
|
|
||||
private final View.OnClickListener clickListener = v -> { |
|
||||
final Object tag = v.getTag(); |
|
||||
if (tag instanceof NotificationModel) { |
|
||||
notificationModel = (NotificationModel) tag; |
|
||||
|
|
||||
final String username = notificationModel.getUsername(); |
|
||||
final SpannableString title = new SpannableString(username + ":\n" + notificationModel.getText()); |
|
||||
title.setSpan(new RelativeSizeSpan(1.23f), 0, username.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); |
|
||||
|
|
||||
if (notificationModel.getShortcode() != null) commentDialogList = new String[]{ |
|
||||
resources.getString(R.string.open_profile), |
|
||||
resources.getString(R.string.view_post) |
|
||||
}; |
|
||||
else if (notificationModel.getType() == NotificationType.REQUEST) |
|
||||
commentDialogList = new String[]{ |
|
||||
resources.getString(R.string.open_profile), |
|
||||
resources.getString(R.string.request_approve), |
|
||||
resources.getString(R.string.request_reject) |
|
||||
}; |
|
||||
else commentDialogList = new String[]{ |
|
||||
resources.getString(R.string.open_profile) |
|
||||
}; |
|
||||
|
|
||||
commmentDialogAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, commentDialogList); |
|
||||
|
|
||||
new AlertDialog.Builder(this).setTitle(title) |
|
||||
.setAdapter(commmentDialogAdapter, profileDialogListener) |
|
||||
.setNeutralButton(R.string.cancel, null) |
|
||||
.show(); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
private final MentionClickListener mentionClickListener = (view, text, isHashtag, isLocation) -> |
|
||||
new AlertDialog.Builder(this).setTitle(text) |
|
||||
.setMessage(isHashtag ? R.string.comment_view_mention_hash_search : R.string.comment_view_mention_user_search) |
|
||||
.setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.ok, |
|
||||
(dialog, which) -> searchUsername(text)).show(); |
|
||||
|
|
||||
|
|
||||
private void searchUsername(final String text) { |
|
||||
// startActivity(new Intent(getApplicationContext(), ProfileViewer.class).putExtra(Constants.EXTRAS_USERNAME, text)); |
|
||||
} |
|
||||
|
|
||||
class ProfileAction extends AsyncTask<String, Void, Void> { |
|
||||
boolean ok = false; |
|
||||
String action; |
|
||||
|
|
||||
protected Void doInBackground(String... rawAction) { |
|
||||
action = rawAction[0]; |
|
||||
final String url = "https://www.instagram.com/web/friendships/"+notificationModel.getId()+action; |
|
||||
try { |
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); |
|
||||
urlConnection.setRequestMethod("POST"); |
|
||||
urlConnection.setUseCaches(false); |
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT); |
|
||||
urlConnection.setRequestProperty("x-csrftoken", |
|
||||
Utils.settingsHelper.getString(Constants.COOKIE).split("csrftoken=")[1].split(";")[0]); |
|
||||
urlConnection.connect(); |
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { |
|
||||
ok = true; |
|
||||
} |
|
||||
urlConnection.disconnect(); |
|
||||
} catch (Throwable ex) { |
|
||||
Log.e("austin_debug", action+": " + ex); |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
protected void onPostExecute(Void result) { |
|
||||
if (ok == true) { |
|
||||
onRefresh(); |
|
||||
} |
|
||||
else Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
class SeenAction extends AsyncTask<Void, Void, Void> { |
|
||||
protected Void doInBackground(Void... lmao) { |
|
||||
try { |
|
||||
final HttpURLConnection urlConnection = |
|
||||
(HttpURLConnection) new URL("https://www.instagram.com/web/activity/mark_checked/").openConnection(); |
|
||||
urlConnection.setRequestMethod("POST"); |
|
||||
urlConnection.setUseCaches(false); |
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT); |
|
||||
urlConnection.setRequestProperty("x-csrftoken", |
|
||||
Utils.settingsHelper.getString(Constants.COOKIE).split("csrftoken=")[1].split(";")[0]); |
|
||||
final String urlParameters = "timestamp="+(System.currentTimeMillis()/1000); |
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |
|
||||
urlConnection.setRequestProperty("Content-Length", "" + |
|
||||
urlParameters.getBytes().length); |
|
||||
urlConnection.setDoOutput(true); |
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream()); |
|
||||
wr.writeBytes(urlParameters); |
|
||||
wr.flush(); |
|
||||
wr.close(); |
|
||||
urlConnection.connect(); |
|
||||
} catch (Throwable ex) { |
|
||||
Log.e("austin_debug", "seen: " + ex); |
|
||||
} |
|
||||
return null; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,91 +1,55 @@ |
|||||
package awais.instagrabber.adapters; |
package awais.instagrabber.adapters; |
||||
|
|
||||
import android.content.Context; |
|
||||
import android.view.LayoutInflater; |
import android.view.LayoutInflater; |
||||
import android.view.View; |
|
||||
import android.view.ViewGroup; |
import android.view.ViewGroup; |
||||
|
|
||||
import androidx.annotation.NonNull; |
import androidx.annotation.NonNull; |
||||
import androidx.recyclerview.widget.RecyclerView; |
|
||||
|
import androidx.recyclerview.widget.DiffUtil; |
||||
|
import androidx.recyclerview.widget.ListAdapter; |
||||
|
|
||||
import com.bumptech.glide.Glide; |
|
||||
import com.bumptech.glide.RequestManager; |
|
||||
import com.bumptech.glide.request.RequestOptions; |
|
||||
|
|
||||
import awais.instagrabber.R; |
|
||||
import awais.instagrabber.adapters.viewholder.NotificationViewHolder; |
import awais.instagrabber.adapters.viewholder.NotificationViewHolder; |
||||
|
import awais.instagrabber.databinding.ItemNotificationBinding; |
||||
import awais.instagrabber.interfaces.MentionClickListener; |
import awais.instagrabber.interfaces.MentionClickListener; |
||||
import awais.instagrabber.models.NotificationModel; |
import awais.instagrabber.models.NotificationModel; |
||||
import awais.instagrabber.models.enums.NotificationType; |
|
||||
|
|
||||
public final class NotificationsAdapter extends RecyclerView.Adapter<NotificationViewHolder> { |
|
||||
private final View.OnClickListener onClickListener; |
|
||||
|
public final class NotificationsAdapter extends ListAdapter<NotificationModel, NotificationViewHolder> { |
||||
|
private final OnNotificationClickListener notificationClickListener; |
||||
private final MentionClickListener mentionClickListener; |
private final MentionClickListener mentionClickListener; |
||||
private final NotificationModel[] notificationModels; |
|
||||
private LayoutInflater layoutInflater; |
|
||||
|
|
||||
public NotificationsAdapter(final NotificationModel[] notificationModels, final View.OnClickListener onClickListener, |
|
||||
|
private static final DiffUtil.ItemCallback<NotificationModel> DIFF_CALLBACK = new DiffUtil.ItemCallback<NotificationModel>() { |
||||
|
@Override |
||||
|
public boolean areItemsTheSame(@NonNull final NotificationModel oldItem, @NonNull final NotificationModel newItem) { |
||||
|
return oldItem.getId().equals(newItem.getId()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean areContentsTheSame(@NonNull final NotificationModel oldItem, @NonNull final NotificationModel newItem) { |
||||
|
return oldItem.getId().equals(newItem.getId()); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
public NotificationsAdapter(final OnNotificationClickListener notificationClickListener, |
||||
final MentionClickListener mentionClickListener) { |
final MentionClickListener mentionClickListener) { |
||||
this.notificationModels = notificationModels; |
|
||||
this.onClickListener = onClickListener; |
|
||||
|
super(DIFF_CALLBACK); |
||||
|
this.notificationClickListener = notificationClickListener; |
||||
this.mentionClickListener = mentionClickListener; |
this.mentionClickListener = mentionClickListener; |
||||
} |
} |
||||
|
|
||||
@NonNull |
@NonNull |
||||
@Override |
@Override |
||||
public NotificationViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) { |
public NotificationViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) { |
||||
final Context context = parent.getContext(); |
|
||||
if (layoutInflater == null) layoutInflater = LayoutInflater.from(context); |
|
||||
return new NotificationViewHolder(layoutInflater.inflate(R.layout.item_notification, |
|
||||
parent, false), onClickListener, mentionClickListener); |
|
||||
|
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); |
||||
|
final ItemNotificationBinding binding = ItemNotificationBinding.inflate(layoutInflater, parent, false); |
||||
|
return new NotificationViewHolder(binding); |
||||
} |
} |
||||
|
|
||||
@Override |
@Override |
||||
public void onBindViewHolder(@NonNull final NotificationViewHolder holder, final int position) { |
public void onBindViewHolder(@NonNull final NotificationViewHolder holder, final int position) { |
||||
final NotificationModel notificationModel = notificationModels[position]; |
|
||||
if (notificationModel != null) { |
|
||||
holder.setNotificationModel(notificationModel); |
|
||||
|
|
||||
int text = -1; |
|
||||
CharSequence subtext = null; |
|
||||
switch (notificationModel.getType()) { |
|
||||
case LIKE: |
|
||||
text = R.string.liked_notif; |
|
||||
break; |
|
||||
case COMMENT: |
|
||||
text = R.string.comment_notif; |
|
||||
subtext = notificationModel.getText(); |
|
||||
break; |
|
||||
case MENTION: |
|
||||
text = R.string.mention_notif; |
|
||||
subtext = notificationModel.getText(); |
|
||||
break; |
|
||||
case FOLLOW: |
|
||||
text = R.string.follow_notif; |
|
||||
break; |
|
||||
case REQUEST: |
|
||||
text = R.string.request_notif; |
|
||||
subtext = notificationModel.getText(); |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
holder.setCommment(text); |
|
||||
holder.setSubCommment(subtext); |
|
||||
if (notificationModel.getType() != NotificationType.REQUEST) |
|
||||
holder.setDate(notificationModel.getDateTime()); |
|
||||
|
|
||||
holder.setUsername(notificationModel.getUsername()); |
|
||||
|
|
||||
final RequestManager rm = Glide.with(layoutInflater.getContext()) |
|
||||
.applyDefaultRequestOptions(new RequestOptions().skipMemoryCache(true)); |
|
||||
|
|
||||
rm.load(notificationModel.getProfilePic()).into(holder.getProfilePicView()); |
|
||||
rm.load(notificationModel.getPreviewPic()).into(holder.getPreviewPicView()); |
|
||||
} |
|
||||
|
final NotificationModel notificationModel = getItem(position); |
||||
|
holder.bind(notificationModel, notificationClickListener); |
||||
} |
} |
||||
|
|
||||
@Override |
|
||||
public int getItemCount() { |
|
||||
return notificationModels == null ? 0 : notificationModels.length; |
|
||||
|
public interface OnNotificationClickListener { |
||||
|
void onNotificationClick(final NotificationModel model); |
||||
} |
} |
||||
} |
} |
@ -1,75 +1,68 @@ |
|||||
package awais.instagrabber.adapters.viewholder; |
package awais.instagrabber.adapters.viewholder; |
||||
|
|
||||
import android.text.Spannable; |
import android.text.Spannable; |
||||
|
import android.text.TextUtils; |
||||
import android.view.View; |
import android.view.View; |
||||
import android.widget.ImageView; |
|
||||
import android.widget.TextView; |
import android.widget.TextView; |
||||
|
|
||||
import androidx.annotation.NonNull; |
|
||||
import androidx.recyclerview.widget.RecyclerView; |
import androidx.recyclerview.widget.RecyclerView; |
||||
|
|
||||
import awais.instagrabber.R; |
import awais.instagrabber.R; |
||||
import awais.instagrabber.customviews.RamboTextView; |
|
||||
import awais.instagrabber.interfaces.MentionClickListener; |
|
||||
|
import awais.instagrabber.adapters.NotificationsAdapter.OnNotificationClickListener; |
||||
|
import awais.instagrabber.databinding.ItemNotificationBinding; |
||||
import awais.instagrabber.models.NotificationModel; |
import awais.instagrabber.models.NotificationModel; |
||||
|
import awais.instagrabber.models.enums.NotificationType; |
||||
|
|
||||
public final class NotificationViewHolder extends RecyclerView.ViewHolder { |
public final class NotificationViewHolder extends RecyclerView.ViewHolder { |
||||
private final MentionClickListener mentionClickListener; |
|
||||
private final ImageView ivProfilePic, ivPreviewPic; |
|
||||
private final TextView tvUsername, tvDate, tvComment, tvSubComment; |
|
||||
private final View container, rightContainer; |
|
||||
|
private final ItemNotificationBinding binding; |
||||
|
|
||||
public NotificationViewHolder(@NonNull final View itemView, final View.OnClickListener onClickListener, final MentionClickListener mentionClickListener) { |
|
||||
super(itemView); |
|
||||
|
|
||||
container = itemView.findViewById(R.id.container); |
|
||||
rightContainer = itemView.findViewById(R.id.rightContainer); |
|
||||
if (onClickListener != null) container.setOnClickListener(onClickListener); |
|
||||
|
|
||||
this.mentionClickListener = mentionClickListener; |
|
||||
|
|
||||
ivProfilePic = itemView.findViewById(R.id.ivProfilePic); |
|
||||
ivPreviewPic = itemView.findViewById(R.id.ivPreviewPic); |
|
||||
tvUsername = itemView.findViewById(R.id.tvUsername); |
|
||||
tvDate = itemView.findViewById(R.id.tvDate); |
|
||||
tvComment = itemView.findViewById(R.id.tvComment); |
|
||||
tvSubComment = itemView.findViewById(R.id.tvSubComment); |
|
||||
|
|
||||
tvUsername.setSelected(true); |
|
||||
tvDate.setSelected(true); |
|
||||
|
public NotificationViewHolder(final ItemNotificationBinding binding) { |
||||
|
super(binding.getRoot()); |
||||
|
this.binding = binding; |
||||
} |
} |
||||
|
|
||||
public final ImageView getProfilePicView() { |
|
||||
return ivProfilePic; |
|
||||
} |
|
||||
|
|
||||
public final ImageView getPreviewPicView() { |
|
||||
return ivPreviewPic; |
|
||||
} |
|
||||
|
|
||||
public final void setNotificationModel(final NotificationModel notificationModel) { |
|
||||
if (container != null) container.setTag(notificationModel); |
|
||||
if (rightContainer != null) rightContainer.setTag(notificationModel); |
|
||||
} |
|
||||
|
|
||||
public final void setUsername(final String username) { |
|
||||
if (tvUsername != null) tvUsername.setText(username); |
|
||||
} |
|
||||
|
|
||||
public final void setDate(final String date) { |
|
||||
if (tvDate != null) tvDate.setText(date); |
|
||||
} |
|
||||
|
|
||||
public final void setCommment(final int commment) { |
|
||||
if (tvComment != null) { |
|
||||
tvComment.setText(commment); |
|
||||
|
public void bind(final NotificationModel model, |
||||
|
final OnNotificationClickListener notificationClickListener) { |
||||
|
if (model == null) return; |
||||
|
itemView.setOnClickListener(v -> { |
||||
|
if (notificationClickListener == null) return; |
||||
|
notificationClickListener.onNotificationClick(model); |
||||
|
}); |
||||
|
int text = -1; |
||||
|
CharSequence subtext = null; |
||||
|
switch (model.getType()) { |
||||
|
case LIKE: |
||||
|
text = R.string.liked_notif; |
||||
|
break; |
||||
|
case COMMENT: |
||||
|
text = R.string.comment_notif; |
||||
|
subtext = model.getText(); |
||||
|
break; |
||||
|
case MENTION: |
||||
|
text = R.string.mention_notif; |
||||
|
subtext = model.getText(); |
||||
|
break; |
||||
|
case FOLLOW: |
||||
|
text = R.string.follow_notif; |
||||
|
break; |
||||
|
case REQUEST: |
||||
|
text = R.string.request_notif; |
||||
|
subtext = model.getText(); |
||||
|
break; |
||||
} |
} |
||||
} |
|
||||
|
|
||||
public final void setSubCommment(final CharSequence commment) { |
|
||||
if (tvSubComment != null) { |
|
||||
tvSubComment.setText(commment, commment instanceof Spannable ? TextView.BufferType.SPANNABLE : TextView.BufferType.NORMAL); |
|
||||
((RamboTextView) tvSubComment).setMentionClickListener(mentionClickListener); |
|
||||
|
binding.tvUsername.setText(model.getUsername()); |
||||
|
binding.tvComment.setText(text); |
||||
|
binding.tvSubComment.setText(subtext, subtext instanceof Spannable ? TextView.BufferType.SPANNABLE : TextView.BufferType.NORMAL); |
||||
|
// binding.tvSubComment.setMentionClickListener(mentionClickListener); |
||||
|
if (model.getType() != NotificationType.REQUEST) { |
||||
|
binding.tvDate.setText(model.getDateTime()); |
||||
|
} |
||||
|
binding.ivProfilePic.setImageURI(model.getProfilePic()); |
||||
|
if (TextUtils.isEmpty(model.getPreviewPic())) { |
||||
|
binding.ivPreviewPic.setVisibility(View.GONE); |
||||
|
} else { |
||||
|
binding.ivPreviewPic.setVisibility(View.VISIBLE); |
||||
|
binding.ivPreviewPic.setImageURI(model.getPreviewPic()); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
@ -0,0 +1,215 @@ |
|||||
|
package awais.instagrabber.fragments; |
||||
|
|
||||
|
import android.content.DialogInterface; |
||||
|
import android.os.AsyncTask; |
||||
|
import android.os.Bundle; |
||||
|
import android.text.SpannableString; |
||||
|
import android.text.Spanned; |
||||
|
import android.text.style.RelativeSizeSpan; |
||||
|
import android.util.Log; |
||||
|
import android.view.LayoutInflater; |
||||
|
import android.view.View; |
||||
|
import android.view.ViewGroup; |
||||
|
import android.widget.Toast; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.annotation.Nullable; |
||||
|
import androidx.appcompat.app.AlertDialog; |
||||
|
import androidx.fragment.app.Fragment; |
||||
|
import androidx.lifecycle.ViewModelProvider; |
||||
|
import androidx.navigation.NavDirections; |
||||
|
import androidx.navigation.fragment.NavHostFragment; |
||||
|
import androidx.recyclerview.widget.LinearLayoutManager; |
||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; |
||||
|
|
||||
|
import awais.instagrabber.R; |
||||
|
import awais.instagrabber.adapters.NotificationsAdapter; |
||||
|
import awais.instagrabber.adapters.NotificationsAdapter.OnNotificationClickListener; |
||||
|
import awais.instagrabber.asyncs.NotificationsFetcher; |
||||
|
import awais.instagrabber.databinding.FragmentNotificationsViewerBinding; |
||||
|
import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections; |
||||
|
import awais.instagrabber.interfaces.MentionClickListener; |
||||
|
import awais.instagrabber.models.enums.NotificationType; |
||||
|
import awais.instagrabber.repositories.responses.FriendshipRepoChangeRootResponse; |
||||
|
import awais.instagrabber.services.FriendshipService; |
||||
|
import awais.instagrabber.services.NewsService; |
||||
|
import awais.instagrabber.services.ServiceCallback; |
||||
|
import awais.instagrabber.utils.Constants; |
||||
|
import awais.instagrabber.utils.CookieUtils; |
||||
|
import awais.instagrabber.utils.TextUtils; |
||||
|
import awais.instagrabber.utils.Utils; |
||||
|
import awais.instagrabber.viewmodels.NotificationViewModel; |
||||
|
|
||||
|
import static awais.instagrabber.utils.Utils.notificationManager; |
||||
|
|
||||
|
public final class NotificationsViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { |
||||
|
private static final String TAG = "NotificationsViewer"; |
||||
|
|
||||
|
private FragmentNotificationsViewerBinding binding; |
||||
|
private SwipeRefreshLayout root; |
||||
|
private boolean shouldRefresh = true; |
||||
|
private NotificationViewModel notificationViewModel; |
||||
|
private FriendshipService friendshipService; |
||||
|
private String userId; |
||||
|
private String csrfToken; |
||||
|
private NewsService newsService; |
||||
|
|
||||
|
private final OnNotificationClickListener clickListener = model -> { |
||||
|
if (model == null) return; |
||||
|
final String username = model.getUsername(); |
||||
|
final SpannableString title = new SpannableString(username + (TextUtils.isEmpty(model.getText()) ? "" : (":\n" + model.getText()))); |
||||
|
title.setSpan(new RelativeSizeSpan(1.23f), 0, username.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); |
||||
|
|
||||
|
String[] commentDialogList; |
||||
|
if (model.getShortCode() != null) { |
||||
|
commentDialogList = new String[]{ |
||||
|
getString(R.string.open_profile), |
||||
|
getString(R.string.view_post) |
||||
|
}; |
||||
|
} else if (model.getType() == NotificationType.REQUEST) { |
||||
|
commentDialogList = new String[]{ |
||||
|
getString(R.string.open_profile), |
||||
|
getString(R.string.request_approve), |
||||
|
getString(R.string.request_reject) |
||||
|
}; |
||||
|
} else { |
||||
|
commentDialogList = new String[]{getString(R.string.open_profile)}; |
||||
|
} |
||||
|
if (getContext() == null) return; |
||||
|
final DialogInterface.OnClickListener profileDialogListener = (dialog, which) -> { |
||||
|
switch (which) { |
||||
|
case 0: |
||||
|
openProfile(model.getUsername()); |
||||
|
break; |
||||
|
case 1: |
||||
|
if (model.getType() == NotificationType.REQUEST) { |
||||
|
friendshipService.approve(userId, model.getUserId(), csrfToken, new ServiceCallback<FriendshipRepoChangeRootResponse>() { |
||||
|
@Override |
||||
|
public void onSuccess(final FriendshipRepoChangeRootResponse result) { |
||||
|
// Log.d(TAG, "onSuccess: " + result); |
||||
|
if (result.getStatus().equals("ok")) { |
||||
|
onRefresh(); |
||||
|
return; |
||||
|
} |
||||
|
Log.e(TAG, "approve: status was not ok!"); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onFailure(final Throwable t) { |
||||
|
Log.e(TAG, "approve: onFailure: ", t); |
||||
|
} |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
final NavDirections action = MorePreferencesFragmentDirections |
||||
|
.actionGlobalPostViewFragment(0, new String[]{model.getShortCode()}, false); |
||||
|
NavHostFragment.findNavController(this).navigate(action); |
||||
|
break; |
||||
|
case 2: |
||||
|
friendshipService.ignore(userId, model.getUserId(), csrfToken, new ServiceCallback<FriendshipRepoChangeRootResponse>() { |
||||
|
@Override |
||||
|
public void onSuccess(final FriendshipRepoChangeRootResponse result) { |
||||
|
// Log.d(TAG, "onSuccess: " + result); |
||||
|
if (result.getStatus().equals("ok")) { |
||||
|
onRefresh(); |
||||
|
return; |
||||
|
} |
||||
|
Log.e(TAG, "ignore: status was not ok!"); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onFailure(final Throwable t) { |
||||
|
Log.e(TAG, "ignore: onFailure: ", t); |
||||
|
} |
||||
|
}); |
||||
|
break; |
||||
|
} |
||||
|
}; |
||||
|
new AlertDialog.Builder(getContext()) |
||||
|
.setTitle(title) |
||||
|
.setItems(commentDialogList, profileDialogListener) |
||||
|
.setNegativeButton(R.string.cancel, null) |
||||
|
.show(); |
||||
|
}; |
||||
|
private final MentionClickListener mentionClickListener = (view, text, isHashtag, isLocation) -> { |
||||
|
if (getContext() == null) return; |
||||
|
new AlertDialog.Builder(getContext()) |
||||
|
.setTitle(text) |
||||
|
.setMessage(isHashtag ? R.string.comment_view_mention_hash_search |
||||
|
: R.string.comment_view_mention_user_search) |
||||
|
.setNegativeButton(R.string.cancel, null) |
||||
|
.setPositiveButton(R.string.ok, (dialog, which) -> openProfile(text)) |
||||
|
.show(); |
||||
|
}; |
||||
|
|
||||
|
@Override |
||||
|
public void onCreate(@Nullable final Bundle savedInstanceState) { |
||||
|
super.onCreate(savedInstanceState); |
||||
|
notificationManager.cancel(Constants.ACTIVITY_NOTIFICATION_ID); |
||||
|
final String cookie = Utils.settingsHelper.getString(Constants.COOKIE); |
||||
|
if (TextUtils.isEmpty(cookie)) { |
||||
|
Toast.makeText(getContext(), R.string.activity_notloggedin, Toast.LENGTH_SHORT).show(); |
||||
|
} |
||||
|
friendshipService = FriendshipService.getInstance(); |
||||
|
newsService = NewsService.getInstance(); |
||||
|
userId = CookieUtils.getUserIdFromCookie(cookie); |
||||
|
csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); |
||||
|
} |
||||
|
|
||||
|
@NonNull |
||||
|
@Override |
||||
|
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { |
||||
|
if (root != null) { |
||||
|
shouldRefresh = false; |
||||
|
return root; |
||||
|
} |
||||
|
binding = FragmentNotificationsViewerBinding.inflate(getLayoutInflater()); |
||||
|
root = binding.getRoot(); |
||||
|
return root; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { |
||||
|
if (!shouldRefresh) return; |
||||
|
init(); |
||||
|
shouldRefresh = false; |
||||
|
} |
||||
|
|
||||
|
private void init() { |
||||
|
binding.swipeRefreshLayout.setOnRefreshListener(this); |
||||
|
notificationViewModel = new ViewModelProvider(this).get(NotificationViewModel.class); |
||||
|
final NotificationsAdapter adapter = new NotificationsAdapter(clickListener, mentionClickListener); |
||||
|
binding.rvComments.setLayoutManager(new LinearLayoutManager(getContext())); |
||||
|
binding.rvComments.setAdapter(adapter); |
||||
|
notificationViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList); |
||||
|
onRefresh(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onRefresh() { |
||||
|
binding.swipeRefreshLayout.setRefreshing(true); |
||||
|
new NotificationsFetcher(notificationModels -> { |
||||
|
binding.swipeRefreshLayout.setRefreshing(false); |
||||
|
notificationViewModel.getList().postValue(notificationModels); |
||||
|
final String timestamp = String.valueOf(System.currentTimeMillis() / 1000); |
||||
|
newsService.markChecked(timestamp, csrfToken, new ServiceCallback<Boolean>() { |
||||
|
@Override |
||||
|
public void onSuccess(@NonNull final Boolean result) { |
||||
|
// Log.d(TAG, "onResponse: body: " + result); |
||||
|
if (!result) Log.e(TAG, "onSuccess: Error marking activity checked, response is false"); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onFailure(final Throwable t) { |
||||
|
Log.e(TAG, "onFailure: Error marking activity checked", t); |
||||
|
} |
||||
|
}); |
||||
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
||||
|
} |
||||
|
|
||||
|
private void openProfile(final String username) { |
||||
|
final NavDirections action = MorePreferencesFragmentDirections |
||||
|
.actionGlobalProfileFragment("@" + username); |
||||
|
NavHostFragment.findNavController(this).navigate(action); |
||||
|
} |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
package awais.instagrabber.repositories; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
|
||||
|
import awais.instagrabber.utils.Constants; |
||||
|
import retrofit2.Call; |
||||
|
import retrofit2.http.FieldMap; |
||||
|
import retrofit2.http.FormUrlEncoded; |
||||
|
import retrofit2.http.Header; |
||||
|
import retrofit2.http.Headers; |
||||
|
import retrofit2.http.POST; |
||||
|
|
||||
|
public interface NewsRepository { |
||||
|
|
||||
|
Call<String> inbox(); |
||||
|
|
||||
|
@FormUrlEncoded |
||||
|
@Headers("User-Agent: " + Constants.USER_AGENT) |
||||
|
@POST("https://www.instagram.com/web/activity/mark_checked/") |
||||
|
Call<String> markChecked(@Header("x-csrftoken") String csrfToken, @FieldMap Map<String, String> map); |
||||
|
} |
@ -0,0 +1,69 @@ |
|||||
|
package awais.instagrabber.services; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
|
||||
|
import org.json.JSONException; |
||||
|
import org.json.JSONObject; |
||||
|
|
||||
|
import java.util.HashMap; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
import awais.instagrabber.repositories.NewsRepository; |
||||
|
import retrofit2.Call; |
||||
|
import retrofit2.Callback; |
||||
|
import retrofit2.Response; |
||||
|
import retrofit2.Retrofit; |
||||
|
|
||||
|
public class NewsService extends BaseService { |
||||
|
private static final String TAG = "NewsService"; |
||||
|
|
||||
|
private final NewsRepository repository; |
||||
|
|
||||
|
private static NewsService instance; |
||||
|
|
||||
|
private NewsService() { |
||||
|
final Retrofit retrofit = getRetrofitBuilder() |
||||
|
.baseUrl("https://i.instagram.com") |
||||
|
.build(); |
||||
|
repository = retrofit.create(NewsRepository.class); |
||||
|
} |
||||
|
|
||||
|
public static NewsService getInstance() { |
||||
|
if (instance == null) { |
||||
|
instance = new NewsService(); |
||||
|
} |
||||
|
return instance; |
||||
|
} |
||||
|
|
||||
|
public void markChecked(final String timestamp, |
||||
|
final String csrfToken, |
||||
|
final ServiceCallback<Boolean> callback) { |
||||
|
final Map<String, String> map = new HashMap<>(); |
||||
|
map.put("timestamp", timestamp); |
||||
|
final Call<String> request = repository.markChecked(csrfToken, map); |
||||
|
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(false); |
||||
|
return; |
||||
|
} |
||||
|
try { |
||||
|
final JSONObject jsonObject = new JSONObject(body); |
||||
|
final String status = jsonObject.optString("status"); |
||||
|
callback.onSuccess(status.equals("ok")); |
||||
|
|
||||
|
} 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); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
package awais.instagrabber.viewmodels; |
||||
|
|
||||
|
import androidx.lifecycle.MutableLiveData; |
||||
|
import androidx.lifecycle.ViewModel; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
import awais.instagrabber.models.NotificationModel; |
||||
|
|
||||
|
public class NotificationViewModel extends ViewModel { |
||||
|
private MutableLiveData<List<NotificationModel>> list; |
||||
|
|
||||
|
public MutableLiveData<List<NotificationModel>> getList() { |
||||
|
if (list == null) { |
||||
|
list = new MutableLiveData<>(); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
} |
@ -1,30 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
|
||||
xmlns:tools="http://schemas.android.com/tools" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="match_parent" |
|
||||
android:orientation="vertical" |
|
||||
tools:context=".activities.NotificationsViewer"> |
|
||||
|
|
||||
<include |
|
||||
android:id="@+id/toolbar" |
|
||||
layout="@layout/layout_include_toolbar" /> |
|
||||
|
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout |
|
||||
android:id="@+id/swipeRefreshLayout" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="match_parent"> |
|
||||
<androidx.recyclerview.widget.RecyclerView |
|
||||
android:id="@+id/rvComments" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="match_parent" |
|
||||
android:clipToPadding="false" |
|
||||
android:paddingStart="8dp" |
|
||||
android:paddingLeft="8dp" |
|
||||
android:paddingEnd="8dp" |
|
||||
android:paddingRight="8dp" |
|
||||
app:layoutManager="LinearLayoutManager" |
|
||||
tools:listitem="@layout/item_notification" /> |
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> |
|
||||
</LinearLayout> |
|
@ -0,0 +1,15 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||
|
android:id="@+id/swipeRefreshLayout" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="match_parent" |
||||
|
tools:context=".fragments.NotificationsViewerFragment"> |
||||
|
|
||||
|
<androidx.recyclerview.widget.RecyclerView |
||||
|
android:id="@+id/rvComments" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="match_parent" |
||||
|
android:clipToPadding="false" |
||||
|
tools:listitem="@layout/item_notification" /> |
||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> |
@ -1,19 +1,192 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|
||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
xmlns:tools="http://schemas.android.com/tools" |
xmlns:tools="http://schemas.android.com/tools" |
||||
android:layout_width="match_parent" |
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
android:layout_height="wrap_content" |
||||
android:orientation="vertical" |
|
||||
tools:viewBindingIgnore="true"> |
|
||||
|
|
||||
<include |
|
||||
android:id="@+id/container" |
|
||||
layout="@layout/layout_include_notif_item" /> |
|
||||
|
|
||||
<View |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="1dp" |
|
||||
android:layout_gravity="bottom" |
|
||||
android:layout_marginBottom="4dp" |
|
||||
android:background="#80888888" /> |
|
||||
</LinearLayout> |
|
||||
|
android:background="?android:selectableItemBackground" |
||||
|
android:baselineAligned="false" |
||||
|
android:padding="8dp"> |
||||
|
|
||||
|
<com.facebook.drawee.view.SimpleDraweeView |
||||
|
android:id="@+id/ivProfilePic" |
||||
|
android:layout_width="@dimen/notification_image_size" |
||||
|
android:layout_height="@dimen/notification_image_size" |
||||
|
android:visibility="visible" |
||||
|
app:actualImageScaleType="centerCrop" |
||||
|
app:layout_constraintEnd_toStartOf="@id/barrier" |
||||
|
app:layout_constraintStart_toStartOf="parent" |
||||
|
app:layout_constraintTop_toTopOf="parent" |
||||
|
app:roundAsCircle="true" |
||||
|
tools:placeholderImage="@mipmap/ic_launcher" /> |
||||
|
|
||||
|
|
||||
|
<!--<com.facebook.drawee.view.SimpleDraweeView--> |
||||
|
<!-- android:id="@+id/multi_pic1"--> |
||||
|
<!-- android:layout_width="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- android:layout_height="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- app:actualImageScaleType="centerCrop"--> |
||||
|
<!-- app:layout_constraintBottom_toBottomOf="parent"--> |
||||
|
<!-- app:layout_constraintStart_toStartOf="parent"--> |
||||
|
<!-- app:layout_constraintTop_toTopOf="parent"--> |
||||
|
<!-- app:placeholderImage="@mipmap/ic_launcher" />--> |
||||
|
|
||||
|
<!--<com.facebook.drawee.view.SimpleDraweeView--> |
||||
|
<!-- android:id="@+id/multi_pic2"--> |
||||
|
<!-- android:layout_width="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- android:layout_height="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- app:layout_constraintBottom_toTopOf="@+id/multi_pic3"--> |
||||
|
<!-- app:layout_constraintEnd_toStartOf="@id/barrier"--> |
||||
|
<!-- app:layout_constraintStart_toEndOf="@id/multi_pic1"--> |
||||
|
<!-- app:layout_constraintTop_toTopOf="parent"--> |
||||
|
<!-- app:placeholderImage="@mipmap/ic_launcher" />--> |
||||
|
|
||||
|
<!--<com.facebook.drawee.view.SimpleDraweeView--> |
||||
|
<!-- android:id="@+id/multi_pic3"--> |
||||
|
<!-- android:layout_width="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- android:layout_height="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- app:layout_constraintBottom_toBottomOf="parent"--> |
||||
|
<!-- app:layout_constraintEnd_toStartOf="@id/barrier"--> |
||||
|
<!-- app:layout_constraintStart_toEndOf="@id/multi_pic1"--> |
||||
|
<!-- app:layout_constraintTop_toBottomOf="@+id/multi_pic2"--> |
||||
|
<!-- app:placeholderImage="@mipmap/ic_launcher" />--> |
||||
|
|
||||
|
<androidx.constraintlayout.widget.Barrier |
||||
|
android:id="@+id/barrier" |
||||
|
android:layout_width="wrap_content" |
||||
|
android:layout_height="wrap_content" |
||||
|
app:barrierDirection="end" |
||||
|
app:constraint_referenced_ids="ivProfilePic" /> |
||||
|
|
||||
|
<androidx.appcompat.widget.AppCompatTextView |
||||
|
android:id="@+id/tvUsername" |
||||
|
android:layout_width="0dp" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:ellipsize="marquee" |
||||
|
android:paddingStart="16dp" |
||||
|
android:paddingLeft="16dp" |
||||
|
android:paddingEnd="16dp" |
||||
|
android:paddingRight="16dp" |
||||
|
android:singleLine="true" |
||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium" |
||||
|
android:textStyle="bold" |
||||
|
app:layout_constraintBottom_toTopOf="@id/tvComment" |
||||
|
app:layout_constraintEnd_toStartOf="@id/ivPreviewPic" |
||||
|
app:layout_constraintStart_toStartOf="@id/barrier" |
||||
|
app:layout_constraintTop_toTopOf="parent" |
||||
|
tools:text="username" /> |
||||
|
|
||||
|
<awais.instagrabber.customviews.RamboTextView |
||||
|
android:id="@+id/tvComment" |
||||
|
android:layout_width="0dp" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:linksClickable="true" |
||||
|
android:paddingStart="16dp" |
||||
|
android:paddingLeft="16dp" |
||||
|
android:paddingEnd="16dp" |
||||
|
android:paddingRight="16dp" |
||||
|
android:textAppearance="@style/TextAppearance.AppCompat" |
||||
|
android:textStyle="italic" |
||||
|
app:layout_constraintBottom_toTopOf="@id/tvSubComment" |
||||
|
app:layout_constraintEnd_toStartOf="@id/ivPreviewPic" |
||||
|
app:layout_constraintStart_toStartOf="@id/tvUsername" |
||||
|
app:layout_constraintTop_toBottomOf="@id/tvUsername" |
||||
|
tools:text="comment comment comment comment comment comment comment comment comment comment comment comment comment " /> |
||||
|
|
||||
|
<awais.instagrabber.customviews.RamboTextView |
||||
|
android:id="@+id/tvSubComment" |
||||
|
android:layout_width="0dp" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:autoLink="web|email" |
||||
|
android:ellipsize="end" |
||||
|
android:linksClickable="true" |
||||
|
android:paddingStart="16dp" |
||||
|
android:paddingLeft="16dp" |
||||
|
android:paddingEnd="8dp" |
||||
|
android:paddingRight="8dp" |
||||
|
android:textAppearance="@style/TextAppearance.AppCompat" |
||||
|
app:layout_constraintEnd_toStartOf="@id/tvDate" |
||||
|
app:layout_constraintStart_toStartOf="@id/tvUsername" |
||||
|
app:layout_constraintTop_toBottomOf="@id/tvComment" |
||||
|
tools:text="sub-comment" /> |
||||
|
|
||||
|
<androidx.appcompat.widget.AppCompatTextView |
||||
|
android:id="@+id/tvDate" |
||||
|
android:layout_width="wrap_content" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:ellipsize="marquee" |
||||
|
android:gravity="end" |
||||
|
android:paddingStart="8dp" |
||||
|
android:paddingLeft="8dp" |
||||
|
android:paddingEnd="16dp" |
||||
|
android:paddingRight="16dp" |
||||
|
android:singleLine="true" |
||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Caption" |
||||
|
android:textStyle="italic" |
||||
|
app:layout_constraintBottom_toBottomOf="parent" |
||||
|
app:layout_constraintEnd_toStartOf="@id/ivPreviewPic" |
||||
|
app:layout_constraintStart_toEndOf="@id/tvSubComment" |
||||
|
app:layout_constraintTop_toBottomOf="@id/tvComment" |
||||
|
tools:text="date" /> |
||||
|
|
||||
|
<androidx.constraintlayout.widget.Barrier |
||||
|
android:id="@+id/preview_barrier" |
||||
|
android:layout_width="wrap_content" |
||||
|
android:layout_height="wrap_content" |
||||
|
app:barrierDirection="start" |
||||
|
app:constraint_referenced_ids="ivPreviewPic" /> |
||||
|
|
||||
|
<com.facebook.drawee.view.SimpleDraweeView |
||||
|
android:id="@+id/ivPreviewPic" |
||||
|
android:layout_width="@dimen/notification_image_size" |
||||
|
android:layout_height="@dimen/notification_image_size" |
||||
|
android:visibility="gone" |
||||
|
app:layout_constraintEnd_toEndOf="parent" |
||||
|
app:layout_constraintStart_toEndOf="@id/preview_barrier" |
||||
|
app:layout_constraintTop_toTopOf="parent" |
||||
|
tools:placeholderImage="@mipmap/ic_launcher" |
||||
|
tools:visibility="visible" /> |
||||
|
|
||||
|
<!--<com.facebook.drawee.view.SimpleDraweeView--> |
||||
|
<!-- android:id="@+id/preview_pic1"--> |
||||
|
<!-- android:layout_width="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- android:layout_height="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- app:layout_constraintBottom_toBottomOf="parent"--> |
||||
|
<!-- app:layout_constraintEnd_toStartOf="@id/preview_pic2"--> |
||||
|
<!-- app:layout_constraintStart_toEndOf="@id/preview_barrier"--> |
||||
|
<!-- app:layout_constraintTop_toTopOf="parent"--> |
||||
|
<!-- app:placeholderImage="@mipmap/ic_launcher" />--> |
||||
|
|
||||
|
<!--<com.facebook.drawee.view.SimpleDraweeView--> |
||||
|
<!-- android:id="@+id/preview_pic2"--> |
||||
|
<!-- android:layout_width="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- android:layout_height="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- app:layout_constraintEnd_toEndOf="parent"--> |
||||
|
<!-- app:layout_constraintStart_toEndOf="@id/preview_pic1"--> |
||||
|
<!-- app:layout_constraintTop_toTopOf="parent"--> |
||||
|
<!-- app:placeholderImage="@mipmap/ic_launcher" />--> |
||||
|
|
||||
|
<!--<com.facebook.drawee.view.SimpleDraweeView--> |
||||
|
<!-- android:id="@+id/preview_pic3"--> |
||||
|
<!-- android:layout_width="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- android:layout_height="@dimen/simple_item_picture_size_exact_half"--> |
||||
|
<!-- app:layout_constraintBottom_toBottomOf="parent"--> |
||||
|
<!-- app:layout_constraintEnd_toEndOf="parent"--> |
||||
|
<!-- app:layout_constraintStart_toEndOf="@id/preview_pic1"--> |
||||
|
<!-- app:layout_constraintTop_toBottomOf="@id/preview_pic2"--> |
||||
|
<!-- app:placeholderImage="@mipmap/ic_launcher" />--> |
||||
|
|
||||
|
<!--<androidx.constraintlayout.widget.Group--> |
||||
|
<!-- android:id="@+id/multi_pic_group"--> |
||||
|
<!-- android:layout_width="wrap_content"--> |
||||
|
<!-- android:layout_height="wrap_content"--> |
||||
|
<!-- android:visibility="visible"--> |
||||
|
<!-- app:constraint_referenced_ids="multi_pic1, multi_pic2, multi_pic3" />--> |
||||
|
|
||||
|
<!--<androidx.constraintlayout.widget.Group--> |
||||
|
<!-- android:id="@+id/preview_pic_group"--> |
||||
|
<!-- android:layout_width="wrap_content"--> |
||||
|
<!-- android:layout_height="wrap_content"--> |
||||
|
<!-- android:visibility="gone"--> |
||||
|
<!-- app:constraint_referenced_ids="preview_pic1, preview_pic2, preview_pic3" />--> |
||||
|
</androidx.constraintlayout.widget.ConstraintLayout> |
@ -1,152 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="wrap_content" |
|
||||
android:background="?android:selectableItemBackground" |
|
||||
android:orientation="horizontal" |
|
||||
android:paddingStart="0dp" |
|
||||
android:paddingLeft="0dp" |
|
||||
android:paddingEnd="4dp" |
|
||||
android:paddingRight="4dp"> |
|
||||
|
|
||||
<FrameLayout |
|
||||
android:layout_width="@dimen/simple_item_picture_size" |
|
||||
android:layout_height="@dimen/simple_item_picture_size" |
|
||||
android:gravity="center"> |
|
||||
|
|
||||
<androidx.appcompat.widget.AppCompatImageView |
|
||||
android:id="@+id/ivProfilePic" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="match_parent" /> |
|
||||
|
|
||||
<LinearLayout |
|
||||
android:id="@+id/container" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="match_parent" |
|
||||
android:orientation="horizontal"> |
|
||||
|
|
||||
<androidx.appcompat.widget.AppCompatImageView |
|
||||
android:layout_width="@dimen/simple_item_picture_size_half" |
|
||||
android:layout_height="match_parent" /> |
|
||||
|
|
||||
<LinearLayout |
|
||||
android:layout_width="@dimen/simple_item_picture_size_half" |
|
||||
android:layout_height="match_parent" |
|
||||
android:orientation="vertical"> |
|
||||
|
|
||||
<androidx.appcompat.widget.AppCompatImageView |
|
||||
android:layout_width="@dimen/simple_item_picture_size_half" |
|
||||
android:layout_height="@dimen/simple_item_picture_size_half" /> |
|
||||
|
|
||||
<androidx.appcompat.widget.AppCompatImageView |
|
||||
android:layout_width="@dimen/simple_item_picture_size_half" |
|
||||
android:layout_height="@dimen/simple_item_picture_size_half" /> |
|
||||
</LinearLayout> |
|
||||
</LinearLayout> |
|
||||
</FrameLayout> |
|
||||
|
|
||||
<LinearLayout |
|
||||
android:layout_width="0dp" |
|
||||
android:layout_weight="1" |
|
||||
android:layout_height="wrap_content" |
|
||||
android:orientation="vertical"> |
|
||||
|
|
||||
<androidx.appcompat.widget.AppCompatTextView |
|
||||
android:id="@+id/tvUsername" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="wrap_content" |
|
||||
android:layout_gravity="start" |
|
||||
android:layout_weight="1.0" |
|
||||
android:ellipsize="marquee" |
|
||||
android:paddingStart="8dp" |
|
||||
android:paddingLeft="8dp" |
|
||||
android:paddingTop="4dp" |
|
||||
android:paddingEnd="4dp" |
|
||||
android:paddingRight="4dp" |
|
||||
android:singleLine="true" |
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" |
|
||||
android:textColor="?android:textColorPrimary" |
|
||||
android:textStyle="bold" /> |
|
||||
|
|
||||
<LinearLayout |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="wrap_content" |
|
||||
android:orientation="vertical" |
|
||||
android:paddingLeft="8dp" |
|
||||
android:paddingTop="4dp" |
|
||||
android:paddingRight="8dp"> |
|
||||
|
|
||||
<awais.instagrabber.customviews.RamboTextView |
|
||||
android:id="@+id/tvComment" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="wrap_content" |
|
||||
android:layout_gravity="start" |
|
||||
android:ellipsize="end" |
|
||||
android:linksClickable="true" |
|
||||
android:textStyle="italic" |
|
||||
android:textAppearance="@style/TextAppearance.AppCompat" /> |
|
||||
|
|
||||
<awais.instagrabber.customviews.RamboTextView |
|
||||
android:id="@+id/tvSubComment" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="wrap_content" |
|
||||
android:layout_gravity="start" |
|
||||
android:autoLink="web|email" |
|
||||
android:ellipsize="end" |
|
||||
android:linksClickable="true" |
|
||||
android:textAppearance="@style/TextAppearance.AppCompat" /> |
|
||||
</LinearLayout> |
|
||||
|
|
||||
<androidx.appcompat.widget.AppCompatTextView |
|
||||
android:id="@+id/tvDate" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="wrap_content" |
|
||||
android:layout_gravity="start" |
|
||||
android:ellipsize="marquee" |
|
||||
android:gravity="right" |
|
||||
android:paddingStart="4dp" |
|
||||
android:paddingLeft="4dp" |
|
||||
android:paddingTop="4dp" |
|
||||
android:paddingEnd="8dp" |
|
||||
android:paddingRight="8dp" |
|
||||
android:singleLine="true" |
|
||||
android:textStyle="italic" /> |
|
||||
|
|
||||
</LinearLayout> |
|
||||
|
|
||||
<FrameLayout |
|
||||
android:layout_width="@dimen/simple_item_picture_size" |
|
||||
android:layout_height="@dimen/simple_item_picture_size" |
|
||||
android:gravity="center"> |
|
||||
|
|
||||
<androidx.appcompat.widget.AppCompatImageView |
|
||||
android:id="@+id/ivPreviewPic" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="match_parent" /> |
|
||||
|
|
||||
<LinearLayout |
|
||||
android:id="@+id/rightContainer" |
|
||||
android:layout_width="match_parent" |
|
||||
android:layout_height="match_parent" |
|
||||
android:orientation="horizontal"> |
|
||||
|
|
||||
<androidx.appcompat.widget.AppCompatImageView |
|
||||
android:layout_width="@dimen/simple_item_picture_size_half" |
|
||||
android:layout_height="match_parent" /> |
|
||||
|
|
||||
<LinearLayout |
|
||||
android:layout_width="@dimen/simple_item_picture_size_half" |
|
||||
android:layout_height="match_parent" |
|
||||
android:orientation="vertical"> |
|
||||
|
|
||||
<androidx.appcompat.widget.AppCompatImageView |
|
||||
android:layout_width="@dimen/simple_item_picture_size_half" |
|
||||
android:layout_height="@dimen/simple_item_picture_size_half" /> |
|
||||
|
|
||||
<androidx.appcompat.widget.AppCompatImageView |
|
||||
android:layout_width="@dimen/simple_item_picture_size_half" |
|
||||
android:layout_height="@dimen/simple_item_picture_size_half" /> |
|
||||
</LinearLayout> |
|
||||
</LinearLayout> |
|
||||
</FrameLayout> |
|
||||
</LinearLayout> |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue