mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-26 08:37:29 +00:00
Show tooltip to make user aware of expandable count. Fix FormattedNumberTextView animation.
This commit is contained in:
parent
fb1f3c2cd8
commit
3dde61d91a
@ -169,6 +169,8 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'org.apache.commons:commons-imaging:1.0-alpha2'
|
implementation 'org.apache.commons:commons-imaging:1.0-alpha2'
|
||||||
|
|
||||||
|
implementation 'com.github.skydoves:balloon:1.3.4'
|
||||||
|
|
||||||
implementation 'com.github.ammargitham:AutoLinkTextViewV2:v3.1.0'
|
implementation 'com.github.ammargitham:AutoLinkTextViewV2:v3.1.0'
|
||||||
implementation 'com.github.ammargitham:uCrop:2.3-native-beta-2'
|
implementation 'com.github.ammargitham:uCrop:2.3-native-beta-2'
|
||||||
implementation 'com.github.ammargitham:android-gpuimage:2.1.1-beta4'
|
implementation 'com.github.ammargitham:android-gpuimage:2.1.1-beta4'
|
||||||
|
@ -8,7 +8,10 @@ import android.view.ViewGroup;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.widget.AppCompatTextView;
|
import androidx.appcompat.widget.AppCompatTextView;
|
||||||
|
import androidx.transition.ChangeBounds;
|
||||||
|
import androidx.transition.Transition;
|
||||||
import androidx.transition.TransitionManager;
|
import androidx.transition.TransitionManager;
|
||||||
|
import androidx.transition.TransitionSet;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
@ -17,16 +20,23 @@ import awais.instagrabber.utils.NumberUtils;
|
|||||||
|
|
||||||
public class FormattedNumberTextView extends AppCompatTextView {
|
public class FormattedNumberTextView extends AppCompatTextView {
|
||||||
private static final String TAG = FormattedNumberTextView.class.getSimpleName();
|
private static final String TAG = FormattedNumberTextView.class.getSimpleName();
|
||||||
private static final ChangeText TRANSITION = new ChangeText().setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN);
|
private static final Transition TRANSITION;
|
||||||
|
|
||||||
private long number = Long.MIN_VALUE;
|
private long number = Long.MIN_VALUE;
|
||||||
private boolean showAbbreviation = true;
|
private boolean showAbbreviation = true;
|
||||||
private boolean animateChanges = true;
|
private boolean animateChanges = false;
|
||||||
private boolean toggleOnClick = true;
|
private boolean toggleOnClick = true;
|
||||||
private boolean autoToggleToAbbreviation = true;
|
private boolean autoToggleToAbbreviation = true;
|
||||||
private long autoToggleTimeoutMs = Duration.ofSeconds(2).toMillis();
|
private long autoToggleTimeoutMs = Duration.ofSeconds(2).toMillis();
|
||||||
private boolean initDone = false;
|
private boolean initDone = false;
|
||||||
|
|
||||||
|
static {
|
||||||
|
final TransitionSet transitionSet = new TransitionSet();
|
||||||
|
final ChangeText changeText = new ChangeText().setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN);
|
||||||
|
transitionSet.addTransition(changeText).addTransition(new ChangeBounds());
|
||||||
|
TRANSITION = transitionSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public FormattedNumberTextView(@NonNull final Context context) {
|
public FormattedNumberTextView(@NonNull final Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@ -152,6 +162,4 @@ public class FormattedNumberTextView extends AppCompatTextView {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,20 +9,20 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewPropertyAnimator;
|
import android.view.ViewPropertyAnimator;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.widget.AppCompatTextView;
|
import androidx.appcompat.widget.AppCompatTextView;
|
||||||
|
|
||||||
import awais.instagrabber.utils.AppExecutors;
|
import awais.instagrabber.utils.AppExecutors;
|
||||||
import awais.instagrabber.utils.Utils;
|
import awais.instagrabber.utils.Utils;
|
||||||
import awais.instagrabber.utils.ViewUtils;
|
import awais.instagrabber.utils.ViewUtils;
|
||||||
|
|
||||||
|
|
||||||
public class Tooltip extends AppCompatTextView {
|
public class Tooltip extends AppCompatTextView {
|
||||||
|
|
||||||
private View anchor;
|
private View anchor;
|
||||||
private ViewPropertyAnimator animator;
|
private ViewPropertyAnimator animator;
|
||||||
private boolean showing;
|
private boolean showing;
|
||||||
|
|
||||||
private final AppExecutors appExecutors;
|
private final AppExecutors appExecutors = AppExecutors.getInstance();
|
||||||
private final Runnable dismissRunnable = () -> {
|
private final Runnable dismissRunnable = () -> {
|
||||||
animator = animate().alpha(0).setListener(new AnimatorListenerAdapter() {
|
animator = animate().alpha(0).setListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
@ -33,7 +33,7 @@ public class Tooltip extends AppCompatTextView {
|
|||||||
animator.start();
|
animator.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
public Tooltip(Context context, ViewGroup parentView, int backgroundColor, int textColor) {
|
public Tooltip(@NonNull Context context, @NonNull ViewGroup parentView, int backgroundColor, int textColor) {
|
||||||
super(context);
|
super(context);
|
||||||
setBackgroundDrawable(ViewUtils.createRoundRectDrawable(Utils.convertDpToPx(3), backgroundColor));
|
setBackgroundDrawable(ViewUtils.createRoundRectDrawable(Utils.convertDpToPx(3), backgroundColor));
|
||||||
setTextColor(textColor);
|
setTextColor(textColor);
|
||||||
@ -43,7 +43,6 @@ public class Tooltip extends AppCompatTextView {
|
|||||||
parentView.addView(this, ViewUtils.createFrame(
|
parentView.addView(this, ViewUtils.createFrame(
|
||||||
ViewUtils.WRAP_CONTENT, ViewUtils.WRAP_CONTENT, Gravity.START | Gravity.TOP, 5, 0, 5, 3));
|
ViewUtils.WRAP_CONTENT, ViewUtils.WRAP_CONTENT, Gravity.START | Gravity.TOP, 5, 0, 5, 3));
|
||||||
setVisibility(GONE);
|
setVisibility(GONE);
|
||||||
appExecutors = AppExecutors.getInstance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -5,6 +5,7 @@ import android.content.Intent;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -45,6 +46,14 @@ import com.facebook.imagepipeline.request.ImageRequest;
|
|||||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||||
import com.google.android.material.snackbar.BaseTransientBottomBar;
|
import com.google.android.material.snackbar.BaseTransientBottomBar;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.skydoves.balloon.ArrowOrientation;
|
||||||
|
import com.skydoves.balloon.ArrowPositionRules;
|
||||||
|
import com.skydoves.balloon.Balloon;
|
||||||
|
import com.skydoves.balloon.BalloonAnimation;
|
||||||
|
import com.skydoves.balloon.BalloonHighlightAnimation;
|
||||||
|
import com.skydoves.balloon.BalloonSizeSpec;
|
||||||
|
import com.skydoves.balloon.overlay.BalloonOverlayAnimation;
|
||||||
|
import com.skydoves.balloon.overlay.BalloonOverlayCircle;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -81,6 +90,7 @@ import awais.instagrabber.viewmodels.PostViewV2ViewModel;
|
|||||||
|
|
||||||
import static androidx.core.content.PermissionChecker.checkSelfPermission;
|
import static androidx.core.content.PermissionChecker.checkSelfPermission;
|
||||||
import static awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG;
|
import static awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG;
|
||||||
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_SHOWN_COUNT_TOOLTIP;
|
||||||
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
|
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION;
|
||||||
import static awais.instagrabber.utils.Utils.getAttrValue;
|
import static awais.instagrabber.utils.Utils.getAttrValue;
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
@ -278,17 +288,16 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
|
|||||||
bottom.date.setText(date);
|
bottom.date.setText(date);
|
||||||
}));
|
}));
|
||||||
viewModel.getLikeCount().observe(getViewLifecycleOwner(), count -> {
|
viewModel.getLikeCount().observe(getViewLifecycleOwner(), count -> {
|
||||||
bottom.likesCount.setAnimateChanges(false);
|
|
||||||
bottom.likesCount.setNumber(getSafeCount(count));
|
bottom.likesCount.setNumber(getSafeCount(count));
|
||||||
// final String likesString = getResources().getQuantityString(R.plurals.likes_count, (int) safeCount, safeCount);
|
binding.getRoot().postDelayed(() -> bottom.likesCount.setAnimateChanges(true), 1000);
|
||||||
// bottom.likesCount.setText(likesString);
|
if (count > 1000 && !settingsHelper.getBoolean(PREF_SHOWN_COUNT_TOOLTIP)) {
|
||||||
|
binding.getRoot().postDelayed(this::showCountTooltip, 1000);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (!viewModel.getMedia().isCommentsDisabled()) {
|
if (!viewModel.getMedia().isCommentsDisabled()) {
|
||||||
viewModel.getCommentCount().observe(getViewLifecycleOwner(), count -> {
|
viewModel.getCommentCount().observe(getViewLifecycleOwner(), count -> {
|
||||||
bottom.commentsCount.setAnimateChanges(false);
|
|
||||||
bottom.commentsCount.setNumber(getSafeCount(count));
|
bottom.commentsCount.setNumber(getSafeCount(count));
|
||||||
// final String likesString = getResources().getQuantityString(R.plurals.comments_count, (int) safeCount, safeCount);
|
binding.getRoot().postDelayed(() -> bottom.commentsCount.setAnimateChanges(true), 1000);
|
||||||
// bottom.commentsCount.setText(likesString);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
viewModel.getViewCount().observe(getViewLifecycleOwner(), count -> {
|
viewModel.getViewCount().observe(getViewLifecycleOwner(), count -> {
|
||||||
@ -310,6 +319,45 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showCountTooltip() {
|
||||||
|
final Context context = getContext();
|
||||||
|
if (context == null) return;
|
||||||
|
final Rect rect = new Rect();
|
||||||
|
bottom.likesCount.getGlobalVisibleRect(rect);
|
||||||
|
final Balloon balloon = new Balloon.Builder(context)
|
||||||
|
.setArrowSize(8)
|
||||||
|
.setArrowOrientation(ArrowOrientation.TOP)
|
||||||
|
.setArrowPositionRules(ArrowPositionRules.ALIGN_ANCHOR)
|
||||||
|
.setArrowPosition(0.5f)
|
||||||
|
.setWidth(BalloonSizeSpec.WRAP)
|
||||||
|
.setHeight(BalloonSizeSpec.WRAP)
|
||||||
|
.setPadding(4)
|
||||||
|
.setTextSize(16)
|
||||||
|
.setAlpha(0.9f)
|
||||||
|
.setBalloonAnimation(BalloonAnimation.ELASTIC)
|
||||||
|
.setBalloonHighlightAnimation(BalloonHighlightAnimation.HEARTBEAT, 0)
|
||||||
|
.setIsVisibleOverlay(true)
|
||||||
|
.setOverlayColorResource(R.color.black_a50)
|
||||||
|
.setOverlayShape(new BalloonOverlayCircle((float) Math.max(
|
||||||
|
bottom.likesCount.getMeasuredWidth(),
|
||||||
|
bottom.likesCount.getMeasuredHeight()
|
||||||
|
) / 2f))
|
||||||
|
.setBalloonOverlayAnimation(BalloonOverlayAnimation.FADE)
|
||||||
|
.setLifecycleOwner(getViewLifecycleOwner())
|
||||||
|
.setTextResource(R.string.click_to_show_full)
|
||||||
|
.setDismissWhenTouchOutside(false)
|
||||||
|
.setDismissWhenOverlayClicked(false)
|
||||||
|
.build();
|
||||||
|
balloon.showAlignBottom(bottom.likesCount);
|
||||||
|
settingsHelper.putBoolean(PREF_SHOWN_COUNT_TOOLTIP, true);
|
||||||
|
balloon.setOnBalloonOutsideTouchListener((view, motionEvent) -> {
|
||||||
|
if (rect.contains((int) motionEvent.getRawX(), (int) motionEvent.getRawY())) {
|
||||||
|
bottom.likesCount.setShowAbbreviation(false);
|
||||||
|
}
|
||||||
|
balloon.dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private Long getSafeCount(final Long count) {
|
private Long getSafeCount(final Long count) {
|
||||||
Long safeCount = count;
|
Long safeCount = count;
|
||||||
|
@ -7,4 +7,5 @@ public final class PreferenceKeys {
|
|||||||
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER = "enable_dm_auto_refresh_freq_number";
|
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER = "enable_dm_auto_refresh_freq_number";
|
||||||
public static final String PREF_ENABLE_SENTRY = "enable_sentry";
|
public static final String PREF_ENABLE_SENTRY = "enable_sentry";
|
||||||
public static final String PREF_TAB_ORDER = "tab_order";
|
public static final String PREF_TAB_ORDER = "tab_order";
|
||||||
|
public static final String PREF_SHOWN_COUNT_TOOLTIP = "shown_count_tooltip";
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,6 @@ public class CombinedDrawable extends Drawable implements Drawable.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIconSize(int width, int height) {
|
|
||||||
iconWidth = width;
|
|
||||||
iconHeight = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CombinedDrawable(Drawable backgroundDrawable, Drawable iconDrawable) {
|
public CombinedDrawable(Drawable backgroundDrawable, Drawable iconDrawable) {
|
||||||
background = backgroundDrawable;
|
background = backgroundDrawable;
|
||||||
icon = iconDrawable;
|
icon = iconDrawable;
|
||||||
@ -49,6 +44,11 @@ public class CombinedDrawable extends Drawable implements Drawable.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIconSize(int width, int height) {
|
||||||
|
iconWidth = width;
|
||||||
|
iconHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
public void setCustomSize(int width, int height) {
|
public void setCustomSize(int width, int height) {
|
||||||
backWidth = width;
|
backWidth = width;
|
||||||
backHeight = height;
|
backHeight = height;
|
||||||
@ -82,11 +82,12 @@ public class CombinedDrawable extends Drawable implements Drawable.Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setState(int[] stateSet) {
|
public boolean setState(@NonNull int[] stateSet) {
|
||||||
icon.setState(stateSet);
|
icon.setState(stateSet);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public int[] getState() {
|
public int[] getState() {
|
||||||
return icon.getState();
|
return icon.getState();
|
||||||
@ -108,7 +109,7 @@ public class CombinedDrawable extends Drawable implements Drawable.Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Canvas canvas) {
|
public void draw(@NonNull Canvas canvas) {
|
||||||
background.setBounds(getBounds());
|
background.setBounds(getBounds());
|
||||||
background.draw(canvas);
|
background.draw(canvas);
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
|
@ -16,6 +16,7 @@ import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_D
|
|||||||
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT;
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT;
|
||||||
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_NOTIFICATIONS;
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_NOTIFICATIONS;
|
||||||
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_SENTRY;
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_SENTRY;
|
||||||
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_SHOWN_COUNT_TOOLTIP;
|
||||||
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_TAB_ORDER;
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_TAB_ORDER;
|
||||||
import static awais.instagrabber.utils.Constants.APP_LANGUAGE;
|
import static awais.instagrabber.utils.Constants.APP_LANGUAGE;
|
||||||
import static awais.instagrabber.utils.Constants.APP_THEME;
|
import static awais.instagrabber.utils.Constants.APP_THEME;
|
||||||
@ -165,7 +166,7 @@ public final class SettingsHelper {
|
|||||||
@StringDef({DOWNLOAD_USER_FOLDER, DOWNLOAD_PREPEND_USER_NAME, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
|
@StringDef({DOWNLOAD_USER_FOLDER, DOWNLOAD_PREPEND_USER_NAME, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
|
||||||
SHOW_CAPTIONS, CUSTOM_DATE_TIME_FORMAT_ENABLED, MARK_AS_SEEN, DM_MARK_AS_SEEN, CHECK_ACTIVITY,
|
SHOW_CAPTIONS, CUSTOM_DATE_TIME_FORMAT_ENABLED, MARK_AS_SEEN, DM_MARK_AS_SEEN, CHECK_ACTIVITY,
|
||||||
CHECK_UPDATES, SWAP_DATE_TIME_FORMAT_ENABLED, PREF_ENABLE_DM_NOTIFICATIONS, PREF_ENABLE_DM_AUTO_REFRESH,
|
CHECK_UPDATES, SWAP_DATE_TIME_FORMAT_ENABLED, PREF_ENABLE_DM_NOTIFICATIONS, PREF_ENABLE_DM_AUTO_REFRESH,
|
||||||
FLAG_SECURE, TOGGLE_KEYWORD_FILTER, PREF_ENABLE_SENTRY, HIDE_MUTED_REELS, PLAY_IN_BACKGROUND})
|
FLAG_SECURE, TOGGLE_KEYWORD_FILTER, PREF_ENABLE_SENTRY, HIDE_MUTED_REELS, PLAY_IN_BACKGROUND, PREF_SHOWN_COUNT_TOOLTIP})
|
||||||
public @interface BooleanSettings {}
|
public @interface BooleanSettings {}
|
||||||
|
|
||||||
@StringDef({PREV_INSTALL_VERSION, BROWSER_UA_CODE, APP_UA_CODE, PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER})
|
@StringDef({PREV_INSTALL_VERSION, BROWSER_UA_CODE, APP_UA_CODE, PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER})
|
||||||
|
@ -503,4 +503,5 @@
|
|||||||
<string name="recent">Recent</string>
|
<string name="recent">Recent</string>
|
||||||
<string name="clear">Clear</string>
|
<string name="clear">Clear</string>
|
||||||
<string name="no_external_map_app">No Map app found!</string>
|
<string name="no_external_map_app">No Map app found!</string>
|
||||||
|
<string name="click_to_show_full">Click to view full count</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user