parent
e0febda372
commit
a7c707f62e
|
@ -11,6 +11,7 @@ import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import me.grishka.appkit.api.Callback;
|
import me.grishka.appkit.api.Callback;
|
||||||
import me.grishka.appkit.api.ErrorResponse;
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
|
@ -25,7 +26,7 @@ public class StatusInteractionController{
|
||||||
this.accountID=accountID;
|
this.accountID=accountID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFavorited(Status status, boolean favorited){
|
public void setFavorited(Status status, boolean favorited, Consumer<Status> cb){
|
||||||
if(!Looper.getMainLooper().isCurrentThread())
|
if(!Looper.getMainLooper().isCurrentThread())
|
||||||
throw new IllegalStateException("Can only be called from main thread");
|
throw new IllegalStateException("Can only be called from main thread");
|
||||||
|
|
||||||
|
@ -38,6 +39,8 @@ public class StatusInteractionController{
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Status result){
|
public void onSuccess(Status result){
|
||||||
runningFavoriteRequests.remove(status.id);
|
runningFavoriteRequests.remove(status.id);
|
||||||
|
result.favouritesCount = Math.max(0, status.favouritesCount) + (favorited ? 1 : -1);
|
||||||
|
cb.accept(result);
|
||||||
E.post(new StatusCountersUpdatedEvent(result));
|
E.post(new StatusCountersUpdatedEvent(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,24 +49,17 @@ public class StatusInteractionController{
|
||||||
runningFavoriteRequests.remove(status.id);
|
runningFavoriteRequests.remove(status.id);
|
||||||
error.showToast(MastodonApp.context);
|
error.showToast(MastodonApp.context);
|
||||||
status.favourited=!favorited;
|
status.favourited=!favorited;
|
||||||
if(favorited)
|
cb.accept(status);
|
||||||
status.favouritesCount--;
|
|
||||||
else
|
|
||||||
status.favouritesCount++;
|
|
||||||
E.post(new StatusCountersUpdatedEvent(status));
|
E.post(new StatusCountersUpdatedEvent(status));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.exec(accountID);
|
.exec(accountID);
|
||||||
runningFavoriteRequests.put(status.id, req);
|
runningFavoriteRequests.put(status.id, req);
|
||||||
status.favourited=favorited;
|
status.favourited=favorited;
|
||||||
if(favorited)
|
|
||||||
status.favouritesCount++;
|
|
||||||
else
|
|
||||||
status.favouritesCount--;
|
|
||||||
E.post(new StatusCountersUpdatedEvent(status));
|
E.post(new StatusCountersUpdatedEvent(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReblogged(Status status, boolean reblogged){
|
public void setReblogged(Status status, boolean reblogged, Consumer<Status> cb){
|
||||||
if(!Looper.getMainLooper().isCurrentThread())
|
if(!Looper.getMainLooper().isCurrentThread())
|
||||||
throw new IllegalStateException("Can only be called from main thread");
|
throw new IllegalStateException("Can only be called from main thread");
|
||||||
|
|
||||||
|
@ -76,6 +72,8 @@ public class StatusInteractionController{
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Status result){
|
public void onSuccess(Status result){
|
||||||
runningReblogRequests.remove(status.id);
|
runningReblogRequests.remove(status.id);
|
||||||
|
result.reblogsCount = Math.max(0, status.reblogsCount) + (reblogged ? 1 : -1);
|
||||||
|
cb.accept(result);
|
||||||
E.post(new StatusCountersUpdatedEvent(result));
|
E.post(new StatusCountersUpdatedEvent(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,24 +82,21 @@ public class StatusInteractionController{
|
||||||
runningReblogRequests.remove(status.id);
|
runningReblogRequests.remove(status.id);
|
||||||
error.showToast(MastodonApp.context);
|
error.showToast(MastodonApp.context);
|
||||||
status.reblogged=!reblogged;
|
status.reblogged=!reblogged;
|
||||||
if(reblogged)
|
cb.accept(status);
|
||||||
status.reblogsCount--;
|
|
||||||
else
|
|
||||||
status.reblogsCount++;
|
|
||||||
E.post(new StatusCountersUpdatedEvent(status));
|
E.post(new StatusCountersUpdatedEvent(status));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.exec(accountID);
|
.exec(accountID);
|
||||||
runningReblogRequests.put(status.id, req);
|
runningReblogRequests.put(status.id, req);
|
||||||
status.reblogged=reblogged;
|
status.reblogged=reblogged;
|
||||||
if(reblogged)
|
|
||||||
status.reblogsCount++;
|
|
||||||
else
|
|
||||||
status.reblogsCount--;
|
|
||||||
E.post(new StatusCountersUpdatedEvent(status));
|
E.post(new StatusCountersUpdatedEvent(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBookmarked(Status status, boolean bookmarked){
|
public void setBookmarked(Status status, boolean bookmarked){
|
||||||
|
setBookmarked(status, bookmarked, r->{});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBookmarked(Status status, boolean bookmarked, Consumer<Status> cb){
|
||||||
if(!Looper.getMainLooper().isCurrentThread())
|
if(!Looper.getMainLooper().isCurrentThread())
|
||||||
throw new IllegalStateException("Can only be called from main thread");
|
throw new IllegalStateException("Can only be called from main thread");
|
||||||
|
|
||||||
|
@ -114,6 +109,7 @@ public class StatusInteractionController{
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Status result){
|
public void onSuccess(Status result){
|
||||||
runningBookmarkRequests.remove(status.id);
|
runningBookmarkRequests.remove(status.id);
|
||||||
|
cb.accept(result);
|
||||||
E.post(new StatusCountersUpdatedEvent(result));
|
E.post(new StatusCountersUpdatedEvent(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +118,7 @@ public class StatusInteractionController{
|
||||||
runningBookmarkRequests.remove(status.id);
|
runningBookmarkRequests.remove(status.id);
|
||||||
error.showToast(MastodonApp.context);
|
error.showToast(MastodonApp.context);
|
||||||
status.bookmarked=!bookmarked;
|
status.bookmarked=!bookmarked;
|
||||||
|
cb.accept(status);
|
||||||
E.post(new StatusCountersUpdatedEvent(status));
|
E.post(new StatusCountersUpdatedEvent(status));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,9 +4,14 @@ import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.accessibility.AccessibilityNodeInfo;
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
|
import android.view.animation.AlphaAnimation;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.view.animation.AnimationSet;
|
||||||
|
import android.view.animation.ScaleAnimation;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -20,10 +25,8 @@ import org.joinmastodon.android.model.StatusPrivacy;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import me.grishka.appkit.Nav;
|
import me.grishka.appkit.Nav;
|
||||||
import me.grishka.appkit.utils.BindableViewHolder;
|
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
public class FooterStatusDisplayItem extends StatusDisplayItem{
|
public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
|
@ -45,6 +48,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
public static class Holder extends StatusDisplayItem.Holder<FooterStatusDisplayItem>{
|
public static class Holder extends StatusDisplayItem.Holder<FooterStatusDisplayItem>{
|
||||||
private final TextView reply, boost, favorite;
|
private final TextView reply, boost, favorite;
|
||||||
private final ImageView share;
|
private final ImageView share;
|
||||||
|
private static final AnimationSet scaleDown, scaleUp;
|
||||||
|
|
||||||
private final View.AccessibilityDelegate buttonAccessibilityDelegate=new View.AccessibilityDelegate(){
|
private final View.AccessibilityDelegate buttonAccessibilityDelegate=new View.AccessibilityDelegate(){
|
||||||
@Override
|
@Override
|
||||||
|
@ -55,6 +59,27 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static {
|
||||||
|
// 20dp to center in middle of icon, because: (icon width = 24dp) / 2 + (paddingStart = 8dp)
|
||||||
|
Animation scaleDownAnim = new ScaleAnimation(1, 0.85f, 1, 0.85f, Animation.ABSOLUTE, V.dp(20), Animation.RELATIVE_TO_SELF, 0.5f);
|
||||||
|
Animation scaleUpAnim = new ScaleAnimation(0.85f, 1, 0.85f, 1, Animation.ABSOLUTE, V.dp(20), Animation.RELATIVE_TO_SELF, 0.5f);
|
||||||
|
Animation opacityOutAnim = new AlphaAnimation(1, 0.75f);
|
||||||
|
Animation opacityInAnim = new AlphaAnimation(0.75f, 1);
|
||||||
|
|
||||||
|
scaleDown = new AnimationSet(true);
|
||||||
|
scaleDown.setDuration(350);
|
||||||
|
scaleDown.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||||
|
scaleDown.setFillAfter(true);
|
||||||
|
scaleDown.addAnimation(scaleDownAnim);
|
||||||
|
scaleDown.addAnimation(opacityOutAnim);
|
||||||
|
|
||||||
|
scaleUp = new AnimationSet(true);
|
||||||
|
scaleUp.setDuration(100);
|
||||||
|
scaleUp.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||||
|
scaleUp.addAnimation(scaleUpAnim);
|
||||||
|
scaleUp.addAnimation(opacityInAnim);
|
||||||
|
}
|
||||||
|
|
||||||
public Holder(Activity activity, ViewGroup parent){
|
public Holder(Activity activity, ViewGroup parent){
|
||||||
super(activity, R.layout.display_item_footer, parent);
|
super(activity, R.layout.display_item_footer, parent);
|
||||||
reply=findViewById(R.id.reply);
|
reply=findViewById(R.id.reply);
|
||||||
|
@ -70,12 +95,16 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
View boost=findViewById(R.id.boost_btn);
|
View boost=findViewById(R.id.boost_btn);
|
||||||
View favorite=findViewById(R.id.favorite_btn);
|
View favorite=findViewById(R.id.favorite_btn);
|
||||||
View share=findViewById(R.id.share_btn);
|
View share=findViewById(R.id.share_btn);
|
||||||
|
reply.setOnTouchListener(this::onButtonTouch);
|
||||||
reply.setOnClickListener(this::onReplyClick);
|
reply.setOnClickListener(this::onReplyClick);
|
||||||
reply.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
reply.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
||||||
|
boost.setOnTouchListener(this::onButtonTouch);
|
||||||
boost.setOnClickListener(this::onBoostClick);
|
boost.setOnClickListener(this::onBoostClick);
|
||||||
boost.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
boost.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
||||||
|
favorite.setOnTouchListener(this::onButtonTouch);
|
||||||
favorite.setOnClickListener(this::onFavoriteClick);
|
favorite.setOnClickListener(this::onFavoriteClick);
|
||||||
favorite.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
favorite.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
||||||
|
share.setOnTouchListener(this::onButtonTouch);
|
||||||
share.setOnClickListener(this::onShareClick);
|
share.setOnClickListener(this::onShareClick);
|
||||||
share.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
share.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
||||||
}
|
}
|
||||||
|
@ -102,25 +131,38 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onReplyClick(View v){
|
private void onReplyClick(View v){
|
||||||
|
v.startAnimation(scaleUp);
|
||||||
Bundle args=new Bundle();
|
Bundle args=new Bundle();
|
||||||
args.putString("account", item.accountID);
|
args.putString("account", item.accountID);
|
||||||
args.putParcelable("replyTo", Parcels.wrap(item.status));
|
args.putParcelable("replyTo", Parcels.wrap(item.status));
|
||||||
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
|
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean onButtonTouch(View v, MotionEvent event){
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_UP) v.performClick();
|
||||||
|
else if (event.getAction() == MotionEvent.ACTION_DOWN) v.startAnimation(scaleDown);
|
||||||
|
else if (event.getAction() == MotionEvent.ACTION_CANCEL) v.startAnimation(scaleUp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void onBoostClick(View v){
|
private void onBoostClick(View v){
|
||||||
AccountSessionManager.getInstance().getAccount(item.accountID).getStatusInteractionController().setReblogged(item.status, !item.status.reblogged);
|
AccountSessionManager.getInstance().getAccount(item.accountID).getStatusInteractionController().setReblogged(item.status, !item.status.reblogged, r->{
|
||||||
|
v.startAnimation(scaleUp);
|
||||||
boost.setSelected(item.status.reblogged);
|
boost.setSelected(item.status.reblogged);
|
||||||
bindButton(boost, item.status.reblogsCount);
|
bindButton(boost, r.reblogsCount);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onFavoriteClick(View v){
|
private void onFavoriteClick(View v){
|
||||||
AccountSessionManager.getInstance().getAccount(item.accountID).getStatusInteractionController().setFavorited(item.status, !item.status.favourited);
|
AccountSessionManager.getInstance().getAccount(item.accountID).getStatusInteractionController().setFavorited(item.status, !item.status.favourited, r->{
|
||||||
favorite.setSelected(item.status.favourited);
|
v.startAnimation(scaleUp);
|
||||||
bindButton(favorite, item.status.favouritesCount);
|
favorite.setSelected(r.favourited);
|
||||||
|
bindButton(favorite, r.favouritesCount);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onShareClick(View v){
|
private void onShareClick(View v){
|
||||||
|
v.startAnimation(scaleUp);
|
||||||
Intent intent=new Intent(Intent.ACTION_SEND);
|
Intent intent=new Intent(Intent.ACTION_SEND);
|
||||||
intent.setType("text/plain");
|
intent.setType("text/plain");
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, item.status.url);
|
intent.putExtra(Intent.EXTRA_TEXT, item.status.url);
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:paddingLeft="20dp"
|
android:paddingHorizontal="28dp">
|
||||||
android:paddingRight="20dp">
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/reply_btn"
|
android:id="@+id/reply_btn"
|
||||||
|
@ -15,10 +14,11 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/reply"
|
android:id="@+id/reply"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="24dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center_vertical"
|
||||||
android:drawableStart="@drawable/ic_fluent_chat_multiple_24_regular"
|
android:drawableStart="@drawable/ic_fluent_chat_multiple_24_regular"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="8dp"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
android:drawableTint="?android:textColorSecondary"
|
android:drawableTint="?android:textColorSecondary"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:textAppearance="@style/m3_label_large"
|
android:textAppearance="@style/m3_label_large"
|
||||||
|
@ -38,10 +38,11 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/boost"
|
android:id="@+id/boost"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="24dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center_vertical"
|
||||||
android:drawableStart="@drawable/ic_boost"
|
android:drawableStart="@drawable/ic_boost"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="8dp"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
android:drawableTint="@color/boost_icon"
|
android:drawableTint="@color/boost_icon"
|
||||||
android:textColor="@color/boost_icon"
|
android:textColor="@color/boost_icon"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
@ -62,10 +63,11 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/favorite"
|
android:id="@+id/favorite"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="24dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center_vertical"
|
||||||
android:drawableStart="@drawable/ic_fluent_star_24_selector"
|
android:drawableStart="@drawable/ic_fluent_star_24_selector"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="8dp"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
android:drawableTint="@color/favorite_icon"
|
android:drawableTint="@color/favorite_icon"
|
||||||
android:textColor="@color/favorite_icon"
|
android:textColor="@color/favorite_icon"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
@ -81,14 +83,14 @@
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/share_btn"
|
android:id="@+id/share_btn"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:minWidth="56dp">
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/share"
|
android:id="@+id/share"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center_vertical"
|
||||||
android:src="@drawable/ic_fluent_share_24_regular"
|
android:src="@drawable/ic_fluent_share_24_regular"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
android:tint="?android:textColorSecondary"
|
android:tint="?android:textColorSecondary"
|
||||||
android:gravity="center_vertical"/>
|
android:gravity="center_vertical"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
Loading…
Reference in New Issue