diff options
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod')
24 files changed, 354 insertions, 68 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java index 8c66b6a4c..a0ad99e7d 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java @@ -187,7 +187,7 @@ public class VideoplayerActivity extends MediaplayerActivity { videoControlsHider.stop(); if (System.currentTimeMillis() - lastScreenTap < 300) { - if (event.getX() > v.getMeasuredWidth() / 2) { + if (event.getX() > v.getMeasuredWidth() / 2.0f) { onFastForward(); showSkipAnimation(true); } else { diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java index e45533826..7b41652bd 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/PlaybackControlsDialog.java @@ -94,7 +94,7 @@ public class PlaybackControlsDialog extends DialogFragment { barRightVolume.setEnabled(false); } - final CheckBox skipSilence = (CheckBox) dialog.findViewById(R.id.skipSilence); + final CheckBox skipSilence = dialog.findViewById(R.id.skipSilence); skipSilence.setChecked(UserPreferences.isSkipSilence()); if (!UserPreferences.useExoplayer()) { skipSilence.setEnabled(false); diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java index ef8ed335d..1fc7a77b2 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java @@ -45,9 +45,8 @@ public class VariableSpeedDialog extends DialogFragment { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.no_playback_plugin_title); builder.setMessage(R.string.no_playback_plugin_or_sonic_msg); - builder.setPositiveButton(R.string.enable_sonic, (dialog, which) -> { - UserPreferences.enableSonic(); - }); + builder.setPositiveButton(R.string.enable_sonic, (dialog, which) -> + UserPreferences.enableSonic()); builder.setNeutralButton(R.string.close_label, null); builder.show(); } diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/PodcastIndexPodcastSearcher.java b/app/src/main/java/de/danoeh/antennapod/discovery/PodcastIndexPodcastSearcher.java new file mode 100644 index 000000000..c8e5dc4ef --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/discovery/PodcastIndexPodcastSearcher.java @@ -0,0 +1,126 @@ +package de.danoeh.antennapod.discovery; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; + +import de.danoeh.antennapod.BuildConfig; +import de.danoeh.antennapod.core.ClientConfig; +import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; +import io.reactivex.Single; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +public class PodcastIndexPodcastSearcher implements PodcastSearcher { + private static final String PODCASTINDEX_API_URL = "https://api.podcastindex.org/api/1.0/search/byterm?q=%s"; + + public PodcastIndexPodcastSearcher() { + } + + @Override + public Single<List<PodcastSearchResult>> search(String query) { + return Single.create((SingleOnSubscribe<List<PodcastSearchResult>>) subscriber -> { + + Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + calendar.clear(); + Date now = new Date(); + calendar.setTime(now); + long secondsSinceEpoch = calendar.getTimeInMillis() / 1000L; + String apiHeaderTime = String.valueOf(secondsSinceEpoch); + String data4Hash = BuildConfig.PODCASTINDEX_API_KEY + BuildConfig.PODCASTINDEX_API_SECRET + apiHeaderTime; + String hashString = sha1(data4Hash); + + String encodedQuery; + try { + encodedQuery = URLEncoder.encode(query, "UTF-8"); + } catch (UnsupportedEncodingException e) { + // this won't ever be thrown + encodedQuery = query; + } + + String formattedUrl = String.format(PODCASTINDEX_API_URL, encodedQuery); + + OkHttpClient client = AntennapodHttpClient.getHttpClient(); + Request.Builder httpReq = new Request.Builder() + .addHeader("X-Auth-Date", apiHeaderTime) + .addHeader("X-Auth-Key", BuildConfig.PODCASTINDEX_API_KEY) + .addHeader("Authorization", hashString) + .addHeader("User-Agent", ClientConfig.USER_AGENT) + .url(formattedUrl); + List<PodcastSearchResult> podcasts = new ArrayList<>(); + try { + Response response = client.newCall(httpReq.build()).execute(); + + if (response.isSuccessful()) { + String resultString = response.body().string(); + JSONObject result = new JSONObject(resultString); + JSONArray j = result.getJSONArray("feeds"); + + for (int i = 0; i < j.length(); i++) { + JSONObject podcastJson = j.getJSONObject(i); + PodcastSearchResult podcast = PodcastSearchResult.fromPodcastIndex(podcastJson); + if (podcast.feedUrl != null) { + podcasts.add(podcast); + } + } + } else { + subscriber.onError(new IOException(response.toString())); + } + } catch (IOException | JSONException e) { + subscriber.onError(e); + } + subscriber.onSuccess(podcasts); + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + @Override + public Single<String> lookupUrl(String url) { + return Single.just(url); + } + + @Override + public boolean urlNeedsLookup(String url) { + return false; + } + + @Override + public String getName() { + return "Podcastindex.org"; + } + + private static String sha1(String clearString) { + try { + MessageDigest messageDigest = MessageDigest.getInstance("SHA-1"); + messageDigest.update(clearString.getBytes("UTF-8")); + return toHex(messageDigest.digest()); + } catch (Exception ignored) { + ignored.printStackTrace(); + return null; + } + } + + private static String toHex(byte[] bytes) { + StringBuilder buffer = new StringBuilder(); + for (byte b : bytes) { + buffer.append(String.format(Locale.getDefault(), "%02x", b)); + } + return buffer.toString(); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearchResult.java b/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearchResult.java index 0f0c864b1..bba438d1d 100644 --- a/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearchResult.java +++ b/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearchResult.java @@ -103,4 +103,12 @@ public class PodcastSearchResult { searchHit.getUrl(), searchHit.getAuthor()); } + + public static PodcastSearchResult fromPodcastIndex(JSONObject json) { + String title = json.optString("title", ""); + String imageUrl = json.optString("image", null); + String feedUrl = json.optString("url", null); + String author = json.optString("author", null); + return new PodcastSearchResult(title, imageUrl, feedUrl, author); + } } diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearcherRegistry.java b/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearcherRegistry.java index 3f738424b..ad574cab6 100644 --- a/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearcherRegistry.java +++ b/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearcherRegistry.java @@ -19,6 +19,7 @@ public class PodcastSearcherRegistry { searchProviders.add(new SearcherInfo(new ItunesPodcastSearcher(), 1.f)); searchProviders.add(new SearcherInfo(new FyydPodcastSearcher(), 1.f)); searchProviders.add(new SearcherInfo(new GpodnetPodcastSearcher(), 0.0f)); + searchProviders.add(new SearcherInfo(new PodcastIndexPodcastSearcher(), 0.0f)); } return searchProviders; } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java index 167daa08b..a4646ad64 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java @@ -26,6 +26,7 @@ import de.danoeh.antennapod.activity.OpmlImportActivity; import de.danoeh.antennapod.discovery.CombinedSearcher; import de.danoeh.antennapod.discovery.FyydPodcastSearcher; import de.danoeh.antennapod.discovery.ItunesPodcastSearcher; +import de.danoeh.antennapod.discovery.PodcastIndexPodcastSearcher; import de.danoeh.antennapod.fragment.gpodnet.GpodnetMainFragment; /** @@ -55,6 +56,8 @@ public class AddFeedFragment extends Fragment { -> activity.loadChildFragment(OnlineSearchFragment.newInstance(FyydPodcastSearcher.class))); root.findViewById(R.id.btn_search_gpodder).setOnClickListener(v -> activity.loadChildFragment(new GpodnetMainFragment())); + root.findViewById(R.id.btn_search_podcastindex).setOnClickListener(v + -> activity.loadChildFragment(OnlineSearchFragment.newInstance(PodcastIndexPodcastSearcher.class))); combinedFeedSearchBox = root.findViewById(R.id.combinedFeedSearchBox); combinedFeedSearchBox.setOnEditorActionListener((v, actionId, event) -> { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java index 7eb749681..9999b0b37 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java @@ -124,8 +124,6 @@ public class AudioPlayerFragment extends Fragment implements setupLengthTextView(); setupControlButtons(); setupPlaybackSpeedButton(); - txtvRev.setText(NumberFormat.getInstance().format(UserPreferences.getRewindSecs())); - txtvFF.setText(NumberFormat.getInstance().format(UserPreferences.getFastForwardSecs())); sbPosition.setOnSeekBarChangeListener(this); pager = root.findViewById(R.id.pager); @@ -376,6 +374,8 @@ public class AudioPlayerFragment extends Fragment implements controller.init(); loadMediaInfo(); EventBus.getDefault().register(this); + txtvRev.setText(NumberFormat.getInstance().format(UserPreferences.getRewindSecs())); + txtvFF.setText(NumberFormat.getInstance().format(UserPreferences.getFastForwardSecs())); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java index 79f378249..648fc614a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java @@ -45,6 +45,7 @@ import org.greenrobot.eventbus.ThreadMode; public class CoverFragment extends Fragment { private static final String TAG = "CoverFragment"; + static final double SIXTEEN_BY_NINE = 1.7; private View root; private TextView txtvPodcastTitle; @@ -188,20 +189,31 @@ public class CoverFragment extends Fragment { private void configureForOrientation(Configuration newConfig) { LinearLayout mainContainer = getView().findViewById(R.id.cover_fragment); - ViewGroup.LayoutParams params = imgvCover.getLayoutParams(); + LinearLayout textContainer = getView().findViewById(R.id.cover_fragment_text_container); + + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) imgvCover.getLayoutParams(); + LinearLayout.LayoutParams textParams = (LinearLayout.LayoutParams) textContainer.getLayoutParams(); + double ratio = (float) newConfig.screenHeightDp / (float) newConfig.screenWidthDp; if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { + double percentageWidth = 0.8; + if (ratio <= SIXTEEN_BY_NINE) { + percentageWidth = (ratio / SIXTEEN_BY_NINE) * percentageWidth * 0.8; + } mainContainer.setOrientation(LinearLayout.VERTICAL); if (newConfig.screenWidthDp > 0) { - params.width = (int) (convertDpToPixel(newConfig.screenWidthDp) * .80); + params.width = (int) (convertDpToPixel(newConfig.screenWidthDp) * percentageWidth); params.height = params.width; + textParams.weight = 0; imgvCover.setLayoutParams(params); } } else { + double percentageHeight = ratio * 0.8; mainContainer.setOrientation(LinearLayout.HORIZONTAL); if (newConfig.screenHeightDp > 0) { - params.height = (int) (convertDpToPixel(newConfig.screenHeightDp) * .40); + params.height = (int) (convertDpToPixel(newConfig.screenHeightDp) * percentageHeight); params.width = params.height; + textParams.weight = 1; imgvCover.setLayoutParams(params); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java index c173bf8ee..bc2d85452 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java @@ -51,6 +51,7 @@ public class DownloadsFragment extends Fragment { viewPager = root.findViewById(R.id.viewpager); viewPager.setAdapter(new DownloadsPagerAdapter(this)); + viewPager.setOffscreenPageLimit(2); // Give the TabLayout the ViewPager tabLayout = root.findViewById(R.id.sliding_tabs); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java index e98890627..afd027b3a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java @@ -51,6 +51,7 @@ public class EpisodesFragment extends Fragment { ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar); viewPager = rootView.findViewById(R.id.viewpager); viewPager.setAdapter(new EpisodesPagerAdapter(this)); + viewPager.setOffscreenPageLimit(2); // Give the TabLayout the ViewPager tabLayout = rootView.findViewById(R.id.sliding_tabs); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java index ed8697adb..fc3052e20 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java @@ -11,6 +11,7 @@ import android.view.ViewGroup; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; import de.danoeh.antennapod.core.util.playback.Timeline; import de.danoeh.antennapod.view.ShownotesWebView; @@ -82,8 +83,10 @@ public class ItemDescriptionFragment extends Fragment { if (webViewLoader != null) { webViewLoader.dispose(); } - webViewLoader = Maybe.fromCallable(this::loadData) - .subscribeOn(Schedulers.io()) + webViewLoader = Maybe.<String>create(emitter -> { + Timeline timeline = new Timeline(getActivity(), controller.getMedia()); + emitter.onSuccess(timeline.processShownotes()); + }).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(data -> { webvDescription.loadDataWithBaseURL("https://127.0.0.1", data, "text/html", @@ -92,15 +95,6 @@ public class ItemDescriptionFragment extends Fragment { }, error -> Log.e(TAG, Log.getStackTraceString(error))); } - @Nullable - private String loadData() { - if (controller == null || controller.getMedia() == null) { - return null; - } - Timeline timeline = new Timeline(getActivity(), controller.getMedia()); - return timeline.processShownotes(); - } - @Override public void onPause() { super.onPause(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java index 26216b375..283b4b466 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java @@ -335,10 +335,8 @@ public class QueueFragment extends Fragment { if (keepSortedNew) { SortOrder sortOrder = UserPreferences.getQueueKeepSortedOrder(); DBWriter.reorderQueue(sortOrder, true); - if (recyclerAdapter != null) { - recyclerAdapter.updateDragDropEnabled(); - } - } else if (recyclerAdapter != null) { + } + if (recyclerAdapter != null) { recyclerAdapter.updateDragDropEnabled(); } getActivity().invalidateOptionsMenu(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java index d6bcdd79c..38c068a3f 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java @@ -9,7 +9,9 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; +import android.widget.Button; import android.widget.GridView; +import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; import de.danoeh.antennapod.R; @@ -33,6 +35,7 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView. private FeedDiscoverAdapter adapter; private GridView discoverGridLayout; private TextView errorTextView; + private LinearLayout errorView; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -44,7 +47,10 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView. discoverGridLayout = root.findViewById(R.id.discover_grid); progressBar = root.findViewById(R.id.discover_progress_bar); - errorTextView = root.findViewById(R.id.discover_error); + errorView = root.findViewById(R.id.discover_error); + errorTextView = root.findViewById(R.id.discover_error_txtV); + Button errorRetry = root.findViewById(R.id.discover_error_retry_btn); + errorRetry.setOnClickListener((listener) -> loadToplist()); adapter = new FeedDiscoverAdapter((MainActivity) getActivity()); discoverGridLayout.setAdapter(adapter); @@ -81,19 +87,19 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView. private void loadToplist() { progressBar.setVisibility(View.VISIBLE); discoverGridLayout.setVisibility(View.INVISIBLE); - errorTextView.setVisibility(View.GONE); + errorView.setVisibility(View.GONE); ItunesTopListLoader loader = new ItunesTopListLoader(getContext()); disposable = loader.loadToplist(NUM_SUGGESTIONS) .subscribe(podcasts -> { - errorTextView.setVisibility(View.GONE); + errorView.setVisibility(View.GONE); progressBar.setVisibility(View.GONE); discoverGridLayout.setVisibility(View.VISIBLE); adapter.updateData(podcasts); }, error -> { Log.e(TAG, Log.getStackTraceString(error)); errorTextView.setText(error.getLocalizedMessage()); - errorTextView.setVisibility(View.VISIBLE); + errorView.setVisibility(View.VISIBLE); progressBar.setVisibility(View.GONE); discoverGridLayout.setVisibility(View.INVISIBLE); }); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java index 064c4b3bc..0d6e79e84 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AutoDownloadPreferencesFragment.java @@ -168,7 +168,7 @@ public class AutoDownloadPreferencesFragment extends PreferenceFragmentCompat { private void buildEpisodeCleanupPreference() { final Resources res = getActivity().getResources(); - ListPreference pref = (ListPreference) findPreference(UserPreferences.PREF_EPISODE_CLEANUP); + ListPreference pref = findPreference(UserPreferences.PREF_EPISODE_CLEANUP); String[] values = res.getStringArray( R.array.episode_cleanup_values); String[] entries = new String[values.length]; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java index 3f1cec729..2d640458e 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/MainPreferencesFragment.java @@ -10,6 +10,7 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.BugReportActivity; import de.danoeh.antennapod.activity.PreferenceActivity; import de.danoeh.antennapod.core.util.IntentUtils; +import de.danoeh.antennapod.fragment.preferences.about.AboutFragment; public class MainPreferencesFragment extends PreferenceFragmentCompat { private static final String TAG = "MainPreferencesFragment"; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java index f07e59afe..1fa1fed58 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/PlaybackPreferencesFragment.java @@ -109,7 +109,7 @@ public class PlaybackPreferencesFragment extends PreferenceFragmentCompat { private void buildSmartMarkAsPlayedPreference() { final Resources res = getActivity().getResources(); - ListPreference pref = (ListPreference) findPreference(UserPreferences.PREF_SMART_MARK_AS_PLAYED_SECS); + ListPreference pref = findPreference(UserPreferences.PREF_SMART_MARK_AS_PLAYED_SECS); String[] values = res.getStringArray(R.array.smart_mark_as_played_values); String[] entries = new String[values.length]; for (int x = 0; x < values.length; x++) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/AboutFragment.java index eb57972a1..b440d053b 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/AboutFragment.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.fragment.preferences; +package de.danoeh.antennapod.fragment.preferences.about; import android.content.ClipData; import android.content.ClipboardManager; @@ -27,14 +27,9 @@ public class AboutFragment extends PreferenceFragmentCompat { Snackbar.make(getView(), R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT).show(); return true; }); - findPreference("about_developers").setOnPreferenceClickListener((preference) -> { - getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutDevelopersFragment()) - .addToBackStack(getString(R.string.developers)).commit(); - return true; - }); - findPreference("about_translators").setOnPreferenceClickListener((preference) -> { - getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutTranslatorsFragment()) - .addToBackStack(getString(R.string.translators)).commit(); + findPreference("about_contributors").setOnPreferenceClickListener((preference) -> { + getParentFragmentManager().beginTransaction().replace(R.id.content, new ContributorsPagerFragment()) + .addToBackStack(getString(R.string.contributors)).commit(); return true; }); findPreference("about_privacy_policy").setOnPreferenceClickListener((preference) -> { @@ -42,7 +37,7 @@ public class AboutFragment extends PreferenceFragmentCompat { return true; }); findPreference("about_licenses").setOnPreferenceClickListener((preference) -> { - getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutLicensesFragment()) + getParentFragmentManager().beginTransaction().replace(R.id.content, new LicensesFragment()) .addToBackStack(getString(R.string.translators)).commit(); return true; }); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/ContributorsPagerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/ContributorsPagerFragment.java new file mode 100644 index 000000000..20cef1313 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/ContributorsPagerFragment.java @@ -0,0 +1,95 @@ +package de.danoeh.antennapod.fragment.preferences.about; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import androidx.annotation.NonNull; +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.PreferenceActivity; + +/** + * Displays the 'about->Contributors' pager screen. + */ +public class ContributorsPagerFragment extends Fragment { + + public static final String TAG = "StatisticsFragment"; + + private static final int POS_DEVELOPERS = 0; + private static final int POS_TRANSLATORS = 1; + private static final int POS_SPECIAL_THANKS = 2; + private static final int TOTAL_COUNT = 3; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + setHasOptionsMenu(true); + + View rootView = inflater.inflate(R.layout.pager_fragment, container, false); + ViewPager2 viewPager = rootView.findViewById(R.id.viewpager); + viewPager.setAdapter(new StatisticsPagerAdapter(this)); + // Give the TabLayout the ViewPager + TabLayout tabLayout = rootView.findViewById(R.id.sliding_tabs); + new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> { + switch (position) { + case POS_DEVELOPERS: + tab.setText(R.string.developers); + break; + case POS_TRANSLATORS: + tab.setText(R.string.translators); + break; + case POS_SPECIAL_THANKS: + tab.setText(R.string.special_thanks); + break; + default: + break; + } + }).attach(); + + rootView.findViewById(R.id.toolbar).setVisibility(View.GONE); + + return rootView; + } + + @Override + public void onStart() { + super.onStart(); + ((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.contributors); + } + + public static class StatisticsPagerAdapter extends FragmentStateAdapter { + + StatisticsPagerAdapter(@NonNull Fragment fragment) { + super(fragment); + } + + @NonNull + @Override + public Fragment createFragment(int position) { + switch (position) { + case POS_TRANSLATORS: + return new TranslatorsFragment(); + case POS_SPECIAL_THANKS: + return new SpecialThanksFragment(); + default: + case POS_DEVELOPERS: + return new DevelopersFragment(); + } + } + + @Override + public int getItemCount() { + return TOTAL_COUNT; + } + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutDevelopersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/DevelopersFragment.java index 62a5eb306..60d9f95dd 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutDevelopersFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/DevelopersFragment.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.fragment.preferences; +package de.danoeh.antennapod.fragment.preferences.about; import android.os.Bundle; import android.view.View; @@ -19,7 +19,7 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; -public class AboutDevelopersFragment extends ListFragment { +public class DevelopersFragment extends ListFragment { private Disposable developersLoader; @Override @@ -44,7 +44,7 @@ public class AboutDevelopersFragment extends ListFragment { .observeOn(AndroidSchedulers.mainThread()) .subscribe( developers -> setListAdapter(new SimpleIconListAdapter<>(getContext(), developers)), - error -> Toast.makeText(getContext(), "Error while loading developers", Toast.LENGTH_LONG).show() + error -> Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_LONG).show() ); } @@ -56,10 +56,4 @@ public class AboutDevelopersFragment extends ListFragment { developersLoader.dispose(); } } - - @Override - public void onStart() { - super.onStart(); - ((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.developers); - } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutLicensesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/LicensesFragment.java index 536d11e01..97565a613 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutLicensesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/LicensesFragment.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.fragment.preferences; +package de.danoeh.antennapod.fragment.preferences.about; import android.os.Bundle; import android.view.View; @@ -28,7 +28,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; -public class AboutLicensesFragment extends ListFragment { +public class LicensesFragment extends ListFragment { private Disposable licensesLoader; private final ArrayList<LicenseItem> licenses = new ArrayList<>(); @@ -59,7 +59,7 @@ public class AboutLicensesFragment extends ListFragment { .observeOn(AndroidSchedulers.mainThread()) .subscribe( developers -> setListAdapter(new SimpleIconListAdapter<LicenseItem>(getContext(), developers)), - error -> Toast.makeText(getContext(), "Error while loading licenses", Toast.LENGTH_LONG).show() + error -> Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_LONG).show() ); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/SpecialThanksFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/SpecialThanksFragment.java new file mode 100644 index 000000000..6db1389ea --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/SpecialThanksFragment.java @@ -0,0 +1,58 @@ +package de.danoeh.antennapod.fragment.preferences.about; + +import android.os.Bundle; +import android.view.View; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.ListFragment; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.PreferenceActivity; +import de.danoeh.antennapod.adapter.SimpleIconListAdapter; +import io.reactivex.Single; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; + +public class SpecialThanksFragment extends ListFragment { + private Disposable translatorsLoader; + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + getListView().setDivider(null); + getListView().setSelector(android.R.color.transparent); + + translatorsLoader = Single.create((SingleOnSubscribe<ArrayList<SimpleIconListAdapter.ListItem>>) emitter -> { + ArrayList<SimpleIconListAdapter.ListItem> translators = new ArrayList<>(); + BufferedReader reader = new BufferedReader(new InputStreamReader( + getContext().getAssets().open("special_thanks.csv"))); + String line; + while ((line = reader.readLine()) != null) { + String[] info = line.split(";"); + translators.add(new SimpleIconListAdapter.ListItem(info[0], info[1], info[2])); + } + emitter.onSuccess(translators); + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + translators -> setListAdapter(new SimpleIconListAdapter<>(getContext(), translators)), + error -> Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_LONG).show() + ); + + } + + @Override + public void onStop() { + super.onStop(); + if (translatorsLoader != null) { + translatorsLoader.dispose(); + } + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutTranslatorsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/TranslatorsFragment.java index 914dbb9a2..e8d8e113b 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/AboutTranslatorsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/TranslatorsFragment.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.fragment.preferences; +package de.danoeh.antennapod.fragment.preferences.about; import android.os.Bundle; import android.view.View; @@ -19,7 +19,7 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; -public class AboutTranslatorsFragment extends ListFragment { +public class TranslatorsFragment extends ListFragment { private Disposable translatorsLoader; @Override @@ -43,7 +43,7 @@ public class AboutTranslatorsFragment extends ListFragment { .observeOn(AndroidSchedulers.mainThread()) .subscribe( translators -> setListAdapter(new SimpleIconListAdapter<>(getContext(), translators)), - error -> Toast.makeText(getContext(), "Error while loading translators", Toast.LENGTH_LONG).show() + error -> Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_LONG).show() ); } @@ -55,10 +55,4 @@ public class AboutTranslatorsFragment extends ListFragment { translatorsLoader.dispose(); } } - - @Override - public void onStart() { - super.onStart(); - ((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.translators); - } } diff --git a/app/src/main/java/de/danoeh/antennapod/view/LockableBottomSheetBehavior.java b/app/src/main/java/de/danoeh/antennapod/view/LockableBottomSheetBehavior.java index 8e8d98fc9..1b96c7c4f 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/LockableBottomSheetBehavior.java +++ b/app/src/main/java/de/danoeh/antennapod/view/LockableBottomSheetBehavior.java @@ -47,11 +47,11 @@ public class LockableBottomSheetBehavior<V extends View> extends ViewPagerBottom @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, - View target, int nestedScrollAxes) { + View target, int axes, int type) { boolean handled = false; if (!isLocked) { - handled = super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); + handled = super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type); } return handled; @@ -59,16 +59,16 @@ public class LockableBottomSheetBehavior<V extends View> extends ViewPagerBottom @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, - int dx, int dy, int[] consumed) { + int dx, int dy, int[] consumed, int type) { if (!isLocked) { - super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); + super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type); } } @Override - public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { + public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target, int type) { if (!isLocked) { - super.onStopNestedScroll(coordinatorLayout, child, target); + super.onStopNestedScroll(coordinatorLayout, child, target, type); } } |