diff --git a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java index 32a1d414e..8790c3059 100644 --- a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java @@ -1,7 +1,6 @@ package org.schabi.newpipe.local; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.content.res.Resources; import android.os.Bundle; import android.util.Log; @@ -26,6 +25,7 @@ import org.schabi.newpipe.fragments.list.ListViewContract; import static org.schabi.newpipe.ktx.ViewUtils.animate; import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling; +import static org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout; /** * This fragment is design to be used with persistent data such as @@ -77,7 +77,7 @@ public abstract class BaseLocalListFragment extends BaseStateFragment super.onResume(); if (updateFlags != 0) { if ((updateFlags & LIST_MODE_UPDATE_FLAG) != 0) { - final boolean useGrid = isGridLayout(); + final boolean useGrid = shouldUseGridLayout(requireContext()); itemsList.setLayoutManager( useGrid ? getGridLayoutManager() : getListLayoutManager()); itemListAdapter.setUseGridVariant(useGrid); @@ -121,7 +121,7 @@ public abstract class BaseLocalListFragment extends BaseStateFragment itemListAdapter = new LocalItemListAdapter(activity); - final boolean useGrid = isGridLayout(); + final boolean useGrid = shouldUseGridLayout(requireContext()); itemsList = rootView.findViewById(R.id.items_list); itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager()); @@ -260,17 +260,4 @@ public abstract class BaseLocalListFragment extends BaseStateFragment updateFlags |= LIST_MODE_UPDATE_FLAG; } } - - protected boolean isGridLayout() { - final String listMode = PreferenceManager.getDefaultSharedPreferences(activity) - .getString(getString(R.string.list_view_mode_key), - getString(R.string.list_view_mode_value)); - if ("auto".equals(listMode)) { - final Configuration configuration = getResources().getConfiguration(); - return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE - && configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE); - } else { - return "grid".equals(listMode); - } - } } diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index a64ffee1e..03d39b13c 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -23,7 +23,6 @@ import android.annotation.SuppressLint import android.app.Activity import android.content.Intent import android.content.SharedPreferences -import android.content.res.Configuration import android.os.Bundle import android.os.Parcelable import android.view.LayoutInflater @@ -74,10 +73,10 @@ import org.schabi.newpipe.player.helper.PlayerHolder import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.NavigationHelper import org.schabi.newpipe.util.StreamDialogEntry +import org.schabi.newpipe.util.ThemeHelper.getGridSpanCount +import org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout import java.time.OffsetDateTime import java.util.ArrayList -import kotlin.math.floor -import kotlin.math.max class FeedFragment : BaseStateFragment() { private var _feedBinding: FragmentFeedBinding? = null @@ -161,7 +160,7 @@ class FeedFragment : BaseStateFragment() { fun setupListViewMode() { // does everything needed to setup the layouts for grid or list modes - groupAdapter.spanCount = if (shouldUseGridLayout()) getGridSpanCount() else 1 + groupAdapter.spanCount = if (shouldUseGridLayout(context)) getGridSpanCount(context) else 1 feedBinding.itemsList.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply { spanSizeLookup = groupAdapter.spanSizeLookup } @@ -376,7 +375,7 @@ class FeedFragment : BaseStateFragment() { @SuppressLint("StringFormatMatches") private fun handleLoadedState(loadedState: FeedState.LoadedState) { - val itemVersion = if (shouldUseGridLayout()) { + val itemVersion = if (shouldUseGridLayout(context)) { StreamItem.ItemVersion.GRID } else { StreamItem.ItemVersion.NORMAL @@ -520,35 +519,6 @@ class FeedFragment : BaseStateFragment() { listState = null } - // ///////////////////////////////////////////////////////////////////////// - // Grid Mode - // ///////////////////////////////////////////////////////////////////////// - - // TODO: Move these out of this class, as it can be reused - - private fun shouldUseGridLayout(): Boolean { - val listMode = PreferenceManager.getDefaultSharedPreferences(requireContext()) - .getString(getString(R.string.list_view_mode_key), getString(R.string.list_view_mode_value)) - - return when (listMode) { - getString(R.string.list_view_mode_auto_key) -> { - val configuration = resources.configuration - - ( - configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && - configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE) - ) - } - getString(R.string.list_view_mode_grid_key) -> true - else -> false - } - } - - private fun getGridSpanCount(): Int { - val minWidth = resources.getDimensionPixelSize(R.dimen.video_item_grid_thumbnail_image_width) - return max(1, floor(resources.displayMetrics.widthPixels / minWidth.toDouble()).toInt()) - } - companion object { const val KEY_GROUP_ID = "ARG_GROUP_ID" const val KEY_GROUP_NAME = "ARG_GROUP_NAME" diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 3edbff45a..947b21767 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -68,6 +68,7 @@ import io.reactivex.rxjava3.subjects.PublishSubject; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; import static org.schabi.newpipe.ktx.ViewUtils.animate; +import static org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout; public class LocalPlaylistFragment extends BaseLocalListFragment, Void> { // Save the list 10 seconds after the last change occurred @@ -678,7 +679,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment() { private var _binding: FragmentSubscriptionBinding? = null @@ -269,8 +267,7 @@ class SubscriptionFragment : BaseStateFragment() { super.initViews(rootView, savedInstanceState) _binding = FragmentSubscriptionBinding.bind(rootView) - val shouldUseGridLayout = shouldUseGridLayout() - groupAdapter.spanCount = if (shouldUseGridLayout) getGridSpanCount() else 1 + groupAdapter.spanCount = if (shouldUseGridLayout(context)) getGridSpanCount(context) else 1 binding.itemsList.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply { spanSizeLookup = groupAdapter.spanSizeLookup } @@ -349,7 +346,7 @@ class SubscriptionFragment : BaseStateFragment() { override fun handleResult(result: SubscriptionState) { super.handleResult(result) - val shouldUseGridLayout = shouldUseGridLayout() + val shouldUseGridLayout = shouldUseGridLayout(context) when (result) { is SubscriptionState.LoadedState -> { result.subscriptions.forEach { @@ -410,30 +407,4 @@ class SubscriptionFragment : BaseStateFragment() { super.hideLoading() binding.itemsList.animate(true, 200) } - - // ///////////////////////////////////////////////////////////////////////// - // Grid Mode - // ///////////////////////////////////////////////////////////////////////// - - // TODO: Move these out of this class, as it can be reused - - private fun shouldUseGridLayout(): Boolean { - val listMode = PreferenceManager.getDefaultSharedPreferences(requireContext()) - .getString(getString(R.string.list_view_mode_key), getString(R.string.list_view_mode_value)) - - return when (listMode) { - getString(R.string.list_view_mode_auto_key) -> { - val configuration = resources.configuration - configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && - configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE) - } - getString(R.string.list_view_mode_grid_key) -> true - else -> false - } - } - - private fun getGridSpanCount(): Int { - val minWidth = resources.getDimensionPixelSize(R.dimen.channel_item_grid_min_width) - return max(1, floor(resources.displayMetrics.widthPixels / minWidth.toDouble()).toInt()) - } } diff --git a/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java b/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java index 907bcf0ba..f3ae002dd 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java @@ -298,4 +298,43 @@ public final class ThemeHelper { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); } } + + + /** + * Returns whether the grid layout or the list layout should be used. If the user set "auto" + * mode in settings, decides based on screen orientation (landscape) and size. + * + * @param context the context to use + * @return true:use grid layout, false:use list layout + */ + public static boolean shouldUseGridLayout(final Context context) { + final String listMode = PreferenceManager.getDefaultSharedPreferences(context) + .getString(context.getString(R.string.list_view_mode_key), + context.getString(R.string.list_view_mode_value)); + + if (listMode.equals(context.getString(R.string.list_view_mode_list_key))) { + return false; + } else if (listMode.equals(context.getString(R.string.list_view_mode_grid_key))) { + return true; + } else { + final Configuration configuration = context.getResources().getConfiguration(); + return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE + && configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE); + } + } + + /** + * Calculates the number of grid items that can fit horizontally on the screen. The width of a + * grid item is obtained from the thumbnail width plus the right and left paddings. + * + * @param context the context to use + * @return the span count of grid list items + */ + public static int getGridSpanCount(final Context context) { + final Resources res = context.getResources(); + final int minWidth + = res.getDimensionPixelSize(R.dimen.video_item_grid_thumbnail_image_width) + + res.getDimensionPixelSize(R.dimen.video_item_search_padding) * 2; + return Math.max(1, res.getDisplayMetrics().widthPixels / minWidth); + } }