Two new options: Long Press on Post (Non-Media Area) and Long Press on Media in Settings->Gestures & Buttons. SharedPreferencesLiveData.

This commit is contained in:
Docile-Alligator 2025-07-07 10:53:02 -04:00
parent f0f3719fdc
commit ba99e7e55e
14 changed files with 377 additions and 34 deletions

View File

@ -22,6 +22,7 @@ import android.os.Handler;
import android.os.Looper;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
@ -43,6 +44,8 @@ import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import org.greenrobot.eventbus.EventBus;
import java.lang.reflect.Field;
import java.util.Locale;
@ -51,6 +54,7 @@ import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.account.Account;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.FinishViewMediaActivityEvent;
import ml.docilealligator.infinityforreddit.font.ContentFontFamily;
import ml.docilealligator.infinityforreddit.font.ContentFontStyle;
import ml.docilealligator.infinityforreddit.font.FontFamily;
@ -71,6 +75,7 @@ public abstract class BaseActivity extends AppCompatActivity implements CustomFo
private boolean isImmersiveInterfaceApplicable = true;
private int systemVisibilityToolbarExpanded = 0;
private int systemVisibilityToolbarCollapsed = 0;
private boolean shouldTrackFullscreenMediaPeekTouchEvent;
public CustomThemeWrapper customThemeWrapper;
public Typeface typeface;
public Typeface titleTypeface;
@ -261,6 +266,18 @@ public abstract class BaseActivity extends AppCompatActivity implements CustomFo
mHandler.removeCallbacksAndMessages(null);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (shouldTrackFullscreenMediaPeekTouchEvent) {
if (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP) {
shouldTrackFullscreenMediaPeekTouchEvent = false;
EventBus.getDefault().post(new FinishViewMediaActivityEvent());
}
return true;
}
return super.dispatchTouchEvent(ev);
}
public abstract SharedPreferences getDefaultSharedPreferences();
public abstract SharedPreferences getCurrentAccountSharedPreferences();
@ -527,4 +544,8 @@ public abstract class BaseActivity extends AppCompatActivity implements CustomFo
public void triggerBackPress() {
getOnBackPressedDispatcher().onBackPressed();
}
public void setShouldTrackFullscreenMediaPeekTouchEvent(boolean value) {
shouldTrackFullscreenMediaPeekTouchEvent = value;
}
}

View File

@ -47,6 +47,9 @@ import com.github.piasy.biv.BigImageViewer;
import com.github.piasy.biv.loader.ImageLoader;
import com.github.piasy.biv.loader.glide.GlideImageLoader;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.io.File;
import java.util.concurrent.Executor;
@ -68,6 +71,7 @@ import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrConfig;
import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrPosition;
import ml.docilealligator.infinityforreddit.databinding.ActivityViewImageOrGifBinding;
import ml.docilealligator.infinityforreddit.events.FinishViewMediaActivityEvent;
import ml.docilealligator.infinityforreddit.font.ContentFontFamily;
import ml.docilealligator.infinityforreddit.font.ContentFontStyle;
import ml.docilealligator.infinityforreddit.font.FontFamily;
@ -136,6 +140,8 @@ public class ViewImageOrGifActivity extends AppCompatActivity implements SetAsWa
binding = ActivityViewImageOrGifBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
EventBus.getDefault().register(this);
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
@ -541,12 +547,18 @@ public class ViewImageOrGifActivity extends AppCompatActivity implements SetAsWa
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
BigImageViewer.imageLoader().cancelAll();
super.onDestroy();
}
@Override
public void setCustomFont(Typeface typeface, Typeface titleTypeface, Typeface contentTypeface) {
this.typeface = typeface;
}
@Subscribe
public void onFinishViewMediaActivityEvent(FinishViewMediaActivityEvent e) {
finish();
}
}

View File

@ -30,6 +30,9 @@ import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
import java.util.concurrent.Executor;
@ -43,6 +46,7 @@ import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.SetAsWallpaperCallback;
import ml.docilealligator.infinityforreddit.WallpaperSetter;
import ml.docilealligator.infinityforreddit.databinding.ActivityViewRedditGalleryBinding;
import ml.docilealligator.infinityforreddit.events.FinishViewMediaActivityEvent;
import ml.docilealligator.infinityforreddit.font.ContentFontFamily;
import ml.docilealligator.infinityforreddit.font.ContentFontStyle;
import ml.docilealligator.infinityforreddit.font.FontFamily;
@ -135,6 +139,8 @@ public class ViewRedditGalleryActivity extends AppCompatActivity implements SetA
binding = ActivityViewRedditGalleryBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
EventBus.getDefault().register(this);
useBottomAppBar = sharedPreferences.getBoolean(SharedPreferencesUtils.USE_BOTTOM_TOOLBAR_IN_MEDIA_VIEWER, false);
if (!useBottomAppBar) {
@ -304,6 +310,11 @@ public class ViewRedditGalleryActivity extends AppCompatActivity implements SetA
this.isActionBarHidden = isActionBarHidden;
}
@Subscribe
public void onFinishViewMediaActivityEvent(FinishViewMediaActivityEvent e) {
finish();
}
private class SectionsPagerAdapter extends FragmentStatePagerAdapter {
SectionsPagerAdapter(@NonNull FragmentManager fm) {

View File

@ -81,6 +81,8 @@ import com.otaliastudios.zoom.ZoomEngine;
import com.otaliastudios.zoom.ZoomSurfaceView;
import org.apache.commons.io.FilenameUtils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.concurrent.Executor;
@ -99,6 +101,7 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.PlaybackSpeedBo
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.databinding.ActivityViewVideoBinding;
import ml.docilealligator.infinityforreddit.databinding.ActivityViewVideoZoomableBinding;
import ml.docilealligator.infinityforreddit.events.FinishViewMediaActivityEvent;
import ml.docilealligator.infinityforreddit.font.ContentFontFamily;
import ml.docilealligator.infinityforreddit.font.ContentFontStyle;
import ml.docilealligator.infinityforreddit.font.FontFamily;
@ -285,6 +288,8 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe
setContentView(binding.getRoot());
}
EventBus.getDefault().register(this);
applyCustomTheme();
setVolumeControlStream(AudioManager.STREAM_MUSIC);
@ -905,6 +910,7 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe
@Override
protected void onDestroy() {
EventBus.getDefault().unregister(this);
super.onDestroy();
player.seekToDefaultPosition();
player.stop();
@ -1052,4 +1058,9 @@ public class ViewVideoActivity extends AppCompatActivity implements CustomFontRe
public void setCustomFont(Typeface typeface, Typeface titleTypeface, Typeface contentTypeface) {
this.typeface = typeface;
}
@Subscribe
public void onFinishViewMediaActivityEvent(FinishViewMediaActivityEvent e) {
finish();
}
}

View File

@ -10,6 +10,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@ -255,6 +256,8 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
private boolean mFixedHeightPreviewInCard;
private boolean mHideTextPostContent;
private boolean mEasierToWatchInFullScreen;
private String mLongPressPostNonMediaAreaAction = SharedPreferencesUtils.LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS;
private String mLongPressPostMediaAction = SharedPreferencesUtils.LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS;
private boolean mHandleReadPost;
private ExoCreator mExoCreator;
private Callback mCallback;
@ -1567,6 +1570,14 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
this.mEasierToWatchInFullScreen = easierToWatchInFullScreen;
}
public void setLongPressPostNonMediaAreaAction(String value) {
mLongPressPostNonMediaAreaAction = value;
}
public void setLongPressPostMediaAction(String value) {
mLongPressPostMediaAction = value;
}
@OptIn(markerClass = UnstableApi.class)
@Override
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
@ -1766,21 +1777,31 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
}
private void openMedia(Post post) {
openMedia(post, 0);
openMedia(post, 0, false);
}
private void openMedia(Post post, int galleryItemIndex) {
openMedia(post, galleryItemIndex, -1);
private void openMedia(Post post, boolean peekMedia) {
openMedia(post, 0, peekMedia);
}
private void openMedia(Post post, int galleryItemIndex, boolean peekMedia) {
openMedia(post, galleryItemIndex, -1, peekMedia);
}
private void openMedia(Post post, long videoProgress) {
openMedia(post, 0, videoProgress);
openMedia(post, 0, videoProgress, false);
}
private void openMedia(Post post, int galleryItemIndex, long videoProgress) {
private void openMedia(Post post, long videoProgress, boolean peekMedia) {
openMedia(post, 0, videoProgress, peekMedia);
}
private void openMedia(Post post, int galleryItemIndex, long videoProgress, boolean peekMedia) {
if (canStartActivity) {
canStartActivity = false;
if (post.getPostType() == Post.VIDEO_TYPE) {
mActivity.setShouldTrackFullscreenMediaPeekTouchEvent(true);
Intent intent = new Intent(mActivity, ViewVideoActivity.class);
if (post.isImgur()) {
intent.setData(Uri.parse(post.getVideoUrl()));
@ -1812,6 +1833,8 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
intent.putExtra(ViewVideoActivity.EXTRA_IS_NSFW, post.isNSFW());
mActivity.startActivity(intent);
} else if (post.getPostType() == Post.IMAGE_TYPE) {
mActivity.setShouldTrackFullscreenMediaPeekTouchEvent(true);
Intent intent = new Intent(mActivity, ViewImageOrGifActivity.class);
intent.putExtra(ViewImageOrGifActivity.EXTRA_IMAGE_URL_KEY, post.getUrl());
intent.putExtra(ViewImageOrGifActivity.EXTRA_FILE_NAME_KEY, post.getSubredditName()
@ -1821,6 +1844,8 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
intent.putExtra(ViewImageOrGifActivity.EXTRA_IS_NSFW, post.isNSFW());
mActivity.startActivity(intent);
} else if (post.getPostType() == Post.GIF_TYPE) {
mActivity.setShouldTrackFullscreenMediaPeekTouchEvent(true);
if (post.getMp4Variant() != null) {
Intent intent = new Intent(mActivity, ViewVideoActivity.class);
intent.setData(Uri.parse(post.getMp4Variant()));
@ -1841,13 +1866,15 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
intent.putExtra(ViewImageOrGifActivity.EXTRA_IS_NSFW, post.isNSFW());
mActivity.startActivity(intent);
}
} else if (post.getPostType() == Post.LINK_TYPE || post.getPostType() == Post.NO_PREVIEW_LINK_TYPE) {
} else if (!peekMedia && post.getPostType() == Post.LINK_TYPE || post.getPostType() == Post.NO_PREVIEW_LINK_TYPE) {
Intent intent = new Intent(mActivity, LinkResolverActivity.class);
Uri uri = Uri.parse(post.getUrl());
intent.setData(uri);
intent.putExtra(LinkResolverActivity.EXTRA_IS_NSFW, post.isNSFW());
mActivity.startActivity(intent);
} else if (post.getPostType() == Post.GALLERY_TYPE) {
mActivity.setShouldTrackFullscreenMediaPeekTouchEvent(true);
Intent intent = new Intent(mActivity, ViewRedditGalleryActivity.class);
intent.putExtra(ViewRedditGalleryActivity.EXTRA_POST, post);
intent.putExtra(ViewRedditGalleryActivity.EXTRA_GALLERY_ITEM_INDEX, galleryItemIndex);
@ -2936,10 +2963,21 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
itemView.setOnLongClickListener(v -> {
Post post = getItem(getBindingAdapterPosition());
if (post == null) {
if (post == null || mLongPressPostNonMediaAreaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_NONE)) {
return false;
}
if (mLongPressPostNonMediaAreaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS)) {
showPostOptions();
} else if (mLongPressPostNonMediaAreaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_PREVIEW_IN_FULLSCREEN)) {
markPostRead(post, true);
openMedia(post, true);
}
return true;
});
}
void showPostOptions() {
PostOptionsBottomSheetFragment postOptionsBottomSheetFragment;
if (post.getPostType() == Post.GALLERY_TYPE && this instanceof PostBaseGalleryTypeViewHolder) {
postOptionsBottomSheetFragment = PostOptionsBottomSheetFragment.newInstance(post,
@ -2949,8 +2987,6 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
postOptionsBottomSheetFragment = PostOptionsBottomSheetFragment.newInstance(post, getBindingAdapterPosition());
}
postOptionsBottomSheetFragment.show(mActivity.getSupportFragmentManager(), postOptionsBottomSheetFragment.getTag());
return true;
});
}
@Override
@ -3318,7 +3354,17 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
}
});
imageView.setOnLongClickListener(view -> itemView.performLongClick());
imageView.setOnLongClickListener(view -> {
if (mLongPressPostMediaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS)) {
showPostOptions();
return true;
} else if (mLongPressPostMediaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_PREVIEW_IN_FULLSCREEN)) {
markPostRead(post, true);
openMedia(post, true);
return true;
}
return false;
});
loadImageErrorTextView.setOnClickListener(view -> {
loadingIndicator.setVisibility(View.VISIBLE);
@ -3480,8 +3526,16 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
if (!dragged && !longPressed) {
if (System.currentTimeMillis() - downTime >= longClickThreshold) {
itemView.performLongClick();
if (mLongPressPostMediaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS)) {
galleryRecyclerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
showPostOptions();
longPressed = true;
} else if (mLongPressPostMediaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_PREVIEW_IN_FULLSCREEN)) {
galleryRecyclerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
markPostRead(post, true);
openMedia(post, layoutManager.findFirstVisibleItemPosition(), true);
longPressed = true;
}
}
}
@ -3548,7 +3602,17 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
}
});
noPreviewImageView.setOnLongClickListener(view -> itemView.performLongClick());
noPreviewImageView.setOnLongClickListener(view -> {
if (mLongPressPostMediaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS)) {
showPostOptions();
return true;
} else if (mLongPressPostMediaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_PREVIEW_IN_FULLSCREEN)) {
markPostRead(post, true);
openMedia(post, layoutManager.findFirstVisibleItemPosition(), true);
return true;
}
return false;
});
}
public boolean isSwipeLocked() {
@ -3880,17 +3944,16 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
params.height = 0;
bottomConstraintLayout.setLayoutParams(params);
}
} else {
Post post = getItem(getBindingAdapterPosition());
if (post == null) {
return false;
}
PostOptionsBottomSheetFragment postOptionsBottomSheetFragment;
postOptionsBottomSheetFragment = PostOptionsBottomSheetFragment.newInstance(post, getBindingAdapterPosition());
postOptionsBottomSheetFragment.show(mActivity.getSupportFragmentManager(), postOptionsBottomSheetFragment.getTag());
}
return true;
} else if (mLongPressPostNonMediaAreaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS)) {
showPostOptions();
return true;
} else if (mLongPressPostNonMediaAreaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_PREVIEW_IN_FULLSCREEN)) {
markPostRead(post, true);
openMedia(post, true);
return true;
}
return false;
});
imageView.setOnClickListener(view -> {
@ -3905,10 +3968,24 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
}
});
imageView.setOnLongClickListener(v -> {
if (mLongPressPostMediaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS)) {
showPostOptions();
return true;
} else if (mLongPressPostMediaAction.equals(SharedPreferencesUtils.LONG_PRESS_POST_VALUE_PREVIEW_IN_FULLSCREEN)) {
markPostRead(post, true);
openMedia(post, true);
return true;
}
return false;
});
noPreviewLinkImageFrameLayout.setOnClickListener(view -> {
imageView.performClick();
});
noPreviewLinkImageFrameLayout.setOnLongClickListener(view -> imageView.performLongClick());
requestListener = new RequestListener<>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
@ -3924,6 +4001,17 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter<Post, RecyclerVie
};
}
void showPostOptions() {
Post post = getItem(getBindingAdapterPosition());
if (post == null) {
return;
}
PostOptionsBottomSheetFragment postOptionsBottomSheetFragment;
postOptionsBottomSheetFragment = PostOptionsBottomSheetFragment.newInstance(post, getBindingAdapterPosition());
postOptionsBottomSheetFragment.show(mActivity.getSupportFragmentManager(), postOptionsBottomSheetFragment.getTag());
}
@Override
void setItemViewBackgroundColor(boolean isReadPost) {
itemView.setBackgroundColor(isReadPost ? mReadPostCardViewBackgroundColor : mCardViewBackgroundColor);

View File

@ -0,0 +1,22 @@
package ml.docilealligator.infinityforreddit.customviews
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import com.google.android.material.card.MaterialCardView
class TouchInterceptableMaterialCardView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : MaterialCardView(context, attrs) {
private var mShouldInterceptTouchEvent: Boolean = false
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
return mShouldInterceptTouchEvent || super.onInterceptTouchEvent(ev)
}
public fun setShouldInterceptTouch(value: Boolean) {
mShouldInterceptTouchEvent = value
}
}

View File

@ -0,0 +1,4 @@
package ml.docilealligator.infinityforreddit.events
class FinishViewMediaActivityEvent {
}

View File

@ -102,6 +102,7 @@ import ml.docilealligator.infinityforreddit.events.PostUpdateEventToPostList;
import ml.docilealligator.infinityforreddit.events.ShowDividerInCompactLayoutPreferenceEvent;
import ml.docilealligator.infinityforreddit.events.ShowThumbnailOnTheLeftInCompactLayoutEvent;
import ml.docilealligator.infinityforreddit.post.Post;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesLiveDataKt;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
import retrofit2.Retrofit;
@ -340,6 +341,18 @@ public abstract class PostFragmentBase extends Fragment {
});
}
SharedPreferencesLiveDataKt.stringLiveData(mSharedPreferences, SharedPreferencesUtils.LONG_PRESS_POST_NON_MEDIA_AREA, SharedPreferencesUtils.LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS).observe(getViewLifecycleOwner(), s -> {
if (getPostAdapter() != null) {
getPostAdapter().setLongPressPostNonMediaAreaAction(s);
}
});
SharedPreferencesLiveDataKt.stringLiveData(mSharedPreferences, SharedPreferencesUtils.LONG_PRESS_POST_MEDIA, SharedPreferencesUtils.LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS).observe(getViewLifecycleOwner(), s -> {
if (getPostAdapter() != null) {
getPostAdapter().setLongPressPostMediaAction(s);
}
});
return super.onCreateView(inflater, container, savedInstanceState);
}
@ -970,7 +983,6 @@ public abstract class PostFragmentBase extends Fragment {
int spanIndex = layoutParams.getSpanIndex();
int viewPosition = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
if (parent.getAdapter() != null) {
RecyclerView.ViewHolder viewHolder = parent.getChildViewHolder(view);
if (viewHolder instanceof PostRecyclerViewAdapter.PostMaterial3CardVideoAutoplayViewHolder ||

View File

@ -0,0 +1,112 @@
package ml.docilealligator.infinityforreddit.utils
import android.content.SharedPreferences
import androidx.lifecycle.LiveData
abstract class SharedPreferenceLiveData<T>(
val sharedPrefs: SharedPreferences,
val key: String,
private val defValue: T
) : LiveData<T>() {
private val preferenceChangeListener =
SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
if (key == this.key) {
value = getValueFromPreferences(key, defValue)
}
}
abstract fun getValueFromPreferences(key: String, defValue: T): T
override fun onActive() {
super.onActive()
value = getValueFromPreferences(key, defValue)
sharedPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
}
override fun onInactive() {
sharedPrefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
super.onInactive()
}
}
class SharedPreferenceIntLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Int) :
SharedPreferenceLiveData<Int>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Int): Int =
sharedPrefs.getInt(key, defValue)
}
class SharedPreferenceStringLiveData(
sharedPrefs: SharedPreferences,
key: String,
defValue: String
) :
SharedPreferenceLiveData<String>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: String): String =
sharedPrefs.getString(key, defValue)!!
}
class SharedPreferenceBooleanLiveData(
sharedPrefs: SharedPreferences,
key: String,
defValue: Boolean
) :
SharedPreferenceLiveData<Boolean>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Boolean): Boolean =
sharedPrefs.getBoolean(key, defValue)
}
class SharedPreferenceFloatLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Float) :
SharedPreferenceLiveData<Float>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Float): Float =
sharedPrefs.getFloat(key, defValue)
}
class SharedPreferenceLongLiveData(sharedPrefs: SharedPreferences, key: String, defValue: Long) :
SharedPreferenceLiveData<Long>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Long): Long =
sharedPrefs.getLong(key, defValue)
}
class SharedPreferenceStringSetLiveData(
sharedPrefs: SharedPreferences,
key: String,
defValue: Set<String>
) :
SharedPreferenceLiveData<Set<String>>(sharedPrefs, key, defValue) {
override fun getValueFromPreferences(key: String, defValue: Set<String>): Set<String> =
sharedPrefs.getStringSet(key, defValue)!!
}
fun SharedPreferences.intLiveData(key: String, defValue: Int): SharedPreferenceLiveData<Int> {
return SharedPreferenceIntLiveData(this, key, defValue)
}
fun SharedPreferences.stringLiveData(
key: String,
defValue: String
): SharedPreferenceLiveData<String> {
return SharedPreferenceStringLiveData(this, key, defValue)
}
fun SharedPreferences.booleanLiveData(
key: String,
defValue: Boolean
): SharedPreferenceLiveData<Boolean> {
return SharedPreferenceBooleanLiveData(this, key, defValue)
}
fun SharedPreferences.floatLiveData(key: String, defValue: Float): SharedPreferenceLiveData<Float> {
return SharedPreferenceFloatLiveData(this, key, defValue)
}
fun SharedPreferences.longLiveData(key: String, defValue: Long): SharedPreferenceLiveData<Long> {
return SharedPreferenceLongLiveData(this, key, defValue)
}
fun SharedPreferences.stringSetLiveData(
key: String,
defValue: Set<String>
): SharedPreferenceLiveData<Set<String>> {
return SharedPreferenceStringSetLiveData(this, key, defValue)
}

View File

@ -226,6 +226,11 @@ public class SharedPreferencesUtils {
private static final String POST_DETAIL_FAB_LANDSCAPE_Y_BASE = "fab_landscape_y_";
public static final String REDDIT_VIDEO_DEFAULT_RESOLUTION_NO_DATA_SAVING = "reddit_video_default_resolution_no_data_saving";
public static final String HIDE_FAB_IN_POST_DETAILS = "hide_fab_in_post_details";
public static final String LONG_PRESS_POST_NON_MEDIA_AREA = "long_press_post_non_media_area";
public static final String LONG_PRESS_POST_MEDIA = "long_press_post_media";
public static final String LONG_PRESS_POST_VALUE_NONE = "0";
public static final String LONG_PRESS_POST_VALUE_SHOW_POST_OPTIONS = "1";
public static final String LONG_PRESS_POST_VALUE_PREVIEW_IN_FULLSCREEN = "2";
public static String getPostDetailFabPortraitX(@Nullable Display display) {
if (display == null) {

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
<ml.docilealligator.infinityforreddit.customviews.TouchInterceptableMaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -355,4 +355,4 @@
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</ml.docilealligator.infinityforreddit.customviews.TouchInterceptableMaterialCardView>

View File

@ -749,4 +749,28 @@
<item>DIRECT</item>
</string-array>
<string-array name="settings_long_press_post_non_media_area_action">
<item>@string/none</item>
<item>@string/show_post_options</item>
<item>@string/preview_in_fullscreen</item>
</string-array>
<string-array name="settings_long_press_post_non_media_area_action_values">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
<string-array name="settings_long_press_post_media_action">
<item>@string/none</item>
<item>@string/show_post_options</item>
<item>@string/preview_in_fullscreen</item>
</string-array>
<string-array name="settings_long_press_post_media_action_values">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
</resources>

View File

@ -1542,4 +1542,8 @@
<string name="proxy_direct">Direct</string>
<string name="jump_to_parent_comment">Jump to Parent Comment</string>
<string name="long_press_post_non_media_area">Long Press on Post (Non-Media Area)</string>
<string name="long_press_post_media">Long Press on Media</string>
<string name="show_post_options">Show Post Options</string>
<string name="preview_in_fullscreen">Preview in Fullscreen</string>
</resources>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<ml.docilealligator.infinityforreddit.customviews.preference.CustomFontSwitchPreference
app:defaultValue="true"
@ -60,6 +61,22 @@
app:title="@string/settings_pinch_to_zoom_video_title"
app:summary="@string/settings_experimental_feature" />
<ml.docilealligator.infinityforreddit.customviews.preference.CustomFontListPreference
app:defaultValue="1"
android:entries="@array/settings_long_press_post_non_media_area_action"
app:entryValues="@array/settings_long_press_post_non_media_area_action_values"
app:key="long_press_post_non_media_area"
app:title="@string/long_press_post_non_media_area"
app:useSimpleSummaryProvider="true" />
<ml.docilealligator.infinityforreddit.customviews.preference.CustomFontListPreference
app:defaultValue="1"
android:entries="@array/settings_long_press_post_media_action"
app:entryValues="@array/settings_long_press_post_media_action_values"
app:key="long_press_post_media"
app:title="@string/long_press_post_media"
app:useSimpleSummaryProvider="true" />
<ml.docilealligator.infinityforreddit.customviews.preference.CustomFontPreference
app:title="@string/settings_swipe_action_title"
app:fragment="ml.docilealligator.infinityforreddit.settings.SwipeActionPreferenceFragment" />