Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it possible to sort the home screen #7048

Merged
merged 37 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
795f1f0
Possibility to drag sections
Mar 28, 2024
14798ae
Styling and prepare to start using sort order
Mar 28, 2024
14c0cdb
Make home sorted depending on order
Mar 29, 2024
ff72e22
Revert unintended change
Mar 29, 2024
7e0ed97
Merge branch 'develop' into feature/sortable-home-screen
Mar 29, 2024
499797f
Let users move sections to disabled
Mar 30, 2024
7df56cf
Merge branch 'develop' into feature/sortable-home-screen
Mar 30, 2024
13792ba
Fix merge conflicts
Mar 30, 2024
3064bf5
Rename variable
Mar 30, 2024
ac32486
Renaming
Mar 30, 2024
9e04011
Style changes
Mar 30, 2024
a1dc666
Extract to another method
Mar 30, 2024
83c8c3d
Renamings
Mar 30, 2024
94fb00a
Fix code style
Mar 30, 2024
b1cda5b
Fix code style
Mar 30, 2024
26200d1
Fix code style
Mar 30, 2024
f6a3abb
Code style fixes
Mar 30, 2024
4a0082e
Code style fixes
Mar 30, 2024
2864205
XML code style fixes
Mar 30, 2024
61b2a7a
More XML code style fixes
Mar 30, 2024
d4a6327
PR comments
Apr 1, 2024
854b5dd
PR comments
Apr 1, 2024
47929cf
PR comments
Apr 1, 2024
1e20681
PR comments
Apr 1, 2024
7e90028
PR comments
Apr 1, 2024
b6fa46c
Ads home section items directly to the member variable
Apr 1, 2024
1de718f
PR Comments
Apr 1, 2024
dee6489
PR Comments
Apr 1, 2024
617057b
PR Comments
Apr 1, 2024
7001d90
Fixed bug where the hidden sections would switch place
Apr 1, 2024
0ba2654
Merge branch 'develop' into feature/sortable-home-screen
Apr 1, 2024
d86afdf
Moved stuff to code restructuring
Apr 1, 2024
4f17369
Small design improvement
Apr 1, 2024
f3ff2db
Fixes long lines
Apr 1, 2024
b229eeb
Decreases the text size of the hidden text
Apr 3, 2024
1e1f820
Small code style changes, add reset button
ByteHamster Apr 5, 2024
151a3b0
Merge branch 'develop' into fork/feature/sortable-home-screen
ByteHamster Apr 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,54 @@
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentContainerView;

import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.databinding.HomeFragmentBinding;
import de.danoeh.antennapod.event.FeedListUpdateEvent;
import de.danoeh.antennapod.event.FeedUpdateRunningEvent;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
import de.danoeh.antennapod.net.download.serviceinterface.FeedUpdateManager;
import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.ui.echo.EchoConfig;
import de.danoeh.antennapod.ui.screen.SearchFragment;
import de.danoeh.antennapod.ui.screen.home.sections.AllowNotificationsSection;
import de.danoeh.antennapod.ui.screen.home.sections.DownloadsSection;
import de.danoeh.antennapod.ui.screen.home.sections.EchoSection;
import de.danoeh.antennapod.ui.screen.home.sections.EpisodesSurpriseSection;
import de.danoeh.antennapod.ui.screen.home.sections.InboxSection;
import de.danoeh.antennapod.ui.screen.home.sections.QueueSection;
import de.danoeh.antennapod.ui.screen.home.sections.SubscriptionsSection;
import de.danoeh.antennapod.ui.screen.home.settingsdialog.HomePreferences;
import de.danoeh.antennapod.ui.screen.home.settingsdialog.HomeSectionsSettingsDialog;
import de.danoeh.antennapod.ui.view.LiftOnScrollListener;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;

import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.databinding.HomeFragmentBinding;
import de.danoeh.antennapod.event.FeedListUpdateEvent;
import de.danoeh.antennapod.event.FeedUpdateRunningEvent;
import de.danoeh.antennapod.ui.screen.SearchFragment;
import de.danoeh.antennapod.ui.view.LiftOnScrollListener;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

/**
* Shows unread or recently published episodes
*/
public class HomeFragment extends Fragment implements Toolbar.OnMenuItemClickListener {

public static final String TAG = "HomeFragment";
public static final String PREF_NAME = "PrefHomeFragment";
public static final String PREF_HIDDEN_SECTIONS = "PrefHomeSectionsString";
public static final String PREF_DISABLE_NOTIFICATION_PERMISSION_NAG = "DisableNotificationPermissionNag";
public static final String PREF_HIDE_ECHO = "HideEcho";

Expand Down Expand Up @@ -106,12 +101,8 @@ private void populateSectionList() {
addSection(new EchoSection());
}

List<String> hiddenSections = getHiddenSections(getContext());
String[] sectionTags = getResources().getStringArray(R.array.home_section_tags);
List<String> sectionTags = HomePreferences.getSortedSectionTags(getContext());
for (String sectionTag : sectionTags) {
if (hiddenSections.contains(sectionTag)) {
continue;
}
addSection(getSection(sectionTag));
}
}
Expand Down Expand Up @@ -140,12 +131,6 @@ private Fragment getSection(String tag) {
}
}

public static List<String> getHiddenSections(Context context) {
SharedPreferences prefs = context.getSharedPreferences(HomeFragment.PREF_NAME, Context.MODE_PRIVATE);
String hiddenSectionsString = prefs.getString(HomeFragment.PREF_HIDDEN_SECTIONS, "");
return new ArrayList<>(Arrays.asList(TextUtils.split(hiddenSectionsString, ",")));
}

@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventMainThread(FeedUpdateRunningEvent event) {
viewBinding.swipeRefresh.setRefreshing(event.isFeedUpdateRunning);
Expand All @@ -154,7 +139,7 @@ public void onEventMainThread(FeedUpdateRunningEvent event) {
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.homesettings_items) {
HomeSectionsSettingsDialog.open(getContext(), (dialogInterface, i) -> populateSectionList());
HomeSectionsSettingsDialog.open(getContext(), this::populateSectionList);
return true;
} else if (item.getItemId() == R.id.refresh_item) {
FeedUpdateManager.getInstance().runOnceOrAsk(requireContext());
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package de.danoeh.antennapod.ui.screen.home.settingsdialog;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import de.danoeh.antennapod.R;
import de.danoeh.antennapod.ui.screen.home.HomeFragment;

public class HomePreferences {
private static final String PREF_HIDDEN_SECTIONS = "PrefHomeSectionsString";
private static final String PREF_SECTION_ORDER = "PrefHomeSectionOrder";
private static HashMap<String, String> sectionTagToName;

public static String getNameFromTag(Context context, String sectionTag) {
if (sectionTagToName == null) {
initializeMap(context);
}

return sectionTagToName.get(sectionTag);
}

private static void initializeMap(Context context) {
Resources resources = context.getResources();
String[] sectionLabels = resources.getStringArray(R.array.home_section_titles);
String[] sectionTags = resources.getStringArray(R.array.home_section_tags);

sectionTagToName = new HashMap<>(sectionTags.length);

for (int i = 0; i < sectionLabels.length; i++) {
String label = sectionLabels[i];
String tag = sectionTags[i];

sectionTagToName.put(tag, label);
}
}

public static List<String> getHiddenSectionTags(Context context) {
return getListPreference(context, PREF_HIDDEN_SECTIONS);
}

public static List<String> getSortedSectionTags(Context context) {
List<String> sectionTagOrder = getListPreference(context, PREF_SECTION_ORDER);
List<String> hiddenSectionTags = getHiddenSectionTags(context);
String[] sectionTags = context.getResources().getStringArray(R.array.home_section_tags);
Arrays.sort(sectionTags, (String a, String b) -> Integer.signum(
indexOfOrMaxValue(sectionTagOrder, a) - indexOfOrMaxValue(sectionTagOrder, b)));

List<String> finalSectionTags = new ArrayList<>();
for (String sectionTag: sectionTags) {
if (hiddenSectionTags.contains(sectionTag)) {
continue;
}

finalSectionTags.add(sectionTag);
}

return finalSectionTags;
}

private static List<String> getListPreference(Context context, String preferenceKey) {
SharedPreferences prefs = context.getSharedPreferences(HomeFragment.PREF_NAME, Context.MODE_PRIVATE);
String hiddenSectionsString = prefs.getString(preferenceKey, "");
return new ArrayList<>(Arrays.asList(TextUtils.split(hiddenSectionsString, ",")));
}

private static int indexOfOrMaxValue(List<String> haystack, String needle) {
int index = haystack.indexOf(needle);
return index == -1 ? Integer.MAX_VALUE : index;
}

public static void saveChanges(Context context, List<String> hiddenSections, List<String> sectionOrder) {
SharedPreferences prefs = context.getSharedPreferences(HomeFragment.PREF_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
edit.putString(PREF_HIDDEN_SECTIONS, TextUtils.join(",", hiddenSections));
edit.putString(PREF_SECTION_ORDER, TextUtils.join(",", sectionOrder));
edit.apply();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package de.danoeh.antennapod.ui.screen.home.settingsdialog;

import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Consumer;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import de.danoeh.antennapod.databinding.ChooseHomeScreenOrderDialogEntryBinding;
import de.danoeh.antennapod.databinding.ChooseHomeScreenOrderDialogHeaderBinding;

class HomeScreenSettingDialogAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int HEADER_VIEW = 0;
private static final int ITEM_VIEW = 1;
private final List<HomeScreenSettingsDialogItem> settingsDialogItems;
@Nullable private Consumer<ItemViewHolder> dragListener;

public HomeScreenSettingDialogAdapter(@NonNull List<HomeScreenSettingsDialogItem> dialogItems) {
settingsDialogItems = dialogItems;
}

public void setDragListener(@Nullable Consumer<ItemViewHolder> dragListener) {
this.dragListener = dragListener;
}

@NonNull
public List<String> getOrderedSectionTags() {
List<String> orderedSectionTags = new ArrayList<>();
for (HomeScreenSettingsDialogItem item: settingsDialogItems) {
if (item.getViewType() == HomeScreenSettingsDialogItem.ViewType.Header) {
continue;
}

orderedSectionTags.add(item.getTitle());
}

return orderedSectionTags;
}

public List<String> getHiddenSectionTags() {
List<String> hiddenSections = new ArrayList<>();
for (int i = settingsDialogItems.size() - 1; i >= 0; i--) {
HomeScreenSettingsDialogItem item = settingsDialogItems.get(i);
if (item.getViewType() == HomeScreenSettingsDialogItem.ViewType.Header) {
return hiddenSections;
}

hiddenSections.add(item.getTitle());
}

Collections.reverse(hiddenSections);
return hiddenSections;
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
if (viewType == HEADER_VIEW) {
ChooseHomeScreenOrderDialogHeaderBinding binding = ChooseHomeScreenOrderDialogHeaderBinding.inflate(
inflater, parent, false);
return new HeaderViewHolder(binding.getRoot(), binding.headerLabel);
}

ChooseHomeScreenOrderDialogEntryBinding binding = ChooseHomeScreenOrderDialogEntryBinding.inflate(
inflater, parent, false);
return new ItemViewHolder(binding.getRoot(), binding.sectionLabel, binding.dragHandle);
}

@Override
public int getItemViewType(int position) {
HomeScreenSettingsDialogItem.ViewType viewType = settingsDialogItems.get(position).getViewType();
boolean isHeader = viewType == HomeScreenSettingsDialogItem.ViewType.Header;
return isHeader ? HEADER_VIEW : ITEM_VIEW;
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
String title = settingsDialogItems.get(position).getTitle();
if (holder instanceof HeaderViewHolder) {
HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder;
headerViewHolder.categoryLabel.setText(title);
} else if (holder instanceof ItemViewHolder) {
ItemViewHolder itemViewHolder = (ItemViewHolder) holder;
String sectionName = HomePreferences.getNameFromTag(itemViewHolder.nameLabel.getContext(), title);
itemViewHolder.nameLabel.setText(sectionName);
itemViewHolder.dragImage.setOnTouchListener((view, motionEvent) -> {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
if (dragListener != null) {
dragListener.accept(itemViewHolder);
}
}
return true;
});
}
}

@Override
public int getItemCount() {
return settingsDialogItems.size();
}

public boolean onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(settingsDialogItems, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(settingsDialogItems, i, i - 1);
}
}

notifyItemMoved(fromPosition, toPosition);
return true;
}

static class ItemViewHolder extends RecyclerView.ViewHolder {
private final TextView nameLabel;
private final ImageView dragImage;

ItemViewHolder(@NonNull View itemView, TextView nameLabel, ImageView dragImage) {
super(itemView);
this.nameLabel = nameLabel;
this.dragImage = dragImage;
}
}

static class HeaderViewHolder extends RecyclerView.ViewHolder {

private final TextView categoryLabel;

HeaderViewHolder(@NonNull View itemView, @NonNull TextView categoryLabel) {
super(itemView);
this.categoryLabel = categoryLabel;
}
}
}
Loading