Remove gpodder toplist

Half of the toplist no longer returns a valid podcast feed.
Some of the suggested tags are just random characters and none of them
is actually helpful.

This does not remove search or synchronization.
Just gpodder discovery.
This commit is contained in:
ByteHamster 2022-05-13 20:22:47 +02:00
parent 6e5004be22
commit 5448e1f390
18 changed files with 136 additions and 1054 deletions

View File

@ -1,110 +0,0 @@
package de.test.antennapod.gpodnet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService;
import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetServiceException;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetDevice;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetTag;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import static java.util.Collections.singletonList;
/**
* Test class for GpodnetService
*/
@Ignore("Needs valid credentials to run")
@RunWith(AndroidJUnit4.class)
public class GPodnetServiceTest {
private GpodnetService service;
private static final String USER = "";
private static final String PW = "";
private static final String DEVICE_ID = "radio";
@Before
public void setUp() {
service = new GpodnetService(AntennapodHttpClient.getHttpClient(),
GpodnetService.DEFAULT_BASE_HOST, DEVICE_ID, USER, PW);
}
private void authenticate() throws GpodnetServiceException {
service.login();
}
@Test
public void testUploadSubscription() throws GpodnetServiceException {
authenticate();
ArrayList<String> l = new ArrayList<>();
l.add("http://bitsundso.de/feed");
service.uploadSubscriptions(DEVICE_ID, l);
}
@Test
public void testUploadSubscription2() throws GpodnetServiceException {
authenticate();
ArrayList<String> l = new ArrayList<>();
l.add("http://bitsundso.de/feed");
l.add("http://gamesundso.de/feed");
service.uploadSubscriptions(DEVICE_ID, l);
}
@Test
public void testUploadChanges() throws GpodnetServiceException {
authenticate();
String[] URLS = {"http://bitsundso.de/feed", "http://gamesundso.de/feed", "http://cre.fm/feed/mp3/", "http://freakshow.fm/feed/m4a/"};
List<String> subscriptions = Arrays.asList(URLS[0], URLS[1]);
List<String> removed = singletonList(URLS[0]);
List<String> added = Arrays.asList(URLS[2], URLS[3]);
service.uploadSubscriptions(DEVICE_ID, subscriptions);
service.uploadSubscriptionChanges(added, removed);
}
@Test
public void testGetSubscriptionChanges() throws GpodnetServiceException {
authenticate();
service.getSubscriptionChanges(1362322610L);
}
@Test
public void testConfigureDevices() throws GpodnetServiceException {
authenticate();
service.configureDevice("foo", "This is an updated caption", GpodnetDevice.DeviceType.LAPTOP);
}
@Test
public void testGetDevices() throws GpodnetServiceException {
authenticate();
service.getDevices();
}
@Test
public void testTags() throws GpodnetServiceException {
service.getTopTags(20);
}
@Test
public void testPodcastForTags() throws GpodnetServiceException {
List<GpodnetTag> tags = service.getTopTags(20);
service.getPodcastsForTag(tags.get(1),
10);
}
@Test
public void testSearch() throws GpodnetServiceException {
service.searchPodcasts("linux", 64);
}
@Test
public void testToplist() throws GpodnetServiceException {
service.getPodcastToplist(10);
}
}

View File

@ -1,83 +0,0 @@
package de.danoeh.antennapod.adapter.gpodnet;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.FitCenter;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast;
import org.apache.commons.lang3.StringUtils;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import java.util.List;
/**
* Adapter for displaying a list of GPodnetPodcast-Objects.
*/
public class PodcastListAdapter extends ArrayAdapter<GpodnetPodcast> {
public PodcastListAdapter(Context context, int resource, List<GpodnetPodcast> objects) {
super(context, resource, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
GpodnetPodcast podcast = getItem(position);
// Inflate Layout
if (convertView == null) {
holder = new Holder();
LayoutInflater inflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.gpodnet_podcast_listitem, parent, false);
holder.image = convertView.findViewById(R.id.imgvCover);
holder.title = convertView.findViewById(R.id.txtvTitle);
holder.subscribers = convertView.findViewById(R.id.txtvSubscribers);
holder.author = convertView.findViewById(R.id.txtvAuthor);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
if (StringUtils.isNotBlank(podcast.getLogoUrl())) {
Glide.with(convertView.getContext())
.load(podcast.getLogoUrl())
.apply(new RequestOptions()
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.transforms(new FitCenter(),
new RoundedCorners((int) (4 * convertView.getContext()
.getResources().getDisplayMetrics().density)))
.dontAnimate())
.into(holder.image);
}
holder.title.setText(podcast.getTitle());
holder.subscribers.setText(String.valueOf(podcast.getSubscribers()));
holder.author.setText(podcast.getAuthor());
return convertView;
}
static class Holder {
ImageView image;
TextView title;
TextView subscribers;
TextView author;
}
}

View File

@ -1,54 +0,0 @@
package de.danoeh.antennapod.adapter.gpodnet;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetTag;
import java.util.List;
/**
* Adapter for displaying a list of GPodnetPodcast-Objects.
*/
public class TagListAdapter extends ArrayAdapter<GpodnetTag> {
public TagListAdapter(Context context, int resource, List<GpodnetTag> objects) {
super(context, resource, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
GpodnetTag tag = getItem(position);
// Inflate Layout
if (convertView == null) {
holder = new Holder();
LayoutInflater inflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.gpodnet_tag_listitem, parent, false);
holder.title = convertView.findViewById(R.id.txtvTitle);
holder.usage = convertView.findViewById(R.id.txtvUsage);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.title.setText(tag.getTitle());
holder.usage.setText(String.valueOf(tag.getUsage()));
return convertView;
}
static class Holder {
TextView title;
TextView usage;
}
}

View File

@ -35,9 +35,9 @@ import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.model.feed.SortOrder;
import de.danoeh.antennapod.databinding.AddfeedBinding;
import de.danoeh.antennapod.databinding.EditTextDialogBinding;
import de.danoeh.antennapod.fragment.gpodnet.GpodnetMainFragment;
import de.danoeh.antennapod.net.discovery.CombinedSearcher;
import de.danoeh.antennapod.net.discovery.FyydPodcastSearcher;
import de.danoeh.antennapod.net.discovery.GpodnetPodcastSearcher;
import de.danoeh.antennapod.net.discovery.ItunesPodcastSearcher;
import de.danoeh.antennapod.net.discovery.PodcastIndexPodcastSearcher;
import io.reactivex.Observable;
@ -84,7 +84,7 @@ public class AddFeedFragment extends Fragment {
viewBinding.searchFyydButton.setOnClickListener(v
-> activity.loadChildFragment(OnlineSearchFragment.newInstance(FyydPodcastSearcher.class)));
viewBinding.searchGPodderButton.setOnClickListener(v
-> activity.loadChildFragment(new GpodnetMainFragment()));
-> activity.loadChildFragment(OnlineSearchFragment.newInstance(GpodnetPodcastSearcher.class)));
viewBinding.searchPodcastIndexButton.setOnClickListener(v
-> activity.loadChildFragment(OnlineSearchFragment.newInstance(PodcastIndexPodcastSearcher.class)));

View File

@ -1,112 +0,0 @@
package de.danoeh.antennapod.fragment.gpodnet;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.fragment.OnlineSearchFragment;
import de.danoeh.antennapod.net.discovery.GpodnetPodcastSearcher;
/**
* Main navigation hub for gpodder.net podcast directory
*/
public class GpodnetMainFragment extends Fragment {
private static final int NUM_PAGES = 2;
private static final int POS_TOPLIST = 0;
private static final int POS_TAGS = 1;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View root = inflater.inflate(R.layout.pager_fragment, container, false);
setupToolbar(root.findViewById(R.id.toolbar));
ViewPager2 viewPager = root.findViewById(R.id.viewpager);
GpodnetPagerAdapter pagerAdapter = new GpodnetPagerAdapter(this);
viewPager.setAdapter(pagerAdapter);
// Give the TabLayout the ViewPager
TabLayout tabLayout = root.findViewById(R.id.sliding_tabs);
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
switch (position) {
case POS_TAGS:
tab.setText(R.string.gpodnet_taglist_header);
break;
case POS_TOPLIST: // Fall-through
default:
tab.setText(R.string.gpodnet_toplist_header);
break;
}
}).attach();
return root;
}
private void setupToolbar(Toolbar toolbar) {
toolbar.setTitle(R.string.gpodnet_main_label);
toolbar.setNavigationOnClickListener(v -> getParentFragmentManager().popBackStack());
toolbar.inflateMenu(R.menu.search);
MenuItem searchItem = toolbar.getMenu().findItem(R.id.action_search);
final SearchView sv = (SearchView) searchItem.getActionView();
sv.setQueryHint(getString(R.string.gpodnet_search_hint));
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
Activity activity = getActivity();
if (activity != null) {
searchItem.collapseActionView();
((MainActivity) activity).loadChildFragment(
OnlineSearchFragment.newInstance(GpodnetPodcastSearcher.class, query));
}
return true;
}
@Override
public boolean onQueryTextChange(String s) {
return false;
}
});
}
public static class GpodnetPagerAdapter extends FragmentStateAdapter {
GpodnetPagerAdapter(@NonNull Fragment fragment) {
super(fragment);
}
@NonNull
@Override
public Fragment createFragment(int position) {
switch (position) {
case POS_TAGS:
return new TagListFragment();
case POS_TOPLIST: // Fall-through
default:
return new PodcastTopListFragment();
}
}
@Override
public int getItemCount() {
return NUM_PAGES;
}
}
}

View File

@ -1,110 +0,0 @@
package de.danoeh.antennapod.fragment.gpodnet;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
import de.danoeh.antennapod.adapter.gpodnet.PodcastListAdapter;
import de.danoeh.antennapod.core.sync.SynchronizationCredentials;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService;
import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetServiceException;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import java.util.List;
/**
* Displays a list of GPodnetPodcast-Objects in a GridView
*/
public abstract class PodcastListFragment extends Fragment {
private static final String TAG = "PodcastListFragment";
private GridView gridView;
private ProgressBar progressBar;
private TextView txtvError;
private Button butRetry;
private Disposable disposable;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.gpodnet_podcast_list, container, false);
gridView = root.findViewById(R.id.gridView);
progressBar = root.findViewById(R.id.progressBar);
txtvError = root.findViewById(R.id.txtvError);
butRetry = root.findViewById(R.id.butRetry);
gridView.setOnItemClickListener((parent, view, position, id) ->
onPodcastSelected((GpodnetPodcast) gridView.getAdapter().getItem(position)));
butRetry.setOnClickListener(v -> loadData());
loadData();
return root;
}
private void onPodcastSelected(GpodnetPodcast selection) {
Log.d(TAG, "Selected podcast: " + selection.toString());
Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, selection.getUrl());
intent.putExtra(MainActivity.EXTRA_STARTED_FROM_SEARCH, true);
startActivity(intent);
}
protected abstract List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException;
final void loadData() {
if (disposable != null) {
disposable.dispose();
}
gridView.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
txtvError.setVisibility(View.GONE);
butRetry.setVisibility(View.GONE);
disposable = Observable.fromCallable(
() -> {
GpodnetService service = new GpodnetService(AntennapodHttpClient.getHttpClient(),
SynchronizationCredentials.getHosturl(), SynchronizationCredentials.getDeviceID(),
SynchronizationCredentials.getUsername(), SynchronizationCredentials.getPassword());
return loadPodcastData(service);
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
podcasts -> {
progressBar.setVisibility(View.GONE);
butRetry.setVisibility(View.GONE);
if (podcasts.size() > 0) {
PodcastListAdapter listAdapter = new PodcastListAdapter(getContext(), 0, podcasts);
gridView.setAdapter(listAdapter);
listAdapter.notifyDataSetChanged();
gridView.setVisibility(View.VISIBLE);
txtvError.setVisibility(View.GONE);
} else {
gridView.setVisibility(View.GONE);
txtvError.setText(getString(R.string.search_status_no_results));
txtvError.setVisibility(View.VISIBLE);
}
}, error -> {
gridView.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
txtvError.setText(error.getMessage());
txtvError.setVisibility(View.VISIBLE);
butRetry.setVisibility(View.VISIBLE);
Log.e(TAG, Log.getStackTraceString(error));
});
}
}

View File

@ -1,16 +0,0 @@
package de.danoeh.antennapod.fragment.gpodnet;
import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService;
import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetServiceException;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast;
import java.util.List;
public class PodcastTopListFragment extends PodcastListFragment {
private static final int PODCAST_COUNT = 50;
@Override
protected List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException {
return service.getPodcastToplist(PODCAST_COUNT);
}
}

View File

@ -1,45 +0,0 @@
package de.danoeh.antennapod.fragment.gpodnet;
import android.os.Bundle;
import androidx.annotation.NonNull;
import java.util.List;
import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService;
import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetServiceException;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetTag;
/**
* Shows all podcasts from gpodder.net that belong to a specific tag.
* Use the newInstance method of this class to create a new TagFragment.
*/
public class TagFragment extends PodcastListFragment {
private static final int PODCAST_COUNT = 50;
private GpodnetTag tag;
public static TagFragment newInstance(@NonNull GpodnetTag tag) {
TagFragment fragment = new TagFragment();
Bundle args = new Bundle();
args.putParcelable("tag", tag);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args == null || args.getParcelable("tag") == null) {
throw new IllegalArgumentException("Arguments not given");
}
tag = args.getParcelable("tag");
}
@Override
protected List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException {
return service.getPodcastsForTag(tag, PODCAST_COUNT);
}
}

View File

@ -1,73 +0,0 @@
package de.danoeh.antennapod.fragment.gpodnet;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.ListFragment;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.gpodnet.TagListAdapter;
import de.danoeh.antennapod.core.sync.SynchronizationCredentials;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetTag;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
public class TagListFragment extends ListFragment {
private static final int COUNT = 50;
private static final String TAG = "TagListFragment";
private Disposable disposable;
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getListView().setOnItemClickListener((parent, view1, position, id) -> {
GpodnetTag tag = (GpodnetTag) getListAdapter().getItem(position);
((MainActivity) getActivity()).loadChildFragment(TagFragment.newInstance(tag));
});
startLoadTask();
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (disposable != null) {
disposable.dispose();
}
}
private void startLoadTask() {
if (disposable != null) {
disposable.dispose();
}
setListShown(false);
disposable = Observable.fromCallable(
() -> {
GpodnetService service = new GpodnetService(AntennapodHttpClient.getHttpClient(),
SynchronizationCredentials.getHosturl(), SynchronizationCredentials.getDeviceID(),
SynchronizationCredentials.getUsername(), SynchronizationCredentials.getPassword());
return service.getTopTags(COUNT);
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
tags -> {
setListAdapter(new TagListAdapter(getContext(), android.R.layout.simple_list_item_1, tags));
setListShown(true);
}, error -> {
TextView txtvError = new TextView(getActivity());
txtvError.setText(error.getMessage());
getListView().setEmptyView(txtvError);
setListShown(true);
Log.e(TAG, Log.getStackTraceString(error));
});
}
}

View File

@ -1,153 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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="match_parent"
android:orientation="vertical">
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="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:title="@string/add_feed_label"
app:navigationIcon="?homeAsUpIndicator"
android:id="@+id/toolbar"/>
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:title="@string/add_feed_label"
app:navigationIcon="?homeAsUpIndicator" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
app:cardElevation="4dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:cardCornerRadius="4dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:contentDescription="@string/search_podcast_hint"
app:srcCompat="@drawable/ic_search"
android:id="@+id/searchButton"
android:scaleType="center"/>
android:id="@+id/searchButton"
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:contentDescription="@string/search_podcast_hint"
android:scaleType="center"
app:srcCompat="@drawable/ic_search" />
<EditText
android:id="@+id/combinedFeedSearchEditText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="text"
android:imeOptions="actionSearch"
android:importantForAutofill="no"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:hint="@string/search_podcast_hint"
android:background="@null"/>
android:id="@+id/combinedFeedSearchEditText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="text"
android:imeOptions="actionSearch"
android:importantForAutofill="no"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:hint="@string/search_podcast_hint"
android:background="@null" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="vertical">
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:focusableInTouchMode="true"
android:padding="16dp">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:focusableInTouchMode="true"
android:padding="16dp">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/quickFeedDiscovery"
android:name="de.danoeh.antennapod.fragment.QuickFeedDiscoveryFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
android:id="@+id/quickFeedDiscovery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:name="de.danoeh.antennapod.fragment.QuickFeedDiscoveryFragment" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/advanced"
android:textSize="18sp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:textColor="?android:attr/textColorPrimary"/>
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/advanced"
android:textSize="18sp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/addViaUrlButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:drawableStartCompat="@drawable/ic_feed"
app:drawableLeftCompat="@drawable/ic_feed"
style="@style/AddPodcastTextView"
android:text="@string/add_podcast_by_url"/>
android:id="@+id/addViaUrlButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/add_podcast_by_url"
app:drawableStartCompat="@drawable/ic_feed"
app:drawableLeftCompat="@drawable/ic_feed"
style="@style/AddPodcastTextView" />
<TextView
android:id="@+id/addLocalFolderButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:drawableStartCompat="@drawable/ic_folder"
app:drawableLeftCompat="@drawable/ic_folder"
style="@style/AddPodcastTextView"
android:text="@string/add_local_folder"/>
android:id="@+id/addLocalFolderButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/add_local_folder"
app:drawableStartCompat="@drawable/ic_folder"
app:drawableLeftCompat="@drawable/ic_folder"
style="@style/AddPodcastTextView" />
<TextView
android:id="@+id/searchItunesButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:drawableStartCompat="@drawable/ic_search"
app:drawableLeftCompat="@drawable/ic_search"
style="@style/AddPodcastTextView"
android:text="@string/search_itunes_label"/>
android:id="@+id/searchItunesButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/search_itunes_label"
app:drawableStartCompat="@drawable/ic_search"
app:drawableLeftCompat="@drawable/ic_search"
style="@style/AddPodcastTextView" />
<TextView
android:id="@+id/searchFyydButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:drawableStartCompat="@drawable/ic_search"
app:drawableLeftCompat="@drawable/ic_search"
style="@style/AddPodcastTextView"
android:text="@string/search_fyyd_label"/>
android:id="@+id/searchFyydButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/search_fyyd_label"
app:drawableStartCompat="@drawable/ic_search"
app:drawableLeftCompat="@drawable/ic_search"
style="@style/AddPodcastTextView" />
<TextView
android:id="@+id/searchGPodderButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:drawableStartCompat="@drawable/ic_search"
app:drawableLeftCompat="@drawable/ic_search"
style="@style/AddPodcastTextView"
android:text="@string/browse_gpoddernet_label"/>
android:id="@+id/searchGPodderButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/gpodnet_search_hint"
app:drawableStartCompat="@drawable/ic_search"
app:drawableLeftCompat="@drawable/ic_search"
style="@style/AddPodcastTextView" />
<TextView
android:id="@+id/searchPodcastIndexButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:drawableStartCompat="@drawable/ic_search"
app:drawableLeftCompat="@drawable/ic_search"
style="@style/AddPodcastTextView"
android:text="@string/search_podcastindex_label"/>
android:id="@+id/searchPodcastIndexButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/search_podcastindex_label"
app:drawableStartCompat="@drawable/ic_search"
app:drawableLeftCompat="@drawable/ic_search"
style="@style/AddPodcastTextView" />
<TextView
android:id="@+id/opmlImportButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:drawableStartCompat="@drawable/ic_download"
app:drawableLeftCompat="@drawable/ic_download"
style="@style/AddPodcastTextView"
android:text="@string/opml_add_podcast_label"/>
android:id="@+id/opmlImportButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/opml_add_podcast_label"
app:drawableStartCompat="@drawable/ic_download"
app:drawableLeftCompat="@drawable/ic_download"
style="@style/AddPodcastTextView" />
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@ -1,23 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/browsing"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/browsing"
android:layout_alignParentTop="true">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:navigationIcon="?homeAsUpIndicator"
app:title="@string/discover"
android:id="@+id/toolbar"/>
app:title="@string/discover" />
<android.widget.Spinner
android:id="@+id/spinner_country"
@ -29,13 +32,14 @@
android:minHeight="?attr/actionBarSize"
android:spinnerMode="dropdown"
android:textAlignment="textEnd" />
</LinearLayout>
<GridView
android:layout_below="@id/browsing"
android:id="@+id/gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/browsing"
android:clipToPadding="false"
android:columnWidth="400dp"
android:gravity="center"
@ -45,7 +49,7 @@
android:paddingTop="@dimen/list_vertical_padding"
android:stretchMode="columnWidth"
android:verticalSpacing="8dp"
tools:listitem="@layout/gpodnet_podcast_listitem" />
tools:listitem="@layout/itunes_podcast_listitem" />
<TextView
android:id="@android:id/empty"
@ -62,7 +66,7 @@
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateOnly="true"
android:visibility="gone"/>
android:visibility="gone" />
<TextView
android:id="@+id/txtvError"
@ -101,5 +105,6 @@
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:textAlignment="textEnd"/>
android:textAlignment="textEnd" />
</RelativeLayout>

View File

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="@+id/gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:columnWidth="400dp"
android:gravity="center"
android:horizontalSpacing="8dp"
android:numColumns="auto_fit"
android:paddingBottom="@dimen/list_vertical_padding"
android:paddingTop="@dimen/list_vertical_padding"
android:stretchMode="columnWidth"
android:verticalSpacing="8dp"
android:layout_alignParentTop="true"
tools:listitem="@layout/gpodnet_podcast_listitem" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateOnly="true" />
<TextView
android:id="@+id/txtvError"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="16dp"
android:textAlignment="center"
android:textSize="@dimen/text_size_small"
android:visibility="gone"
tools:visibility="visible"
tools:text="Error message"
tools:background="@android:color/holo_red_light" />
<Button
android:id="@+id/butRetry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/txtvError"
android:layout_centerHorizontal="true"
android:layout_margin="16dp"
android:text="@string/retry_label"
android:visibility="gone"
tools:visibility="visible"
tools:background="@android:color/holo_red_light" />
</RelativeLayout>

View File

@ -1,80 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingBottom="8dp"
tools:background="@android:color/darker_gray">
<ImageView
android:id="@+id/imgvCover"
android:layout_width="@dimen/thumbnail_length_itemlist"
android:layout_height="@dimen/thumbnail_length_itemlist"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:adjustViewBounds="true"
android:importantForAccessibility="no"
android:cropToPadding="true"
android:scaleType="fitXY"
tools:src="@tools:sample/avatars"
tools:background="@android:color/holo_green_dark"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/imgvCover"
android:layout_toEndOf="@id/imgvCover"
android:orientation="vertical">
<TextView
android:id="@+id/txtvTitle"
style="@style/AntennaPod.TextView.ListItemPrimaryTitle2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="2"
android:includeFontPadding="false"
tools:text="Title"
tools:background="@android:color/holo_green_dark"/>
<TextView
android:id="@+id/txtvAuthor"
style="android:style/TextAppearance.Small"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary"
android:ellipsize="middle"
android:maxLines="2"
tools:text="author"
tools:background="@android:color/holo_green_dark"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:layout_width="14sp"
android:layout_height="14sp"
app:srcCompat="@drawable/ic_feed"/>
<TextView
android:id="@+id/txtvSubscribers"
style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
tools:text="150"
tools:background="@android:color/holo_green_dark"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
tools:background="@android:color/darker_gray">
<TextView
android:id="@+id/txtvTitle"
style="@style/AntennaPod.TextView.ListItemPrimaryTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding"
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding"
android:lines="1"
tools:text="Tag Title"
tools:background="@android:color/holo_green_dark" />
<TextView
android:id="@+id/txtvUsage"
style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="@dimen/listitem_threeline_horizontalpadding"
android:layout_marginEnd="@dimen/listitem_threeline_horizontalpadding"
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding"
tools:text="301"
tools:background="@android:color/holo_green_dark"/>
</RelativeLayout>

View File

@ -18,7 +18,6 @@
<dimen name="listitem_threeline_textleftpadding">16dp</dimen>
<dimen name="listitem_threeline_textrightpadding">8dp</dimen>
<dimen name="listitem_threeline_verticalpadding">8dp</dimen>
<dimen name="listitem_threeline_horizontalpadding">16dp</dimen>
<dimen name="list_vertical_padding">8dp</dimen>
<dimen name="listitem_icon_leftpadding">16dp</dimen>

View File

@ -26,7 +26,6 @@ import de.danoeh.antennapod.net.sync.gpoddernet.mapper.ResponseMapper;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetDevice;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetEpisodeActionPostResponse;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetTag;
import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetUploadChangesResponse;
import de.danoeh.antennapod.net.sync.model.EpisodeAction;
import de.danoeh.antennapod.net.sync.model.EpisodeActionChanges;
@ -79,86 +78,6 @@ public class GpodnetService implements ISyncService {
}
}
/**
* Returns the [count] most used tags.
*/
public List<GpodnetTag> getTopTags(int count) throws GpodnetServiceException {
URL url;
try {
url = new URI(baseScheme, null, baseHost, basePort,
String.format(Locale.US, "/api/2/tags/%d.json", count), null, null).toURL();
} catch (MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
try {
JSONArray jsonTagList = new JSONArray(response);
List<GpodnetTag> tagList = new ArrayList<>(jsonTagList.length());
for (int i = 0; i < jsonTagList.length(); i++) {
JSONObject jsonObject = jsonTagList.getJSONObject(i);
String title = jsonObject.getString("title");
String tag = jsonObject.getString("tag");
int usage = jsonObject.getInt("usage");
tagList.add(new GpodnetTag(title, tag, usage));
}
return tagList;
} catch (JSONException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
}
/**
* Returns the [count] most subscribed podcasts for the given tag.
*
* @throws IllegalArgumentException if tag is null
*/
public List<GpodnetPodcast> getPodcastsForTag(@NonNull GpodnetTag tag, int count)
throws GpodnetServiceException {
try {
URL url = new URI(baseScheme, null, baseHost, basePort,
String.format(Locale.US, "/api/2/tag/%s/%d.json", tag.getTag(), count), null, null).toURL();
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
JSONArray jsonArray = new JSONArray(response);
return readPodcastListFromJsonArray(jsonArray);
} catch (JSONException | MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
}
/**
* Returns the toplist of podcast.
*
* @param count of elements that should be returned. Must be in range 1..100.
* @throws IllegalArgumentException if count is out of range.
*/
public List<GpodnetPodcast> getPodcastToplist(int count) throws GpodnetServiceException {
if (count < 1 || count > 100) {
throw new IllegalArgumentException("Count must be in range 1..100");
}
try {
URL url = new URI(baseScheme, null, baseHost, basePort,
String.format(Locale.US, "/toplist/%d.json", count), null, null).toURL();
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
JSONArray jsonArray = new JSONArray(response);
return readPodcastListFromJsonArray(jsonArray);
} catch (JSONException | MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
}
/**
* Searches the podcast directory for a given string.
*

View File

@ -1,66 +0,0 @@
package de.danoeh.antennapod.net.sync.gpoddernet.model;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
public class GpodnetTag implements Parcelable {
private final String title;
private final String tag;
private final int usage;
public GpodnetTag(@NonNull String title, @NonNull String tag, int usage) {
this.title = title;
this.tag = tag;
this.usage = usage;
}
private GpodnetTag(Parcel in) {
title = in.readString();
tag = in.readString();
usage = in.readInt();
}
@Override
public String toString() {
return "GpodnetTag [title="+title+", tag=" + tag + ", usage=" + usage + "]";
}
public String getTitle() {
return title;
}
public String getTag() {
return tag;
}
public int getUsage() {
return usage;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
dest.writeString(tag);
dest.writeInt(usage);
}
public static final Creator<GpodnetTag> CREATOR = new Creator<GpodnetTag>() {
@Override
public GpodnetTag createFromParcel(Parcel in) {
return new GpodnetTag(in);
}
@Override
public GpodnetTag[] newArray(int size) {
return new GpodnetTag[size];
}
};
}

View File

@ -23,7 +23,6 @@
<string name="subscriptions_list_label">Subscriptions List</string>
<string name="cancel_download_label">Cancel Download</string>
<string name="playback_history_label">Playback History</string>
<string name="gpodnet_main_label">gpodder.net</string>
<string name="episode_cache_full_title">Episode cache full</string>
<string name="episode_cache_full_message">The episode cache limit has been reached. You can increase the cache size in the Settings.</string>
<string name="years_statistics_label">Years</string>
@ -624,9 +623,6 @@
<string name="sleep_timer_enabled_label">Sleep timer enabled</string>
<!-- gpodder.net -->
<string name="gpodnet_taglist_header">CATEGORIES</string>
<string name="gpodnet_toplist_header">TOP PODCASTS</string>
<string name="gpodnet_search_hint">Search gpodder.net</string>
<string name="gpodnetauth_login_butLabel">Login</string>
<string name="gpodnetauth_encryption_warning">Password and data are not encrypted!</string>
<string name="create_account">Create account</string>
@ -715,10 +711,10 @@
<string name="search_itunes_label">Search iTunes</string>
<string name="search_podcastindex_label">Search Podcastindex.org</string>
<string name="search_fyyd_label">Search fyyd</string>
<string name="gpodnet_search_hint">Search gpodder.net</string>
<string name="advanced">Advanced</string>
<string name="add_podcast_by_url">Add Podcast by RSS address</string>
<string name="add_podcast_by_url_hint" translatable="false">www.example.com/feed</string>
<string name="browse_gpoddernet_label">Browse gpodder.net</string>
<string name="discover">Discover</string>
<string name="discover_hide">Hide</string>
<string name="discover_is_hidden">You selected to hide suggestions.</string>