Loading app/src/main/java/app/fedilab/android/mastodon/ui/drawer/StatusAdapter.java +124 −4 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import static app.fedilab.android.mastodon.helper.Helper.PREF_USER_ID; import static app.fedilab.android.mastodon.helper.Helper.PREF_USER_INSTANCE; import static app.fedilab.android.mastodon.helper.Helper.PREF_USER_SOFTWARE; import static app.fedilab.android.mastodon.helper.Helper.PREF_USER_TOKEN; import static app.fedilab.android.mastodon.helper.Helper.TAG; import static app.fedilab.android.mastodon.helper.Helper.getCurrentAccount; import android.annotation.SuppressLint; Loading @@ -59,7 +58,6 @@ import android.os.Looper; import android.text.Html; import android.text.SpannableString; import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MotionEvent; Loading Loading @@ -305,6 +303,47 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> Status statusToDeal, Status statusReturned, boolean remote) { manageSubAction(context, holder, typeOfAction, statusToDeal, statusReturned, remote); adapter.notifyItemChanged(holder.getBindingAdapterPosition()); } /*** * Methode that will deal with results of actions (bookmark, favourite, boost) * @param context Context * @param adapter RecyclerView.Adapter<RecyclerView.ViewHolder> * @param holder StatusViewHolder used by the reycler * @param typeOfAction CrossActionHelper.TypeOfCrossAction * @param statusToDeal Status that received the action * @param statusReturned Status returned by the API * @param remote boolean - it's a remote message */ private static void manageAction(Context context, SliderAdapter adapter, StatusViewHolder holder, CrossActionHelper.TypeOfCrossAction typeOfAction, Status statusToDeal, Status statusReturned, boolean remote) { manageSubAction(context, holder, typeOfAction, statusToDeal, statusReturned, remote); adapter.notifyDataSetChanged(); } /*** * Methode that will deal with results of actions (bookmark, favourite, boost) * @param context Context * @param holder StatusViewHolder used by the reycler * @param typeOfAction CrossActionHelper.TypeOfCrossAction * @param statusToDeal Status that received the action * @param statusReturned Status returned by the API * @param remote boolean - it's a remote message */ private static void manageSubAction(Context context, StatusViewHolder holder, CrossActionHelper.TypeOfCrossAction typeOfAction, Status statusToDeal, Status statusReturned, boolean remote) { if (statusReturned == null) { switch (typeOfAction) { case BOOKMARK_ACTION -> statusToDeal.bookmarked = true; Loading Loading @@ -378,9 +417,9 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> }).start(); } sendAction(context, Helper.ARG_STATUS_ACTION, statusToDeal, null); adapter.notifyItemChanged(holder.getBindingAdapterPosition()); } /** * Manage status, this method is also reused in notifications timelines * Loading Loading @@ -3342,7 +3381,11 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> } else { holder.bindingPixelfed.artReblogPp.setVisibility(View.GONE); } boolean remote = timelineType == Timeline.TimeLineEnum.REMOTE || checkRemotely; SearchVM searchVM = new ViewModelProvider((ViewModelStoreOwner) context).get(SearchVM.class); StatusesVM statusesVM = new ViewModelProvider((ViewModelStoreOwner) context).get(StatusesVM.class); SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context); boolean confirmFav = sharedpreferences.getBoolean(context.getString(R.string.SET_NOTIF_VALIDATION_FAV), false); MastodonHelper.loadPPMastodon(holder.bindingPixelfed.artPp, statusToDeal.account); SliderAdapter adapter = new SliderAdapter(statusToDeal); holder.bindingPixelfed.artMedia.setSliderAdapter(adapter); Loading @@ -3351,6 +3394,83 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> holder.bindingPixelfed.artMedia.setScrollTimeInSec(4); holder.bindingPixelfed.artMedia.startAutoCycle(); holder.bindingPixelfed.commentNumber.setText(String.valueOf(statusToDeal.replies_count)); holder.bindingPixelfed.actionButtonLike.setActiveImage(R.drawable.ic_heart_filled_24); holder.bindingPixelfed.actionButtonLike.setInactiveImage(R.drawable.ic_heart_24); holder.bindingPixelfed.actionButtonLike.setActiveImageTint(R.color.red_color_picker); holder.bindingPixelfed.actionButtonLike.setChecked(statusToDeal.favourited); float normalSize = Helper.convertDpToPixel(28, context); final float scaleIcon = sharedpreferences.getFloat(context.getString(R.string.SET_FONT_SCALE_ICON), 1.1f); holder.bindingPixelfed.actionButtonLike.setImageSize((int) (normalSize * scaleIcon)); holder.bindingPixelfed.actionButtonLike.setOnLongClickListener(v -> { if (statusToDeal.visibility.equals("direct") || (statusToDeal.visibility.equals("private"))) { return true; } CrossActionHelper.doCrossAction(context, CrossActionHelper.TypeOfCrossAction.FAVOURITE_ACTION, null, statusToDeal); return true; }); holder.bindingPixelfed.actionButtonLike.setOnClickListener(v -> { if (confirmFav) { AlertDialog.Builder alt_bld = new MaterialAlertDialogBuilder(context); if (status.favourited) { alt_bld.setMessage(context.getString(R.string.favourite_remove)); } else { alt_bld.setMessage(context.getString(R.string.favourite_add)); } alt_bld.setPositiveButton(R.string.yes, (dialog, id) -> { if (remote) { Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.uri, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results != null && results.statuses != null && results.statuses.size() > 0) { Status fetchedStatus = results.statuses.get(0); statusesVM.favourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchedStatus.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.FAVOURITE_ACTION, statusToDeal, _status, true)); } else { Toasty.info(context, context.getString(R.string.toast_error_search), Toasty.LENGTH_SHORT).show(); } }); } else { if (status.favourited) { statusesVM.unFavourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.UNFAVOURITE_ACTION, statusToDeal, _status, false)); } else { ((SparkButton) v).playAnimation(); statusesVM.favourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.FAVOURITE_ACTION, statusToDeal, _status, false)); } } dialog.dismiss(); }); alt_bld.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss()); AlertDialog alert = alt_bld.create(); alert.show(); } else { if (remote) { Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.uri, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results != null && results.statuses != null && !results.statuses.isEmpty()) { Status fetchedStatus = results.statuses.get(0); statusesVM.favourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchedStatus.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.FAVOURITE_ACTION, statusToDeal, _status, true)); } else { Toasty.info(context, context.getString(R.string.toast_error_search), Toasty.LENGTH_SHORT).show(); } }); } else { if (statusToDeal.favourited) { statusesVM.unFavourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.UNFAVOURITE_ACTION, statusToDeal, _status, false)); } else { ((SparkButton) v).playAnimation(); statusesVM.favourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.FAVOURITE_ACTION, statusToDeal, _status, false)); } } } }); holder.bindingPixelfed.artUsername.setText( statusToDeal.account.getSpanDisplayName(context, new WeakReference<>(holder.bindingPixelfed.artUsername)), Loading app/src/main/res/drawables/mastodon/drawable/ic_heart_24.xml 0 → 100644 +12 −0 Original line number Diff line number Diff line <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path android:strokeColor="@color/white" android:strokeWidth="2" android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/> </vector> No newline at end of file app/src/main/res/drawables/mastodon/drawable/ic_heart_filled_24.xml 0 → 100644 +13 −0 Original line number Diff line number Diff line <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path android:fillColor="@color/red_color_picker" android:strokeColor="@color/red_color_picker" android:strokeWidth="2" android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/> </vector> No newline at end of file app/src/main/res/layouts/mastodon/layout/drawer_status_pixelfed.xml +19 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ <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:sparkbutton="http://schemas.android.com/apk/res-auto" android:id="@+id/art_container" android:layout_width="match_parent" android:layout_height="wrap_content" Loading Loading @@ -49,7 +50,7 @@ android:id="@+id/bottom_banner" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#44000000" android:background="#77000000" android:orientation="horizontal" android:padding="10dp" app:layout_constraintBottom_toBottomOf="@+id/art_media" Loading Loading @@ -98,10 +99,27 @@ android:textColor="@color/white" /> </androidx.appcompat.widget.LinearLayoutCompat> <com.varunest.sparkbutton.SparkButton android:id="@+id/action_button_like" android:layout_width="48dp" android:layout_height="48dp" android:layout_gravity="center" android:adjustViewBounds="true" android:contentDescription="@string/favourite_add" app:activeImage="@drawable/ic_heart_filled_24" app:animationSpeed="1.5" app:inactiveImage="@drawable/ic_heart_24" app:primaryColor="@color/red_color_picker" app:secondaryColor="@color/red_color_picker" sparkbutton:iconSize="28dp" /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/comment_number" android:layout_width="wrap_content" android:layout_gravity="center_vertical" android:layout_height="wrap_content" android:drawableTint="@color/white" android:textColor="@color/white" android:layout_marginStart="10dp" android:drawableStart="@drawable/ic_baseline_chat_bubble_24" android:drawablePadding="5dp" Loading Loading
app/src/main/java/app/fedilab/android/mastodon/ui/drawer/StatusAdapter.java +124 −4 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import static app.fedilab.android.mastodon.helper.Helper.PREF_USER_ID; import static app.fedilab.android.mastodon.helper.Helper.PREF_USER_INSTANCE; import static app.fedilab.android.mastodon.helper.Helper.PREF_USER_SOFTWARE; import static app.fedilab.android.mastodon.helper.Helper.PREF_USER_TOKEN; import static app.fedilab.android.mastodon.helper.Helper.TAG; import static app.fedilab.android.mastodon.helper.Helper.getCurrentAccount; import android.annotation.SuppressLint; Loading @@ -59,7 +58,6 @@ import android.os.Looper; import android.text.Html; import android.text.SpannableString; import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MotionEvent; Loading Loading @@ -305,6 +303,47 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> Status statusToDeal, Status statusReturned, boolean remote) { manageSubAction(context, holder, typeOfAction, statusToDeal, statusReturned, remote); adapter.notifyItemChanged(holder.getBindingAdapterPosition()); } /*** * Methode that will deal with results of actions (bookmark, favourite, boost) * @param context Context * @param adapter RecyclerView.Adapter<RecyclerView.ViewHolder> * @param holder StatusViewHolder used by the reycler * @param typeOfAction CrossActionHelper.TypeOfCrossAction * @param statusToDeal Status that received the action * @param statusReturned Status returned by the API * @param remote boolean - it's a remote message */ private static void manageAction(Context context, SliderAdapter adapter, StatusViewHolder holder, CrossActionHelper.TypeOfCrossAction typeOfAction, Status statusToDeal, Status statusReturned, boolean remote) { manageSubAction(context, holder, typeOfAction, statusToDeal, statusReturned, remote); adapter.notifyDataSetChanged(); } /*** * Methode that will deal with results of actions (bookmark, favourite, boost) * @param context Context * @param holder StatusViewHolder used by the reycler * @param typeOfAction CrossActionHelper.TypeOfCrossAction * @param statusToDeal Status that received the action * @param statusReturned Status returned by the API * @param remote boolean - it's a remote message */ private static void manageSubAction(Context context, StatusViewHolder holder, CrossActionHelper.TypeOfCrossAction typeOfAction, Status statusToDeal, Status statusReturned, boolean remote) { if (statusReturned == null) { switch (typeOfAction) { case BOOKMARK_ACTION -> statusToDeal.bookmarked = true; Loading Loading @@ -378,9 +417,9 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> }).start(); } sendAction(context, Helper.ARG_STATUS_ACTION, statusToDeal, null); adapter.notifyItemChanged(holder.getBindingAdapterPosition()); } /** * Manage status, this method is also reused in notifications timelines * Loading Loading @@ -3342,7 +3381,11 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> } else { holder.bindingPixelfed.artReblogPp.setVisibility(View.GONE); } boolean remote = timelineType == Timeline.TimeLineEnum.REMOTE || checkRemotely; SearchVM searchVM = new ViewModelProvider((ViewModelStoreOwner) context).get(SearchVM.class); StatusesVM statusesVM = new ViewModelProvider((ViewModelStoreOwner) context).get(StatusesVM.class); SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context); boolean confirmFav = sharedpreferences.getBoolean(context.getString(R.string.SET_NOTIF_VALIDATION_FAV), false); MastodonHelper.loadPPMastodon(holder.bindingPixelfed.artPp, statusToDeal.account); SliderAdapter adapter = new SliderAdapter(statusToDeal); holder.bindingPixelfed.artMedia.setSliderAdapter(adapter); Loading @@ -3351,6 +3394,83 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> holder.bindingPixelfed.artMedia.setScrollTimeInSec(4); holder.bindingPixelfed.artMedia.startAutoCycle(); holder.bindingPixelfed.commentNumber.setText(String.valueOf(statusToDeal.replies_count)); holder.bindingPixelfed.actionButtonLike.setActiveImage(R.drawable.ic_heart_filled_24); holder.bindingPixelfed.actionButtonLike.setInactiveImage(R.drawable.ic_heart_24); holder.bindingPixelfed.actionButtonLike.setActiveImageTint(R.color.red_color_picker); holder.bindingPixelfed.actionButtonLike.setChecked(statusToDeal.favourited); float normalSize = Helper.convertDpToPixel(28, context); final float scaleIcon = sharedpreferences.getFloat(context.getString(R.string.SET_FONT_SCALE_ICON), 1.1f); holder.bindingPixelfed.actionButtonLike.setImageSize((int) (normalSize * scaleIcon)); holder.bindingPixelfed.actionButtonLike.setOnLongClickListener(v -> { if (statusToDeal.visibility.equals("direct") || (statusToDeal.visibility.equals("private"))) { return true; } CrossActionHelper.doCrossAction(context, CrossActionHelper.TypeOfCrossAction.FAVOURITE_ACTION, null, statusToDeal); return true; }); holder.bindingPixelfed.actionButtonLike.setOnClickListener(v -> { if (confirmFav) { AlertDialog.Builder alt_bld = new MaterialAlertDialogBuilder(context); if (status.favourited) { alt_bld.setMessage(context.getString(R.string.favourite_remove)); } else { alt_bld.setMessage(context.getString(R.string.favourite_add)); } alt_bld.setPositiveButton(R.string.yes, (dialog, id) -> { if (remote) { Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.uri, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results != null && results.statuses != null && results.statuses.size() > 0) { Status fetchedStatus = results.statuses.get(0); statusesVM.favourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchedStatus.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.FAVOURITE_ACTION, statusToDeal, _status, true)); } else { Toasty.info(context, context.getString(R.string.toast_error_search), Toasty.LENGTH_SHORT).show(); } }); } else { if (status.favourited) { statusesVM.unFavourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.UNFAVOURITE_ACTION, statusToDeal, _status, false)); } else { ((SparkButton) v).playAnimation(); statusesVM.favourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.FAVOURITE_ACTION, statusToDeal, _status, false)); } } dialog.dismiss(); }); alt_bld.setNegativeButton(R.string.cancel, (dialog, id) -> dialog.dismiss()); AlertDialog alert = alt_bld.create(); alert.show(); } else { if (remote) { Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.uri, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results != null && results.statuses != null && !results.statuses.isEmpty()) { Status fetchedStatus = results.statuses.get(0); statusesVM.favourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchedStatus.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.FAVOURITE_ACTION, statusToDeal, _status, true)); } else { Toasty.info(context, context.getString(R.string.toast_error_search), Toasty.LENGTH_SHORT).show(); } }); } else { if (statusToDeal.favourited) { statusesVM.unFavourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.UNFAVOURITE_ACTION, statusToDeal, _status, false)); } else { ((SparkButton) v).playAnimation(); statusesVM.favourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id) .observe((LifecycleOwner) context, _status -> manageAction(context, adapter, holder, CrossActionHelper.TypeOfCrossAction.FAVOURITE_ACTION, statusToDeal, _status, false)); } } } }); holder.bindingPixelfed.artUsername.setText( statusToDeal.account.getSpanDisplayName(context, new WeakReference<>(holder.bindingPixelfed.artUsername)), Loading
app/src/main/res/drawables/mastodon/drawable/ic_heart_24.xml 0 → 100644 +12 −0 Original line number Diff line number Diff line <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path android:strokeColor="@color/white" android:strokeWidth="2" android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/> </vector> No newline at end of file
app/src/main/res/drawables/mastodon/drawable/ic_heart_filled_24.xml 0 → 100644 +13 −0 Original line number Diff line number Diff line <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path android:fillColor="@color/red_color_picker" android:strokeColor="@color/red_color_picker" android:strokeWidth="2" android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/> </vector> No newline at end of file
app/src/main/res/layouts/mastodon/layout/drawer_status_pixelfed.xml +19 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ <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:sparkbutton="http://schemas.android.com/apk/res-auto" android:id="@+id/art_container" android:layout_width="match_parent" android:layout_height="wrap_content" Loading Loading @@ -49,7 +50,7 @@ android:id="@+id/bottom_banner" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#44000000" android:background="#77000000" android:orientation="horizontal" android:padding="10dp" app:layout_constraintBottom_toBottomOf="@+id/art_media" Loading Loading @@ -98,10 +99,27 @@ android:textColor="@color/white" /> </androidx.appcompat.widget.LinearLayoutCompat> <com.varunest.sparkbutton.SparkButton android:id="@+id/action_button_like" android:layout_width="48dp" android:layout_height="48dp" android:layout_gravity="center" android:adjustViewBounds="true" android:contentDescription="@string/favourite_add" app:activeImage="@drawable/ic_heart_filled_24" app:animationSpeed="1.5" app:inactiveImage="@drawable/ic_heart_24" app:primaryColor="@color/red_color_picker" app:secondaryColor="@color/red_color_picker" sparkbutton:iconSize="28dp" /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/comment_number" android:layout_width="wrap_content" android:layout_gravity="center_vertical" android:layout_height="wrap_content" android:drawableTint="@color/white" android:textColor="@color/white" android:layout_marginStart="10dp" android:drawableStart="@drawable/ic_baseline_chat_bubble_24" android:drawablePadding="5dp" Loading