diff options
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod')
50 files changed, 257 insertions, 310 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java index bff11fa5e..721291597 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/BugReportActivity.java @@ -11,10 +11,15 @@ import android.os.Build; import android.os.Bundle; import android.util.Log; import com.google.android.material.snackbar.Snackbar; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.FileProvider; +import android.view.Menu; +import android.view.MenuItem; import android.widget.TextView; @@ -67,42 +72,65 @@ public class BugReportActivity extends AppCompatActivity { clipboard.setPrimaryClip(clip); Snackbar.make(findViewById(android.R.id.content), R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT).show(); }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bug_report_options, menu); + return super.onCreateOptionsMenu(menu); + } - findViewById(R.id.btn_export_logcat).setOnClickListener(v -> { + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if (item.getItemId() == R.id.export_logcat) { + AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this); + alertBuilder.setMessage(R.string.confirm_export_log_dialog_message); + alertBuilder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { + exportLog(); + dialog.dismiss(); + }); + alertBuilder.setNegativeButton(R.string.cancel_label, null); + alertBuilder.show(); + return true; + } + return super.onOptionsItemSelected(item); + } + + private void exportLog() { + try { + File filename = new File(UserPreferences.getDataFolder(null), "full-logs.txt"); + filename.createNewFile(); + String cmd = "logcat -d -f " + filename.getAbsolutePath(); + Runtime.getRuntime().exec(cmd); + //share file try { - File filename = new File(UserPreferences.getDataFolder(null), "full-logs.txt"); - filename.createNewFile(); - String cmd = "logcat -d -f " + filename.getAbsolutePath(); - Runtime.getRuntime().exec(cmd); - //share file - try { - Intent i = new Intent(Intent.ACTION_SEND); - i.setType("text/*"); - String authString = getString(de.danoeh.antennapod.core.R.string.provider_authority); - Uri fileUri = FileProvider.getUriForFile(this, authString, filename); - i.putExtra(Intent.EXTRA_STREAM, fileUri); - i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { - PackageManager pm = getPackageManager(); - List<ResolveInfo> resInfos = pm.queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY); - for (ResolveInfo resolveInfo : resInfos) { - String packageName = resolveInfo.activityInfo.packageName; - grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); - } + Intent i = new Intent(Intent.ACTION_SEND); + i.setType("text/*"); + String authString = getString(de.danoeh.antennapod.core.R.string.provider_authority); + Uri fileUri = FileProvider.getUriForFile(this, authString, filename); + i.putExtra(Intent.EXTRA_STREAM, fileUri); + i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { + PackageManager pm = getPackageManager(); + List<ResolveInfo> resInfos = pm.queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY); + for (ResolveInfo resolveInfo : resInfos) { + String packageName = resolveInfo.activityInfo.packageName; + grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); } - String chooserTitle = getString(de.danoeh.antennapod.core.R.string.share_file_label); - startActivity(Intent.createChooser(i, chooserTitle)); - } catch (Exception e) { - e.printStackTrace(); - int strResId = R.string.log_file_share_exception; - Snackbar.make(findViewById(android.R.id.content), strResId, Snackbar.LENGTH_LONG) - .show(); } - } catch (IOException e) { + String chooserTitle = getString(de.danoeh.antennapod.core.R.string.share_file_label); + startActivity(Intent.createChooser(i, chooserTitle)); + } catch (Exception e) { e.printStackTrace(); - Snackbar.make(findViewById(android.R.id.content), e.getMessage(), Snackbar.LENGTH_LONG).show(); + int strResId = R.string.log_file_share_exception; + Snackbar.make(findViewById(android.R.id.content), strResId, Snackbar.LENGTH_LONG) + .show(); } - }); + } catch (IOException e) { + e.printStackTrace(); + Snackbar.make(findViewById(android.R.id.content), e.getMessage(), Snackbar.LENGTH_LONG).show(); + } } + } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java index 1d3d9bf11..912038e4c 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java @@ -5,7 +5,6 @@ import android.content.Intent; import android.os.Bundle; import androidx.annotation.NonNull; -import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import android.widget.Button; import android.widget.EditText; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java index b03d1e5cd..deb2fe0db 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -31,7 +31,6 @@ import java.text.NumberFormat; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityOptionsCompat; import androidx.core.content.ContextCompat; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java index 3f58e4a92..18620a56a 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -509,11 +509,21 @@ public class OnlineFeedViewActivity extends AppCompatActivity { viewBinding.subscribeButton.setEnabled(true); viewBinding.subscribeButton.setText(R.string.open_podcast); if (didPressSubscribe) { + didPressSubscribe = false; + if (UserPreferences.isEnableAutodownload()) { + Feed feed1 = DBReader.getFeed(getFeedId(feed)); + FeedPreferences feedPreferences = feed1.getPreferences(); + feedPreferences.setAutoDownload(viewBinding.autoDownloadCheckBox.isChecked()); + feed1.savePreferences(); + } openFeed(); } } else { viewBinding.subscribeButton.setEnabled(true); viewBinding.subscribeButton.setText(R.string.subscribe_label); + if (UserPreferences.isEnableAutodownload()) { + viewBinding.autoDownloadCheckBox.setVisibility(View.VISIBLE); + } } } } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java index 10292b892..d4e9ee5d9 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java @@ -17,9 +17,8 @@ import de.danoeh.antennapod.asynctask.OpmlFeedQueuer; import de.danoeh.antennapod.asynctask.OpmlImportWorker; import de.danoeh.antennapod.core.export.opml.OpmlElement; import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.util.LangUtils; + import org.apache.commons.io.ByteOrderMark; -import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.BOMInputStream; import org.apache.commons.lang3.ArrayUtils; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java index d85235cf9..f0c76d545 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java @@ -13,9 +13,9 @@ import android.widget.ProgressBar; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.storage.PodDBAdapter; +import de.danoeh.antennapod.error.CrashReportWriter; import io.reactivex.Completable; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; /** @@ -44,13 +44,15 @@ public class SplashActivity extends AppCompatActivity { }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(() -> { - Intent intent = new Intent(SplashActivity.this, MainActivity.class); - startActivity(intent); - overridePendingTransition(0, 0); - finish(); - }, error -> { + .subscribe( + () -> { + Intent intent = new Intent(SplashActivity.this, MainActivity.class); + startActivity(intent); + overridePendingTransition(0, 0); + finish(); + }, error -> { error.printStackTrace(); + CrashReportWriter.write(error); Toast.makeText(this, error.getLocalizedMessage(), Toast.LENGTH_LONG).show(); finish(); }); 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 9ab1755f5..1c8619e99 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java @@ -15,7 +15,6 @@ import android.view.animation.ScaleAnimation; import android.widget.EditText; import android.widget.ImageView; -import androidx.appcompat.view.menu.ActionMenuItem; import androidx.core.view.WindowCompat; import androidx.appcompat.app.ActionBar; import android.text.TextUtils; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/WidgetConfigActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/WidgetConfigActivity.java index 474b96c38..4805dba10 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/WidgetConfigActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/WidgetConfigActivity.java @@ -6,7 +6,6 @@ import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; import android.os.Build; import android.widget.ImageView; -import android.widget.RemoteViews; import androidx.appcompat.app.AppCompatActivity; import android.appwidget.AppWidgetManager; diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java index df81156b5..4fa8acc43 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java @@ -22,12 +22,14 @@ import de.danoeh.antennapod.core.util.EmbeddedChapterImage; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.ThemeUtils; import de.danoeh.antennapod.core.util.playback.Playable; +import de.danoeh.antennapod.view.CircularProgressBar; public class ChaptersListAdapter extends RecyclerView.Adapter<ChaptersListAdapter.ChapterHolder> { private Playable media; private final Callback callback; private final Context context; private int currentChapterIndex = -1; + private long currentChapterPosition = -1; private boolean hasImages = false; public ChaptersListAdapter(Context context, Callback callback) { @@ -48,7 +50,6 @@ public class ChaptersListAdapter extends RecyclerView.Adapter<ChaptersListAdapte notifyDataSetChanged(); } - @Override public void onBindViewHolder(@NonNull ChapterHolder holder, int position) { Chapter sc = getItem(position); @@ -83,8 +84,14 @@ public class ChaptersListAdapter extends RecyclerView.Adapter<ChaptersListAdapte if (position == currentChapterIndex) { int playingBackGroundColor = ThemeUtils.getColorFromAttr(context, R.attr.currently_playing_background); holder.itemView.setBackgroundColor(playingBackGroundColor); + float progress = ((float) (currentChapterPosition - sc.getStart())) / duration; + progress = Math.max(progress, CircularProgressBar.MINIMUM_PERCENTAGE); + progress = Math.min(progress, CircularProgressBar.MAXIMUM_PERCENTAGE); + holder.progressBar.setPercentage(progress, position); + holder.secondaryActionIcon.setImageResource(ThemeUtils.getDrawableFromAttr(context, R.attr.av_replay)); } else { holder.itemView.setBackgroundColor(ContextCompat.getColor(context, android.R.color.transparent)); + holder.progressBar.setPercentage(0, null); } if (hasImages) { @@ -136,6 +143,7 @@ public class ChaptersListAdapter extends RecyclerView.Adapter<ChaptersListAdapte final ImageView image; final View secondaryActionButton; final ImageView secondaryActionIcon; + final CircularProgressBar progressBar; public ChapterHolder(@NonNull View itemView) { super(itemView); @@ -146,14 +154,23 @@ public class ChaptersListAdapter extends RecyclerView.Adapter<ChaptersListAdapte duration = itemView.findViewById(R.id.txtvDuration); secondaryActionButton = itemView.findViewById(R.id.secondaryActionButton); secondaryActionIcon = itemView.findViewById(R.id.secondaryActionIcon); + progressBar = itemView.findViewById(R.id.secondaryActionProgress); } } public void notifyChapterChanged(int newChapterIndex) { currentChapterIndex = newChapterIndex; + currentChapterPosition = getItem(newChapterIndex).getStart(); notifyDataSetChanged(); } + public void notifyTimeChanged(long timeMs) { + currentChapterPosition = timeMs; + // Passing an argument prevents flickering. + // See EpisodeItemListAdapter.notifyItemChangedCompat. + notifyItemChanged(currentChapterIndex, "foo"); + } + private boolean ignoreChapter(Chapter c) { return media.getDuration() > 0 && media.getDuration() < c.getStart(); } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java index 7d195a9ad..0c4aaf6ed 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java @@ -1,23 +1,15 @@ package de.danoeh.antennapod.adapter; import android.app.Activity; -import android.content.Context; -import android.os.Build; -import android.text.Layout; import android.text.format.DateUtils; import android.util.Log; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; -import android.widget.TextView; import android.widget.Toast; import androidx.core.content.ContextCompat; -import com.joanzapata.iconify.widget.IconButton; -import com.joanzapata.iconify.widget.IconTextView; - import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java index 540cd054c..268a21409 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java @@ -65,6 +65,7 @@ public class DownloadlistAdapter extends BaseAdapter { holder.title.setText(request.getTitle()); holder.secondaryActionIcon.setImageResource(ThemeUtils.getDrawableFromAttr(context, R.attr.navigation_cancel)); + holder.secondaryActionButton.setContentDescription(context.getString(R.string.cancel_download_label)); holder.secondaryActionButton.setTag(downloader); holder.secondaryActionButton.setOnClickListener(butSecondaryListener); holder.secondaryActionProgress.setPercentage(0, request); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java index 6bfd34d5c..8cb0fd30a 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java @@ -13,8 +13,6 @@ import androidx.annotation.Nullable; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.MediaType; -import de.danoeh.antennapod.core.preferences.PlaybackPreferences; -import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.NetworkUtils; import de.danoeh.antennapod.core.util.playback.RemoteMedia; import de.danoeh.antennapod.core.feed.FeedItem; diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java index 7ce086694..01712ea29 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java @@ -6,7 +6,6 @@ import android.view.ContextMenu; import android.view.MenuInflater; import android.view.MotionEvent; import android.view.View; -import androidx.core.view.MotionEventCompat; import androidx.recyclerview.widget.ItemTouchHelper; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java index 8c294a9c9..919a4e217 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java @@ -13,8 +13,6 @@ import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; -import com.bumptech.glide.Glide; - import java.lang.ref.WeakReference; import java.text.NumberFormat; import java.util.Locale; @@ -23,7 +21,6 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.LocalFeedUpdater; -import de.danoeh.antennapod.fragment.AddFeedFragment; import de.danoeh.antennapod.fragment.FeedItemlistFragment; import jp.shts.android.library.TriangleLabelView; diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/PlayLocalActionButton.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/PlayLocalActionButton.java index 31dfe15da..78ea3b93f 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/PlayLocalActionButton.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/PlayLocalActionButton.java @@ -7,11 +7,8 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; -import de.danoeh.antennapod.core.preferences.UsageStatistics; import de.danoeh.antennapod.core.service.playback.PlaybackService; -import de.danoeh.antennapod.core.util.NetworkUtils; import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter; -import de.danoeh.antennapod.dialog.StreamingConfirmationDialog; public class PlayLocalActionButton extends ItemActionButton { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/VisitWebsiteActionButton.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/VisitWebsiteActionButton.java index 7b8659968..e45280eed 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/VisitWebsiteActionButton.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/VisitWebsiteActionButton.java @@ -1,8 +1,6 @@ package de.danoeh.antennapod.adapter.actionbutton; import android.content.Context; -import android.content.Intent; -import android.net.Uri; import android.view.View; import androidx.annotation.AttrRes; import androidx.annotation.StringRes; diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/DocumentFileExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/DocumentFileExportWorker.java index 3ac05e842..906d50c61 100644 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/DocumentFileExportWorker.java +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/DocumentFileExportWorker.java @@ -9,10 +9,10 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.nio.charset.Charset; import de.danoeh.antennapod.core.export.ExportWriter; import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.util.LangUtils; import io.reactivex.Observable; /** @@ -44,7 +44,7 @@ public class DocumentFileExportWorker { if (outputStream == null) { throw new IOException(); } - writer = new OutputStreamWriter(outputStream, LangUtils.UTF_8); + writer = new OutputStreamWriter(outputStream, Charset.forName("UTF-8")); exportWriter.writeDocument(DBReader.getFeedList(), writer, context); subscriber.onNext(output); } catch (IOException e) { diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java index f81a52402..0930b59eb 100644 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java @@ -8,11 +8,11 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; +import java.nio.charset.Charset; import de.danoeh.antennapod.core.export.ExportWriter; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.util.LangUtils; import io.reactivex.Observable; /** @@ -47,7 +47,7 @@ public class ExportWorker { return Observable.create(subscriber -> { OutputStreamWriter writer = null; try { - writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8); + writer = new OutputStreamWriter(new FileOutputStream(output), Charset.forName("UTF-8")); exportWriter.writeDocument(DBReader.getFeedList(), writer, context); subscriber.onNext(output); } catch (IOException e) { diff --git a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java index 6e584d34f..7a5cf431f 100644 --- a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java +++ b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.config; import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; +import de.danoeh.antennapod.core.storage.APDownloadAlgorithm; /** * Configures the ClientConfig class of the core package. @@ -15,7 +16,7 @@ class ClientConfigurator { ClientConfig.applicationCallbacks = new ApplicationCallbacksImpl(); ClientConfig.downloadServiceCallbacks = new DownloadServiceCallbacksImpl(); ClientConfig.playbackServiceCallbacks = new PlaybackServiceCallbacksImpl(); - ClientConfig.dbTasksCallbacks = new DBTasksCallbacksImpl(); + ClientConfig.automaticDownloadAlgorithm = new APDownloadAlgorithm(); ClientConfig.castCallbacks = new CastCallbackImpl(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/config/DBTasksCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/DBTasksCallbacksImpl.java deleted file mode 100644 index c3f7ae9c8..000000000 --- a/app/src/main/java/de/danoeh/antennapod/config/DBTasksCallbacksImpl.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.danoeh.antennapod.config; - -import de.danoeh.antennapod.core.DBTasksCallbacks; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.storage.APDownloadAlgorithm; -import de.danoeh.antennapod.core.storage.AutomaticDownloadAlgorithm; -import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm; - -public class DBTasksCallbacksImpl implements DBTasksCallbacks { - - @Override - public AutomaticDownloadAlgorithm getAutomaticDownloadAlgorithm() { - return new APDownloadAlgorithm(); - } - - @Override - public EpisodeCleanupAlgorithm getEpisodeCacheCleanupAlgorithm() { - return UserPreferences.getEpisodeCleanupAlgorithm(); - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java index 71442f50b..55bf05e43 100644 --- a/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java +++ b/app/src/main/java/de/danoeh/antennapod/config/DownloadServiceCallbacksImpl.java @@ -54,9 +54,4 @@ public class DownloadServiceCallbacksImpl implements DownloadServiceCallbacks { return PendingIntent.getActivity(context, R.id.pending_intent_download_service_autodownload_report, intent, PendingIntent.FLAG_UPDATE_CURRENT); } - - @Override - public boolean shouldCreateReport() { - return true; - } } diff --git a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java index 44f18e9da..f70cb26ff 100644 --- a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java +++ b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java @@ -3,7 +3,6 @@ package de.danoeh.antennapod.config; import android.content.Context; import android.content.Intent; import android.os.Build; -import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.VideoplayerActivity; import de.danoeh.antennapod.core.PlaybackServiceCallbacks; @@ -22,10 +21,4 @@ public class PlaybackServiceCallbacksImpl implements PlaybackServiceCallbacks { return i; } } - - @Override - public boolean useQueue() { - return true; - } - } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java index 5aee3f2be..efaff1da3 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java @@ -436,13 +436,18 @@ public class EpisodesApplyActionFragment extends Fragment implements Toolbar.OnM } private void deleteChecked() { + int countHasMedia = 0; + int countNoMedia = 0; for (long id : checkedIds.toArray()) { FeedItem episode = idMap.get(id); - if (episode.hasMedia()) { + if (episode.hasMedia() && episode.getMedia().isDownloaded()) { + countHasMedia++; DBWriter.deleteFeedMediaOfItem(getActivity(), episode.getMedia().getId()); + } else { + countNoMedia++; } } - close(R.plurals.deleted_episode_batch_label, checkedIds.size()); + closeMore(R.plurals.deleted_multi_episode_batch_label, countNoMedia, countHasMedia); } private void close(@PluralsRes int msgId, int numItems) { @@ -451,4 +456,12 @@ public class EpisodesApplyActionFragment extends Fragment implements Toolbar.OnM getActivity().getSupportFragmentManager().popBackStack(); } + private void closeMore(@PluralsRes int msgId, int countNoMedia, int countHasMedia) { + ((MainActivity) getActivity()).showSnackbarAbovePlayer( + getResources().getQuantityString(msgId, + (countHasMedia + countNoMedia), + (countHasMedia + countNoMedia), countHasMedia), + Snackbar.LENGTH_LONG); + getActivity().getSupportFragmentManager().popBackStack(); + } } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java index 699c6f492..a4e49ff96 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java @@ -1,16 +1,15 @@ package de.danoeh.antennapod.dialog; import android.app.Activity; -import android.text.InputType; import java.lang.ref.WeakReference; import android.view.View; -import android.widget.EditText; import androidx.appcompat.app.AlertDialog; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.databinding.EditTextDialogBinding; public class RenameFeedDialog { @@ -29,13 +28,14 @@ public class RenameFeedDialog { } View content = View.inflate(activity, R.layout.edit_text_dialog, null); - EditText editText = content.findViewById(R.id.text); - editText.setText(feed.getTitle()); + EditTextDialogBinding alertViewBinding = EditTextDialogBinding.bind(content); + + alertViewBinding.urlEditText.setText(feed.getTitle()); AlertDialog dialog = new AlertDialog.Builder(activity) .setView(content) .setTitle(de.danoeh.antennapod.core.R.string.rename_feed_label) .setPositiveButton(android.R.string.ok, (d, input) -> { - feed.setCustomTitle(editText.getText().toString()); + feed.setCustomTitle(alertViewBinding.urlEditText.getText().toString()); DBWriter.setFeedCustomTitle(feed); }) .setNeutralButton(de.danoeh.antennapod.core.R.string.reset, null) @@ -44,7 +44,7 @@ public class RenameFeedDialog { // To prevent cancelling the dialog on button click dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener( - (view) -> editText.setText(feed.getFeedTitle())); + (view) -> alertViewBinding.urlEditText.setText(feed.getFeedTitle())); } } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java index 274c3b7bd..f1a41d753 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java @@ -3,7 +3,6 @@ package de.danoeh.antennapod.dialog; import android.app.Activity; import android.app.Dialog; import android.content.Context; -import android.content.DialogInterface; import android.os.Bundle; import android.view.View; import android.view.inputmethod.InputMethodManager; @@ -88,6 +87,27 @@ public class SleepTimerDialog extends DialogFragment { timeSetup = content.findViewById(R.id.timeSetup); timeDisplay = content.findViewById(R.id.timeDisplay); time = content.findViewById(R.id.time); + Button extendSleepFiveMinutesButton = content.findViewById(R.id.extendSleepFiveMinutesButton); + extendSleepFiveMinutesButton.setText(getString(R.string.extend_sleep_timer_label, 5)); + Button extendSleepTenMinutesButton = content.findViewById(R.id.extendSleepTenMinutesButton); + extendSleepTenMinutesButton.setText(getString(R.string.extend_sleep_timer_label, 10)); + Button extendSleepTwentyMinutesButton = content.findViewById(R.id.extendSleepTwentyMinutesButton); + extendSleepTwentyMinutesButton.setText(getString(R.string.extend_sleep_timer_label, 20)); + extendSleepFiveMinutesButton.setOnClickListener(v -> { + if (controller != null) { + controller.extendSleepTimer(5 * 1000 * 60); + } + }); + extendSleepTenMinutesButton.setOnClickListener(v -> { + if (controller != null) { + controller.extendSleepTimer(10 * 1000 * 60); + } + }); + extendSleepTwentyMinutesButton.setOnClickListener(v -> { + if (controller != null) { + controller.extendSleepTimer(20 * 1000 * 60); + } + }); etxtTime.setText(SleepTimerPreferences.lastTimerValue()); etxtTime.postDelayed(() -> { diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/ItunesPodcastSearcher.java b/app/src/main/java/de/danoeh/antennapod/discovery/ItunesPodcastSearcher.java index 796ec556f..6e894176f 100644 --- a/app/src/main/java/de/danoeh/antennapod/discovery/ItunesPodcastSearcher.java +++ b/app/src/main/java/de/danoeh/antennapod/discovery/ItunesPodcastSearcher.java @@ -1,7 +1,5 @@ package de.danoeh.antennapod.discovery; -import android.content.Context; -import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import io.reactivex.Single; import io.reactivex.SingleOnSubscribe; diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearcher.java b/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearcher.java index eeebd2ebf..8fbc8c76b 100644 --- a/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearcher.java +++ b/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearcher.java @@ -1,8 +1,6 @@ package de.danoeh.antennapod.discovery; import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.reactivex.functions.Consumer; import java.util.List; public interface PodcastSearcher { 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 28456c01e..06a974dfd 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java @@ -12,7 +12,6 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.EditText; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -30,6 +29,8 @@ import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.util.SortOrder; +import de.danoeh.antennapod.databinding.AddfeedBinding; +import de.danoeh.antennapod.databinding.EditTextDialogBinding; import de.danoeh.antennapod.discovery.CombinedSearcher; import de.danoeh.antennapod.discovery.FyydPodcastSearcher; import de.danoeh.antennapod.discovery.ItunesPodcastSearcher; @@ -50,7 +51,7 @@ public class AddFeedFragment extends Fragment { private static final int REQUEST_CODE_CHOOSE_OPML_IMPORT_PATH = 1; private static final int REQUEST_CODE_ADD_LOCAL_FOLDER = 2; - private EditText combinedFeedSearchBox; + private AddfeedBinding viewBinding; private MainActivity activity; @Override @@ -59,29 +60,30 @@ public class AddFeedFragment extends Fragment { @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); - View root = inflater.inflate(R.layout.addfeed, container, false); + viewBinding = AddfeedBinding.inflate(getLayoutInflater()); activity = (MainActivity) getActivity(); - Toolbar toolbar = root.findViewById(R.id.toolbar); + + Toolbar toolbar = viewBinding.toolbar; ((MainActivity) getActivity()).setupToolbarToggle(toolbar); - root.findViewById(R.id.btn_search_itunes).setOnClickListener(v + viewBinding.searchItunesButton.setOnClickListener(v -> activity.loadChildFragment(OnlineSearchFragment.newInstance(ItunesPodcastSearcher.class))); - root.findViewById(R.id.btn_search_fyyd).setOnClickListener(v + viewBinding.searchFyydButton.setOnClickListener(v -> activity.loadChildFragment(OnlineSearchFragment.newInstance(FyydPodcastSearcher.class))); - root.findViewById(R.id.btn_search_gpodder).setOnClickListener(v + viewBinding.searchGPodderButton.setOnClickListener(v -> activity.loadChildFragment(new GpodnetMainFragment())); - root.findViewById(R.id.btn_search_podcastindex).setOnClickListener(v + viewBinding.searchPodcastIndexButton.setOnClickListener(v -> activity.loadChildFragment(OnlineSearchFragment.newInstance(PodcastIndexPodcastSearcher.class))); - combinedFeedSearchBox = root.findViewById(R.id.combinedFeedSearchBox); - combinedFeedSearchBox.setOnEditorActionListener((v, actionId, event) -> { + viewBinding.combinedFeedSearchEditText.setOnEditorActionListener((v, actionId, event) -> { performSearch(); return true; }); - root.findViewById(R.id.btn_add_via_url).setOnClickListener(v + + viewBinding.addViaUrlButton.setOnClickListener(v -> showAddViaUrlDialog()); - root.findViewById(R.id.btn_opml_import).setOnClickListener(v -> { + viewBinding.opmlImportButton.setOnClickListener(v -> { try { Intent intentGetContentAction = new Intent(Intent.ACTION_GET_CONTENT); intentGetContentAction.addCategory(Intent.CATEGORY_OPENABLE); @@ -93,7 +95,8 @@ public class AddFeedFragment extends Fragment { .showSnackbarAbovePlayer(R.string.unable_to_start_system_file_manager, Snackbar.LENGTH_LONG); } }); - root.findViewById(R.id.btn_add_local_folder).setOnClickListener(v -> { + + viewBinding.addLocalFolderButton.setOnClickListener(v -> { if (Build.VERSION.SDK_INT < 21) { return; } @@ -108,25 +111,29 @@ public class AddFeedFragment extends Fragment { } }); if (Build.VERSION.SDK_INT < 21) { - root.findViewById(R.id.btn_add_local_folder).setVisibility(View.GONE); + viewBinding.addLocalFolderButton.setVisibility(View.GONE); } - root.findViewById(R.id.search_icon).setOnClickListener(view -> performSearch()); - return root; + + viewBinding.searchButton.setOnClickListener(view -> performSearch()); + + return viewBinding.getRoot(); } private void showAddViaUrlDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(R.string.add_podcast_by_url); View content = View.inflate(getContext(), R.layout.edit_text_dialog, null); - EditText editText = content.findViewById(R.id.text); - editText.setHint(R.string.add_podcast_by_url_hint); + EditTextDialogBinding alertViewBinding = EditTextDialogBinding.bind(content); + alertViewBinding.urlEditText.setHint(R.string.add_podcast_by_url_hint); + ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); String clipboardContent = clipboard.getText() != null ? clipboard.getText().toString() : ""; if (clipboardContent.trim().startsWith("http")) { - editText.setText(clipboardContent.trim()); + alertViewBinding.urlEditText.setText(clipboardContent.trim()); } - builder.setView(content); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> addUrl(editText.getText().toString())); + builder.setView(alertViewBinding.getRoot()); + builder.setPositiveButton(R.string.confirm_label, + (dialog, which) -> addUrl(alertViewBinding.urlEditText.getText().toString())); builder.setNegativeButton(R.string.cancel_label, null); builder.show(); } @@ -138,8 +145,7 @@ public class AddFeedFragment extends Fragment { } private void performSearch() { - String query = combinedFeedSearchBox.getText().toString(); - + String query = viewBinding.combinedFeedSearchEditText.getText().toString(); if (query.matches("http[s]?://.*")) { addUrl(query); return; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java index ae3ba3a54..4423a2ebe 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -4,7 +4,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import androidx.annotation.NonNull; 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 5a65f956c..82e2b3a6a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AudioPlayerFragment.java @@ -22,6 +22,8 @@ import androidx.viewpager2.adapter.FragmentStateAdapter; import androidx.viewpager2.widget.ViewPager2; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.snackbar.Snackbar; +import com.google.android.material.tabs.TabLayout; +import com.google.android.material.tabs.TabLayoutMediator; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.CastEnabledActivity; import de.danoeh.antennapod.activity.MainActivity; @@ -43,7 +45,6 @@ import de.danoeh.antennapod.dialog.SkipPreferenceDialog; import de.danoeh.antennapod.dialog.SleepTimerDialog; import de.danoeh.antennapod.dialog.VariableSpeedDialog; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; -import de.danoeh.antennapod.view.PagerIndicatorView; import de.danoeh.antennapod.view.PlaybackSpeedIndicatorView; import io.reactivex.Maybe; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -74,7 +75,6 @@ public class AudioPlayerFragment extends Fragment implements PlaybackSpeedIndicatorView butPlaybackSpeed; TextView txtvPlaybackSpeed; private ViewPager2 pager; - private PagerIndicatorView pageIndicator; private TextView txtvPosition; private TextView txtvLength; private SeekBar sbPosition; @@ -90,6 +90,8 @@ public class AudioPlayerFragment extends Fragment implements private PlaybackController controller; private Disposable disposable; private boolean showTimeLeft; + private boolean hasChapters = false; + private TabLayoutMediator tabLayoutMediator; @Override public View onCreateView(@NonNull LayoutInflater inflater, @@ -141,13 +143,37 @@ public class AudioPlayerFragment extends Fragment implements }); } }); - pageIndicator = root.findViewById(R.id.page_indicator); - pageIndicator.setViewPager(pager); - pageIndicator.setOnClickListener(v -> - pager.setCurrentItem((pager.getCurrentItem() + 1) % NUM_CONTENT_FRAGMENTS)); + + TabLayout tabLayout = root.findViewById(R.id.sliding_tabs); + tabLayoutMediator = new TabLayoutMediator(tabLayout, pager, (tab, position) -> { + tab.view.setAlpha(1.0f); + switch (position) { + case POS_COVER: + tab.setText(R.string.cover_label); + break; + case POS_DESCR: + tab.setText(R.string.description_label); + break; + case POS_CHAPTERS: + tab.setText(R.string.chapters_label); + if (!hasChapters) { + tab.view.setAlpha(0.5f); + } + break; + default: + break; + } + }); + tabLayoutMediator.attach(); return root; } + public void setHasChapters(boolean hasChapters) { + this.hasChapters = hasChapters; + tabLayoutMediator.detach(); + tabLayoutMediator.attach(); + } + public View getExternalPlayerHolder() { return getView().findViewById(R.id.playerFragment); } @@ -362,10 +388,6 @@ public class AudioPlayerFragment extends Fragment implements setupOptionsMenu(media); } - public void setHasChapters(boolean hasChapters) { - pageIndicator.setDisabledPage(hasChapters ? -1 : 2); - } - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java index 6f95d71da..d781d0774 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java @@ -106,6 +106,7 @@ public class ChaptersFragment extends Fragment { @Subscribe(threadMode = ThreadMode.MAIN) public void onEventMainThread(PlaybackPositionEvent event) { updateChapterSelection(getCurrentChapter(media)); + adapter.notifyTimeChanged(event.getPosition()); } private int getCurrentChapter(Playable media) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java index 59b2cd234..3519a34b4 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java @@ -4,7 +4,6 @@ import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java index c2c45c581..2e11ea4ec 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java @@ -4,7 +4,6 @@ import android.app.Dialog; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; -import android.content.res.TypedArray; import android.os.Bundle; import androidx.annotation.NonNull; @@ -13,7 +12,6 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.ListFragment; import android.util.Log; import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.ListView; 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 fc3052e20..18a61f1e6 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java @@ -8,10 +8,8 @@ import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; 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; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java index 669dbdac2..07f59bb42 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java @@ -17,7 +17,6 @@ import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; import androidx.core.text.TextUtilsCompat; import androidx.core.util.ObjectsCompat; import androidx.core.view.ViewCompat; @@ -71,7 +70,6 @@ import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; -import java.util.Date; import java.util.List; import java.util.Locale; @@ -120,6 +118,7 @@ public class ItemFragment extends Fragment { private View butAction2; private ItemActionButton actionButton1; private ItemActionButton actionButton2; + private View noMediaLabel; private Disposable disposable; private PlaybackController controller; @@ -169,6 +168,7 @@ public class ItemFragment extends Fragment { butAction2Icon = layout.findViewById(R.id.butAction2Icon); butAction1Text = layout.findViewById(R.id.butAction1Text); butAction2Text = layout.findViewById(R.id.butAction2Text); + noMediaLabel = layout.findViewById(R.id.noMediaLabel); butAction1.setOnClickListener(v -> { if (actionButton1 instanceof StreamActionButton && !UserPreferences.isStreamOverDownload() @@ -319,7 +319,9 @@ public class ItemFragment extends Fragment { if (media == null) { actionButton1 = new MarkAsPlayedActionButton(item); actionButton2 = new VisitWebsiteActionButton(item); + noMediaLabel.setVisibility(View.VISIBLE); } else { + noMediaLabel.setVisibility(View.GONE); if (media.getDuration() > 0) { txtvDuration.setText(Converter.getDurationStringLong(media.getDuration())); txtvDuration.setContentDescription( diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java index d748d14c9..1aa66dcbb 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java @@ -1,7 +1,6 @@ package de.danoeh.antennapod.fragment; import android.os.Bundle; -import android.view.MenuInflater; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.ItemTouchHelper; 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 c994b4d8b..14f355b52 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QuickFeedDiscoveryFragment.java @@ -46,6 +46,7 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView. private FeedDiscoverAdapter adapter; private GridView discoverGridLayout; private TextView errorTextView; + private TextView poweredByTextView; private LinearLayout errorView; private Button errorRetry; @@ -63,6 +64,7 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView. errorTextView = root.findViewById(R.id.discover_error_txtV); errorRetry = root.findViewById(R.id.discover_error_retry_btn); errorRetry.setOnClickListener((listener) -> loadToplist()); + poweredByTextView = root.findViewById(R.id.discover_powered_by_itunes); adapter = new FeedDiscoverAdapter((MainActivity) getActivity()); discoverGridLayout.setAdapter(adapter); @@ -110,6 +112,7 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView. discoverGridLayout.setVisibility(View.INVISIBLE); errorView.setVisibility(View.GONE); errorRetry.setVisibility(View.INVISIBLE); + poweredByTextView.setVisibility(View.VISIBLE); ItunesTopListLoader loader = new ItunesTopListLoader(getContext()); SharedPreferences prefs = getActivity().getSharedPreferences(ItunesTopListLoader.PREFS, MODE_PRIVATE); @@ -122,6 +125,7 @@ public class QuickFeedDiscoveryFragment extends Fragment implements AdapterView. progressBar.setVisibility(View.GONE); discoverGridLayout.setVisibility(View.INVISIBLE); errorRetry.setVisibility(View.INVISIBLE); + poweredByTextView.setVisibility(View.INVISIBLE); return; } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java index 087abc327..fc500a223 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java @@ -6,7 +6,6 @@ import androidx.annotation.NonNull; import androidx.fragment.app.ListFragment; import android.util.Log; import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.ListView; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java index 0894c2df6..4735cab42 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java @@ -27,6 +27,7 @@ import android.widget.TextView; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.joanzapata.iconify.Iconify; +import java.util.Locale; import java.util.concurrent.Callable; import de.danoeh.antennapod.R; @@ -65,6 +66,12 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem public static final String TAG = "SubscriptionFragment"; private static final String PREFS = "SubscriptionFragment"; private static final String PREF_NUM_COLUMNS = "columns"; + private static final int MIN_NUM_COLUMNS = 2; + private static final int[] COLUMN_CHECKBOX_IDS = { + R.id.subscription_num_columns_2, + R.id.subscription_num_columns_3, + R.id.subscription_num_columns_4, + R.id.subscription_num_columns_5}; private GridView subscriptionGridLayout; private DBReader.NavDrawerData navDrawerData; @@ -97,6 +104,11 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem toolbar.setOnMenuItemClickListener(this); ((MainActivity) getActivity()).setupToolbarToggle(toolbar); toolbar.inflateMenu(R.menu.subscriptions); + for (int i = 0; i < COLUMN_CHECKBOX_IDS.length; i++) { + // Do this in Java to localize numbers + toolbar.getMenu().findItem(COLUMN_CHECKBOX_IDS[i]) + .setTitle(String.format(Locale.getDefault(), "%d", i + MIN_NUM_COLUMNS)); + } refreshToolbarState(); subscriptionGridLayout = root.findViewById(R.id.subscriptions_grid); @@ -119,10 +131,7 @@ public class SubscriptionFragment extends Fragment implements Toolbar.OnMenuItem private void refreshToolbarState() { int columns = prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()); - toolbar.getMenu().findItem(R.id.subscription_num_columns_2).setChecked(columns == 2); - toolbar.getMenu().findItem(R.id.subscription_num_columns_3).setChecked(columns == 3); - toolbar.getMenu().findItem(R.id.subscription_num_columns_4).setChecked(columns == 4); - toolbar.getMenu().findItem(R.id.subscription_num_columns_5).setChecked(columns == 5); + toolbar.getMenu().findItem(COLUMN_CHECKBOX_IDS[columns - MIN_NUM_COLUMNS]).setChecked(true); isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(), R.id.refresh_item, updateRefreshMenuItemChecker); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java index e272b2869..1f5434688 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java @@ -4,12 +4,9 @@ import android.content.Context; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; -import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; -import androidx.appcompat.widget.SearchView; import android.util.Log; import android.view.LayoutInflater; -import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Button; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java index bec73894c..eb23a5eb1 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java @@ -1,15 +1,12 @@ package de.danoeh.antennapod.fragment.preferences; import android.app.Activity; -import android.content.SharedPreferences; import android.os.Bundle; import androidx.core.text.HtmlCompat; -import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import android.text.Spanned; import android.text.format.DateUtils; -import android.widget.Toast; import com.google.android.material.snackbar.Snackbar; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.PreferenceActivity; 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 99fd12021..7bf602e35 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 @@ -1,8 +1,11 @@ package de.danoeh.antennapod.fragment.preferences; import android.content.Intent; +import android.os.Build; import android.os.Bundle; +import android.provider.Settings; import androidx.appcompat.app.AppCompatActivity; +import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import com.bytehamster.lib.preferencesearch.SearchConfiguration; import com.bytehamster.lib.preferencesearch.SearchPreference; @@ -20,7 +23,7 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat { private static final String PREF_SCREEN_NETWORK = "prefScreenNetwork"; private static final String PREF_SCREEN_GPODDER = "prefScreenGpodder"; private static final String PREF_SCREEN_STORAGE = "prefScreenStorage"; - private static final String PREF_FAQ = "prefFaq"; + private static final String PREF_DOCUMENTATION = "prefDocumentation"; private static final String PREF_VIEW_FORUM = "prefViewForum"; private static final String PREF_SEND_BUG_REPORT = "prefSendBugReport"; private static final String PREF_CATEGORY_PROJECT = "project"; @@ -35,10 +38,18 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat { setupSearch(); // If you are writing a spin-off, please update the details on screens like "About" and "Report bug" - // and afterwards remove the following lines. + // and afterwards remove the following lines. Please keep in mind that AntennaPod is licensed under the GPL. + // This means that your application needs to be open-source under the GPL, too. + // It must also include a prominent copyright notice. String packageName = getContext().getPackageName(); if (!"de.danoeh.antennapod".equals(packageName) && !"de.danoeh.antennapod.debug".equals(packageName)) { findPreference(PREF_CATEGORY_PROJECT).setVisible(false); + Preference copyrightNotice = new Preference(getContext()); + copyrightNotice.setSummary("This application is based on AntennaPod." + + " The AntennaPod team does NOT provide support for this unofficial version." + + " If you can read this message, the developers of this modification" + + " violate the GNU General Public License (GPL)."); + findPreference(PREF_CATEGORY_PROJECT).getParent().addPreference(copyrightNotice); } } @@ -70,10 +81,16 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat { return true; }); findPreference(PREF_NOTIFICATION).setOnPreferenceClickListener(preference -> { - ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_notifications); + if (Build.VERSION.SDK_INT >= 26) { + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS); + intent.putExtra(Settings.EXTRA_APP_PACKAGE, getActivity().getPackageName()); + startActivity(intent); + } else { + ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_notifications); + } return true; }); - findPreference(PREF_ABOUT).setOnPreferenceClickListener( preference -> { getParentFragmentManager().beginTransaction().replace(R.id.content, new AboutFragment()) @@ -88,8 +105,8 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat { return true; } ); - findPreference(PREF_FAQ).setOnPreferenceClickListener(preference -> { - IntentUtils.openInBrowser(getContext(), "https://antennapod.org/faq.html"); + findPreference(PREF_DOCUMENTATION).setOnPreferenceClickListener(preference -> { + IntentUtils.openInBrowser(getContext(), "https://antennapod.org/documentation/"); return true; }); findPreference(PREF_VIEW_FORUM).setOnPreferenceClickListener(preference -> { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java index fcc37f644..77f8063f2 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java @@ -15,7 +15,6 @@ import org.apache.commons.lang3.ArrayUtils; import java.util.Calendar; import java.util.GregorianCalendar; -import java.util.Locale; import java.util.concurrent.TimeUnit; public class NetworkPreferencesFragment extends PreferenceFragmentCompat { @@ -97,8 +96,7 @@ public class NetworkPreferencesFragment extends PreferenceFragmentCompat { private void setParallelDownloadsText(int downloads) { final Resources res = getActivity().getResources(); - String s = String.format(Locale.getDefault(), "%d%s", - downloads, res.getString(R.string.parallel_downloads_suffix)); + String s = res.getString(R.string.parallel_downloads, downloads); findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS).setSummary(s); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/AboutFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/AboutFragment.java index b440d053b..0a64bbe71 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/AboutFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/AboutFragment.java @@ -33,7 +33,7 @@ public class AboutFragment extends PreferenceFragmentCompat { return true; }); findPreference("about_privacy_policy").setOnPreferenceClickListener((preference) -> { - IntentUtils.openInBrowser(getContext(), "https://antennapod.org/privacy.html"); + IntentUtils.openInBrowser(getContext(), "https://antennapod.org/privacy/"); return true; }); findPreference("about_licenses").setOnPreferenceClickListener((preference) -> { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/DevelopersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/DevelopersFragment.java index 60d9f95dd..b844234b7 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/DevelopersFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/DevelopersFragment.java @@ -6,8 +6,6 @@ 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; 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 index 6db1389ea..d759a5ff2 100644 --- 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 @@ -6,8 +6,6 @@ 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; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/TranslatorsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/TranslatorsFragment.java index e8d8e113b..b77c74de6 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/TranslatorsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/about/TranslatorsFragment.java @@ -6,8 +6,6 @@ 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; diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java index 9ceed9369..0086a75ab 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java @@ -4,7 +4,6 @@ import android.content.Context; import android.content.DialogInterface; import android.util.Log; import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import androidx.annotation.NonNull; diff --git a/app/src/main/java/de/danoeh/antennapod/view/CircularProgressBar.java b/app/src/main/java/de/danoeh/antennapod/view/CircularProgressBar.java index f755a4c84..2fd570ece 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/CircularProgressBar.java +++ b/app/src/main/java/de/danoeh/antennapod/view/CircularProgressBar.java @@ -11,7 +11,8 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.util.ThemeUtils; public class CircularProgressBar extends View { - private static final float EPSILON = 0.005f; + public static final float MINIMUM_PERCENTAGE = 0.005f; + public static final float MAXIMUM_PERCENTAGE = 1 - MINIMUM_PERCENTAGE; private final Paint paintBackground = new Paint(); private final Paint paintProgress = new Paint(); @@ -74,11 +75,11 @@ public class CircularProgressBar extends View { bounds.set(padding, padding, getWidth() - padding, getHeight() - padding); canvas.drawArc(bounds, 0, 360, false, paintBackground); - if (percentage > EPSILON && 1 - percentage > EPSILON) { + if (MINIMUM_PERCENTAGE <= percentage && percentage <= MAXIMUM_PERCENTAGE) { canvas.drawArc(bounds, -90, percentage * 360, false, paintProgress); } - if (Math.abs(percentage - targetPercentage) > EPSILON) { + if (Math.abs(percentage - targetPercentage) > MINIMUM_PERCENTAGE) { float speed = 0.02f; if (Math.abs(targetPercentage - percentage) < 0.1 && targetPercentage > percentage) { speed = 0.006f; diff --git a/app/src/main/java/de/danoeh/antennapod/view/PagerIndicatorView.java b/app/src/main/java/de/danoeh/antennapod/view/PagerIndicatorView.java deleted file mode 100644 index 10ed98769..000000000 --- a/app/src/main/java/de/danoeh/antennapod/view/PagerIndicatorView.java +++ /dev/null @@ -1,124 +0,0 @@ -package de.danoeh.antennapod.view; - -import android.animation.ArgbEvaluator; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.util.AttributeSet; -import android.view.View; - -import androidx.annotation.Nullable; -import androidx.core.text.TextUtilsCompat; -import androidx.core.view.ViewCompat; -import androidx.recyclerview.widget.RecyclerView; -import androidx.viewpager2.widget.ViewPager2; - -import java.util.Locale; - -public class PagerIndicatorView extends View { - private final Paint paint = new Paint(); - private float position = 0; - private int numPages = 0; - private int disabledPage = -1; - private int circleColor = 0; - private int circleColorHighlight = -1; - private boolean isLocaleRtl = false; - - public PagerIndicatorView(Context context) { - super(context); - setup(); - } - - public PagerIndicatorView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - setup(); - } - - public PagerIndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - setup(); - } - - private void setup() { - isLocaleRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) - == ViewCompat.LAYOUT_DIRECTION_RTL; - - paint.setAntiAlias(true); - paint.setStyle(Paint.Style.FILL); - - int[] colorAttrs = new int[]{android.R.attr.textColorSecondary}; - TypedArray a = getContext().obtainStyledAttributes(colorAttrs); - circleColorHighlight = a.getColor(0, 0xffffffff); - circleColor = (Integer) new ArgbEvaluator().evaluate(0.8f, 0x00ffffff, circleColorHighlight); - a.recycle(); - } - - /** - * Visual and logical position distinction only happens in RTL locales (e.g. Persian) - * where pages positions are flipped thus it does nothing in LTR locales (e.g. English) - */ - private float logicalPositionToVisual(float position) { - return isLocaleRtl ? numPages - 1 - position : position; - } - - public void setViewPager(ViewPager2 pager) { - numPages = pager.getAdapter().getItemCount(); - pager.getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { - @Override - public void onChanged() { - numPages = pager.getAdapter().getItemCount(); - invalidate(); - } - }); - pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - PagerIndicatorView.this.position = logicalPositionToVisual( - position + positionOffset); - invalidate(); - } - }); - } - - public void setDisabledPage(int disabledPage) { - this.disabledPage = (int) logicalPositionToVisual(disabledPage); - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - for (int i = 0; i < numPages; i++) { - if ((int) Math.floor(position) == i) { - // This is the current dot - drawCircle(canvas, i, (float) (1 - (position - Math.floor(position)))); - } else if ((int) Math.ceil(position) == i) { - // This is the next dot - drawCircle(canvas, i, (float) (position - Math.floor(position))); - } else { - drawCircle(canvas, i, 0); - } - } - } - - private void drawCircle(Canvas canvas, int position, float frac) { - float availableHeight = canvas.getHeight() - getPaddingTop() - getPaddingBottom(); - float circleRadiusSmall = availableHeight * 0.26f; - float circleRadiusBig = availableHeight * 0.35f; - float circleRadiusDelta = (circleRadiusBig - circleRadiusSmall); - float start = 0.5f * (canvas.getWidth() - numPages * 1.5f * availableHeight); - paint.setStrokeWidth(availableHeight * 0.3f); - - if (position == disabledPage) { - paint.setStyle(Paint.Style.STROKE); - } else { - paint.setStyle(Paint.Style.FILL_AND_STROKE); - } - - paint.setColor((Integer) new ArgbEvaluator().evaluate(frac, circleColor, circleColorHighlight)); - canvas.drawCircle(start + (position * 1.5f + 0.75f) * availableHeight, 0.5f * availableHeight + getPaddingTop(), - circleRadiusSmall + frac * circleRadiusDelta, paint); - } -}
\ No newline at end of file |