regular maintenance
1. fix notification can't open post + remove duplicate code 2. optimize bio (long)click mechanism 3. remove the old deprecated RamboTextView and its MentionClickListener
This commit is contained in:
parent
c25864ba60
commit
de86668caf
@ -10,8 +10,8 @@ android {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
|
||||
versionCode 58
|
||||
versionName '19.1.0-a1'
|
||||
versionCode 59
|
||||
versionName '19.1.0-a2'
|
||||
|
||||
multiDexEnabled true
|
||||
|
||||
|
@ -14,13 +14,11 @@ import java.util.List;
|
||||
|
||||
import awais.instagrabber.adapters.viewholder.NotificationViewHolder;
|
||||
import awais.instagrabber.databinding.ItemNotificationBinding;
|
||||
import awais.instagrabber.interfaces.MentionClickListener;
|
||||
import awais.instagrabber.models.NotificationModel;
|
||||
import awais.instagrabber.models.enums.NotificationType;
|
||||
|
||||
public final class NotificationsAdapter extends ListAdapter<NotificationModel, NotificationViewHolder> {
|
||||
private final OnNotificationClickListener notificationClickListener;
|
||||
private final MentionClickListener mentionClickListener;
|
||||
|
||||
private static final DiffUtil.ItemCallback<NotificationModel> DIFF_CALLBACK = new DiffUtil.ItemCallback<NotificationModel>() {
|
||||
@Override
|
||||
@ -34,11 +32,9 @@ public final class NotificationsAdapter extends ListAdapter<NotificationModel, N
|
||||
}
|
||||
};
|
||||
|
||||
public NotificationsAdapter(final OnNotificationClickListener notificationClickListener,
|
||||
final MentionClickListener mentionClickListener) {
|
||||
public NotificationsAdapter(final OnNotificationClickListener notificationClickListener) {
|
||||
super(DIFF_CALLBACK);
|
||||
this.notificationClickListener = notificationClickListener;
|
||||
this.mentionClickListener = mentionClickListener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -32,7 +32,7 @@ public final class NotificationViewHolder extends RecyclerView.ViewHolder {
|
||||
text = R.string.comment_notif;
|
||||
subtext = model.getText();
|
||||
break;
|
||||
case MENTION:
|
||||
case COMMENT_MENTION:
|
||||
text = R.string.mention_notif;
|
||||
subtext = model.getText();
|
||||
break;
|
||||
|
@ -1,205 +0,0 @@
|
||||
package awais.instagrabber.customviews;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.text.Layout;
|
||||
import android.text.Selection;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.BackgroundColorSpan;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.interfaces.MentionClickListener;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
|
||||
@Deprecated
|
||||
public final class RamboTextView extends AppCompatTextView {
|
||||
private static final String TAG = "RamboTextView";
|
||||
private static final int highlightBackgroundSpanKey = R.id.tvComment;
|
||||
private static final RectF touchedLineBounds = new RectF();
|
||||
private ClickableSpan clickableSpanUnderTouchOnActionDown;
|
||||
private MentionClickListener mentionClickListener;
|
||||
private boolean isUrlHighlighted;
|
||||
private boolean isExpanded;
|
||||
private OnLongClickListener longClickListener;
|
||||
|
||||
private final Handler handler = new Handler();
|
||||
private final Runnable longPressRunnable = () -> {
|
||||
if (longClickListener != null) longClickListener.onLongClick(this);
|
||||
};
|
||||
|
||||
public RamboTextView(final Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public RamboTextView(final Context context, final AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public RamboTextView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public void setMentionClickListener(final MentionClickListener mentionClickListener) {
|
||||
this.mentionClickListener = mentionClickListener;
|
||||
}
|
||||
|
||||
// public void setCaptionIsExpandable(final boolean isExpandable) {
|
||||
// this.isExpandable = isExpandable;
|
||||
// }
|
||||
|
||||
// public void setCaptionIsExpanded(final boolean isExpanded) {
|
||||
// this.isExpanded = isExpanded;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void setOnLongClickListener(@Nullable final OnLongClickListener l) {
|
||||
if (l == null) return;
|
||||
this.longClickListener = l;
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouchEvent(final MotionEvent event) {
|
||||
final CharSequence text = getText();
|
||||
if (text instanceof SpannableString || text instanceof SpannableStringBuilder) {
|
||||
final Spannable spanText = (Spannable) text;
|
||||
final ClickableSpan clickableSpanUnderTouch = findClickableSpanUnderTouch(this, spanText, event);
|
||||
|
||||
final int action = event.getAction();
|
||||
|
||||
if (action == MotionEvent.ACTION_DOWN) clickableSpanUnderTouchOnActionDown = clickableSpanUnderTouch;
|
||||
final boolean touchStartedOverAClickableSpan = clickableSpanUnderTouchOnActionDown != null;
|
||||
final boolean isURLSpan = clickableSpanUnderTouch instanceof URLSpan;
|
||||
|
||||
// feed view caption hacks
|
||||
// if (isExpandable && !touchStartedOverAClickableSpan)
|
||||
// return !isExpanded | super.onTouchEvent(event); // short operator, because we want two shits to work
|
||||
|
||||
// final Object tag = getTag();
|
||||
// final FeedModel feedModel = tag instanceof FeedModel ? (FeedModel) tag : null;
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
final int longPressTimeout = ViewConfiguration.getLongPressTimeout();
|
||||
handler.postDelayed(longPressRunnable, longPressTimeout);
|
||||
// if (feedModel != null) feedModel.setMentionClicked(false);
|
||||
if (clickableSpanUnderTouch != null) {
|
||||
highlightUrl(clickableSpanUnderTouch, spanText);
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
case MotionEvent.ACTION_UP:
|
||||
handler.removeCallbacks(longPressRunnable);
|
||||
if (touchStartedOverAClickableSpan && clickableSpanUnderTouch == clickableSpanUnderTouchOnActionDown) {
|
||||
dispatchUrlClick(spanText, clickableSpanUnderTouch);
|
||||
// if (feedModel != null) feedModel.setMentionClicked(true);
|
||||
}
|
||||
cleanupOnTouchUp(spanText);
|
||||
return super.onTouchEvent(event);
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
// handler.removeCallbacks(longPressRunnable);
|
||||
// if (feedModel != null) feedModel.setMentionClicked(false);
|
||||
if (clickableSpanUnderTouch != null) highlightUrl(clickableSpanUnderTouch, spanText);
|
||||
else removeUrlHighlightColor(spanText);
|
||||
return super.onTouchEvent(event);
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
handler.removeCallbacks(longPressRunnable);
|
||||
// if (feedModel != null) feedModel.setMentionClicked(false);
|
||||
cleanupOnTouchUp(spanText);
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
protected void dispatchUrlClick(final Spanned s, final ClickableSpan clickableSpan) {
|
||||
if (mentionClickListener != null) {
|
||||
final int spanStart = s.getSpanStart(clickableSpan);
|
||||
final boolean ishHashtag = s.charAt(spanStart) == '#';
|
||||
|
||||
final int start = ishHashtag || s.charAt(spanStart) != '@' ? spanStart : spanStart + 1;
|
||||
|
||||
CharSequence subSequence = s.subSequence(start, s.getSpanEnd(clickableSpan));
|
||||
|
||||
// for feed ellipsize
|
||||
final int indexOfEllipsize = TextUtils.indexOfChar(subSequence, '…', 0);
|
||||
if (indexOfEllipsize != -1)
|
||||
subSequence = subSequence.subSequence(0, indexOfEllipsize - 1);
|
||||
|
||||
mentionClickListener.onClick(this, subSequence.toString(), ishHashtag, false);
|
||||
}
|
||||
}
|
||||
|
||||
protected void highlightUrl(final ClickableSpan clickableSpan, final Spannable text) {
|
||||
if (!isUrlHighlighted) {
|
||||
isUrlHighlighted = true;
|
||||
|
||||
final int spanStart = text.getSpanStart(clickableSpan);
|
||||
final int spanEnd = text.getSpanEnd(clickableSpan);
|
||||
final BackgroundColorSpan highlightSpan = new BackgroundColorSpan(getHighlightColor());
|
||||
text.setSpan(highlightSpan, spanStart, spanEnd, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
setTag(highlightBackgroundSpanKey, highlightSpan);
|
||||
Selection.setSelection(text, spanStart, spanEnd);
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeUrlHighlightColor(final Spannable text) {
|
||||
if (isUrlHighlighted) {
|
||||
isUrlHighlighted = false;
|
||||
|
||||
final BackgroundColorSpan highlightSpan = (BackgroundColorSpan) getTag(highlightBackgroundSpanKey);
|
||||
text.removeSpan(highlightSpan);
|
||||
|
||||
Selection.removeSelection(text);
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanupOnTouchUp(final Spannable text) {
|
||||
clickableSpanUnderTouchOnActionDown = null;
|
||||
removeUrlHighlightColor(text);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ClickableSpan findClickableSpanUnderTouch(@NonNull final TextView textView,
|
||||
final Spanned text,
|
||||
@NonNull final MotionEvent event) {
|
||||
final int touchX = (int) (event.getX() - textView.getTotalPaddingLeft() + textView.getScrollX());
|
||||
final int touchY = (int) (event.getY() - textView.getTotalPaddingTop() + textView.getScrollY());
|
||||
|
||||
final Layout layout = textView.getLayout();
|
||||
final int touchedLine = layout.getLineForVertical(touchY);
|
||||
final int touchOffset = layout.getOffsetForHorizontal(touchedLine, touchX);
|
||||
|
||||
touchedLineBounds.left = layout.getLineLeft(touchedLine);
|
||||
touchedLineBounds.top = layout.getLineTop(touchedLine);
|
||||
touchedLineBounds.right = layout.getLineWidth(touchedLine) + touchedLineBounds.left;
|
||||
touchedLineBounds.bottom = layout.getLineBottom(touchedLine);
|
||||
|
||||
if (touchedLineBounds.contains(touchX, touchY)) {
|
||||
final Object[] spans = text.getSpans(touchOffset, touchOffset, ClickableSpan.class);
|
||||
for (final Object span : spans)
|
||||
if (span instanceof ClickableSpan) return (ClickableSpan) span;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isCaptionExpanded() {
|
||||
return isExpanded;
|
||||
}
|
||||
}
|
@ -33,7 +33,6 @@ import awais.instagrabber.asyncs.NotificationsFetcher;
|
||||
import awais.instagrabber.databinding.FragmentNotificationsViewerBinding;
|
||||
import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.interfaces.MentionClickListener;
|
||||
import awais.instagrabber.models.NotificationModel;
|
||||
import awais.instagrabber.models.enums.NotificationType;
|
||||
import awais.instagrabber.repositories.requests.StoryViewerOptions;
|
||||
@ -145,33 +144,8 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
||||
}
|
||||
});
|
||||
return;
|
||||
} else if (model.getType() == NotificationType.RESPONDED_STORY) {
|
||||
final NavDirections action = NotificationsViewerFragmentDirections
|
||||
.actionNotificationsViewerFragmentToStoryViewerFragment(StoryViewerOptions.forStory(model.getPostId(),
|
||||
model.getUsername()));
|
||||
NavHostFragment.findNavController(NotificationsViewerFragment.this).navigate(action);
|
||||
return;
|
||||
}
|
||||
final AlertDialog alertDialog = new AlertDialog.Builder(context)
|
||||
.setCancelable(false)
|
||||
.setView(R.layout.dialog_opening_post)
|
||||
.create();
|
||||
alertDialog.show();
|
||||
mediaService.fetch(model.getPostId(), new ServiceCallback<Media>() {
|
||||
@Override
|
||||
public void onSuccess(final Media feedModel) {
|
||||
final PostViewV2Fragment fragment = PostViewV2Fragment
|
||||
.builder(feedModel)
|
||||
.build();
|
||||
fragment.setOnShowListener(dialog1 -> alertDialog.dismiss());
|
||||
fragment.show(getChildFragmentManager(), "post_view");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
clickListener.onPreviewClick(model);
|
||||
break;
|
||||
case 2:
|
||||
friendshipService.ignore(model.getUserId(), new ServiceCallback<FriendshipChangeResponse>() {
|
||||
@ -196,16 +170,6 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
||||
}
|
||||
}
|
||||
};
|
||||
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) {
|
||||
@ -250,7 +214,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
|
||||
CookieUtils.setupCookies(settingsHelper.getString(Constants.COOKIE));
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
notificationViewModel = new ViewModelProvider(this).get(NotificationViewModel.class);
|
||||
final NotificationsAdapter adapter = new NotificationsAdapter(clickListener, mentionClickListener);
|
||||
final NotificationsAdapter adapter = new NotificationsAdapter(clickListener);
|
||||
binding.rvComments.setLayoutManager(new LinearLayoutManager(context));
|
||||
binding.rvComments.setAdapter(adapter);
|
||||
notificationViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
||||
|
@ -710,7 +710,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
.trim()));
|
||||
profileDetailsBinding.mainBiography
|
||||
.addOnURLClickListener(autoLinkItem -> Utils.openURL(getContext(), autoLinkItem.getOriginalText().trim()));
|
||||
profileDetailsBinding.mainBiography.setOnClickListener(v -> {
|
||||
profileDetailsBinding.mainBiography.setOnLongClickListener(v -> {
|
||||
String[] commentDialogList;
|
||||
if (!TextUtils.isEmpty(cookie)) {
|
||||
commentDialogList = new String[]{
|
||||
@ -754,9 +754,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
});
|
||||
profileDetailsBinding.mainBiography.setOnLongClickListener(v -> {
|
||||
Utils.copyText(context, biography);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
package awais.instagrabber.interfaces;
|
||||
|
||||
import awais.instagrabber.customviews.RamboTextView;
|
||||
|
||||
@Deprecated
|
||||
public interface MentionClickListener {
|
||||
void onClick(final RamboTextView view,
|
||||
final String text,
|
||||
final boolean isHashtag,
|
||||
final boolean isLocation);
|
||||
}
|
@ -9,7 +9,7 @@ public enum NotificationType implements Serializable {
|
||||
LIKE("GraphLikeAggregatedStory"),
|
||||
FOLLOW("GraphFollowAggregatedStory"),
|
||||
COMMENT("GraphCommentMediaStory"),
|
||||
MENTION("GraphMentionStory"),
|
||||
COMMENT_MENTION("GraphMentionStory"),
|
||||
TAGGED("GraphUserTaggedStory"),
|
||||
// app story_type
|
||||
COMMENT_LIKE("13"),
|
||||
|
@ -18,8 +18,8 @@ public class UserAgentUtils {
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15"
|
||||
};
|
||||
// use APKpure, assume x86
|
||||
private static final String igVersion = "175.1.0.25.119";
|
||||
private static final String igVersionCode = "273907115";
|
||||
private static final String igVersion = "177.0.0.30.119";
|
||||
private static final String igVersionCode = "276028050";
|
||||
// only pick the ones that has width 1440 for maximum download quality
|
||||
public static final String[] devices = {
|
||||
// https://github.com/dilame/instagram-private-api/blob/master/src/samples/devices.json
|
||||
|
@ -131,7 +131,7 @@ public class NewsService extends BaseService {
|
||||
user.getLong("id"),
|
||||
user.getString("username"),
|
||||
user.getString("profile_pic_url"),
|
||||
data.has("media") ? data.getJSONObject("media").getLong("id") : 0,
|
||||
!data.isNull("media") ? Long.valueOf(data.getJSONObject("media").getString("id").split("_")[0]) : 0,
|
||||
data.has("media") ? data.getJSONObject("media").getString("thumbnail_src") : null,
|
||||
notificationType));
|
||||
}
|
||||
|
@ -45,11 +45,11 @@
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="username" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/tvComment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:linksClickable="true"
|
||||
android:linksClickable="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
@ -62,13 +62,13 @@
|
||||
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
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/tvSubComment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="web|email"
|
||||
android:ellipsize="end"
|
||||
android:linksClickable="true"
|
||||
android:linksClickable="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingEnd="8dp"
|
||||
|
@ -96,16 +96,13 @@
|
||||
app:layout_constraintTop_toBottomOf="@id/locationFullName"
|
||||
tools:text="IN THE MIDDLE OF OUR STREET" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
<awais.instagrabber.customviews.RamboTextViewV2
|
||||
android:id="@+id/locationUrl"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/locationBiography"
|
||||
android:layout_below="@id/mainBiography"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:padding="8dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
@ -113,5 +110,7 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/locationBiography"
|
||||
tools:text="https://austinhuang.me/"
|
||||
tools:textColor="@android:color/holo_blue_dark"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in New Issue
Block a user