diff --git a/README.md b/README.md
index c7cfdeaf..16aa28cb 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ PodVinci is an open source podcast manager/player project.
This is based on a fork from the popular project AntennaPod (https://github.com/AntennaPod/AntennaPod) as of Feb 5 2024.
-This project is purely Kotlin based, relies on the most recent dependencies, and most importantly has migrated the media player to androidx.media3, and added mechanism of AudioOffloadMode which is supposed to be kind to device battery. App build is also upgraded to target Android 14.
+Differing from the forked project, this project is purely Kotlin based, relies on the most recent dependencies, and most importantly has migrated the media player to androidx.media3, and added mechanism of AudioOffloadMode which is supposed to be kind to device battery. Efficiencies are also sought on running the app. App build is also upgraded to target Android 14.
## Privacy Policy
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ce1f72b3..9f6ff86f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -8,7 +8,6 @@
tools:ignore="ScopedStorage" />
-
+
+
+
+
+
+
+
finish() }
- viewBinding!!.closeButton.setOnClickListener { view: View? -> finish() }
- viewBinding!!.card.setOnClickListener(null)
- viewBinding!!.card.setCardBackgroundColor(getColorFromAttr(this, R.attr.colorSurface))
+ viewBinding.transparentBackground.setOnClickListener { v: View? -> finish() }
+ viewBinding.closeButton.setOnClickListener { view: View? -> finish() }
+ viewBinding.card.setOnClickListener(null)
+ viewBinding.card.setCardBackgroundColor(getColorFromAttr(this, R.attr.colorSurface))
headerBinding = OnlinefeedviewHeaderBinding.inflate(layoutInflater)
var feedUrl: String? = null
@@ -165,8 +165,8 @@ class OnlineFeedViewActivity : AppCompatActivity() {
* Displays a progress indicator.
*/
private fun setLoadingLayout() {
- viewBinding!!.progressBar.visibility = View.VISIBLE
- viewBinding!!.feedDisplayContainer.visibility = View.GONE
+ viewBinding.progressBar.visibility = View.VISIBLE
+ viewBinding.feedDisplayContainer.visibility = View.GONE
}
override fun onStart() {
@@ -189,15 +189,9 @@ class OnlineFeedViewActivity : AppCompatActivity() {
public override fun onDestroy() {
super.onDestroy()
- if (updater != null) {
- updater!!.dispose()
- }
- if (download != null) {
- download!!.dispose()
- }
- if (parser != null) {
- parser!!.dispose()
- }
+ updater?.dispose()
+ download?.dispose()
+ parser?.dispose()
}
override fun onSaveInstanceState(outState: Bundle) {
@@ -264,8 +258,9 @@ class OnlineFeedViewActivity : AppCompatActivity() {
val results = searcher.search(query)?.blockingGet()
if (results.isNullOrEmpty()) return null
for (result in results) {
- if (result?.feedUrl != null && result.author != null && result.author.equals(artistName,
- ignoreCase = true) && result.title.equals(trackName, ignoreCase = true)) {
+ if (result?.feedUrl != null && result.author != null &&
+ result.author.equals(artistName, ignoreCase = true) &&
+ result.title.equals(trackName, ignoreCase = true)) {
return result.feedUrl
}
}
@@ -301,7 +296,7 @@ class OnlineFeedViewActivity : AppCompatActivity() {
if (username != null && password != null) {
Toast.makeText(this, R.string.download_error_unauthorized, Toast.LENGTH_LONG).show()
}
- if (downloader!!.downloadRequest.source != null) {
+ if (downloader?.downloadRequest?.source != null) {
dialog = FeedViewAuthenticationDialog(this@OnlineFeedViewActivity,
R.string.authentication_notification_title, downloader!!.downloadRequest.source!!).create()
dialog?.show()
@@ -376,8 +371,7 @@ class OnlineFeedViewActivity : AppCompatActivity() {
} else {
throw UnsupportedFeedtypeException(getString(R.string.download_error_unsupported_type_html))
}
- }
- else null
+ } else null
} else {
throw e
}
@@ -395,18 +389,18 @@ class OnlineFeedViewActivity : AppCompatActivity() {
* This method is executed on the GUI thread.
*/
@UnstableApi private fun showFeedInformation(feed: Feed, alternateFeedUrls: Map) {
- viewBinding!!.progressBar.visibility = View.GONE
- viewBinding!!.feedDisplayContainer.visibility = View.VISIBLE
+ viewBinding.progressBar.visibility = View.GONE
+ viewBinding.feedDisplayContainer.visibility = View.VISIBLE
if (isFeedFoundBySearch) {
val resId = R.string.no_feed_url_podcast_found_by_search
Snackbar.make(findViewById(android.R.id.content), resId, Snackbar.LENGTH_LONG).show()
}
- viewBinding!!.backgroundImage.colorFilter = LightingColorFilter(-0x7d7d7e, 0x000000)
+ viewBinding.backgroundImage.colorFilter = LightingColorFilter(-0x7d7d7e, 0x000000)
- viewBinding!!.listView.addHeaderView(headerBinding!!.root)
- viewBinding!!.listView.setSelector(android.R.color.transparent)
- viewBinding!!.listView.adapter = FeedItemlistDescriptionAdapter(this, 0, feed.items)
+ viewBinding.listView.addHeaderView(headerBinding.root)
+ viewBinding.listView.setSelector(android.R.color.transparent)
+ viewBinding.listView.adapter = FeedItemlistDescriptionAdapter(this, 0, feed.items)
if (StringUtils.isNotBlank(feed.imageUrl)) {
Glide.with(this)
@@ -416,7 +410,7 @@ class OnlineFeedViewActivity : AppCompatActivity() {
.error(R.color.light_gray)
.fitCenter()
.dontAnimate())
- .into(viewBinding!!.coverImage)
+ .into(viewBinding.coverImage)
Glide.with(this)
.load(feed.imageUrl)
.apply(RequestOptions()
@@ -424,14 +418,14 @@ class OnlineFeedViewActivity : AppCompatActivity() {
.error(R.color.image_readability_tint)
.transform(FastBlurTransformation())
.dontAnimate())
- .into(viewBinding!!.backgroundImage)
+ .into(viewBinding.backgroundImage)
}
- viewBinding!!.titleLabel.text = feed.title
- viewBinding!!.authorLabel.text = feed.author
- headerBinding!!.txtvDescription.text = HtmlToPlainText.getPlainText(feed.description)
+ viewBinding.titleLabel.text = feed.title
+ viewBinding.authorLabel.text = feed.author
+ headerBinding.txtvDescription.text = HtmlToPlainText.getPlainText(feed.description)
- viewBinding!!.subscribeButton.setOnClickListener { v: View? ->
+ viewBinding.subscribeButton.setOnClickListener { v: View? ->
if (feedInFeedlist()) {
openFeed()
} else {
@@ -441,29 +435,29 @@ class OnlineFeedViewActivity : AppCompatActivity() {
}
}
- viewBinding!!.stopPreviewButton.setOnClickListener { v: View? ->
+ viewBinding.stopPreviewButton.setOnClickListener { v: View? ->
writeNoMediaPlaying()
sendLocalBroadcast(this, PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE)
}
if (isEnableAutodownload) {
val preferences = getSharedPreferences(PREFS, MODE_PRIVATE)
- viewBinding!!.autoDownloadCheckBox.isChecked = preferences.getBoolean(PREF_LAST_AUTO_DOWNLOAD, true)
+ viewBinding.autoDownloadCheckBox.isChecked = preferences.getBoolean(PREF_LAST_AUTO_DOWNLOAD, true)
}
- headerBinding!!.txtvDescription.maxLines = DESCRIPTION_MAX_LINES_COLLAPSED
- headerBinding!!.txtvDescription.setOnClickListener { v: View? ->
- if (headerBinding!!.txtvDescription.maxLines > DESCRIPTION_MAX_LINES_COLLAPSED) {
- headerBinding!!.txtvDescription.maxLines = DESCRIPTION_MAX_LINES_COLLAPSED
+ headerBinding.txtvDescription.maxLines = DESCRIPTION_MAX_LINES_COLLAPSED
+ headerBinding.txtvDescription.setOnClickListener { v: View? ->
+ if (headerBinding.txtvDescription.maxLines > DESCRIPTION_MAX_LINES_COLLAPSED) {
+ headerBinding.txtvDescription.maxLines = DESCRIPTION_MAX_LINES_COLLAPSED
} else {
- headerBinding!!.txtvDescription.maxLines = 2000
+ headerBinding.txtvDescription.maxLines = 2000
}
}
if (alternateFeedUrls.isEmpty()) {
- viewBinding!!.alternateUrlsSpinner.visibility = View.GONE
+ viewBinding.alternateUrlsSpinner.visibility = View.GONE
} else {
- viewBinding!!.alternateUrlsSpinner.visibility = View.VISIBLE
+ viewBinding.alternateUrlsSpinner.visibility = View.VISIBLE
val alternateUrlsList: MutableList = ArrayList()
val alternateUrlsTitleList: MutableList = ArrayList()
@@ -486,8 +480,8 @@ class OnlineFeedViewActivity : AppCompatActivity() {
}
adapter.setDropDownViewResource(R.layout.alternate_urls_dropdown_item)
- viewBinding!!.alternateUrlsSpinner.adapter = adapter
- viewBinding!!.alternateUrlsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ viewBinding.alternateUrlsSpinner.adapter = adapter
+ viewBinding.alternateUrlsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
selectedDownloadUrl = alternateUrlsList[position]
}
@@ -510,13 +504,15 @@ class OnlineFeedViewActivity : AppCompatActivity() {
}
@UnstableApi private fun handleUpdatedFeedStatus() {
- if (DownloadServiceInterface.get() == null || selectedDownloadUrl == null) return
- if (DownloadServiceInterface.get()!!.isDownloadingEpisode(selectedDownloadUrl!!)) {
- viewBinding!!.subscribeButton.isEnabled = false
- viewBinding!!.subscribeButton.setText(R.string.subscribing_label)
+ val dli = DownloadServiceInterface.get()
+ if (dli == null || selectedDownloadUrl == null) return
+
+ if (dli.isDownloadingEpisode(selectedDownloadUrl!!)) {
+ viewBinding.subscribeButton.isEnabled = false
+ viewBinding.subscribeButton.setText(R.string.subscribing_label)
} else if (feedInFeedlist()) {
- viewBinding!!.subscribeButton.isEnabled = true
- viewBinding!!.subscribeButton.setText(R.string.open_podcast)
+ viewBinding.subscribeButton.isEnabled = true
+ viewBinding.subscribeButton.setText(R.string.open_podcast)
if (didPressSubscribe) {
didPressSubscribe = false
@@ -524,7 +520,7 @@ class OnlineFeedViewActivity : AppCompatActivity() {
val feedPreferences = feed1.preferences
if (feedPreferences != null) {
if (isEnableAutodownload) {
- val autoDownload = viewBinding!!.autoDownloadCheckBox.isChecked
+ val autoDownload = viewBinding.autoDownloadCheckBox.isChecked
feedPreferences.autoDownload = autoDownload
val preferences = getSharedPreferences(PREFS, MODE_PRIVATE)
@@ -541,10 +537,10 @@ class OnlineFeedViewActivity : AppCompatActivity() {
openFeed()
}
} else {
- viewBinding!!.subscribeButton.isEnabled = true
- viewBinding!!.subscribeButton.setText(R.string.subscribe_label)
+ viewBinding.subscribeButton.isEnabled = true
+ viewBinding.subscribeButton.setText(R.string.subscribe_label)
if (isEnableAutodownload) {
- viewBinding!!.autoDownloadCheckBox.visibility = View.VISIBLE
+ viewBinding.autoDownloadCheckBox.visibility = View.VISIBLE
}
}
}
@@ -622,7 +618,7 @@ class OnlineFeedViewActivity : AppCompatActivity() {
@Subscribe(threadMode = ThreadMode.MAIN)
fun playbackStateChanged(event: PlayerStatusEvent?) {
val isPlayingPreview = currentlyPlayingMediaType == RemoteMedia.PLAYABLE_TYPE_REMOTE_MEDIA.toLong()
- viewBinding!!.stopPreviewButton.visibility = if (isPlayingPreview) View.VISIBLE else View.GONE
+ viewBinding.stopPreviewButton.visibility = if (isPlayingPreview) View.VISIBLE else View.GONE
}
/**
@@ -631,7 +627,7 @@ class OnlineFeedViewActivity : AppCompatActivity() {
*/
private fun showFeedDiscoveryDialog(feedFile: File, baseUrl: String): Boolean {
val fd = FeedDiscoverer()
- val urlsMap: Map?
+ val urlsMap: Map
try {
urlsMap = fd.findLinks(feedFile, baseUrl)
if (urlsMap.isEmpty()) {
diff --git a/app/src/main/java/ac/mdiq/podvinci/activity/OpmlImportActivity.kt b/app/src/main/java/ac/mdiq/podvinci/activity/OpmlImportActivity.kt
index 48ef81e1..881a38f1 100644
--- a/app/src/main/java/ac/mdiq/podvinci/activity/OpmlImportActivity.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/activity/OpmlImportActivity.kt
@@ -45,54 +45,59 @@ import java.io.Reader
*/
class OpmlImportActivity : AppCompatActivity() {
private var uri: Uri? = null
- private var viewBinding: OpmlSelectionBinding? = null
+ private lateinit var viewBinding: OpmlSelectionBinding
+ private lateinit var selectAll: MenuItem
+ private lateinit var deselectAll: MenuItem
+
private var listAdapter: ArrayAdapter? = null
- private var selectAll: MenuItem? = null
- private var deselectAll: MenuItem? = null
private var readElements: ArrayList? = null
@UnstableApi override fun onCreate(savedInstanceState: Bundle?) {
setTheme(getTheme(this))
super.onCreate(savedInstanceState)
- supportActionBar!!.setDisplayHomeAsUpEnabled(true)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
viewBinding = OpmlSelectionBinding.inflate(layoutInflater)
- setContentView(viewBinding!!.root)
+ setContentView(viewBinding.root)
- viewBinding!!.feedlist.choiceMode = ListView.CHOICE_MODE_MULTIPLE
- viewBinding!!.feedlist.onItemClickListener =
+ viewBinding.feedlist.choiceMode = ListView.CHOICE_MODE_MULTIPLE
+ viewBinding.feedlist.onItemClickListener =
OnItemClickListener { parent: AdapterView<*>?, view: View?, position: Int, id: Long ->
- val checked = viewBinding!!.feedlist.checkedItemPositions
+ val checked = viewBinding.feedlist.checkedItemPositions
var checkedCount = 0
for (i in 0 until checked.size()) {
if (checked.valueAt(i)) {
checkedCount++
}
}
- if (checkedCount == listAdapter!!.count) {
- selectAll!!.setVisible(false)
- deselectAll!!.setVisible(true)
- } else {
- deselectAll!!.setVisible(false)
- selectAll!!.setVisible(true)
+ if (listAdapter != null) {
+ if (checkedCount == listAdapter!!.count) {
+ selectAll.setVisible(false)
+ deselectAll.setVisible(true)
+ } else {
+ deselectAll.setVisible(false)
+ selectAll.setVisible(true)
+ }
}
}
- viewBinding!!.butCancel.setOnClickListener { v: View? ->
+ viewBinding.butCancel.setOnClickListener { v: View? ->
setResult(RESULT_CANCELED)
finish()
}
- viewBinding!!.butConfirm.setOnClickListener { v: View? ->
- viewBinding!!.progressBar.visibility = View.VISIBLE
+ viewBinding.butConfirm.setOnClickListener { v: View? ->
+ viewBinding.progressBar.visibility = View.VISIBLE
Completable.fromAction {
- val checked = viewBinding!!.feedlist.checkedItemPositions
+ val checked = viewBinding.feedlist.checkedItemPositions
for (i in 0 until checked.size()) {
if (!checked.valueAt(i)) {
continue
}
- val element = readElements!![checked.keyAt(i)]
- val feed = Feed(element.xmlUrl, null,
- if (element.text != null) element.text else "Unknown podcast")
- feed.items = mutableListOf()
- DBTasks.updateFeed(this, feed, false)
+ if (!readElements.isNullOrEmpty()) {
+ val element = readElements!![checked.keyAt(i)]
+ val feed = Feed(element.xmlUrl, null,
+ if (element.text != null) element.text else "Unknown podcast")
+ feed.items = mutableListOf()
+ DBTasks.updateFeed(this, feed, false)
+ }
}
runOnce(this)
}
@@ -100,14 +105,14 @@ class OpmlImportActivity : AppCompatActivity() {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
- viewBinding!!.progressBar.visibility = View.GONE
+ viewBinding.progressBar.visibility = View.GONE
val intent = Intent(this@OpmlImportActivity, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
finish()
}, { e: Throwable ->
e.printStackTrace()
- viewBinding!!.progressBar.visibility = View.GONE
+ viewBinding.progressBar.visibility = View.GONE
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
})
}
@@ -139,7 +144,7 @@ class OpmlImportActivity : AppCompatActivity() {
private val titleList: List
get() {
val result: MutableList = ArrayList()
- if (readElements != null) {
+ if (!readElements.isNullOrEmpty()) {
for (element in readElements!!) {
if (element.text != null) result.add(element.text!!)
}
@@ -153,7 +158,7 @@ class OpmlImportActivity : AppCompatActivity() {
inflater.inflate(R.menu.opml_selection_options, menu)
selectAll = menu.findItem(R.id.select_all_item)
deselectAll = menu.findItem(R.id.deselect_all_item)
- deselectAll?.setVisible(false)
+ deselectAll.setVisible(false)
return true
}
@@ -161,15 +166,15 @@ class OpmlImportActivity : AppCompatActivity() {
val itemId = item.itemId
when (itemId) {
R.id.select_all_item -> {
- selectAll!!.setVisible(false)
+ selectAll.setVisible(false)
selectAllItems(true)
- deselectAll!!.setVisible(true)
+ deselectAll.setVisible(true)
return true
}
R.id.deselect_all_item -> {
- deselectAll!!.setVisible(false)
+ deselectAll.setVisible(false)
selectAllItems(false)
- selectAll!!.setVisible(true)
+ selectAll.setVisible(true)
return true
}
android.R.id.home -> {
@@ -180,8 +185,8 @@ class OpmlImportActivity : AppCompatActivity() {
}
private fun selectAllItems(b: Boolean) {
- for (i in 0 until viewBinding!!.feedlist.count) {
- viewBinding!!.feedlist.setItemChecked(i, b)
+ for (i in 0 until viewBinding.feedlist.count) {
+ viewBinding.feedlist.setItemChecked(i, b)
}
}
@@ -204,13 +209,13 @@ class OpmlImportActivity : AppCompatActivity() {
/** Starts the import process. */
private fun startImport() {
- viewBinding!!.progressBar.visibility = View.VISIBLE
+ viewBinding.progressBar.visibility = View.VISIBLE
Observable.fromCallable {
val opmlFileStream = contentResolver.openInputStream(uri!!)
val bomInputStream = BOMInputStream(opmlFileStream)
val bom = bomInputStream.bom
- val charsetName = if ((bom == null)) "UTF-8" else bom.charsetName
+ val charsetName = if (bom == null) "UTF-8" else bom.charsetName
val reader: Reader = InputStreamReader(bomInputStream, charsetName)
val opmlReader = OpmlReader()
val result = opmlReader.readDocument(reader)
@@ -221,13 +226,13 @@ class OpmlImportActivity : AppCompatActivity() {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ result: ArrayList? ->
- viewBinding!!.progressBar.visibility = View.GONE
+ viewBinding.progressBar.visibility = View.GONE
Log.d(TAG, "Parsing was successful")
readElements = result
listAdapter = ArrayAdapter(this@OpmlImportActivity,
android.R.layout.simple_list_item_multiple_choice,
titleList)
- viewBinding!!.feedlist.adapter = listAdapter
+ viewBinding.feedlist.adapter = listAdapter
}, { e: Throwable ->
Log.d(TAG, Log.getStackTraceString(e))
val message = if (e.message == null) "" else e.message!!
@@ -240,7 +245,7 @@ class OpmlImportActivity : AppCompatActivity() {
return@subscribe
}
}
- viewBinding!!.progressBar.visibility = View.GONE
+ viewBinding.progressBar.visibility = View.GONE
val alert = MaterialAlertDialogBuilder(this)
alert.setTitle(R.string.error_label)
val userReadable = getString(R.string.opml_reader_error)
diff --git a/app/src/main/java/ac/mdiq/podvinci/activity/PreferenceActivity.kt b/app/src/main/java/ac/mdiq/podvinci/activity/PreferenceActivity.kt
index f624f837..4473ede6 100644
--- a/app/src/main/java/ac/mdiq/podvinci/activity/PreferenceActivity.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/activity/PreferenceActivity.kt
@@ -30,7 +30,7 @@ import org.greenrobot.eventbus.ThreadMode
* PreferenceController.
*/
class PreferenceActivity : AppCompatActivity(), SearchPreferenceResultListener {
- private var binding: SettingsActivityBinding? = null
+ private lateinit var binding: SettingsActivityBinding
@SuppressLint("CommitTransaction")
override fun onCreate(savedInstanceState: Bundle?) {
@@ -41,11 +41,11 @@ class PreferenceActivity : AppCompatActivity(), SearchPreferenceResultListener {
ab?.setDisplayHomeAsUpEnabled(true)
binding = SettingsActivityBinding.inflate(layoutInflater)
- setContentView(binding!!.root)
+ setContentView(binding.root)
if (supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) == null) {
supportFragmentManager.beginTransaction()
- .replace(binding!!.settingsContainer.id, MainPreferencesFragment(), FRAGMENT_TAG)
+ .replace(binding.settingsContainer.id, MainPreferencesFragment(), FRAGMENT_TAG)
.commit()
}
val intent = intent
@@ -96,7 +96,7 @@ class PreferenceActivity : AppCompatActivity(), SearchPreferenceResultListener {
startActivity(intent)
} else {
supportFragmentManager.beginTransaction()
- .replace(binding!!.settingsContainer.id, fragment!!)
+ .replace(binding.settingsContainer.id, fragment!!)
.addToBackStack(getString(getTitleOfPage(screen)))
.commit()
}
@@ -156,7 +156,7 @@ class PreferenceActivity : AppCompatActivity(), SearchPreferenceResultListener {
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: MessageEvent) {
Log.d(FRAGMENT_TAG, "onEvent($event)")
- val s = Snackbar.make(binding!!.root, event.message, Snackbar.LENGTH_LONG)
+ val s = Snackbar.make(binding.root, event.message, Snackbar.LENGTH_LONG)
if (event.action != null) {
s.setAction(event.actionText) { v: View? -> event.action!!.accept(this) }
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/activity/SelectSubscriptionActivity.kt b/app/src/main/java/ac/mdiq/podvinci/activity/SelectSubscriptionActivity.kt
index 9a8eb0f8..6d3ada7e 100644
--- a/app/src/main/java/ac/mdiq/podvinci/activity/SelectSubscriptionActivity.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/activity/SelectSubscriptionActivity.kt
@@ -1,7 +1,13 @@
package ac.mdiq.podvinci.activity
-import ac.mdiq.podvinci.activity.MainActivity
+import ac.mdiq.podvinci.R
import ac.mdiq.podvinci.activity.MainActivity.Companion.EXTRA_FEED_ID
+import ac.mdiq.podvinci.core.preferences.ThemeSwitcher
+import ac.mdiq.podvinci.core.storage.DBReader
+import ac.mdiq.podvinci.core.storage.NavDrawerData
+import ac.mdiq.podvinci.databinding.SubscriptionSelectionActivityBinding
+import ac.mdiq.podvinci.model.feed.Feed
+import ac.mdiq.podvinci.storage.preferences.UserPreferences
import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
@@ -15,19 +21,13 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
+import androidx.media3.common.util.UnstableApi
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
-import ac.mdiq.podvinci.R
-import ac.mdiq.podvinci.core.preferences.ThemeSwitcher
-import ac.mdiq.podvinci.core.storage.DBReader
-import ac.mdiq.podvinci.core.storage.NavDrawerData
-import ac.mdiq.podvinci.databinding.SubscriptionSelectionActivityBinding
-import ac.mdiq.podvinci.model.feed.Feed
-import ac.mdiq.podvinci.storage.preferences.UserPreferences
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
@@ -39,29 +39,29 @@ class SelectSubscriptionActivity : AppCompatActivity() {
@Volatile
private var listItems: List? = null
- private var viewBinding: SubscriptionSelectionActivityBinding? = null
+ private lateinit var viewBinding: SubscriptionSelectionActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(ThemeSwitcher.getTranslucentTheme(this))
super.onCreate(savedInstanceState)
viewBinding = SubscriptionSelectionActivityBinding.inflate(layoutInflater)
- setContentView(viewBinding!!.root)
- setSupportActionBar(viewBinding!!.toolbar)
+ setContentView(viewBinding.root)
+ setSupportActionBar(viewBinding.toolbar)
setTitle(R.string.shortcut_select_subscription)
- viewBinding!!.transparentBackground.setOnClickListener { v: View? -> finish() }
- viewBinding!!.card.setOnClickListener(null)
+ viewBinding.transparentBackground.setOnClickListener { v: View? -> finish() }
+ viewBinding.card.setOnClickListener(null)
loadSubscriptions()
val checkedPosition = arrayOfNulls(1)
- viewBinding!!.list.choiceMode = ListView.CHOICE_MODE_SINGLE
- viewBinding!!.list.onItemClickListener =
+ viewBinding.list.choiceMode = ListView.CHOICE_MODE_SINGLE
+ viewBinding.list.onItemClickListener =
AdapterView.OnItemClickListener { listView: AdapterView<*>?, view1: View?, position: Int, rowId: Long ->
checkedPosition[0] = position
}
- viewBinding!!.shortcutBtn.setOnClickListener { view: View? ->
+ viewBinding.shortcutBtn.setOnClickListener { view: View? ->
if (checkedPosition[0] != null && Intent.ACTION_CREATE_SHORTCUT == intent.action) {
getBitmapFromUrl(listItems!![checkedPosition[0]!!])
}
@@ -83,7 +83,7 @@ class SelectSubscriptionActivity : AppCompatActivity() {
return result
}
- private fun addShortcut(feed: Feed, bitmap: Bitmap?) {
+ @UnstableApi private fun addShortcut(feed: Feed, bitmap: Bitmap?) {
val intent = Intent(this, MainActivity::class.java)
intent.setAction(Intent.ACTION_MAIN)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
@@ -114,15 +114,15 @@ class SelectSubscriptionActivity : AppCompatActivity() {
.load(feed.imageUrl)
.apply(RequestOptions.overrideOf(iconSize, iconSize))
.listener(object : RequestListener {
- override fun onLoadFailed(e: GlideException?, model: Any?,
- target: Target, isFirstResource: Boolean
+ @UnstableApi override fun onLoadFailed(e: GlideException?, model: Any?,
+ target: Target, isFirstResource: Boolean
): Boolean {
addShortcut(feed, null)
return true
}
- override fun onResourceReady(resource: Bitmap, model: Any,
- target: Target, dataSource: DataSource, isFirstResource: Boolean
+ @UnstableApi override fun onResourceReady(resource: Bitmap, model: Any,
+ target: Target, dataSource: DataSource, isFirstResource: Boolean
): Boolean {
addShortcut(feed, resource)
return true
@@ -131,9 +131,8 @@ class SelectSubscriptionActivity : AppCompatActivity() {
}
private fun loadSubscriptions() {
- if (disposable != null) {
- disposable?.dispose()
- }
+ disposable?.dispose()
+
disposable = Observable.fromCallable {
val data: NavDrawerData = DBReader.getNavDrawerData(UserPreferences.subscriptionsFilter)
getFeedItems(data.items, ArrayList())
@@ -149,7 +148,7 @@ class SelectSubscriptionActivity : AppCompatActivity() {
}
val adapter: ArrayAdapter = ArrayAdapter(this,
R.layout.simple_list_item_multiple_choice_on_start, titles)
- viewBinding!!.list.adapter = adapter
+ viewBinding.list.adapter = adapter
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/activity/VideoplayerActivity.kt b/app/src/main/java/ac/mdiq/podvinci/activity/VideoplayerActivity.kt
index f7283a52..be5cd8d8 100644
--- a/app/src/main/java/ac/mdiq/podvinci/activity/VideoplayerActivity.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/activity/VideoplayerActivity.kt
@@ -66,6 +66,9 @@ import org.greenrobot.eventbus.ThreadMode
*/
@UnstableApi
class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
+
+ private lateinit var viewBinding: VideoplayerActivityBinding
+
/**
* True if video controls are currently visible.
*/
@@ -74,7 +77,6 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
private var destroyingDueToReload = false
private var lastScreenTap: Long = 0
private val videoControlsHider = Handler(Looper.getMainLooper())
- private var viewBinding: VideoplayerActivityBinding? = null
private var controller: PlaybackController? = null
private var showTimeLeft = false
private var isFavorite = false
@@ -94,10 +96,10 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
window.setFormat(PixelFormat.TRANSPARENT)
viewBinding = VideoplayerActivityBinding.inflate(LayoutInflater.from(this))
- setContentView(viewBinding!!.root)
+ setContentView(viewBinding.root)
setupView()
- supportActionBar!!.setBackgroundDrawable(ColorDrawable(-0x80000000))
- supportActionBar!!.setDisplayHomeAsUpEnabled(true)
+ supportActionBar?.setBackgroundDrawable(ColorDrawable(-0x80000000))
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
@UnstableApi
@@ -116,20 +118,17 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
@UnstableApi
override fun onStop() {
- if (controller != null) {
- controller!!.release()
- controller = null // prevent leak
- }
- if (disposable != null) {
- disposable!!.dispose()
- }
+ controller?.release()
+ controller = null // prevent leak
+ disposable?.dispose()
+
EventBus.getDefault().unregister(this)
super.onStop()
if (!PictureInPictureUtil.isInPictureInPictureMode(this)) {
videoControlsHider.removeCallbacks(hideVideoControls)
}
// Controller released; we will not receive buffering updates
- viewBinding!!.progressBar.visibility = View.GONE
+ viewBinding.progressBar.visibility = View.GONE
}
public override fun onUserLeaveHint() {
@@ -172,7 +171,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
private fun newPlaybackController(): PlaybackController {
return object : PlaybackController(this@VideoplayerActivity) {
override fun updatePlayButtonShowsPlay(showPlay: Boolean) {
- viewBinding!!.playButton.setIsShowPlay(showPlay)
+ viewBinding.playButton.setIsShowPlay(showPlay)
if (showPlay) {
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} else {
@@ -180,7 +179,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
setupVideoAspectRatio()
if (videoSurfaceCreated && controller != null) {
Log.d(TAG, "Videosurface already created, setting videosurface now")
- controller!!.setVideoSurface(viewBinding!!.videoView.holder)
+ controller!!.setVideoSurface(viewBinding.videoView.holder)
}
}
}
@@ -199,11 +198,11 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
@Suppress("unused")
fun bufferUpdate(event: BufferUpdateEvent) {
if (event.hasStarted()) {
- viewBinding!!.progressBar.visibility = View.VISIBLE
+ viewBinding.progressBar.visibility = View.VISIBLE
} else if (event.hasEnded()) {
- viewBinding!!.progressBar.visibility = View.INVISIBLE
+ viewBinding.progressBar.visibility = View.INVISIBLE
} else {
- viewBinding!!.sbPosition.secondaryProgress = (event.progress * viewBinding!!.sbPosition.max).toInt()
+ viewBinding.sbPosition.secondaryProgress = (event.progress * viewBinding.sbPosition.max).toInt()
}
}
@@ -216,9 +215,9 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
}
@UnstableApi
- protected fun loadMediaInfo() {
+ private fun loadMediaInfo() {
Log.d(TAG, "loadMediaInfo()")
- if (controller == null || controller!!.getMedia() == null) {
+ if (controller?.getMedia() == null) {
return
}
if (controller!!.status == PlayerStatus.PLAYING && !controller!!.isPlayingVideoLocally) {
@@ -239,12 +238,12 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
}
@UnstableApi
- protected fun setupView() {
+ private fun setupView() {
showTimeLeft = shouldShowRemainingTime()
Log.d("timeleft", if (showTimeLeft) "true" else "false")
- viewBinding!!.durationLabel.setOnClickListener { v: View? ->
+ viewBinding.durationLabel.setOnClickListener { v: View? ->
showTimeLeft = !showTimeLeft
- val media = controller!!.getMedia() ?: return@setOnClickListener
+ val media = controller?.getMedia() ?: return@setOnClickListener
val converter = TimeSpeedConverter(controller!!.currentPlaybackSpeedMultiplier)
val length: String
@@ -255,48 +254,48 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
val duration = converter.convert(media.getDuration())
length = getDurationStringLong(duration)
}
- viewBinding!!.durationLabel.text = length
+ viewBinding.durationLabel.text = length
setShowRemainTimeSetting(showTimeLeft)
Log.d("timeleft on click", if (showTimeLeft) "true" else "false")
}
- viewBinding!!.sbPosition.setOnSeekBarChangeListener(this)
- viewBinding!!.rewindButton.setOnClickListener { v: View? -> onRewind() }
- viewBinding!!.rewindButton.setOnLongClickListener { v: View? ->
+ viewBinding.sbPosition.setOnSeekBarChangeListener(this)
+ viewBinding.rewindButton.setOnClickListener { v: View? -> onRewind() }
+ viewBinding.rewindButton.setOnLongClickListener { v: View? ->
SkipPreferenceDialog.showSkipPreference(this@VideoplayerActivity,
SkipPreferenceDialog.SkipDirection.SKIP_REWIND, null)
true
}
- viewBinding!!.playButton.setIsVideoScreen(true)
- viewBinding!!.playButton.setOnClickListener { v: View? -> onPlayPause() }
- viewBinding!!.fastForwardButton.setOnClickListener { v: View? -> onFastForward() }
- viewBinding!!.fastForwardButton.setOnLongClickListener { v: View? ->
+ viewBinding.playButton.setIsVideoScreen(true)
+ viewBinding.playButton.setOnClickListener { v: View? -> onPlayPause() }
+ viewBinding.fastForwardButton.setOnClickListener { v: View? -> onFastForward() }
+ viewBinding.fastForwardButton.setOnLongClickListener { v: View? ->
SkipPreferenceDialog.showSkipPreference(this@VideoplayerActivity,
SkipPreferenceDialog.SkipDirection.SKIP_FORWARD, null)
false
}
// To suppress touches directly below the slider
- viewBinding!!.bottomControlsContainer.setOnTouchListener { view: View?, motionEvent: MotionEvent? -> true }
- viewBinding!!.bottomControlsContainer.fitsSystemWindows = true
- viewBinding!!.videoView.holder.addCallback(surfaceHolderCallback)
- viewBinding!!.videoView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ viewBinding.bottomControlsContainer.setOnTouchListener { view: View?, motionEvent: MotionEvent? -> true }
+ viewBinding.bottomControlsContainer.fitsSystemWindows = true
+ viewBinding.videoView.holder.addCallback(surfaceHolderCallback)
+ viewBinding.videoView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
setupVideoControlsToggler()
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN)
- viewBinding!!.videoPlayerContainer.setOnTouchListener(onVideoviewTouched)
- viewBinding!!.videoPlayerContainer.viewTreeObserver.addOnGlobalLayoutListener {
- viewBinding!!.videoView.setAvailableSize(
- viewBinding!!.videoPlayerContainer.width.toFloat(), viewBinding!!.videoPlayerContainer.height.toFloat())
+ viewBinding.videoPlayerContainer.setOnTouchListener(onVideoviewTouched)
+ viewBinding.videoPlayerContainer.viewTreeObserver.addOnGlobalLayoutListener {
+ viewBinding.videoView.setAvailableSize(
+ viewBinding.videoPlayerContainer.width.toFloat(), viewBinding.videoPlayerContainer.height.toFloat())
}
}
private val hideVideoControls = Runnable {
if (videoControlsShowing) {
Log.d(TAG, "Hiding video controls")
- supportActionBar!!.hide()
+ supportActionBar?.hide()
hideVideoControls(true)
videoControlsShowing = false
}
@@ -320,7 +319,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
showSkipAnimation(false)
}
if (videoControlsShowing) {
- supportActionBar!!.hide()
+ supportActionBar?.hide()
hideVideoControls(false)
videoControlsShowing = false
}
@@ -344,24 +343,24 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
skipAnimation.fillAfter = false
skipAnimation.duration = 800
- val params = viewBinding!!.skipAnimationImage.layoutParams as FrameLayout.LayoutParams
+ val params = viewBinding.skipAnimationImage.layoutParams as FrameLayout.LayoutParams
if (isForward) {
- viewBinding!!.skipAnimationImage.setImageResource(R.drawable.ic_fast_forward_video_white)
+ viewBinding.skipAnimationImage.setImageResource(R.drawable.ic_fast_forward_video_white)
params.gravity = Gravity.RIGHT or Gravity.CENTER_VERTICAL
} else {
- viewBinding!!.skipAnimationImage.setImageResource(R.drawable.ic_fast_rewind_video_white)
+ viewBinding.skipAnimationImage.setImageResource(R.drawable.ic_fast_rewind_video_white)
params.gravity = Gravity.LEFT or Gravity.CENTER_VERTICAL
}
- viewBinding!!.skipAnimationImage.visibility = View.VISIBLE
- viewBinding!!.skipAnimationImage.layoutParams = params
- viewBinding!!.skipAnimationImage.startAnimation(skipAnimation)
+ viewBinding.skipAnimationImage.visibility = View.VISIBLE
+ viewBinding.skipAnimationImage.layoutParams = params
+ viewBinding.skipAnimationImage.startAnimation(skipAnimation)
skipAnimation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
}
override fun onAnimationEnd(animation: Animation) {
- viewBinding!!.skipAnimationImage.visibility = View.GONE
+ viewBinding.skipAnimationImage.visibility = View.GONE
}
override fun onAnimationRepeat(animation: Animation) {
@@ -380,7 +379,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
val videoSize = controller!!.videoSize
if (videoSize != null && videoSize.first > 0 && videoSize.second > 0) {
Log.d(TAG, "Width,height of video: " + videoSize.first + ", " + videoSize.second)
- viewBinding!!.videoView.setVideoSize(videoSize.first, videoSize.second)
+ viewBinding.videoView.setVideoSize(videoSize.first, videoSize.second)
} else {
Log.e(TAG, "Could not determine video size")
}
@@ -389,10 +388,10 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
private fun toggleVideoControlsVisibility() {
if (videoControlsShowing) {
- supportActionBar!!.hide()
+ supportActionBar?.hide()
hideVideoControls(true)
} else {
- supportActionBar!!.show()
+ supportActionBar?.show()
showVideoControls()
}
videoControlsShowing = !videoControlsShowing
@@ -436,7 +435,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
override fun surfaceCreated(holder: SurfaceHolder) {
Log.d(TAG, "Videoview holder created")
videoSurfaceCreated = true
- if (controller != null && controller!!.status == PlayerStatus.PLAYING) {
+ if (controller?.status == PlayerStatus.PLAYING) {
controller!!.setVideoSurface(holder)
}
setupVideoAspectRatio()
@@ -452,31 +451,31 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
}
private fun showVideoControls() {
- viewBinding!!.bottomControlsContainer.visibility = View.VISIBLE
- viewBinding!!.controlsContainer.visibility = View.VISIBLE
+ viewBinding.bottomControlsContainer.visibility = View.VISIBLE
+ viewBinding.controlsContainer.visibility = View.VISIBLE
val animation = AnimationUtils.loadAnimation(this, R.anim.fade_in)
if (animation != null) {
- viewBinding!!.bottomControlsContainer.startAnimation(animation)
- viewBinding!!.controlsContainer.startAnimation(animation)
+ viewBinding.bottomControlsContainer.startAnimation(animation)
+ viewBinding.controlsContainer.startAnimation(animation)
}
- viewBinding!!.videoView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
+ viewBinding.videoView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
}
private fun hideVideoControls(showAnimation: Boolean) {
if (showAnimation) {
val animation = AnimationUtils.loadAnimation(this, R.anim.fade_out)
if (animation != null) {
- viewBinding!!.bottomControlsContainer.startAnimation(animation)
- viewBinding!!.controlsContainer.startAnimation(animation)
+ viewBinding.bottomControlsContainer.startAnimation(animation)
+ viewBinding.controlsContainer.startAnimation(animation)
}
}
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE
or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
- viewBinding!!.bottomControlsContainer.fitsSystemWindows = true
+ viewBinding.bottomControlsContainer.fitsSystemWindows = true
- viewBinding!!.bottomControlsContainer.visibility = View.GONE
- viewBinding!!.controlsContainer.visibility = View.GONE
+ viewBinding.bottomControlsContainer.visibility = View.GONE
+ viewBinding.controlsContainer.visibility = View.GONE
}
@Subscribe(threadMode = ThreadMode.MAIN)
@@ -501,12 +500,10 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
Log.d(TAG, "onEvent($event)")
val errorDialog = MaterialAlertDialogBuilder(this)
errorDialog.setMessage(event.message)
- if (event.action != null) {
- errorDialog.setPositiveButton(event.actionText) { dialog: DialogInterface?, which: Int ->
- event.action!!.accept(
- this)
- }
+ errorDialog.setPositiveButton(event.actionText) { dialog: DialogInterface?, which: Int ->
+ event.action?.accept(this)
}
+
errorDialog.show()
}
@@ -533,7 +530,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
menu.findItem(R.id.visit_website_item).setVisible(hasWebsiteLink)
val isItemAndHasLink = isFeedMedia && hasLinkToShare((media as FeedMedia).getItem())
- val isItemHasDownloadLink = isFeedMedia && (media as FeedMedia?)!!.download_url != null
+ val isItemHasDownloadLink = isFeedMedia && (media as FeedMedia?)?.download_url != null
menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink)
menu.findItem(R.id.add_to_favorites_item).setVisible(false)
@@ -555,56 +552,61 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == R.id.player_switch_to_audio_only) {
- switchToAudioOnly = true
- finish()
- return true
- } else if (item.itemId == android.R.id.home) {
- val intent = Intent(this@VideoplayerActivity, MainActivity::class.java)
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
- startActivity(intent)
- finish()
- return true
- } else if (item.itemId == R.id.player_show_chapters) {
- ChaptersFragment().show(supportFragmentManager, ChaptersFragment.TAG)
- return true
- }
-
- if (controller == null) {
- return false
- }
-
- val media = controller!!.getMedia() ?: return false
- val feedItem = getFeedItem(media) // some options option requires FeedItem
- if (item.itemId == R.id.add_to_favorites_item && feedItem != null) {
- DBWriter.addFavoriteItem(feedItem)
- isFavorite = true
- invalidateOptionsMenu()
- } else if (item.itemId == R.id.remove_from_favorites_item && feedItem != null) {
- DBWriter.removeFavoriteItem(feedItem)
- isFavorite = false
- invalidateOptionsMenu()
- } else if (item.itemId == R.id.disable_sleeptimer_item
- || item.itemId == R.id.set_sleeptimer_item) {
- SleepTimerDialog().show(supportFragmentManager, "SleepTimerDialog")
- } else if (item.itemId == R.id.audio_controls) {
- val dialog = PlaybackControlsDialog.newInstance()
- dialog.show(supportFragmentManager, "playback_controls")
- } else if (item.itemId == R.id.open_feed_item && feedItem != null) {
- val intent = MainActivity.getIntentToOpenFeed(this, feedItem.feedId)
- startActivity(intent)
- } else if (item.itemId == R.id.visit_website_item) {
- val url = getWebsiteLinkWithFallback(media)
- if (url != null) openInBrowser(this@VideoplayerActivity, url)
- } else if (item.itemId == R.id.share_item && feedItem != null) {
- val shareDialog = ShareDialog.newInstance(feedItem)
- shareDialog.show(supportFragmentManager, "ShareEpisodeDialog")
- } else if (item.itemId == R.id.playback_speed) {
- VariableSpeedDialog().show(supportFragmentManager, null)
- } else {
- return false
+ // some options option requires FeedItem
+ when {
+ item.itemId == R.id.player_switch_to_audio_only -> {
+ switchToAudioOnly = true
+ finish()
+ return true
+ }
+ item.itemId == android.R.id.home -> {
+ val intent = Intent(this@VideoplayerActivity, MainActivity::class.java)
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
+ startActivity(intent)
+ finish()
+ return true
+ }
+ item.itemId == R.id.player_show_chapters -> {
+ ChaptersFragment().show(supportFragmentManager, ChaptersFragment.TAG)
+ return true
+ }
+ controller == null -> {
+ return false
+ }
+ else -> {
+ val media = controller?.getMedia() ?: return false
+ val feedItem = getFeedItem(media) // some options option requires FeedItem
+ if (item.itemId == R.id.add_to_favorites_item && feedItem != null) {
+ DBWriter.addFavoriteItem(feedItem)
+ isFavorite = true
+ invalidateOptionsMenu()
+ } else if (item.itemId == R.id.remove_from_favorites_item && feedItem != null) {
+ DBWriter.removeFavoriteItem(feedItem)
+ isFavorite = false
+ invalidateOptionsMenu()
+ } else if (item.itemId == R.id.disable_sleeptimer_item
+ || item.itemId == R.id.set_sleeptimer_item) {
+ SleepTimerDialog().show(supportFragmentManager, "SleepTimerDialog")
+ } else if (item.itemId == R.id.audio_controls) {
+ val dialog = PlaybackControlsDialog.newInstance()
+ dialog.show(supportFragmentManager, "playback_controls")
+ } else if (item.itemId == R.id.open_feed_item && feedItem != null) {
+ val intent = MainActivity.getIntentToOpenFeed(this, feedItem.feedId)
+ startActivity(intent)
+ } else if (item.itemId == R.id.visit_website_item) {
+ val url = getWebsiteLinkWithFallback(media)
+ if (url != null) openInBrowser(this@VideoplayerActivity, url)
+ } else if (item.itemId == R.id.share_item && feedItem != null) {
+ val shareDialog = ShareDialog.newInstance(feedItem)
+ shareDialog.show(supportFragmentManager, "ShareEpisodeDialog")
+ } else if (item.itemId == R.id.playback_speed) {
+ VariableSpeedDialog().show(supportFragmentManager, null)
+ } else {
+ return false
+ }
+ return true
+ }
}
- return true
}
fun onPositionObserverUpdate() {
@@ -623,11 +625,11 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
Log.w(TAG, "Could not react to position observer update because of invalid time")
return
}
- viewBinding!!.positionLabel.text = getDurationStringLong(currentPosition)
+ viewBinding.positionLabel.text = getDurationStringLong(currentPosition)
if (showTimeLeft) {
- viewBinding!!.durationLabel.text = "-" + getDurationStringLong(remainingTime)
+ viewBinding.durationLabel.text = "-" + getDurationStringLong(remainingTime)
} else {
- viewBinding!!.durationLabel.text = getDurationStringLong(duration)
+ viewBinding.durationLabel.text = getDurationStringLong(duration)
}
updateProgressbarPosition(currentPosition, duration)
}
@@ -635,7 +637,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
private fun updateProgressbarPosition(position: Int, duration: Int) {
Log.d(TAG, "updateProgressbarPosition($position, $duration)")
val progress = (position.toFloat()) / duration
- viewBinding!!.sbPosition.progress = (progress * viewBinding!!.sbPosition.max).toInt()
+ viewBinding.sbPosition.progress = (progress * viewBinding.sbPosition.max).toInt()
}
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
@@ -646,14 +648,14 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
prog = progress / (seekBar.max.toFloat())
val converter = TimeSpeedConverter(controller!!.currentPlaybackSpeedMultiplier)
val position = converter.convert((prog * controller!!.duration).toInt())
- viewBinding!!.seekPositionLabel.text = getDurationStringLong(position)
+ viewBinding.seekPositionLabel.text = getDurationStringLong(position)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
- viewBinding!!.seekCardView.scaleX = .8f
- viewBinding!!.seekCardView.scaleY = .8f
- viewBinding!!.seekCardView.animate()
+ viewBinding.seekCardView.scaleX = .8f
+ viewBinding.seekCardView.scaleY = .8f
+ viewBinding.seekCardView.animate()
.setInterpolator(FastOutSlowInInterpolator())
.alpha(1f).scaleX(1f).scaleY(1f)
.setDuration(200)
@@ -665,9 +667,9 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
if (controller != null) {
controller!!.seekTo((prog * controller!!.duration).toInt())
}
- viewBinding!!.seekCardView.scaleX = 1f
- viewBinding!!.seekCardView.scaleY = 1f
- viewBinding!!.seekCardView.animate()
+ viewBinding.seekCardView.scaleX = 1f
+ viewBinding.seekCardView.scaleY = 1f
+ viewBinding.seekCardView.animate()
.setInterpolator(FastOutSlowInInterpolator())
.alpha(0f).scaleX(.8f).scaleY(.8f)
.setDuration(200)
@@ -676,26 +678,27 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
}
private fun checkFavorite() {
- val feedItem = getFeedItem(controller!!.getMedia()) ?: return
- if (disposable != null) {
- disposable!!.dispose()
- }
+ val feedItem = getFeedItem(controller?.getMedia()) ?: return
+ disposable?.dispose()
+
disposable = Observable.fromCallable { DBReader.getFeedItem(feedItem.id) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ item: FeedItem? ->
- val isFav = item!!.isTagged(FeedItem.TAG_FAVORITE)
- if (isFavorite != isFav) {
- isFavorite = isFav
- invalidateOptionsMenu()
+ if (item != null) {
+ val isFav = item.isTagged(FeedItem.TAG_FAVORITE)
+ if (isFavorite != isFav) {
+ isFavorite = isFav
+ invalidateOptionsMenu()
+ }
}
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
private fun compatEnterPictureInPicture() {
if (PictureInPictureUtil.supportsPictureInPicture(this) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- supportActionBar!!.hide()
+ supportActionBar?.hide()
hideVideoControls(false)
enterPictureInPictureMode()
}
@@ -753,7 +756,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
}
//Go to x% of video:
if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
- controller!!.seekTo((0.1f * (keyCode - KeyEvent.KEYCODE_0) * controller!!.duration).toInt())
+ controller?.seekTo((0.1f * (keyCode - KeyEvent.KEYCODE_0) * controller!!.duration).toInt())
return true
}
return super.onKeyUp(keyCode, event)
diff --git a/app/src/main/java/ac/mdiq/podvinci/activity/WidgetConfigActivity.kt b/app/src/main/java/ac/mdiq/podvinci/activity/WidgetConfigActivity.kt
index b5da376b..d4bb46b0 100644
--- a/app/src/main/java/ac/mdiq/podvinci/activity/WidgetConfigActivity.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/activity/WidgetConfigActivity.kt
@@ -19,13 +19,13 @@ import ac.mdiq.podvinci.core.widget.WidgetUpdaterWorker
class WidgetConfigActivity : AppCompatActivity() {
private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
- private var opacitySeekBar: SeekBar? = null
- private var opacityTextView: TextView? = null
- private var widgetPreview: View? = null
- private var ckPlaybackSpeed: CheckBox? = null
- private var ckRewind: CheckBox? = null
- private var ckFastForward: CheckBox? = null
- private var ckSkip: CheckBox? = null
+ private lateinit var widgetPreview: View
+ private lateinit var opacitySeekBar: SeekBar
+ private lateinit var opacityTextView: TextView
+ private lateinit var ckPlaybackSpeed: CheckBox
+ private lateinit var ckRewind: CheckBox
+ private lateinit var ckFastForward: CheckBox
+ private lateinit var ckSkip: CheckBox
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(getTheme(this))
@@ -50,84 +50,82 @@ class WidgetConfigActivity : AppCompatActivity() {
opacitySeekBar = findViewById(R.id.widget_opacity_seekBar)
widgetPreview = findViewById(R.id.widgetLayout)
findViewById(R.id.butConfirm).setOnClickListener { v: View? -> confirmCreateWidget() }
- if (opacitySeekBar != null) {
- opacitySeekBar!!.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
- override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
- opacityTextView?.text = seekBar.progress.toString() + "%"
- val color = getColorWithAlpha(PlayerWidget.DEFAULT_COLOR, opacitySeekBar!!.progress)
- widgetPreview?.setBackgroundColor(color)
- }
-
- override fun onStartTrackingTouch(seekBar: SeekBar) {
- }
-
- override fun onStopTrackingTouch(seekBar: SeekBar) {
- }
- })
- }
- if (widgetPreview != null) {
- widgetPreview!!.findViewById(R.id.txtNoPlaying).visibility = View.GONE
- val title = widgetPreview!!.findViewById(R.id.txtvTitle)
- title.visibility = View.VISIBLE
- title.setText(R.string.app_name)
- val progress = widgetPreview!!.findViewById(R.id.txtvProgress)
- progress.visibility = View.VISIBLE
- progress.setText(R.string.position_default_label)
- }
+ opacitySeekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
+ override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
+ opacityTextView.text = seekBar.progress.toString() + "%"
+ val color = getColorWithAlpha(PlayerWidget.DEFAULT_COLOR, opacitySeekBar.progress)
+ widgetPreview.setBackgroundColor(color)
+ }
+
+ override fun onStartTrackingTouch(seekBar: SeekBar) {
+ }
+
+ override fun onStopTrackingTouch(seekBar: SeekBar) {
+ }
+ })
+
+ widgetPreview.findViewById(R.id.txtNoPlaying).visibility = View.GONE
+ val title = widgetPreview.findViewById(R.id.txtvTitle)
+ title.visibility = View.VISIBLE
+ title.setText(R.string.app_name)
+ val progress = widgetPreview.findViewById(R.id.txtvProgress)
+ progress.visibility = View.VISIBLE
+ progress.setText(R.string.position_default_label)
+
ckPlaybackSpeed = findViewById(R.id.ckPlaybackSpeed)
- ckPlaybackSpeed?.setOnClickListener { v: View? -> displayPreviewPanel() }
+ ckPlaybackSpeed.setOnClickListener { v: View? -> displayPreviewPanel() }
ckRewind = findViewById(R.id.ckRewind)
- ckRewind?.setOnClickListener { v: View? -> displayPreviewPanel() }
+ ckRewind.setOnClickListener { v: View? -> displayPreviewPanel() }
ckFastForward = findViewById(R.id.ckFastForward)
- ckFastForward?.setOnClickListener { v: View? -> displayPreviewPanel() }
+ ckFastForward.setOnClickListener { v: View? -> displayPreviewPanel() }
ckSkip = findViewById(R.id.ckSkip)
- ckSkip?.setOnClickListener { v: View? -> displayPreviewPanel() }
+ ckSkip.setOnClickListener { v: View? -> displayPreviewPanel() }
setInitialState()
}
private fun setInitialState() {
val prefs = getSharedPreferences(PlayerWidget.PREFS_NAME, MODE_PRIVATE)
- ckPlaybackSpeed!!.isChecked = prefs.getBoolean(PlayerWidget.KEY_WIDGET_PLAYBACK_SPEED + appWidgetId, false)
- ckRewind!!.isChecked = prefs.getBoolean(PlayerWidget.KEY_WIDGET_REWIND + appWidgetId, false)
- ckFastForward!!.isChecked = prefs.getBoolean(PlayerWidget.KEY_WIDGET_FAST_FORWARD + appWidgetId, false)
- ckSkip!!.isChecked = prefs.getBoolean(PlayerWidget.KEY_WIDGET_SKIP + appWidgetId, false)
+ ckPlaybackSpeed.isChecked = prefs.getBoolean(PlayerWidget.KEY_WIDGET_PLAYBACK_SPEED + appWidgetId, false)
+ ckRewind.isChecked = prefs.getBoolean(PlayerWidget.KEY_WIDGET_REWIND + appWidgetId, false)
+ ckFastForward.isChecked = prefs.getBoolean(PlayerWidget.KEY_WIDGET_FAST_FORWARD + appWidgetId, false)
+ ckSkip.isChecked = prefs.getBoolean(PlayerWidget.KEY_WIDGET_SKIP + appWidgetId, false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val color = prefs.getInt(PlayerWidget.KEY_WIDGET_COLOR + appWidgetId, PlayerWidget.DEFAULT_COLOR)
val opacity = Color.alpha(color) * 100 / 0xFF
- opacitySeekBar!!.setProgress(opacity, false)
+ opacitySeekBar.setProgress(opacity, false)
}
displayPreviewPanel()
}
private fun displayPreviewPanel() {
val showExtendedPreview =
- ckPlaybackSpeed!!.isChecked || ckRewind!!.isChecked || ckFastForward!!.isChecked || ckSkip!!.isChecked
- widgetPreview!!.findViewById(R.id.extendedButtonsContainer).visibility =
+ ckPlaybackSpeed.isChecked || ckRewind.isChecked || ckFastForward.isChecked || ckSkip.isChecked
+ widgetPreview.findViewById(R.id.extendedButtonsContainer).visibility =
if (showExtendedPreview) View.VISIBLE else View.GONE
- widgetPreview!!.findViewById(R.id.butPlay).visibility =
+ widgetPreview.findViewById(R.id.butPlay).visibility =
if (showExtendedPreview) View.GONE else View.VISIBLE
- widgetPreview!!.findViewById(R.id.butPlaybackSpeed).visibility =
- if (ckPlaybackSpeed!!.isChecked) View.VISIBLE else View.GONE
- widgetPreview!!.findViewById(R.id.butFastForward).visibility =
- if (ckFastForward!!.isChecked) View.VISIBLE else View.GONE
- widgetPreview!!.findViewById(R.id.butSkip).visibility =
- if (ckSkip!!.isChecked) View.VISIBLE else View.GONE
- widgetPreview!!.findViewById(R.id.butRew).visibility =
- if (ckRewind!!.isChecked) View.VISIBLE else View.GONE
+ widgetPreview.findViewById(R.id.butPlaybackSpeed).visibility =
+ if (ckPlaybackSpeed.isChecked) View.VISIBLE else View.GONE
+ widgetPreview.findViewById(R.id.butFastForward).visibility =
+ if (ckFastForward.isChecked) View.VISIBLE else View.GONE
+ widgetPreview.findViewById(R.id.butSkip).visibility =
+ if (ckSkip.isChecked) View.VISIBLE else View.GONE
+ widgetPreview.findViewById(R.id.butRew).visibility =
+ if (ckRewind.isChecked) View.VISIBLE else View.GONE
}
private fun confirmCreateWidget() {
- val backgroundColor = getColorWithAlpha(PlayerWidget.DEFAULT_COLOR, opacitySeekBar!!.progress)
+ val backgroundColor = getColorWithAlpha(PlayerWidget.DEFAULT_COLOR, opacitySeekBar.progress)
val prefs = getSharedPreferences(PlayerWidget.PREFS_NAME, MODE_PRIVATE)
val editor = prefs.edit()
editor.putInt(PlayerWidget.KEY_WIDGET_COLOR + appWidgetId, backgroundColor)
- editor.putBoolean(PlayerWidget.KEY_WIDGET_PLAYBACK_SPEED + appWidgetId, ckPlaybackSpeed!!.isChecked)
- editor.putBoolean(PlayerWidget.KEY_WIDGET_SKIP + appWidgetId, ckSkip!!.isChecked)
- editor.putBoolean(PlayerWidget.KEY_WIDGET_REWIND + appWidgetId, ckRewind!!.isChecked)
- editor.putBoolean(PlayerWidget.KEY_WIDGET_FAST_FORWARD + appWidgetId, ckFastForward!!.isChecked)
+ editor.putBoolean(PlayerWidget.KEY_WIDGET_PLAYBACK_SPEED + appWidgetId, ckPlaybackSpeed.isChecked)
+ editor.putBoolean(PlayerWidget.KEY_WIDGET_SKIP + appWidgetId, ckSkip.isChecked)
+ editor.putBoolean(PlayerWidget.KEY_WIDGET_REWIND + appWidgetId, ckRewind.isChecked)
+ editor.putBoolean(PlayerWidget.KEY_WIDGET_FAST_FORWARD + appWidgetId, ckFastForward.isChecked)
editor.apply()
val resultValue = Intent()
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/ChaptersListAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/ChaptersListAdapter.kt
index d4a7c650..d44a75e7 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/ChaptersListAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/ChaptersListAdapter.kt
@@ -26,8 +26,8 @@ import ac.mdiq.podvinci.ui.common.CircularProgressBar
import kotlin.math.max
import kotlin.math.min
-class ChaptersListAdapter(private val context: Context, private val callback: Callback?) :
- RecyclerView.Adapter() {
+class ChaptersListAdapter(private val context: Context, private val callback: Callback?) : RecyclerView.Adapter() {
+
private var media: Playable? = null
private var currentChapterIndex = -1
private var currentChapterPosition: Long = -1
@@ -45,18 +45,13 @@ class ChaptersListAdapter(private val context: Context, private val callback: Ca
}
override fun onBindViewHolder(holder: ChapterHolder, position: Int) {
- val sc = getItem(position)
- if (sc == null) {
- holder.title.text = "Error"
- return
- }
+ val sc = getItem(position)?: return
holder.title.text = sc.title
- holder.start.text = getDurationStringLong(sc
- .start.toInt())
- val duration = if (position + 1 < media!!.getChapters().size) {
+ holder.start.text = getDurationStringLong(sc.start.toInt())
+ val duration = if (position + 1 < itemCount) {
media!!.getChapters()[position + 1].start - sc.start
} else {
- media!!.getDuration() - sc.start
+ (media?.getDuration()?:0) - sc.start
}
holder.duration.text = context.getString(R.string.chapter_duration,
getDurationStringLocalized(context, duration.toInt().toLong()))
@@ -112,10 +107,7 @@ class ChaptersListAdapter(private val context: Context, private val callback: Ca
}
override fun getItemCount(): Int {
- if (media == null) {
- return 0
- }
- return media!!.getChapters().size
+ return media?.getChapters()?.size?:0
}
class ChapterHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
@@ -131,7 +123,7 @@ class ChaptersListAdapter(private val context: Context, private val callback: Ca
fun notifyChapterChanged(newChapterIndex: Int) {
currentChapterIndex = newChapterIndex
- currentChapterPosition = getItem(newChapterIndex).start
+ currentChapterPosition = getItem(newChapterIndex)?.start?:0
notifyDataSetChanged()
}
@@ -142,8 +134,10 @@ class ChaptersListAdapter(private val context: Context, private val callback: Ca
notifyItemChanged(currentChapterIndex, "foo")
}
- fun getItem(position: Int): Chapter {
- return media!!.getChapters()[position]
+ fun getItem(position: Int): Chapter? {
+ val chapters = media?.getChapters()?: return null
+ if (position < 0 || position >= chapters.size) return null
+ return chapters[position]
}
interface Callback {
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/CoverLoader.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/CoverLoader.kt
index baff4b1b..8925b933 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/CoverLoader.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/CoverLoader.kt
@@ -57,9 +57,9 @@ class CoverLoader(activity: MainActivity) {
}
fun load() {
- if (fallbackTitle == null || imgvCover == null) return
+ if (imgvCover == null) return
- val coverTarget = CoverTarget(fallbackTitle!!, imgvCover!!, textAndImageCombined)
+ val coverTarget = CoverTarget(fallbackTitle, imgvCover!!, textAndImageCombined)
if (resource != 0) {
Glide.with(imgvCover!!).clear(coverTarget)
@@ -87,11 +87,12 @@ class CoverLoader(activity: MainActivity) {
builder.into(coverTarget)
}
- internal class CoverTarget(fallbackTitle: TextView,
+ internal class CoverTarget(fallbackTitle: TextView?,
coverImage: ImageView,
private val textAndImageCombined: Boolean
) : CustomViewTarget(coverImage) {
- private val fallbackTitle: WeakReference = WeakReference(fallbackTitle)
+
+ private val fallbackTitle: WeakReference = WeakReference(fallbackTitle)
private val cover: WeakReference = WeakReference(coverImage)
override fun onLoadFailed(errorDrawable: Drawable?) {
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/DataFolderAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/DataFolderAdapter.kt
index b43b0eae..3968f803 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/DataFolderAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/DataFolderAdapter.kt
@@ -16,8 +16,8 @@ import ac.mdiq.podvinci.core.util.StorageUtils.getTotalSpaceAvailable
import ac.mdiq.podvinci.storage.preferences.UserPreferences.getDataFolder
import java.io.File
-class DataFolderAdapter(context: Context, selectionHandler: Consumer) :
- RecyclerView.Adapter() {
+class DataFolderAdapter(context: Context, selectionHandler: Consumer) : RecyclerView.Adapter() {
+
private val selectionHandler: Consumer
private val currentPath: String?
private val entries: List
@@ -63,10 +63,7 @@ class DataFolderAdapter(context: Context, selectionHandler: Consumer) :
private fun getCurrentPath(): String? {
val dataFolder = getDataFolder(null)
- if (dataFolder != null) {
- return dataFolder.absolutePath
- }
- return null
+ return dataFolder?.absolutePath
}
private fun getStorageEntries(context: Context): List {
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/DownloadLogAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/DownloadLogAdapter.kt
index ad009914..6968595e 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/DownloadLogAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/DownloadLogAdapter.kt
@@ -19,6 +19,7 @@ import ac.mdiq.podvinci.model.feed.Feed
import ac.mdiq.podvinci.model.feed.FeedMedia
import ac.mdiq.podvinci.ui.common.ThemeUtils
import ac.mdiq.podvinci.view.viewholder.DownloadLogItemViewHolder
+import androidx.media3.common.util.UnstableApi
/**
* Displays a list of DownloadStatus entries.
@@ -31,7 +32,7 @@ class DownloadLogAdapter(private val context: Activity) : BaseAdapter() {
notifyDataSetChanged()
}
- override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ @UnstableApi override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val holder: DownloadLogItemViewHolder
if (convertView == null) {
holder = DownloadLogItemViewHolder(context, parent)
@@ -44,7 +45,7 @@ class DownloadLogAdapter(private val context: Activity) : BaseAdapter() {
return holder.itemView
}
- private fun bind(holder: DownloadLogItemViewHolder, status: DownloadResult, position: Int) {
+ @UnstableApi private fun bind(holder: DownloadLogItemViewHolder, status: DownloadResult, position: Int) {
var statusText: String? = ""
if (status.feedfileType == Feed.FEEDFILETYPE_FEED) {
statusText += context.getString(R.string.download_type_feed)
@@ -56,7 +57,7 @@ class DownloadLogAdapter(private val context: Activity) : BaseAdapter() {
System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, 0)
holder.status.text = statusText
- if (status.title != null) {
+ if (status.title.isNotEmpty()) {
holder.title.text = status.title
} else {
holder.title.setText(R.string.download_log_title_unknown)
@@ -132,7 +133,7 @@ class DownloadLogAdapter(private val context: Activity) : BaseAdapter() {
}
override fun getItem(position: Int): DownloadResult? {
- if (position < downloadLog.size) {
+ if (position in downloadLog.indices) {
return downloadLog[position]
}
return null
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/EpisodeItemListAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/EpisodeItemListAdapter.kt
index e20414ce..812131b3 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/EpisodeItemListAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/EpisodeItemListAdapter.kt
@@ -1,22 +1,23 @@
package ac.mdiq.podvinci.adapter
-import ac.mdiq.podvinci.activity.MainActivity
-import android.R.color
-import android.app.Activity
-import android.os.Build
-import android.view.*
-import androidx.media3.common.util.UnstableApi
-import androidx.recyclerview.widget.RecyclerView
import ac.mdiq.podvinci.R
+import ac.mdiq.podvinci.activity.MainActivity
import ac.mdiq.podvinci.core.util.FeedItemUtil
import ac.mdiq.podvinci.fragment.ItemPagerFragment
import ac.mdiq.podvinci.menuhandler.FeedItemMenuHandler
import ac.mdiq.podvinci.model.feed.FeedItem
import ac.mdiq.podvinci.ui.common.ThemeUtils
import ac.mdiq.podvinci.view.viewholder.EpisodeItemViewHolder
+import android.R.color
+import android.app.Activity
+import android.os.Build
+import android.view.*
+import androidx.media3.common.util.UnstableApi
+import androidx.recyclerview.widget.RecyclerView
import org.apache.commons.lang3.ArrayUtils
import java.lang.ref.WeakReference
+
/**
* List adapter for the list of new episodes.
*/
@@ -53,7 +54,7 @@ open class EpisodeItemListAdapter(mainActivity: MainActivity) : SelectableAdapte
}
@UnstableApi override fun onBindViewHolder(holder: EpisodeItemViewHolder, pos: Int) {
- if (pos >= episodes.size) {
+ if (pos >= episodes.size || pos < 0) {
beforeBindViewHolder(holder, pos)
holder.bindDummy()
afterBindViewHolder(holder, pos)
@@ -72,10 +73,10 @@ open class EpisodeItemListAdapter(mainActivity: MainActivity) : SelectableAdapte
holder.itemView.setOnClickListener { v: View? ->
val activity: MainActivity? = mainActivityRef.get()
- if (activity != null && !inActionMode()) {
+ if (!inActionMode()) {
val ids: LongArray = FeedItemUtil.getIds(episodes)
val position = ArrayUtils.indexOf(ids, item.id)
- activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position))
+ activity?.loadChildFragment(ItemPagerFragment.newInstance(ids, position))
} else {
toggleSelection(holder.bindingAdapterPosition)
}
@@ -88,8 +89,7 @@ open class EpisodeItemListAdapter(mainActivity: MainActivity) : SelectableAdapte
}
holder.itemView.setOnTouchListener(View.OnTouchListener { v: View?, e: MotionEvent ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if (e.isFromSource(InputDevice.SOURCE_MOUSE)
- && e.buttonState == MotionEvent.BUTTON_SECONDARY) {
+ if (e.isFromSource(InputDevice.SOURCE_MOUSE) && e.buttonState == MotionEvent.BUTTON_SECONDARY) {
longPressedItem = item
longPressedPosition = holder.bindingAdapterPosition
return@OnTouchListener false
@@ -146,26 +146,28 @@ open class EpisodeItemListAdapter(mainActivity: MainActivity) : SelectableAdapte
}
override fun getItemId(position: Int): Long {
- if (position >= episodes.size) {
- return RecyclerView.NO_ID // Dummy views
- }
- val item: FeedItem = episodes[position]
- return item.id
+// if (position >= episodes.size) {
+// return RecyclerView.NO_ID // Dummy views
+// }
+// val item = episodes[position]
+// return item.id ?: RecyclerView.NO_POSITION.toLong()
+ return getItem(position)?.id ?: RecyclerView.NO_ID
}
override fun getItemCount(): Int {
return dummyViews + episodes.size
}
- protected fun getItem(index: Int): FeedItem {
- return episodes[index]
+ protected fun getItem(index: Int): FeedItem? {
+// return episodes[index]
+ return if (index in episodes.indices) episodes[index] else null
}
protected val activity: Activity?
get() = mainActivityRef.get()
@UnstableApi override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
- val inflater: MenuInflater = mainActivityRef.get()!!.menuInflater
+ val inflater: MenuInflater = activity!!.menuInflater
if (inActionMode()) {
inflater.inflate(R.menu.multi_select_context_popup, menu)
} else {
@@ -201,8 +203,9 @@ open class EpisodeItemListAdapter(mainActivity: MainActivity) : SelectableAdapte
get() {
val items: MutableList = ArrayList()
for (i in 0 until itemCount) {
- if (isSelected(i)) {
- items.add(getItem(i))
+ if (i < episodes.size && isSelected(i)) {
+ val item = getItem(i)
+ if (item != null) items.add(item)
}
}
return items
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/FeedDiscoverAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/FeedDiscoverAdapter.kt
index 6850fbb5..cbd9ce5e 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/FeedDiscoverAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/FeedDiscoverAdapter.kt
@@ -17,9 +17,9 @@ class FeedDiscoverAdapter(mainActivity: MainActivity) : BaseAdapter() {
private val mainActivityRef: WeakReference = WeakReference(mainActivity)
private val data: MutableList = ArrayList()
- fun updateData(newData: List?) {
+ fun updateData(newData: List) {
data.clear()
- data.addAll(newData!!)
+ data.addAll(newData)
notifyDataSetChanged()
}
@@ -27,8 +27,8 @@ class FeedDiscoverAdapter(mainActivity: MainActivity) : BaseAdapter() {
return data.size
}
- override fun getItem(position: Int): PodcastSearchResult {
- return data[position]
+ override fun getItem(position: Int): PodcastSearchResult? {
+ return if (position in data.indices) data[position] else null
}
override fun getItemId(position: Int): Long {
@@ -48,12 +48,11 @@ class FeedDiscoverAdapter(mainActivity: MainActivity) : BaseAdapter() {
holder = convertView.tag as Holder
}
-
- val podcast: PodcastSearchResult = getItem(position)
- holder.imageView!!.contentDescription = podcast.title
+ val podcast: PodcastSearchResult? = getItem(position)
+ holder.imageView!!.contentDescription = podcast?.title
Glide.with(mainActivityRef.get()!!)
- .load(podcast.imageUrl)
+ .load(podcast?.imageUrl)
.apply(RequestOptions()
.placeholder(R.color.light_gray)
.transform(FitCenter(), RoundedCorners((8 * mainActivityRef.get()!!.resources.displayMetrics.density).toInt()))
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/FeedItemlistDescriptionAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/FeedItemlistDescriptionAdapter.kt
index b574c315..d2998bf5 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/FeedItemlistDescriptionAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/FeedItemlistDescriptionAdapter.kt
@@ -1,13 +1,5 @@
package ac.mdiq.podvinci.adapter
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ArrayAdapter
-import android.widget.Button
-import android.widget.TextView
-import androidx.media3.common.util.UnstableApi
import ac.mdiq.podvinci.R
import ac.mdiq.podvinci.core.service.playback.PlaybackService.Companion.getPlayerActivityIntent
import ac.mdiq.podvinci.core.util.DateFormatter.formatAbbrev
@@ -19,15 +11,20 @@ import ac.mdiq.podvinci.model.feed.FeedItem
import ac.mdiq.podvinci.model.playback.MediaType
import ac.mdiq.podvinci.model.playback.Playable
import ac.mdiq.podvinci.model.playback.RemoteMedia
-import java.lang.Boolean
-import kotlin.Int
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ArrayAdapter
+import android.widget.Button
+import android.widget.TextView
+import androidx.media3.common.util.UnstableApi
/**
* List adapter for showing a list of FeedItems with their title and description.
*/
-class FeedItemlistDescriptionAdapter(context: Context?, resource: Int, objects: List?) :
- ArrayAdapter(
- context!!, resource, objects!!) {
+class FeedItemlistDescriptionAdapter(context: Context, resource: Int, objects: List?) :
+ ArrayAdapter(context, resource, objects!!) {
@UnstableApi override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var convertView = convertView
val holder: Holder
@@ -59,7 +56,7 @@ class FeedItemlistDescriptionAdapter(context: Context?, resource: Int, objects:
holder.description!!.text = description
holder.description!!.maxLines = MAX_LINES_COLLAPSED
}
- holder.description!!.tag = Boolean.FALSE // not expanded
+ holder.description!!.tag = false
holder.preview!!.visibility = View.GONE
holder.preview!!.setOnClickListener { v: View? ->
if (item.media == null) {
@@ -79,13 +76,13 @@ class FeedItemlistDescriptionAdapter(context: Context?, resource: Int, objects:
}
}
convertView!!.setOnClickListener { v: View? ->
- if (holder.description!!.tag === Boolean.TRUE) {
+ if (holder.description!!.tag == true) {
holder.description!!.maxLines = MAX_LINES_COLLAPSED
holder.preview!!.visibility = View.GONE
- holder.description!!.tag = Boolean.FALSE
+ holder.description!!.tag = false
} else {
holder.description!!.maxLines = 30
- holder.description!!.tag = Boolean.TRUE
+ holder.description!!.tag = true
holder.preview!!.visibility = if (item.media != null) View.VISIBLE else View.GONE
holder.preview!!.setText(R.string.preview_episode)
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/HorizontalFeedListAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/HorizontalFeedListAdapter.kt
index f1170524..f81de721 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/HorizontalFeedListAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/HorizontalFeedListAdapter.kt
@@ -21,7 +21,7 @@ import java.lang.ref.WeakReference
open class HorizontalFeedListAdapter(mainActivity: MainActivity) :
RecyclerView.Adapter(), View.OnCreateContextMenuListener {
- private val mainActivityRef: WeakReference = WeakReference(mainActivity)
+ private val mainActivityRef: WeakReference = WeakReference(mainActivity)
private val data: MutableList = ArrayList()
private var dummyViews = 0
var longPressedItem: Feed? = null
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/HorizontalItemListAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/HorizontalItemListAdapter.kt
index 691ce051..2f44ff2c 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/HorizontalItemListAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/HorizontalItemListAdapter.kt
@@ -18,6 +18,7 @@ import java.lang.ref.WeakReference
open class HorizontalItemListAdapter(mainActivity: MainActivity) : RecyclerView.Adapter(),
View.OnCreateContextMenuListener {
+
private val mainActivityRef: WeakReference = WeakReference(mainActivity)
private var data: List = ArrayList()
var longPressedItem: FeedItem? = null
@@ -70,10 +71,11 @@ open class HorizontalItemListAdapter(mainActivity: MainActivity) : RecyclerView.
}
override fun getItemId(position: Int): Long {
- if (position >= data.size) {
- return RecyclerView.NO_ID // Dummy views
+ if (position in data.indices) {
+ val item: FeedItem = data[position]
+ return item.id
}
- return data[position].id
+ return RecyclerView.NO_ID // Dummy views
}
override fun getItemCount(): Int {
@@ -108,9 +110,8 @@ open class HorizontalItemListAdapter(mainActivity: MainActivity) : RecyclerView.
@UnstableApi override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
val inflater: MenuInflater = mainActivityRef.get()!!.menuInflater
- if (longPressedItem == null) {
- return
- }
+ if (longPressedItem == null) return
+
menu.clear()
inflater.inflate(R.menu.feeditemlist_context, menu)
menu.setHeaderTitle(longPressedItem!!.title)
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/NavListAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/NavListAdapter.kt
index 4aa7a355..928eae2c 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/NavListAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/NavListAdapter.kt
@@ -31,6 +31,7 @@ import ac.mdiq.podvinci.storage.preferences.UserPreferences.hiddenDrawerItems
import ac.mdiq.podvinci.storage.preferences.UserPreferences.isEnableAutodownload
import ac.mdiq.podvinci.storage.preferences.UserPreferences.subscriptionsFilter
import ac.mdiq.podvinci.ui.home.HomeFragment
+import androidx.media3.common.util.UnstableApi
import org.apache.commons.lang3.ArrayUtils
import java.lang.ref.WeakReference
import java.text.NumberFormat
@@ -42,6 +43,7 @@ import kotlin.math.abs
*/
class NavListAdapter(private val itemAccess: ItemAccess, context: Activity) :
RecyclerView.Adapter(), OnSharedPreferenceChangeListener {
+
private val fragmentTags: MutableList = ArrayList()
private val titles: Array = context.resources.getStringArray(R.array.nav_drawer_titles)
private val activity = WeakReference(context)
@@ -87,7 +89,7 @@ class NavListAdapter(private val itemAccess: ItemAccess, context: Activity) :
return titles[index]
}
- @DrawableRes
+ @UnstableApi @DrawableRes
private fun getDrawable(tag: String?): Int {
return when (tag) {
HomeFragment.TAG -> R.drawable.ic_home
@@ -157,7 +159,7 @@ class NavListAdapter(private val itemAccess: ItemAccess, context: Activity) :
}
}
- override fun onBindViewHolder(holder: Holder, position: Int) {
+ @UnstableApi override fun onBindViewHolder(holder: Holder, position: Int) {
val viewType = getItemViewType(position)
holder.itemView.setOnCreateContextMenuListener(null)
@@ -199,7 +201,7 @@ class NavListAdapter(private val itemAccess: ItemAccess, context: Activity) :
}
}
- private fun bindNavView(title: String, position: Int, holder: NavHolder) {
+ @UnstableApi private fun bindNavView(title: String, position: Int, holder: NavHolder) {
val context = activity.get() ?: return
holder.title.text = title
@@ -209,43 +211,48 @@ class NavListAdapter(private val itemAccess: ItemAccess, context: Activity) :
holder.count.isClickable = false
val tag = fragmentTags[position]
- if (tag == QueueFragment.TAG) {
- val queueSize = itemAccess.queueSize
- if (queueSize > 0) {
- holder.count.text = NumberFormat.getInstance().format(queueSize.toLong())
- holder.count.visibility = View.VISIBLE
+ when {
+ tag == QueueFragment.TAG -> {
+ val queueSize = itemAccess.queueSize
+ if (queueSize > 0) {
+ holder.count.text = NumberFormat.getInstance().format(queueSize.toLong())
+ holder.count.visibility = View.VISIBLE
+ }
}
- } else if (tag == InboxFragment.TAG) {
- val unreadItems = itemAccess.numberOfNewItems
- if (unreadItems > 0) {
- holder.count.text = NumberFormat.getInstance().format(unreadItems.toLong())
- holder.count.visibility = View.VISIBLE
+ tag == InboxFragment.TAG -> {
+ val unreadItems = itemAccess.numberOfNewItems
+ if (unreadItems > 0) {
+ holder.count.text = NumberFormat.getInstance().format(unreadItems.toLong())
+ holder.count.visibility = View.VISIBLE
+ }
}
- } else if (tag == SubscriptionFragment.TAG) {
- val sum = itemAccess.feedCounterSum
- if (sum > 0) {
- holder.count.text = NumberFormat.getInstance().format(sum.toLong())
- holder.count.visibility = View.VISIBLE
+ tag == SubscriptionFragment.TAG -> {
+ val sum = itemAccess.feedCounterSum
+ if (sum > 0) {
+ holder.count.text = NumberFormat.getInstance().format(sum.toLong())
+ holder.count.visibility = View.VISIBLE
+ }
}
- } else if (tag == CompletedDownloadsFragment.TAG && isEnableAutodownload) {
- val epCacheSize = episodeCacheSize
- // don't count episodes that can be reclaimed
- val spaceUsed = (itemAccess.numberOfDownloadedItems
- - itemAccess.reclaimableItems)
- if (epCacheSize in 1..spaceUsed) {
- holder.count.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_disc_alert, 0)
- holder.count.visibility = View.VISIBLE
- holder.count.setOnClickListener { v: View? ->
- MaterialAlertDialogBuilder(context)
- .setTitle(R.string.episode_cache_full_title)
- .setMessage(R.string.episode_cache_full_message)
- .setPositiveButton(android.R.string.ok, null)
- .setNeutralButton(R.string.open_autodownload_settings) { dialog: DialogInterface?, which: Int ->
- val intent = Intent(context, PreferenceActivity::class.java)
- intent.putExtra(PreferenceActivity.OPEN_AUTO_DOWNLOAD_SETTINGS, true)
- context.startActivity(intent)
- }
- .show()
+ tag == CompletedDownloadsFragment.TAG && isEnableAutodownload -> {
+ val epCacheSize = episodeCacheSize
+ // don't count episodes that can be reclaimed
+ val spaceUsed = (itemAccess.numberOfDownloadedItems
+ - itemAccess.reclaimableItems)
+ if (epCacheSize in 1..spaceUsed) {
+ holder.count.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_disc_alert, 0)
+ holder.count.visibility = View.VISIBLE
+ holder.count.setOnClickListener { v: View? ->
+ MaterialAlertDialogBuilder(context)
+ .setTitle(R.string.episode_cache_full_title)
+ .setMessage(R.string.episode_cache_full_message)
+ .setPositiveButton(android.R.string.ok, null)
+ .setNeutralButton(R.string.open_autodownload_settings) { dialog: DialogInterface?, which: Int ->
+ val intent = Intent(context, PreferenceActivity::class.java)
+ intent.putExtra(PreferenceActivity.OPEN_AUTO_DOWNLOAD_SETTINGS, true)
+ context.startActivity(intent)
+ }
+ .show()
+ }
}
}
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/QueueRecyclerAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/QueueRecyclerAdapter.kt
index 72fe8e36..ce10ca91 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/QueueRecyclerAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/QueueRecyclerAdapter.kt
@@ -16,11 +16,9 @@ import ac.mdiq.podvinci.view.viewholder.EpisodeItemViewHolder
/**
* List adapter for the queue.
*/
-open class QueueRecyclerAdapter(mainActivity: MainActivity, swipeActions: SwipeActions) : EpisodeItemListAdapter(mainActivity) {
- private val swipeActions: SwipeActions = swipeActions
+open class QueueRecyclerAdapter(mainActivity: MainActivity, private val swipeActions: SwipeActions) : EpisodeItemListAdapter(mainActivity) {
private var dragDropEnabled: Boolean
-
init {
dragDropEnabled = !(UserPreferences.isQueueKeepSorted || UserPreferences.isQueueLocked)
}
@@ -46,7 +44,7 @@ open class QueueRecyclerAdapter(mainActivity: MainActivity, swipeActions: SwipeA
false
}
holder.coverHolder.setOnTouchListener { v1, event ->
- if (event.actionMasked === MotionEvent.ACTION_DOWN) {
+ if (event.actionMasked == MotionEvent.ACTION_DOWN) {
val isLtr = holder.itemView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR
val factor = (if (isLtr) 1 else -1).toFloat()
if (factor * event.x < factor * 0.5 * v1.width) {
@@ -75,10 +73,10 @@ open class QueueRecyclerAdapter(mainActivity: MainActivity, swipeActions: SwipeA
if (!inActionMode()) {
menu.findItem(R.id.multi_select).setVisible(true)
val keepSorted: Boolean = UserPreferences.isQueueKeepSorted
- if (getItem(0).id === longPressedItem?.id || keepSorted) {
+ if (getItem(0)?.id === longPressedItem?.id || keepSorted) {
menu.findItem(R.id.move_to_top_item).setVisible(false)
}
- if (getItem(itemCount - 1).id === longPressedItem?.id || keepSorted) {
+ if (getItem(itemCount - 1)?.id === longPressedItem?.id || keepSorted) {
menu.findItem(R.id.move_to_bottom_item).setVisible(false)
}
} else {
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/SelectableAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/SelectableAdapter.kt
index 113167df..6eec24ed 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/SelectableAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/SelectableAdapter.kt
@@ -23,10 +23,7 @@ abstract class SelectableAdapter(private val activ
if (inActionMode()) {
endSelectMode()
}
-
- if (onSelectModeListener != null) {
- onSelectModeListener!!.onStartSelectMode()
- }
+ onSelectModeListener?.onStartSelectMode()
shouldSelectLazyLoadedItems = false
selectedIds.clear()
@@ -75,7 +72,7 @@ abstract class SelectableAdapter(private val activ
fun endSelectMode() {
if (inActionMode()) {
callOnEndSelectMode()
- actionMode!!.finish()
+ actionMode?.finish()
}
}
@@ -164,9 +161,7 @@ abstract class SelectableAdapter(private val activ
}
private fun callOnEndSelectMode() {
- if (onSelectModeListener != null) {
- onSelectModeListener!!.onEndSelectMode()
- }
+ onSelectModeListener?.onEndSelectMode()
}
fun shouldSelectLazyLoadedItems(): Boolean {
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/SimpleChipAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/SimpleChipAdapter.kt
index 5b06abaa..392f72ad 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/SimpleChipAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/SimpleChipAdapter.kt
@@ -12,7 +12,7 @@ abstract class SimpleChipAdapter(private val context: Context) : RecyclerView.Ad
setHasStableIds(true)
}
- protected abstract fun getChips(): List
+ protected abstract fun getChips(): List
protected abstract fun onRemoveClicked(position: Int)
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/SimpleIconListAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/SimpleIconListAdapter.kt
index f9c368b4..9c687be5 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/SimpleIconListAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/SimpleIconListAdapter.kt
@@ -16,8 +16,8 @@ import ac.mdiq.podvinci.R
*/
class SimpleIconListAdapter(private val context: Context,
private val listItems: List
-) : ArrayAdapter(
- context, R.layout.simple_icon_list_item, listItems) {
+) : ArrayAdapter(context, R.layout.simple_icon_list_item, listItems) {
+
override fun getView(position: Int, view: View?, parent: ViewGroup): View {
var view = view
if (view == null) {
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/SubscriptionsRecyclerAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/SubscriptionsRecyclerAdapter.kt
index 5f1e2ba2..c4ae49bb 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/SubscriptionsRecyclerAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/SubscriptionsRecyclerAdapter.kt
@@ -28,6 +28,7 @@ import java.text.NumberFormat
open class SubscriptionsRecyclerAdapter(mainActivity: MainActivity) :
SelectableAdapter(mainActivity),
View.OnCreateContextMenuListener {
+
private val mainActivityRef: WeakReference = WeakReference(mainActivity)
private var listItems: List
private var selectedItem: NavDrawerData.DrawerItem? = null
@@ -54,8 +55,7 @@ open class SubscriptionsRecyclerAdapter(mainActivity: MainActivity) :
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SubscriptionViewHolder {
val itemView: View =
LayoutInflater.from(mainActivityRef.get()).inflate(R.layout.subscription_item, parent, false)
- itemView.findViewById(R.id.titleLabel).visibility =
- if (viewType == COVER_WITH_TITLE) View.VISIBLE else View.GONE
+ itemView.findViewById(R.id.titleLabel).visibility = if (viewType == COVER_WITH_TITLE) View.VISIBLE else View.GONE
return SubscriptionViewHolder(itemView)
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/DeleteActionButton.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/DeleteActionButton.kt
index 37755ad0..5604193a 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/DeleteActionButton.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/DeleteActionButton.kt
@@ -6,6 +6,7 @@ import ac.mdiq.podvinci.R
import ac.mdiq.podvinci.core.storage.DBWriter
import ac.mdiq.podvinci.model.feed.FeedItem
import ac.mdiq.podvinci.view.LocalDeleteModal.showLocalFeedDeleteWarningIfNecessary
+import androidx.media3.common.util.UnstableApi
class DeleteActionButton(item: FeedItem) : ItemActionButton(item) {
override fun getLabel(): Int {
@@ -14,11 +15,10 @@ class DeleteActionButton(item: FeedItem) : ItemActionButton(item) {
override fun getDrawable(): Int {
return R.drawable.ic_delete
}
- override fun onClick(context: Context) {
+ @UnstableApi override fun onClick(context: Context) {
val media = item.media ?: return
- showLocalFeedDeleteWarningIfNecessary(context, listOf(item)
- ) { DBWriter.deleteFeedMediaOfItem(context, media.id) }
+ showLocalFeedDeleteWarningIfNecessary(context, listOf(item)) { DBWriter.deleteFeedMediaOfItem(context, media.id) }
}
override val visibility: Int
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/ItemActionButton.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/ItemActionButton.kt
index 4360882c..739a344c 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/ItemActionButton.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/ItemActionButton.kt
@@ -30,19 +30,29 @@ abstract class ItemActionButton internal constructor(@JvmField var item: FeedIte
fun forItem(item: FeedItem): ItemActionButton {
val media = item.media ?: return MarkAsPlayedActionButton(item)
- val isDownloadingMedia = if (media.download_url==null) false else DownloadServiceInterface.get()?.isDownloadingEpisode(media.download_url!!)?:false
- return if (isCurrentlyPlaying(media)) {
- PauseActionButton(item)
- } else if (item.feed != null && item.feed!!.isLocalFeed) {
- PlayLocalActionButton(item)
- } else if (media.isDownloaded()) {
- PlayActionButton(item)
- } else if (isDownloadingMedia) {
- CancelDownloadActionButton(item)
- } else if (isStreamOverDownload) {
- StreamActionButton(item)
- } else {
- DownloadActionButton(item)
+ val isDownloadingMedia = when (media.download_url) {
+ null -> false
+ else -> DownloadServiceInterface.get()?.isDownloadingEpisode(media.download_url!!)?:false
+ }
+ return when {
+ isCurrentlyPlaying(media) -> {
+ PauseActionButton(item)
+ }
+ item.feed != null && item.feed!!.isLocalFeed -> {
+ PlayLocalActionButton(item)
+ }
+ media.isDownloaded() -> {
+ PlayActionButton(item)
+ }
+ isDownloadingMedia -> {
+ CancelDownloadActionButton(item)
+ }
+ isStreamOverDownload -> {
+ StreamActionButton(item)
+ }
+ else -> {
+ DownloadActionButton(item)
+ }
}
}
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/MarkAsPlayedActionButton.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/MarkAsPlayedActionButton.kt
index 9b461424..6703562c 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/MarkAsPlayedActionButton.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/MarkAsPlayedActionButton.kt
@@ -5,6 +5,7 @@ import android.view.View
import ac.mdiq.podvinci.R
import ac.mdiq.podvinci.core.storage.DBWriter
import ac.mdiq.podvinci.model.feed.FeedItem
+import androidx.media3.common.util.UnstableApi
class MarkAsPlayedActionButton(item: FeedItem) : ItemActionButton(item) {
override fun getLabel(): Int {
@@ -13,12 +14,12 @@ class MarkAsPlayedActionButton(item: FeedItem) : ItemActionButton(item) {
override fun getDrawable(): Int {
return R.drawable.ic_check
}
- override fun onClick(context: Context) {
+ @UnstableApi override fun onClick(context: Context) {
if (!item.isPlayed()) {
DBWriter.markItemPlayed(item, FeedItem.PLAYED, true)
}
}
override val visibility: Int
- get() = if ((item.isPlayed())) View.INVISIBLE else View.VISIBLE
+ get() = if (item.isPlayed()) View.INVISIBLE else View.VISIBLE
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/VisitWebsiteActionButton.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/VisitWebsiteActionButton.kt
index 5353c3f2..8e20e634 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/VisitWebsiteActionButton.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/actionbutton/VisitWebsiteActionButton.kt
@@ -18,5 +18,5 @@ class VisitWebsiteActionButton(item: FeedItem) : ItemActionButton(item) {
}
override val visibility: Int
- get() = if ((item.link == null)) View.INVISIBLE else View.VISIBLE
+ get() = if (item.link == null) View.INVISIBLE else View.VISIBLE
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/adapter/itunes/ItunesAdapter.kt b/app/src/main/java/ac/mdiq/podvinci/adapter/itunes/ItunesAdapter.kt
index bc63b53f..f46732f7 100644
--- a/app/src/main/java/ac/mdiq/podvinci/adapter/itunes/ItunesAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/adapter/itunes/ItunesAdapter.kt
@@ -14,6 +14,7 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import ac.mdiq.podvinci.R
import ac.mdiq.podvinci.net.discovery.PodcastSearchResult
+import androidx.media3.common.util.UnstableApi
class ItunesAdapter(
/**
@@ -26,7 +27,7 @@ class ItunesAdapter(
*/
private val data: List = objects
- override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ @UnstableApi override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
//Current podcast
val podcast: PodcastSearchResult = data[position]
@@ -38,8 +39,7 @@ class ItunesAdapter(
//Handle view holder stuff
if (convertView == null) {
- view = (context as MainActivity).layoutInflater
- .inflate(R.layout.itunes_podcast_listitem, parent, false)
+ view = (context as MainActivity).layoutInflater.inflate(R.layout.itunes_podcast_listitem, parent, false)
viewHolder = PodcastViewHolder(view)
view.tag = viewHolder
} else {
@@ -86,7 +86,7 @@ class ItunesAdapter(
/**
* TextView holding the Podcast title
*/
- val titleView = view.findViewById(R.id.txtvTitle)
+ val titleView: TextView = view.findViewById(R.id.txtvTitle)
val authorView: TextView = view.findViewById(R.id.txtvAuthor)
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/asynctask/DocumentFileExportWorker.kt b/app/src/main/java/ac/mdiq/podvinci/asynctask/DocumentFileExportWorker.kt
index 2ba24d13..1268827d 100644
--- a/app/src/main/java/ac/mdiq/podvinci/asynctask/DocumentFileExportWorker.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/asynctask/DocumentFileExportWorker.kt
@@ -20,17 +20,15 @@ class DocumentFileExportWorker(private val exportWriter: ExportWriter,
private val outputFileUri: Uri
) {
fun exportObservable(): Observable {
- val output = DocumentFile.fromSingleUri(
- context, outputFileUri)
+ val output = DocumentFile.fromSingleUri(context, outputFileUri)
return Observable.create { subscriber: ObservableEmitter ->
var outputStream: OutputStream? = null
var writer: OutputStreamWriter? = null
try {
- val uri = output!!.uri
+ if (output == null) throw IOException()
+ val uri = output.uri
outputStream = context.contentResolver.openOutputStream(uri, "wt")
- if (outputStream == null) {
- throw IOException()
- }
+ if (outputStream == null) throw IOException()
writer = OutputStreamWriter(outputStream, Charset.forName("UTF-8"))
exportWriter.writeDocument(DBReader.getFeedList(), writer, context)
subscriber.onNext(output)
diff --git a/app/src/main/java/ac/mdiq/podvinci/dialog/RemoveFeedDialog.kt b/app/src/main/java/ac/mdiq/podvinci/dialog/RemoveFeedDialog.kt
index da29a064..e8b6d012 100644
--- a/app/src/main/java/ac/mdiq/podvinci/dialog/RemoveFeedDialog.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/dialog/RemoveFeedDialog.kt
@@ -8,6 +8,8 @@ import ac.mdiq.podvinci.R
import ac.mdiq.podvinci.core.dialog.ConfirmationDialog
import ac.mdiq.podvinci.core.storage.DBWriter
import ac.mdiq.podvinci.model.feed.Feed
+import androidx.annotation.OptIn
+import androidx.media3.common.util.UnstableApi
import io.reactivex.Completable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
@@ -28,7 +30,7 @@ object RemoveFeedDialog {
private fun showDialog(context: Context, feeds: List, message: String, callback: Runnable?) {
val dialog: ConfirmationDialog = object : ConfirmationDialog(context, R.string.remove_feed_label, message) {
- override fun onConfirmButtonPressed(clickedDialog: DialogInterface) {
+ @OptIn(UnstableApi::class) override fun onConfirmButtonPressed(clickedDialog: DialogInterface) {
callback?.run()
clickedDialog.dismiss()
diff --git a/app/src/main/java/ac/mdiq/podvinci/dialog/TagSettingsDialog.kt b/app/src/main/java/ac/mdiq/podvinci/dialog/TagSettingsDialog.kt
index dcb63687..d6165aef 100644
--- a/app/src/main/java/ac/mdiq/podvinci/dialog/TagSettingsDialog.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/dialog/TagSettingsDialog.kt
@@ -43,7 +43,7 @@ class TagSettingsDialog : DialogFragment() {
viewBinding!!.tagsRecycler.layoutManager = GridLayoutManager(context, 2)
viewBinding!!.tagsRecycler.addItemDecoration(ItemOffsetDecoration(requireContext(), 4))
adapter = object : SimpleChipAdapter(requireContext()) {
- override fun getChips(): List {
+ override fun getChips(): List {
return displayedTags?: listOf()
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/AddFeedFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/AddFeedFragment.kt
index 5256fe55..9043e3f0 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/AddFeedFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/AddFeedFragment.kt
@@ -36,7 +36,7 @@ import io.reactivex.schedulers.Schedulers
*/
@UnstableApi
class AddFeedFragment : Fragment() {
- private var viewBinding: AddfeedBinding? = null
+ private lateinit var viewBinding: AddfeedBinding
private var activity: MainActivity? = null
private var displayUpArrow = false
@@ -51,60 +51,58 @@ class AddFeedFragment : Fragment() {
): View {
super.onCreateView(inflater, container, savedInstanceState)
viewBinding = AddfeedBinding.inflate(inflater)
- activity = getActivity() as MainActivity?
+ activity = getActivity() as? MainActivity
displayUpArrow = parentFragmentManager.backStackEntryCount != 0
if (savedInstanceState != null) {
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW)
}
- (getActivity() as MainActivity).setupToolbarToggle(viewBinding!!.toolbar, displayUpArrow)
+ (getActivity() as MainActivity).setupToolbarToggle(viewBinding.toolbar, displayUpArrow)
- viewBinding!!.searchItunesButton.setOnClickListener { v: View? ->
+ viewBinding.searchItunesButton.setOnClickListener { v: View? ->
activity?.loadChildFragment(OnlineSearchFragment.newInstance(
ItunesPodcastSearcher::class.java))
}
- viewBinding!!.searchFyydButton.setOnClickListener { v: View? ->
+ viewBinding.searchFyydButton.setOnClickListener { v: View? ->
activity?.loadChildFragment(OnlineSearchFragment.newInstance(
FyydPodcastSearcher::class.java))
}
- viewBinding!!.searchGPodderButton.setOnClickListener { v: View? ->
+ viewBinding.searchGPodderButton.setOnClickListener { v: View? ->
activity?.loadChildFragment(OnlineSearchFragment.newInstance(
GpodnetPodcastSearcher::class.java))
}
- viewBinding!!.searchPodcastIndexButton.setOnClickListener { v: View? ->
+ viewBinding.searchPodcastIndexButton.setOnClickListener { v: View? ->
activity?.loadChildFragment(OnlineSearchFragment.newInstance(
PodcastIndexPodcastSearcher::class.java))
}
- viewBinding!!.combinedFeedSearchEditText.setOnEditorActionListener { v: TextView?, actionId: Int, event: KeyEvent? ->
+ viewBinding.combinedFeedSearchEditText.setOnEditorActionListener { v: TextView?, actionId: Int, event: KeyEvent? ->
performSearch()
true
}
- viewBinding!!.addViaUrlButton.setOnClickListener { v: View? -> showAddViaUrlDialog() }
+ viewBinding.addViaUrlButton.setOnClickListener { v: View? -> showAddViaUrlDialog() }
- viewBinding!!.opmlImportButton.setOnClickListener { v: View? ->
+ viewBinding.opmlImportButton.setOnClickListener { v: View? ->
try {
chooseOpmlImportPathLauncher.launch("*/*")
} catch (e: ActivityNotFoundException) {
e.printStackTrace()
- (getActivity() as MainActivity)
- .showSnackbarAbovePlayer(R.string.unable_to_start_system_file_manager, Snackbar.LENGTH_LONG)
+ activity?.showSnackbarAbovePlayer(R.string.unable_to_start_system_file_manager, Snackbar.LENGTH_LONG)
}
}
- viewBinding!!.addLocalFolderButton.setOnClickListener { v: View? ->
+ viewBinding.addLocalFolderButton.setOnClickListener { v: View? ->
try {
addLocalFolderLauncher.launch(null)
} catch (e: ActivityNotFoundException) {
e.printStackTrace()
- (getActivity() as MainActivity)
- .showSnackbarAbovePlayer(R.string.unable_to_start_system_file_manager, Snackbar.LENGTH_LONG)
+ activity?.showSnackbarAbovePlayer(R.string.unable_to_start_system_file_manager, Snackbar.LENGTH_LONG)
}
}
- viewBinding!!.searchButton.setOnClickListener { view: View? -> performSearch() }
+ viewBinding.searchButton.setOnClickListener { view: View? -> performSearch() }
- return viewBinding!!.root
+ return viewBinding.root
}
override fun onSaveInstanceState(outState: Bundle) {
@@ -127,8 +125,7 @@ class AddFeedFragment : Fragment() {
}
}
builder.setView(dialogBinding.root)
- builder.setPositiveButton(R.string.confirm_label
- ) { dialog: DialogInterface?, which: Int -> addUrl(dialogBinding.urlEditText.text.toString()) }
+ builder.setPositiveButton(R.string.confirm_label) { dialog: DialogInterface?, which: Int -> addUrl(dialogBinding.urlEditText.text.toString()) }
builder.setNegativeButton(R.string.cancel_label, null)
builder.show()
}
@@ -141,16 +138,16 @@ class AddFeedFragment : Fragment() {
}
private fun performSearch() {
- viewBinding!!.combinedFeedSearchEditText.clearFocus()
+ viewBinding.combinedFeedSearchEditText.clearFocus()
val inVal = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
- inVal.hideSoftInputFromWindow(viewBinding!!.combinedFeedSearchEditText.windowToken, 0)
- val query = viewBinding!!.combinedFeedSearchEditText.text.toString()
+ inVal.hideSoftInputFromWindow(viewBinding.combinedFeedSearchEditText.windowToken, 0)
+ val query = viewBinding.combinedFeedSearchEditText.text.toString()
if (query.matches("http[s]?://.*".toRegex())) {
addUrl(query)
return
}
activity?.loadChildFragment(OnlineSearchFragment.newInstance(CombinedSearcher::class.java, query))
- viewBinding!!.combinedFeedSearchEditText.post { viewBinding!!.combinedFeedSearchEditText.setText("") }
+ viewBinding.combinedFeedSearchEditText.post { viewBinding.combinedFeedSearchEditText.setText("") }
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -205,8 +202,7 @@ class AddFeedFragment : Fragment() {
private class AddLocalFolder : ActivityResultContracts.OpenDocumentTree() {
override fun createIntent(context: Context, input: Uri?): Intent {
- return super.createIntent(context, input)
- .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ return super.createIntent(context, input).addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/AudioPlayerFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/AudioPlayerFragment.kt
index 7dc6d5f2..0d6f41fb 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/AudioPlayerFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/AudioPlayerFragment.kt
@@ -64,22 +64,23 @@ import kotlin.math.min
*/
@UnstableApi
class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar.OnMenuItemClickListener {
- var butPlaybackSpeed: PlaybackSpeedIndicatorView? = null
- var txtvPlaybackSpeed: TextView? = null
- private var pager: ViewPager2? = null
- private var txtvPosition: TextView? = null
- private var txtvLength: TextView? = null
- private var sbPosition: ChapterSeekBar? = null
- private var butRev: ImageButton? = null
- private var txtvRev: TextView? = null
- private var butPlay: PlayButton? = null
- private var butFF: ImageButton? = null
- private var txtvFF: TextView? = null
- private var butSkip: ImageButton? = null
- private var toolbar: MaterialToolbar? = null
- private var progressIndicator: ProgressBar? = null
- private var cardViewSeek: CardView? = null
- private var txtvSeek: TextView? = null
+ lateinit var butPlaybackSpeed: PlaybackSpeedIndicatorView
+ lateinit var txtvPlaybackSpeed: TextView
+ private lateinit var pager: ViewPager2
+ private lateinit var txtvPosition: TextView
+ private lateinit var txtvLength: TextView
+ private lateinit var sbPosition: ChapterSeekBar
+ private lateinit var butRev: ImageButton
+ private lateinit var txtvRev: TextView
+ private lateinit var butPlay: PlayButton
+ private lateinit var butFF: ImageButton
+ private lateinit var txtvFF: TextView
+ private lateinit var butSkip: ImageButton
+ private lateinit var toolbar: MaterialToolbar
+
+ private lateinit var progressIndicator: ProgressBar
+ private lateinit var cardViewSeek: CardView
+ private lateinit var txtvSeek: TextView
private var controller: PlaybackController? = null
private var disposable: Disposable? = null
@@ -97,11 +98,11 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
val root: View = inflater.inflate(R.layout.audioplayer_fragment, container, false)
root.setOnTouchListener { v: View?, event: MotionEvent? -> true } // Avoid clicks going through player to fragments below
toolbar = root.findViewById(R.id.toolbar)
- toolbar?.title = ""
- toolbar?.setNavigationOnClickListener { v: View? ->
+ toolbar.title = ""
+ toolbar.setNavigationOnClickListener { v: View? ->
(activity as MainActivity).bottomSheet?.setState(BottomSheetBehavior.STATE_COLLAPSED)
}
- toolbar?.setOnMenuItemClickListener(this)
+ toolbar.setOnMenuItemClickListener(this)
val externalPlayerFragment = ExternalPlayerFragment()
childFragmentManager.beginTransaction()
@@ -127,19 +128,19 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
setupLengthTextView()
setupControlButtons()
- butPlaybackSpeed?.setOnClickListener { v: View? ->
+ butPlaybackSpeed.setOnClickListener { v: View? ->
VariableSpeedDialog().show(
childFragmentManager, null)
}
- sbPosition?.setOnSeekBarChangeListener(this)
+ sbPosition.setOnSeekBarChangeListener(this)
pager = root.findViewById(R.id.pager)
- pager?.adapter = AudioPlayerPagerAdapter(this@AudioPlayerFragment)
+ pager.adapter = AudioPlayerPagerAdapter(this@AudioPlayerFragment)
// Required for getChildAt(int) in ViewPagerBottomSheetBehavior to return the correct page
- pager?.offscreenPageLimit = NUM_CONTENT_FRAGMENTS
- pager?.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
+ pager.offscreenPageLimit = NUM_CONTENT_FRAGMENTS
+ pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
- pager?.post {
+ pager.post {
if (activity != null) {
// By the time this is posted, the activity might be closed again.
(activity as MainActivity).bottomSheet?.updateScrollingChild()
@@ -167,39 +168,39 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
}
}
- sbPosition?.setDividerPos(dividerPos)
+ sbPosition.setDividerPos(dividerPos)
}
private fun setupControlButtons() {
- butRev?.setOnClickListener { v: View? ->
+ butRev.setOnClickListener { v: View? ->
if (controller != null) {
val curr: Int = controller!!.position
controller!!.seekTo(curr - UserPreferences.rewindSecs * 1000)
}
}
- butRev?.setOnLongClickListener { v: View? ->
+ butRev.setOnLongClickListener { v: View? ->
SkipPreferenceDialog.showSkipPreference(requireContext(),
SkipPreferenceDialog.SkipDirection.SKIP_REWIND, txtvRev)
true
}
- butPlay?.setOnClickListener { v: View? ->
+ butPlay.setOnClickListener { v: View? ->
if (controller != null) {
controller!!.init()
controller!!.playPause()
}
}
- butFF?.setOnClickListener { v: View? ->
+ butFF.setOnClickListener { v: View? ->
if (controller != null) {
val curr: Int = controller!!.position
controller!!.seekTo(curr + UserPreferences.fastForwardSecs * 1000)
}
}
- butFF?.setOnLongClickListener { v: View? ->
+ butFF.setOnLongClickListener { v: View? ->
SkipPreferenceDialog.showSkipPreference(requireContext(),
SkipPreferenceDialog.SkipDirection.SKIP_FORWARD, txtvFF)
false
}
- butSkip?.setOnClickListener { v: View? ->
+ butSkip.setOnClickListener { v: View? ->
activity?.sendBroadcast(
MediaButtonReceiver.createIntent(requireContext(), KeyEvent.KEYCODE_MEDIA_NEXT))
}
@@ -222,7 +223,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
private fun setupLengthTextView() {
showTimeLeft = UserPreferences.shouldShowRemainingTime()
- txtvLength?.setOnClickListener(View.OnClickListener { v: View? ->
+ txtvLength.setOnClickListener(View.OnClickListener { v: View? ->
if (controller == null) {
return@OnClickListener
}
@@ -235,8 +236,8 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
@Subscribe(threadMode = ThreadMode.MAIN)
fun updatePlaybackSpeedButton(event: SpeedChangedEvent) {
val speedStr: String = DecimalFormat("0.00").format(event.newSpeed.toDouble())
- txtvPlaybackSpeed?.text = speedStr
- butPlaybackSpeed?.setSpeed(event.newSpeed)
+ txtvPlaybackSpeed.text = speedStr
+ butPlaybackSpeed.setSpeed(event.newSpeed)
}
private fun loadMediaInfo(includingChapters: Boolean) {
@@ -268,7 +269,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
private fun newPlaybackController(): PlaybackController {
return object : PlaybackController(activity) {
override fun updatePlayButtonShowsPlay(showPlay: Boolean) {
- butPlay?.setIsShowPlay(showPlay)
+ butPlay.setIsShowPlay(showPlay)
}
override fun loadMediaInfo() {
@@ -311,41 +312,37 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
controller?.init()
loadMediaInfo(false)
EventBus.getDefault().register(this)
- txtvRev?.text = NumberFormat.getInstance().format(UserPreferences.rewindSecs.toLong())
- txtvFF?.text = NumberFormat.getInstance().format(UserPreferences.fastForwardSecs.toLong())
+ txtvRev.text = NumberFormat.getInstance().format(UserPreferences.rewindSecs.toLong())
+ txtvFF.text = NumberFormat.getInstance().format(UserPreferences.fastForwardSecs.toLong())
}
override fun onStop() {
super.onStop()
controller?.release()
controller = null
- progressIndicator?.visibility = View.GONE // Controller released; we will not receive buffering updates
+ progressIndicator.visibility = View.GONE // Controller released; we will not receive buffering updates
EventBus.getDefault().unregister(this)
- if (disposable != null) {
- disposable!!.dispose()
- }
+ disposable?.dispose()
}
@Subscribe(threadMode = ThreadMode.MAIN)
@Suppress("unused")
fun bufferUpdate(event: BufferUpdateEvent) {
if (event.hasStarted()) {
- progressIndicator?.visibility = View.VISIBLE
+ progressIndicator.visibility = View.VISIBLE
} else if (event.hasEnded()) {
- progressIndicator?.visibility = View.GONE
+ progressIndicator.visibility = View.GONE
} else if (controller != null && controller!!.isStreaming) {
- sbPosition?.setSecondaryProgress((event.progress * sbPosition!!.max).toInt())
+ sbPosition.setSecondaryProgress((event.progress * sbPosition.max).toInt())
} else {
- sbPosition?.setSecondaryProgress(0)
+ sbPosition.setSecondaryProgress(0)
}
}
@UnstableApi
@Subscribe(threadMode = ThreadMode.MAIN)
fun updatePosition(event: PlaybackPositionEvent) {
- if (controller == null || txtvPosition == null || txtvLength == null || sbPosition == null) {
- return
- }
+ if (controller == null) return
val converter = TimeSpeedConverter(controller!!.currentPlaybackSpeedMultiplier)
val currentPosition: Int = converter.convert(event.position)
@@ -357,23 +354,23 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
Log.w(TAG, "Could not react to position observer update because of invalid time")
return
}
- txtvPosition?.text = Converter.getDurationStringLong(currentPosition)
- txtvPosition?.setContentDescription(getString(R.string.position,
+ txtvPosition.text = Converter.getDurationStringLong(currentPosition)
+ txtvPosition.setContentDescription(getString(R.string.position,
Converter.getDurationStringLocalized(requireContext(), currentPosition.toLong())))
showTimeLeft = UserPreferences.shouldShowRemainingTime()
if (showTimeLeft) {
- txtvLength?.setContentDescription(getString(R.string.remaining_time,
+ txtvLength.setContentDescription(getString(R.string.remaining_time,
Converter.getDurationStringLocalized(requireContext(), remainingTime.toLong())))
- txtvLength?.text = (if ((remainingTime > 0)) "-" else "") + Converter.getDurationStringLong(remainingTime)
+ txtvLength.text = (if ((remainingTime > 0)) "-" else "") + Converter.getDurationStringLong(remainingTime)
} else {
- txtvLength?.setContentDescription(getString(R.string.chapter_duration,
+ txtvLength.setContentDescription(getString(R.string.chapter_duration,
Converter.getDurationStringLocalized(requireContext(), duration.toLong())))
- txtvLength?.text = Converter.getDurationStringLong(duration)
+ txtvLength.text = Converter.getDurationStringLong(duration)
}
- if (sbPosition == null || !sbPosition!!.isPressed) {
+ if (!sbPosition.isPressed) {
val progress: Float = (event.position.toFloat()) / event.duration
- sbPosition?.progress = (progress * sbPosition!!.max).toInt()
+ sbPosition.progress = (progress * sbPosition.max).toInt()
}
}
@@ -388,9 +385,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
}
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (controller == null || txtvLength == null) {
- return
- }
+ if (controller == null) return
if (fromUser) {
val prog: Float = progress / (seekBar.max.toFloat())
@@ -398,19 +393,19 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
var position: Int = converter.convert((prog * controller!!.duration).toInt())
val newChapterIndex: Int = ChapterUtils.getCurrentChapterIndex(controller!!.getMedia(), position)
if (newChapterIndex > -1) {
- if ((sbPosition == null || !sbPosition!!.isPressed) && currentChapterIndex != newChapterIndex) {
+ if (!sbPosition.isPressed && currentChapterIndex != newChapterIndex) {
currentChapterIndex = newChapterIndex
val media = controller!!.getMedia()
position = media?.getChapters()?.get(currentChapterIndex)?.start?.toInt() ?: 0
seekedToChapterStart = true
controller!!.seekTo(position)
updateUi(controller!!.getMedia())
- sbPosition?.highlightCurrentChapter()
+ sbPosition.highlightCurrentChapter()
}
- txtvSeek?.text = controller!!.getMedia()?.getChapters()?.get(newChapterIndex)?.title ?: (""
+ txtvSeek.text = controller!!.getMedia()?.getChapters()?.get(newChapterIndex)?.title ?: (""
+ "\n" + Converter.getDurationStringLong(position))
} else {
- txtvSeek?.text = Converter.getDurationStringLong(position)
+ txtvSeek.text = Converter.getDurationStringLong(position)
}
} else if (duration != controller!!.duration) {
updateUi(controller!!.getMedia())
@@ -419,9 +414,9 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
override fun onStartTrackingTouch(seekBar: SeekBar) {
// interrupt position Observer, restart later
- cardViewSeek?.scaleX = .8f
- cardViewSeek?.scaleY = .8f
- cardViewSeek?.animate()
+ cardViewSeek.scaleX = .8f
+ cardViewSeek.scaleY = .8f
+ cardViewSeek.animate()
?.setInterpolator(FastOutSlowInInterpolator())
?.alpha(1f)?.scaleX(1f)?.scaleY(1f)
?.setDuration(200)
@@ -437,9 +432,9 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
controller!!.seekTo((prog * controller!!.duration).toInt())
}
}
- cardViewSeek?.scaleX = 1f
- cardViewSeek?.scaleY = 1f
- cardViewSeek?.animate()
+ cardViewSeek.scaleX = 1f
+ cardViewSeek.scaleY = 1f
+ cardViewSeek.animate()
?.setInterpolator(FastOutSlowInInterpolator())
?.alpha(0f)?.scaleX(.8f)?.scaleY(.8f)
?.setDuration(200)
@@ -447,29 +442,26 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
}
fun setupOptionsMenu(media: Playable?) {
- if (toolbar == null) return
- if (toolbar!!.menu.size() == 0) {
- toolbar!!.inflateMenu(R.menu.mediaplayer)
- }
- if (controller == null) {
- return
+ if (toolbar.menu.size() == 0) {
+ toolbar.inflateMenu(R.menu.mediaplayer)
}
+
val isFeedMedia = media is FeedMedia
- toolbar?.menu?.findItem(R.id.open_feed_item)?.setVisible(isFeedMedia)
+ toolbar.menu?.findItem(R.id.open_feed_item)?.setVisible(isFeedMedia)
if (isFeedMedia) {
- FeedItemMenuHandler.onPrepareMenu(toolbar!!.menu, (media as FeedMedia).getItem())
+ FeedItemMenuHandler.onPrepareMenu(toolbar.menu, (media as FeedMedia).getItem())
}
- toolbar!!.menu.findItem(R.id.set_sleeptimer_item).setVisible(!controller!!.sleepTimerActive())
- toolbar!!.menu.findItem(R.id.disable_sleeptimer_item).setVisible(controller!!.sleepTimerActive())
-
- (activity as CastEnabledActivity).requestCastButton(toolbar!!.menu)
+ if (controller != null) {
+ toolbar.menu.findItem(R.id.set_sleeptimer_item).setVisible(!controller!!.sleepTimerActive())
+ toolbar.menu.findItem(R.id.disable_sleeptimer_item).setVisible(controller!!.sleepTimerActive())
+ }
+ (activity as CastEnabledActivity).requestCastButton(toolbar.menu)
}
override fun onMenuItemClick(item: MenuItem): Boolean {
- if (controller == null) {
- return false
- }
+ if (controller == null) return false
+
val media: Playable = controller!!.getMedia() ?: return false
val feedItem: FeedItem? = if ((media is FeedMedia)) media.getItem() else null
@@ -497,8 +489,8 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
player.alpha = 1 - playerFadeProgress
player.visibility = if (playerFadeProgress > 0.99f) View.INVISIBLE else View.VISIBLE
val toolbarFadeProgress = (max(0.0, min(0.2, (slideOffset - 0.6f).toDouble())) / 0.2f).toFloat()
- toolbar?.setAlpha(toolbarFadeProgress)
- toolbar?.visibility = if (toolbarFadeProgress < 0.01f) View.INVISIBLE else View.VISIBLE
+ toolbar.setAlpha(toolbarFadeProgress)
+ toolbar.visibility = if (toolbarFadeProgress < 0.01f) View.INVISIBLE else View.VISIBLE
}
private class AudioPlayerPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
@@ -522,11 +514,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
@JvmOverloads
fun scrollToPage(page: Int, smoothScroll: Boolean = false) {
- if (pager == null) {
- return
- }
-
- pager?.setCurrentItem(page, smoothScroll)
+ pager.setCurrentItem(page, smoothScroll)
val visibleChild = childFragmentManager.findFragmentByTag("f$POS_DESCRIPTION")
if (visibleChild is ItemDescriptionFragment) {
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/ChaptersFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/ChaptersFragment.kt
index 7f9ae775..d64ab2ab 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/ChaptersFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/ChaptersFragment.kt
@@ -37,14 +37,15 @@ import org.greenrobot.eventbus.ThreadMode
@UnstableApi
class ChaptersFragment : AppCompatDialogFragment() {
- private var adapter: ChaptersListAdapter? = null
+ private lateinit var layoutManager: LinearLayoutManager
+ private lateinit var progressBar: ProgressBar
+ private lateinit var adapter: ChaptersListAdapter
+
private var controller: PlaybackController? = null
private var disposable: Disposable? = null
private var focusedChapter = -1
private var media: Playable? = null
- private var layoutManager: LinearLayoutManager? = null
- private var progressBar: ProgressBar? = null
-
+
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(R.string.chapters_label))
@@ -55,7 +56,7 @@ class ChaptersFragment : AppCompatDialogFragment() {
dialog.show()
dialog.getButton(DialogInterface.BUTTON_NEUTRAL).visibility = View.INVISIBLE
dialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener { v: View? ->
- progressBar!!.visibility = View.VISIBLE
+ progressBar.visibility = View.VISIBLE
loadMediaInfo(true)
}
@@ -70,22 +71,21 @@ class ChaptersFragment : AppCompatDialogFragment() {
progressBar = root.findViewById(R.id.progLoading)
layoutManager = LinearLayoutManager(activity)
recyclerView.layoutManager = layoutManager
- recyclerView.addItemDecoration(DividerItemDecoration(recyclerView.context,
- layoutManager!!.orientation))
+ recyclerView.addItemDecoration(DividerItemDecoration(recyclerView.context, layoutManager.orientation))
adapter = ChaptersListAdapter(requireContext(), object : ChaptersListAdapter.Callback {
override fun onPlayChapterButtonClicked(pos: Int) {
- if (controller!!.status != PlayerStatus.PLAYING) {
+ if (controller?.status != PlayerStatus.PLAYING) {
controller!!.playPause()
}
- val chapter = adapter!!.getItem(pos)
- controller!!.seekTo(chapter.start.toInt())
+ val chapter = adapter.getItem(pos)
+ if (chapter != null) controller!!.seekTo(chapter.start.toInt())
updateChapterSelection(pos, true)
}
})
recyclerView.adapter = adapter
- progressBar?.visibility = View.VISIBLE
+ progressBar.visibility = View.VISIBLE
val wrapHeight = CoordinatorLayout.LayoutParams(
CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT)
@@ -108,11 +108,8 @@ class ChaptersFragment : AppCompatDialogFragment() {
override fun onStop() {
super.onStop()
-
- if (disposable != null) {
- disposable!!.dispose()
- }
- controller!!.release()
+ disposable?.dispose()
+ controller?.release()
controller = null
EventBus.getDefault().unregister(this)
}
@@ -120,20 +117,18 @@ class ChaptersFragment : AppCompatDialogFragment() {
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: PlaybackPositionEvent) {
updateChapterSelection(getCurrentChapter(media), false)
- adapter!!.notifyTimeChanged(event.position.toLong())
+ adapter.notifyTimeChanged(event.position.toLong())
}
private fun getCurrentChapter(media: Playable?): Int {
- if (controller == null) {
- return -1
- }
+ if (controller == null) return -1
+
return getCurrentChapterIndex(media, controller!!.position)
}
private fun loadMediaInfo(forceRefresh: Boolean) {
- if (disposable != null) {
- disposable!!.dispose()
- }
+ disposable?.dispose()
+
disposable = Maybe.create { emitter: MaybeEmitter ->
val media = controller!!.getMedia()
if (media != null) {
@@ -152,36 +147,29 @@ class ChaptersFragment : AppCompatDialogFragment() {
private fun onMediaChanged(media: Playable) {
this.media = media
focusedChapter = -1
- if (adapter == null) {
- return
- }
+
if (media.getChapters().isEmpty()) {
dismiss()
Toast.makeText(context, R.string.no_chapters_label, Toast.LENGTH_LONG).show()
} else {
- progressBar!!.visibility = View.GONE
+ progressBar.visibility = View.GONE
}
- adapter!!.setMedia(media)
- (dialog as AlertDialog?)!!.getButton(DialogInterface.BUTTON_NEUTRAL).visibility =
- View.INVISIBLE
+ adapter.setMedia(media)
+ (dialog as AlertDialog).getButton(DialogInterface.BUTTON_NEUTRAL).visibility = View.INVISIBLE
if ((media is FeedMedia) && media.getItem() != null && !TextUtils.isEmpty(media.getItem()!!.podcastIndexChapterUrl)) {
- (dialog as AlertDialog?)!!.getButton(DialogInterface.BUTTON_NEUTRAL).visibility = View.VISIBLE
+ (dialog as AlertDialog).getButton(DialogInterface.BUTTON_NEUTRAL).visibility = View.VISIBLE
}
val positionOfCurrentChapter = getCurrentChapter(media)
updateChapterSelection(positionOfCurrentChapter, true)
}
private fun updateChapterSelection(position: Int, scrollTo: Boolean) {
- if (adapter == null) {
- return
- }
-
if (position != -1 && focusedChapter != position) {
focusedChapter = position
- adapter!!.notifyChapterChanged(focusedChapter)
- if (scrollTo && (layoutManager!!.findFirstCompletelyVisibleItemPosition() >= position
- || layoutManager!!.findLastCompletelyVisibleItemPosition() <= position)) {
- layoutManager!!.scrollToPositionWithOffset(position, 100)
+ adapter.notifyChapterChanged(focusedChapter)
+ if (scrollTo && (layoutManager.findFirstCompletelyVisibleItemPosition() >= position
+ || layoutManager.findLastCompletelyVisibleItemPosition() <= position)) {
+ layoutManager.scrollToPositionWithOffset(position, 100)
}
}
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/CompletedDownloadsFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/CompletedDownloadsFragment.kt
index cbd5f4db..30d1bc1e 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/CompletedDownloadsFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/CompletedDownloadsFragment.kt
@@ -39,6 +39,8 @@ import ac.mdiq.podvinci.view.EmptyViewHandler
import ac.mdiq.podvinci.view.EpisodeItemListRecyclerView
import ac.mdiq.podvinci.view.LiftOnScrollListener
import ac.mdiq.podvinci.view.viewholder.EpisodeItemViewHolder
+import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.SimpleItemAnimator
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
@@ -52,75 +54,83 @@ import org.greenrobot.eventbus.ThreadMode
*/
class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeListener, Toolbar.OnMenuItemClickListener {
private var runningDownloads: Set? = HashSet()
- private var items: MutableList? = ArrayList()
- private var adapter: CompletedDownloadsListAdapter? = null
- private var recyclerView: EpisodeItemListRecyclerView? = null
+ private var items: MutableList = mutableListOf()
+
+ private lateinit var adapter: CompletedDownloadsListAdapter
+ private lateinit var toolbar: MaterialToolbar
+ private lateinit var recyclerView: EpisodeItemListRecyclerView
+ private lateinit var swipeActions: SwipeActions
+ private lateinit var speedDialView: SpeedDialView
+ private lateinit var progressBar: ProgressBar
+ private lateinit var emptyView: EmptyViewHandler
+
private var disposable: Disposable? = null
- private var emptyView: EmptyViewHandler? = null
private var displayUpArrow = false
- private var speedDialView: SpeedDialView? = null
- private var swipeActions: SwipeActions? = null
- private var progressBar: ProgressBar? = null
- private var toolbar: MaterialToolbar? = null
+
@UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val root: View = inflater.inflate(R.layout.simple_list_fragment, container, false)
toolbar = root.findViewById(R.id.toolbar)
- toolbar?.setTitle(R.string.downloads_label)
- toolbar?.inflateMenu(R.menu.downloads_completed)
- toolbar?.setOnMenuItemClickListener(this)
- toolbar?.setOnLongClickListener { v: View? ->
- recyclerView?.scrollToPosition(5)
- recyclerView?.post { recyclerView!!.smoothScrollToPosition(0) }
+ toolbar.setTitle(R.string.downloads_label)
+ toolbar.inflateMenu(R.menu.downloads_completed)
+ toolbar.setOnMenuItemClickListener(this)
+ toolbar.setOnLongClickListener { v: View? ->
+ recyclerView.scrollToPosition(5)
+ recyclerView.post { recyclerView.smoothScrollToPosition(0) }
false
}
displayUpArrow = parentFragmentManager.backStackEntryCount != 0
if (savedInstanceState != null) {
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW)
}
- if (toolbar != null) (activity as MainActivity).setupToolbarToggle(toolbar!!, displayUpArrow)
+ (activity as MainActivity).setupToolbarToggle(toolbar, displayUpArrow)
recyclerView = root.findViewById(R.id.recyclerView)
- recyclerView?.setRecycledViewPool((activity as MainActivity).recycledViewPool)
+ recyclerView.setRecycledViewPool((activity as MainActivity).recycledViewPool)
adapter = CompletedDownloadsListAdapter(activity as MainActivity)
- adapter?.setOnSelectModeListener(this)
- recyclerView?.adapter = adapter
- recyclerView?.addOnScrollListener(LiftOnScrollListener(root.findViewById(R.id.appbar)))
+ adapter.setOnSelectModeListener(this)
+ recyclerView.adapter = adapter
+ recyclerView.addOnScrollListener(LiftOnScrollListener(root.findViewById(R.id.appbar)))
swipeActions = SwipeActions(this, TAG).attachTo(recyclerView)
- swipeActions?.setFilter(FeedItemFilter(FeedItemFilter.DOWNLOADED))
+ swipeActions.setFilter(FeedItemFilter(FeedItemFilter.DOWNLOADED))
+
+ val animator: RecyclerView.ItemAnimator? = recyclerView.itemAnimator
+ if (animator is SimpleItemAnimator) {
+ animator.supportsChangeAnimations = false
+ }
progressBar = root.findViewById(R.id.progLoading)
- progressBar?.visibility = View.VISIBLE
+ progressBar.visibility = View.VISIBLE
speedDialView = root.findViewById(R.id.fabSD)
- speedDialView?.overlayLayout = root.findViewById(R.id.fabSDOverlay)
- speedDialView?.inflate(R.menu.episodes_apply_action_speeddial)
- speedDialView?.removeActionItemById(R.id.download_batch)
- speedDialView?.removeActionItemById(R.id.mark_read_batch)
- speedDialView?.removeActionItemById(R.id.mark_unread_batch)
- speedDialView?.removeActionItemById(R.id.remove_from_queue_batch)
- speedDialView?.removeActionItemById(R.id.remove_all_inbox_item)
- speedDialView?.setOnChangeListener(object : SpeedDialView.OnChangeListener {
+ speedDialView.overlayLayout = root.findViewById(R.id.fabSDOverlay)
+ speedDialView.inflate(R.menu.episodes_apply_action_speeddial)
+ speedDialView.removeActionItemById(R.id.download_batch)
+ speedDialView.removeActionItemById(R.id.mark_read_batch)
+ speedDialView.removeActionItemById(R.id.mark_unread_batch)
+ speedDialView.removeActionItemById(R.id.remove_from_queue_batch)
+ speedDialView.removeActionItemById(R.id.remove_all_inbox_item)
+ speedDialView.setOnChangeListener(object : SpeedDialView.OnChangeListener {
override fun onMainActionSelected(): Boolean {
return false
}
override fun onToggleChanged(open: Boolean) {
- if (open && adapter?.selectedCount == 0) {
+ if (open && adapter.selectedCount == 0) {
(activity as MainActivity).showSnackbarAbovePlayer(R.string.no_items_selected,
Snackbar.LENGTH_SHORT)
- speedDialView?.close()
+ speedDialView.close()
}
}
})
- speedDialView?.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
- adapter?.selectedItems?.let {
+ speedDialView.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
+ adapter.selectedItems.let {
EpisodeMultiSelectActionHandler((activity as MainActivity), actionItem.id)
.handleAction(it.filterIsInstance())
}
- adapter?.endSelectMode()
+ adapter.endSelectMode()
true
}
if (arguments != null && requireArguments().getBoolean(ARG_SHOW_LOGS, false)) {
@@ -139,11 +149,10 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
override fun onDestroyView() {
EventBus.getDefault().unregister(this)
- adapter?.endSelectMode()
- if (toolbar != null) {
- toolbar!!.setOnMenuItemClickListener(null)
- toolbar!!.setOnLongClickListener(null)
- }
+ adapter.endSelectMode()
+ toolbar.setOnMenuItemClickListener(null)
+ toolbar.setOnLongClickListener(null)
+
super.onDestroyView()
}
@@ -157,7 +166,7 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
disposable?.dispose()
}
- override fun onMenuItemClick(item: MenuItem): Boolean {
+ @UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
when (item.itemId) {
R.id.refresh_item -> {
FeedUpdateManager.runOnceOrAsk(requireContext())
@@ -193,21 +202,20 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
return // Refreshed anyway
}
for (downloadUrl in event.urls) {
- var pos = -1
- items?.let { pos = FeedItemUtil.indexOfItemWithDownloadUrl(it.toList(), downloadUrl)}
+ val pos = FeedItemUtil.indexOfItemWithDownloadUrl(items.toList(), downloadUrl)
if (pos >= 0) {
- adapter?.notifyItemChangedCompat(pos)
+ adapter.notifyItemChangedCompat(pos)
}
}
}
override fun onContextItemSelected(item: MenuItem): Boolean {
- val selectedItem: FeedItem? = adapter?.longPressedItem
+ val selectedItem: FeedItem? = adapter.longPressedItem
if (selectedItem == null) {
Log.i(TAG, "Selected item at current position was null, ignoring selection")
return super.onContextItemSelected(item)
}
- if (adapter != null && adapter!!.onContextItemSelected(item)) {
+ if (adapter.onContextItemSelected(item)) {
return true
}
@@ -216,51 +224,48 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
private fun addEmptyView() {
emptyView = EmptyViewHandler(activity)
- emptyView?.setIcon(R.drawable.ic_download)
- emptyView?.setTitle(R.string.no_comp_downloads_head_label)
- emptyView?.setMessage(R.string.no_comp_downloads_label)
- if (recyclerView != null) emptyView?.attachToRecyclerView(recyclerView!!)
+ emptyView.setIcon(R.drawable.ic_download)
+ emptyView.setTitle(R.string.no_comp_downloads_head_label)
+ emptyView.setMessage(R.string.no_comp_downloads_label)
+ emptyView.attachToRecyclerView(recyclerView)
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: FeedItemEvent) {
Log.d(TAG, "onEventMainThread() called with: event = [$event]")
- if (items == null) {
- return
- } else if (adapter == null) {
- loadItems()
- return
- }
+
var i = 0
val size: Int = event.items.size
while (i < size) {
val item: FeedItem = event.items[i]
- var pos = -1
- items?.let { pos = FeedItemUtil.indexOfItemWithId(it.toList(), item.id) }
+ val pos = FeedItemUtil.indexOfItemWithId(items.toList(), item.id)
if (pos >= 0) {
- items?.removeAt(pos)
+ items.removeAt(pos)
val media = item.media
if (media != null && media.isDownloaded()) {
- items?.add(pos, item)
- adapter?.notifyItemChangedCompat(pos)
+ items.add(pos, item)
+// adapter.notifyItemChangedCompat(pos)
} else {
- adapter?.notifyItemRemoved(pos)
+// adapter.notifyItemRemoved(pos)
}
}
i++
}
+// have to do this as adapter.notifyItemRemoved(pos) when pos == 0 causes crash
+ if (size > 0) {
+ adapter.setDummyViews(0)
+ adapter.updateItems(items)
+ }
}
@UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
- fun onEventMainThread(event: PlaybackPositionEvent?) {
- if (adapter != null) {
- for (i in 0 until adapter!!.itemCount) {
- val holder: EpisodeItemViewHolder =
- recyclerView?.findViewHolderForAdapterPosition(i) as EpisodeItemViewHolder
- if (holder.isCurrentlyPlayingItem) {
- if (event != null) holder.notifyPlaybackPositionUpdated(event)
- break
- }
+ fun onEventMainThread(event: PlaybackPositionEvent) {
+// if (event == null) return
+ for (i in 0 until adapter.itemCount) {
+ val holder: EpisodeItemViewHolder? = recyclerView.findViewHolderForAdapterPosition(i) as? EpisodeItemViewHolder
+ if (holder != null && holder.isCurrentlyPlayingItem) {
+ holder.notifyPlaybackPositionUpdated(event)
+ break
}
}
}
@@ -283,7 +288,7 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
private fun loadItems() {
disposable?.dispose()
- emptyView?.hide()
+ emptyView.hide()
disposable = Observable.fromCallable {
val sortOrder: SortOrder? = UserPreferences.downloadsSortedOrder
val downloadedItems: List = DBReader.getEpisodes(0, Int.MAX_VALUE,
@@ -306,35 +311,35 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
- { result: List? ->
- items = result?.toMutableList()
- adapter?.setDummyViews(0)
- progressBar?.visibility = View.GONE
- if (result != null) adapter?.updateItems(result)
+ { result: List ->
+ items = result.toMutableList()
+ adapter.setDummyViews(0)
+ progressBar.visibility = View.GONE
+ adapter.updateItems(result)
}, { error: Throwable? ->
- adapter?.setDummyViews(0)
- adapter?.updateItems(emptyList())
+ adapter.setDummyViews(0)
+ adapter.updateItems(emptyList())
Log.e(TAG, Log.getStackTraceString(error))
})
}
override fun onStartSelectMode() {
- swipeActions?.detach()
- speedDialView?.visibility = View.VISIBLE
+ swipeActions.detach()
+ speedDialView.visibility = View.VISIBLE
}
override fun onEndSelectMode() {
- speedDialView?.close()
- speedDialView?.visibility = View.GONE
- swipeActions?.attachTo(recyclerView)
+ speedDialView.close()
+ speedDialView.visibility = View.GONE
+ swipeActions.attachTo(recyclerView)
}
- @UnstableApi private inner class CompletedDownloadsListAdapter(mainActivity: MainActivity) :
- EpisodeItemListAdapter(mainActivity) {
+ @UnstableApi private inner class CompletedDownloadsListAdapter(mainActivity: MainActivity) : EpisodeItemListAdapter(mainActivity) {
@UnstableApi override fun afterBindViewHolder(holder: EpisodeItemViewHolder, pos: Int) {
if (holder.feedItem != null && !inActionMode()) {
if (holder.feedItem!!.isDownloaded) {
- val actionButton = DeleteActionButton(getItem(pos))
+ val item = getItem(pos) ?: return
+ val actionButton = DeleteActionButton(item)
actionButton.configure(holder.secondaryActionButton, holder.secondaryActionIcon, requireContext())
}
}
@@ -345,8 +350,7 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
if (!inActionMode()) {
menu.findItem(R.id.multi_select).setVisible(true)
}
- MenuItemUtils.setOnClickListeners(menu
- ) { item: MenuItem ->
+ MenuItemUtils.setOnClickListeners(menu) { item: MenuItem ->
this@CompletedDownloadsFragment.onContextItemSelected(item)
}
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/CoverFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/CoverFragment.kt
index 05388da3..12ab601f 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/CoverFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/CoverFragment.kt
@@ -1,6 +1,17 @@
package ac.mdiq.podvinci.fragment
+import ac.mdiq.podvinci.R
import ac.mdiq.podvinci.activity.MainActivity
+import ac.mdiq.podvinci.core.feed.util.ImageResourceUtils
+import ac.mdiq.podvinci.core.util.ChapterUtils
+import ac.mdiq.podvinci.core.util.DateFormatter
+import ac.mdiq.podvinci.core.util.playback.PlaybackController
+import ac.mdiq.podvinci.databinding.CoverFragmentBinding
+import ac.mdiq.podvinci.event.playback.PlaybackPositionEvent
+import ac.mdiq.podvinci.model.feed.Chapter
+import ac.mdiq.podvinci.model.feed.EmbeddedChapterImage
+import ac.mdiq.podvinci.model.feed.FeedMedia
+import ac.mdiq.podvinci.model.playback.Playable
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
@@ -13,7 +24,6 @@ import android.graphics.ColorFilter
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
-import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
@@ -30,17 +40,6 @@ import com.bumptech.glide.load.resource.bitmap.FitCenter
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.google.android.material.snackbar.Snackbar
-import ac.mdiq.podvinci.R
-import ac.mdiq.podvinci.core.feed.util.ImageResourceUtils
-import ac.mdiq.podvinci.core.util.ChapterUtils
-import ac.mdiq.podvinci.core.util.DateFormatter
-import ac.mdiq.podvinci.core.util.playback.PlaybackController
-import ac.mdiq.podvinci.databinding.CoverFragmentBinding
-import ac.mdiq.podvinci.event.playback.PlaybackPositionEvent
-import ac.mdiq.podvinci.model.feed.Chapter
-import ac.mdiq.podvinci.model.feed.EmbeddedChapterImage
-import ac.mdiq.podvinci.model.feed.FeedMedia
-import ac.mdiq.podvinci.model.playback.Playable
import io.reactivex.Maybe
import io.reactivex.MaybeEmitter
import io.reactivex.android.schedulers.AndroidSchedulers
@@ -55,7 +54,7 @@ import org.greenrobot.eventbus.ThreadMode
* Displays the cover and the title of a FeedItem.
*/
class CoverFragment : Fragment() {
- private var viewBinding: CoverFragmentBinding? = null
+ private lateinit var viewBinding: CoverFragmentBinding
private var controller: PlaybackController? = null
private var disposable: Disposable? = null
private var displayedChapterIndex = -1
@@ -63,23 +62,23 @@ class CoverFragment : Fragment() {
@UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
viewBinding = CoverFragmentBinding.inflate(inflater)
- viewBinding!!.imgvCover.setOnClickListener { v: View? -> onPlayPause() }
- viewBinding!!.openDescription.setOnClickListener { view: View? ->
+ viewBinding.imgvCover.setOnClickListener { v: View? -> onPlayPause() }
+ viewBinding.openDescription.setOnClickListener { view: View? ->
(requireParentFragment() as AudioPlayerFragment)
.scrollToPage(AudioPlayerFragment.POS_DESCRIPTION, true)
}
val colorFilter: ColorFilter? = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(
- viewBinding!!.txtvPodcastTitle.currentTextColor, BlendModeCompat.SRC_IN)
- viewBinding!!.butNextChapter.colorFilter = colorFilter
- viewBinding!!.butPrevChapter.colorFilter = colorFilter
- viewBinding!!.descriptionIcon.colorFilter = colorFilter
- viewBinding!!.chapterButton.setOnClickListener { v: View? ->
+ viewBinding.txtvPodcastTitle.currentTextColor, BlendModeCompat.SRC_IN)
+ viewBinding.butNextChapter.colorFilter = colorFilter
+ viewBinding.butPrevChapter.colorFilter = colorFilter
+ viewBinding.descriptionIcon.colorFilter = colorFilter
+ viewBinding.chapterButton.setOnClickListener { v: View? ->
ChaptersFragment().show(
childFragmentManager, ChaptersFragment.TAG)
}
- viewBinding!!.butPrevChapter.setOnClickListener { v: View? -> seekToPrevChapter() }
- viewBinding!!.butNextChapter.setOnClickListener { v: View? -> seekToNextChapter() }
- return viewBinding!!.root
+ viewBinding.butPrevChapter.setOnClickListener { v: View? -> seekToPrevChapter() }
+ viewBinding.butNextChapter.setOnClickListener { v: View? -> seekToNextChapter() }
+ return viewBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -87,9 +86,8 @@ class CoverFragment : Fragment() {
}
@UnstableApi private fun loadMediaInfo(includingChapters: Boolean) {
- if (disposable != null) {
- disposable!!.dispose()
- }
+ disposable?.dispose()
+
disposable = Maybe.create { emitter: MaybeEmitter ->
val media: Playable? = controller?.getMedia()
if (media != null) {
@@ -111,9 +109,9 @@ class CoverFragment : Fragment() {
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
- private fun displayMediaInfo(media: Playable) {
+ @UnstableApi private fun displayMediaInfo(media: Playable) {
val pubDateStr = DateFormatter.formatAbbrev(activity, media.getPubDate())
- viewBinding!!.txtvPodcastTitle.text = (StringUtils.stripToEmpty(media.getFeedTitle())
+ viewBinding.txtvPodcastTitle.text = (StringUtils.stripToEmpty(media.getFeedTitle())
+ "\u00A0"
+ "・"
+ "\u00A0"
@@ -122,36 +120,36 @@ class CoverFragment : Fragment() {
if (media.getItem() != null) {
val openFeed: Intent =
MainActivity.getIntentToOpenFeed(requireContext(), media.getItem()!!.feedId)
- viewBinding!!.txtvPodcastTitle.setOnClickListener { v: View? -> startActivity(openFeed) }
+ viewBinding.txtvPodcastTitle.setOnClickListener { v: View? -> startActivity(openFeed) }
}
} else {
- viewBinding!!.txtvPodcastTitle.setOnClickListener(null)
+ viewBinding.txtvPodcastTitle.setOnClickListener(null)
}
- viewBinding!!.txtvPodcastTitle.setOnLongClickListener { v: View? -> copyText(media.getFeedTitle()) }
- viewBinding!!.txtvEpisodeTitle.text = media.getEpisodeTitle()
- viewBinding!!.txtvEpisodeTitle.setOnLongClickListener { v: View? -> copyText(media.getEpisodeTitle()) }
- viewBinding!!.txtvEpisodeTitle.setOnClickListener { v: View? ->
- val lines = viewBinding!!.txtvEpisodeTitle.lineCount
+ viewBinding.txtvPodcastTitle.setOnLongClickListener { v: View? -> copyText(media.getFeedTitle()) }
+ viewBinding.txtvEpisodeTitle.text = media.getEpisodeTitle()
+ viewBinding.txtvEpisodeTitle.setOnLongClickListener { v: View? -> copyText(media.getEpisodeTitle()) }
+ viewBinding.txtvEpisodeTitle.setOnClickListener { v: View? ->
+ val lines = viewBinding.txtvEpisodeTitle.lineCount
val animUnit = 1500
- if (lines > viewBinding!!.txtvEpisodeTitle.maxLines) {
- val titleHeight = (viewBinding!!.txtvEpisodeTitle.height
- - viewBinding!!.txtvEpisodeTitle.paddingTop
- - viewBinding!!.txtvEpisodeTitle.paddingBottom)
+ if (lines > viewBinding.txtvEpisodeTitle.maxLines) {
+ val titleHeight = (viewBinding.txtvEpisodeTitle.height
+ - viewBinding.txtvEpisodeTitle.paddingTop
+ - viewBinding.txtvEpisodeTitle.paddingBottom)
val verticalMarquee: ObjectAnimator = ObjectAnimator.ofInt(
- viewBinding!!.txtvEpisodeTitle, "scrollY", 0,
- (lines - viewBinding!!.txtvEpisodeTitle.maxLines)
- * (titleHeight / viewBinding!!.txtvEpisodeTitle.maxLines))
+ viewBinding.txtvEpisodeTitle, "scrollY", 0,
+ (lines - viewBinding.txtvEpisodeTitle.maxLines)
+ * (titleHeight / viewBinding.txtvEpisodeTitle.maxLines))
.setDuration((lines * animUnit).toLong())
val fadeOut: ObjectAnimator = ObjectAnimator.ofFloat(
- viewBinding!!.txtvEpisodeTitle, "alpha", 0f)
+ viewBinding.txtvEpisodeTitle, "alpha", 0f)
fadeOut.setStartDelay(animUnit.toLong())
fadeOut.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
- viewBinding!!.txtvEpisodeTitle.scrollTo(0, 0)
+ viewBinding.txtvEpisodeTitle.scrollTo(0, 0)
}
})
val fadeBackIn: ObjectAnimator = ObjectAnimator.ofFloat(
- viewBinding!!.txtvEpisodeTitle, "alpha", 1f)
+ viewBinding.txtvEpisodeTitle, "alpha", 1f)
val set = AnimatorSet()
set.playSequentially(verticalMarquee, fadeOut, fadeBackIn)
set.start()
@@ -173,9 +171,9 @@ class CoverFragment : Fragment() {
chapterControlVisible = fm?.getItem() != null && fm.getItem()!!.hasChapters()
}
val newVisibility = if (chapterControlVisible) View.VISIBLE else View.GONE
- if (viewBinding!!.chapterButton.visibility != newVisibility) {
- viewBinding!!.chapterButton.visibility = newVisibility
- ObjectAnimator.ofFloat(viewBinding!!.chapterButton,
+ if (viewBinding.chapterButton.visibility != newVisibility) {
+ viewBinding.chapterButton.visibility = newVisibility
+ ObjectAnimator.ofFloat(viewBinding.chapterButton,
"alpha",
(if (chapterControlVisible) 0 else 1).toFloat(),
(if (chapterControlVisible) 1 else 0).toFloat())
@@ -187,10 +185,10 @@ class CoverFragment : Fragment() {
if (media != null && chapterIndex > -1) {
if (media!!.getPosition() > media!!.getDuration() || chapterIndex >= media!!.getChapters().size - 1) {
displayedChapterIndex = media!!.getChapters().size - 1
- viewBinding!!.butNextChapter.visibility = View.INVISIBLE
+ viewBinding.butNextChapter.visibility = View.INVISIBLE
} else {
displayedChapterIndex = chapterIndex
- viewBinding!!.butNextChapter.visibility = View.VISIBLE
+ viewBinding.butNextChapter.visibility = View.VISIBLE
}
}
@@ -245,10 +243,7 @@ class CoverFragment : Fragment() {
@UnstableApi override fun onStop() {
super.onStop()
-
- if (disposable != null) {
- disposable!!.dispose()
- }
+ disposable?.dispose()
controller?.release()
controller = null
EventBus.getDefault().unregister(this)
@@ -277,14 +272,14 @@ class CoverFragment : Fragment() {
.apply(options)
if (displayedChapterIndex == -1 || media!!.getChapters().isEmpty() || media!!.getChapters()[displayedChapterIndex].imageUrl.isNullOrEmpty()) {
- cover.into(viewBinding!!.imgvCover)
+ cover.into(viewBinding.imgvCover)
} else {
Glide.with(this)
.load(EmbeddedChapterImage.getModelFor(media!!, displayedChapterIndex))
.apply(options)
.thumbnail(cover)
.error(cover)
- .into(viewBinding!!.imgvCover)
+ .into(viewBinding.imgvCover)
}
}
@@ -296,26 +291,26 @@ class CoverFragment : Fragment() {
private fun configureForOrientation(newConfig: Configuration) {
val isPortrait = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
- viewBinding!!.coverFragment.orientation = if (isPortrait) LinearLayout.VERTICAL else LinearLayout.HORIZONTAL
+ viewBinding.coverFragment.orientation = if (isPortrait) LinearLayout.VERTICAL else LinearLayout.HORIZONTAL
if (isPortrait) {
- viewBinding!!.coverHolder.layoutParams =
+ viewBinding.coverHolder.layoutParams =
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f)
- viewBinding!!.coverFragmentTextContainer.layoutParams =
+ viewBinding.coverFragmentTextContainer.layoutParams =
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
} else {
- viewBinding!!.coverHolder.layoutParams =
+ viewBinding.coverHolder.layoutParams =
LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f)
- viewBinding!!.coverFragmentTextContainer.layoutParams =
+ viewBinding.coverFragmentTextContainer.layoutParams =
LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f)
}
- (viewBinding!!.episodeDetails.parent as ViewGroup).removeView(viewBinding!!.episodeDetails)
+ (viewBinding.episodeDetails.parent as ViewGroup).removeView(viewBinding.episodeDetails)
if (isPortrait) {
- viewBinding!!.coverFragment.addView(viewBinding!!.episodeDetails)
+ viewBinding.coverFragment.addView(viewBinding.episodeDetails)
} else {
- viewBinding!!.coverFragmentTextContainer.addView(viewBinding!!.episodeDetails)
+ viewBinding.coverFragmentTextContainer.addView(viewBinding.episodeDetails)
}
}
@@ -326,7 +321,7 @@ class CoverFragment : Fragment() {
controller!!.playPause()
}
- private fun copyText(text: String): Boolean {
+ @UnstableApi private fun copyText(text: String): Boolean {
val clipboardManager: ClipboardManager? = ContextCompat.getSystemService(requireContext(), ClipboardManager::class.java)
clipboardManager?.setPrimaryClip(ClipData.newPlainText("PodVinci", text))
if (Build.VERSION.SDK_INT <= 32) {
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/DiscoveryFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/DiscoveryFragment.kt
index 3ad12842..9387f26b 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/DiscoveryFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/DiscoveryFragment.kt
@@ -38,17 +38,18 @@ import java.util.*
* Searches iTunes store for top podcasts and displays results in a list.
*/
class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
- private var prefs: SharedPreferences? = null
+ private lateinit var prefs: SharedPreferences
+ private lateinit var gridView: GridView
+ private lateinit var progressBar: ProgressBar
+ private lateinit var txtvError: TextView
+ private lateinit var butRetry: Button
+ private lateinit var txtvEmpty: TextView
+ private lateinit var toolbar: MaterialToolbar
/**
* Adapter responsible with the search results.
*/
private var adapter: ItunesAdapter? = null
- private var gridView: GridView? = null
- private var progressBar: ProgressBar? = null
- private var txtvError: TextView? = null
- private var butRetry: Button? = null
- private var txtvEmpty: TextView? = null
/**
* List of podcasts retreived from the search.
@@ -59,7 +60,7 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private var countryCode: String? = "US"
private var hidden = false
private var needsConfirm = false
- private var toolbar: MaterialToolbar? = null
+
/**
* Replace adapter data with provided search results from SearchTask.
@@ -68,28 +69,26 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
*/
private fun updateData(result: List?) {
this.searchResults = result
- adapter!!.clear()
- if (result != null && result.size > 0) {
- gridView!!.visibility = View.VISIBLE
- txtvEmpty!!.visibility = View.GONE
+ adapter?.clear()
+ if (!result.isNullOrEmpty()) {
+ gridView.visibility = View.VISIBLE
+ txtvEmpty.visibility = View.GONE
for (p in result) {
adapter!!.add(p)
}
- adapter!!.notifyDataSetInvalidated()
+ adapter?.notifyDataSetInvalidated()
} else {
- gridView!!.visibility = View.GONE
- txtvEmpty!!.visibility = View.VISIBLE
+ gridView.visibility = View.GONE
+ txtvEmpty.visibility = View.VISIBLE
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
prefs = requireActivity().getSharedPreferences(ItunesTopListLoader.PREFS, Context.MODE_PRIVATE)
- if (prefs != null) {
- countryCode = prefs!!.getString(ItunesTopListLoader.PREF_KEY_COUNTRY_CODE, Locale.getDefault().country)
- hidden = prefs!!.getBoolean(ItunesTopListLoader.PREF_KEY_HIDDEN_DISCOVERY_COUNTRY, false)
- needsConfirm = prefs!!.getBoolean(ItunesTopListLoader.PREF_KEY_NEEDS_CONFIRM, true)
- }
+ countryCode = prefs.getString(ItunesTopListLoader.PREF_KEY_COUNTRY_CODE, Locale.getDefault().country)
+ hidden = prefs.getBoolean(ItunesTopListLoader.PREF_KEY_HIDDEN_DISCOVERY_COUNTRY, false)
+ needsConfirm = prefs.getBoolean(ItunesTopListLoader.PREF_KEY_NEEDS_CONFIRM, true)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@@ -97,19 +96,18 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
val root = inflater.inflate(R.layout.fragment_itunes_search, container, false)
gridView = root.findViewById(R.id.gridView)
adapter = ItunesAdapter(requireActivity(), ArrayList())
- gridView?.setAdapter(adapter)
+ gridView.setAdapter(adapter)
toolbar = root.findViewById(R.id.toolbar)
- toolbar?.setNavigationOnClickListener(View.OnClickListener { v: View? -> parentFragmentManager.popBackStack() })
- toolbar?.inflateMenu(R.menu.countries_menu)
- if (toolbar != null) {
- val discoverHideItem = toolbar!!.getMenu().findItem(R.id.discover_hide_item)
- discoverHideItem.setChecked(hidden)
- }
- toolbar?.setOnMenuItemClickListener(this)
+ toolbar.setNavigationOnClickListener { v: View? -> parentFragmentManager.popBackStack() }
+ toolbar.inflateMenu(R.menu.countries_menu)
+ val discoverHideItem = toolbar.menu.findItem(R.id.discover_hide_item)
+ discoverHideItem.setChecked(hidden)
+
+ toolbar.setOnMenuItemClickListener(this)
//Show information about the podcast when the list item is clicked
- gridView?.setOnItemClickListener(OnItemClickListener { parent: AdapterView<*>?, view1: View?, position: Int, id: Long ->
+ gridView.onItemClickListener = OnItemClickListener { parent: AdapterView<*>?, view1: View?, position: Int, id: Long ->
val podcast = searchResults!![position]
if (podcast.feedUrl == null) {
return@OnItemClickListener
@@ -117,7 +115,7 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
val intent = Intent(activity, OnlineFeedViewActivity::class.java)
intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, podcast.feedUrl)
startActivity(intent)
- })
+ }
progressBar = root.findViewById(R.id.progressBar)
txtvError = root.findViewById(R.id.txtvError)
@@ -130,45 +128,42 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
override fun onDestroy() {
super.onDestroy()
- if (disposable != null) {
- disposable!!.dispose()
- }
+ disposable?.dispose()
+
adapter = null
}
private fun loadToplist(country: String?) {
- if (disposable != null) {
- disposable!!.dispose()
- }
+ disposable?.dispose()
- gridView!!.visibility = View.GONE
- txtvError!!.visibility = View.GONE
- butRetry!!.visibility = View.GONE
- butRetry!!.setText(R.string.retry_label)
- txtvEmpty!!.visibility = View.GONE
- progressBar!!.visibility = View.VISIBLE
+ gridView.visibility = View.GONE
+ txtvError.visibility = View.GONE
+ butRetry.visibility = View.GONE
+ butRetry.setText(R.string.retry_label)
+ txtvEmpty.visibility = View.GONE
+ progressBar.visibility = View.VISIBLE
if (hidden) {
- gridView!!.visibility = View.GONE
- txtvError!!.visibility = View.VISIBLE
- txtvError!!.text = resources.getString(R.string.discover_is_hidden)
- butRetry!!.visibility = View.GONE
- txtvEmpty!!.visibility = View.GONE
- progressBar!!.visibility = View.GONE
+ gridView.visibility = View.GONE
+ txtvError.visibility = View.VISIBLE
+ txtvError.text = resources.getString(R.string.discover_is_hidden)
+ butRetry.visibility = View.GONE
+ txtvEmpty.visibility = View.GONE
+ progressBar.visibility = View.GONE
return
}
if (BuildConfig.FLAVOR == "free" && needsConfirm) {
- txtvError!!.visibility = View.VISIBLE
- txtvError!!.text = ""
- butRetry!!.visibility = View.VISIBLE
- butRetry!!.setText(R.string.discover_confirm)
- butRetry!!.setOnClickListener { v: View? ->
- prefs!!.edit().putBoolean(ItunesTopListLoader.PREF_KEY_NEEDS_CONFIRM, false).apply()
+ txtvError.visibility = View.VISIBLE
+ txtvError.text = ""
+ butRetry.visibility = View.VISIBLE
+ butRetry.setText(R.string.discover_confirm)
+ butRetry.setOnClickListener { v: View? ->
+ prefs.edit().putBoolean(ItunesTopListLoader.PREF_KEY_NEEDS_CONFIRM, false).apply()
needsConfirm = false
loadToplist(country)
}
- txtvEmpty!!.visibility = View.GONE
- progressBar!!.visibility = View.GONE
+ txtvEmpty.visibility = View.GONE
+ progressBar.visibility = View.GONE
return
}
@@ -179,16 +174,16 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ podcasts: List? ->
- progressBar!!.visibility = View.GONE
+ progressBar.visibility = View.GONE
topList = podcasts
updateData(topList)
}, { error: Throwable ->
Log.e(TAG, Log.getStackTraceString(error))
- progressBar!!.visibility = View.GONE
- txtvError!!.text = error.message
- txtvError!!.visibility = View.VISIBLE
- butRetry!!.setOnClickListener { v: View? -> loadToplist(country) }
- butRetry!!.visibility = View.VISIBLE
+ progressBar.visibility = View.GONE
+ txtvError.text = error.message
+ txtvError.visibility = View.VISIBLE
+ butRetry.setOnClickListener { v: View? -> loadToplist(country) }
+ butRetry.visibility = View.VISIBLE
})
}
@@ -200,7 +195,7 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
if (itemId == R.id.discover_hide_item) {
item.setChecked(!item.isChecked)
hidden = item.isChecked
- prefs!!.edit().putBoolean(ItunesTopListLoader.PREF_KEY_HIDDEN_DISCOVERY_COUNTRY, hidden).apply()
+ prefs.edit().putBoolean(ItunesTopListLoader.PREF_KEY_HIDDEN_DISCOVERY_COUNTRY, hidden).apply()
EventBus.getDefault().post(DiscoveryDefaultUpdateEvent())
loadToplist(countryCode)
@@ -211,7 +206,7 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
val builder = MaterialAlertDialogBuilder(requireContext())
builder.setView(selectCountryDialogView)
- val countryCodeArray: List = ArrayList(Arrays.asList(*Locale.getISOCountries()))
+ val countryCodeArray: List = listOf(*Locale.getISOCountries())
val countryCodeNames: MutableMap = HashMap()
val countryNameCodes: MutableMap = HashMap()
for (code in countryCodeArray) {
@@ -221,8 +216,8 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
countryNameCodes[countryName] = code
}
- val countryNamesSort: List = ArrayList(countryCodeNames.values)
- Collections.sort(countryNamesSort)
+ val countryNamesSort: MutableList = ArrayList(countryCodeNames.values)
+ countryNamesSort.sort()
val dataAdapter =
ArrayAdapter(this.requireContext(), android.R.layout.simple_list_item_1, countryNamesSort)
@@ -231,7 +226,7 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
editText!!.setAdapter(dataAdapter)
editText.setText(countryCodeNames[countryCode])
editText.setOnClickListener { view: View? ->
- if (editText.text.length != 0) {
+ if (editText.text.isNotEmpty()) {
editText.setText("")
editText.postDelayed({ editText.showDropDown() }, 100)
}
@@ -247,13 +242,13 @@ class DiscoveryFragment : Fragment(), Toolbar.OnMenuItemClickListener {
val countryName = editText.text.toString()
if (countryNameCodes.containsKey(countryName)) {
countryCode = countryNameCodes[countryName]
- val discoverHideItem = toolbar!!.menu.findItem(R.id.discover_hide_item)
+ val discoverHideItem = toolbar.menu.findItem(R.id.discover_hide_item)
discoverHideItem.setChecked(false)
hidden = false
}
- prefs!!.edit().putBoolean(ItunesTopListLoader.PREF_KEY_HIDDEN_DISCOVERY_COUNTRY, hidden).apply()
- prefs!!.edit().putString(ItunesTopListLoader.PREF_KEY_COUNTRY_CODE, countryCode).apply()
+ prefs.edit().putBoolean(ItunesTopListLoader.PREF_KEY_HIDDEN_DISCOVERY_COUNTRY, hidden).apply()
+ prefs.edit().putString(ItunesTopListLoader.PREF_KEY_COUNTRY_CODE, countryCode).apply()
EventBus.getDefault().post(DiscoveryDefaultUpdateEvent())
loadToplist(countryCode)
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/DownloadLogFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/DownloadLogFragment.kt
index 2057655a..b6835665 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/DownloadLogFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/DownloadLogFragment.kt
@@ -28,10 +28,11 @@ import org.greenrobot.eventbus.Subscribe
* Shows the download log
*/
class DownloadLogFragment : BottomSheetDialogFragment(), OnItemClickListener, Toolbar.OnMenuItemClickListener {
+ private lateinit var viewBinding: DownloadLogFragmentBinding
+ private lateinit var adapter: DownloadLogAdapter
+
private var downloadLog: List = ArrayList()
- private var adapter: DownloadLogAdapter? = null
private var disposable: Disposable? = null
- private var viewBinding: DownloadLogFragmentBinding? = null
override fun onStart() {
super.onStart()
@@ -40,30 +41,28 @@ class DownloadLogFragment : BottomSheetDialogFragment(), OnItemClickListener, To
override fun onStop() {
super.onStop()
- if (disposable != null) {
- disposable!!.dispose()
- }
+ disposable?.dispose()
}
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View {
viewBinding = DownloadLogFragmentBinding.inflate(inflater)
- viewBinding!!.toolbar.inflateMenu(R.menu.download_log)
- viewBinding!!.toolbar.setOnMenuItemClickListener(this)
+ viewBinding.toolbar.inflateMenu(R.menu.download_log)
+ viewBinding.toolbar.setOnMenuItemClickListener(this)
val emptyView = EmptyViewHandler(activity)
emptyView.setIcon(R.drawable.ic_download)
emptyView.setTitle(R.string.no_log_downloads_head_label)
emptyView.setMessage(R.string.no_log_downloads_label)
- emptyView.attachToListView(viewBinding!!.list)
+ emptyView.attachToListView(viewBinding.list)
adapter = DownloadLogAdapter(requireActivity())
- viewBinding!!.list.adapter = adapter
- viewBinding!!.list.onItemClickListener = this
- viewBinding!!.list.isNestedScrollingEnabled = true
+ viewBinding.list.adapter = adapter
+ viewBinding.list.onItemClickListener = this
+ viewBinding.list.isNestedScrollingEnabled = true
EventBus.getDefault().register(this)
- return viewBinding!!.root
+ return viewBinding.root
}
override fun onDestroyView() {
@@ -72,7 +71,7 @@ class DownloadLogFragment : BottomSheetDialogFragment(), OnItemClickListener, To
}
override fun onItemClick(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
- val item = adapter!!.getItem(position)
+ val item = adapter.getItem(position)
if (item is DownloadResult) {
DownloadLogDetailsDialog(requireContext(), item).show()
}
@@ -98,16 +97,15 @@ class DownloadLogFragment : BottomSheetDialogFragment(), OnItemClickListener, To
}
private fun loadDownloadLog() {
- if (disposable != null) {
- disposable!!.dispose()
- }
+ disposable?.dispose()
+
disposable = Observable.fromCallable { DBReader.getDownloadLog() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ result: List? ->
if (result != null) {
downloadLog = result
- adapter!!.setDownloadLog(downloadLog)
+ adapter.setDownloadLog(downloadLog)
}
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/EpisodesListFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/EpisodesListFragment.kt
index 195675e1..f2c314aa 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/EpisodesListFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/EpisodesListFragment.kt
@@ -56,23 +56,20 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
protected var hasMoreItems: Boolean = false
private var displayUpArrow = false
- var recyclerView: EpisodeItemListRecyclerView? = null
- var listAdapter: EpisodeItemListAdapter? = null
- @JvmField
- var emptyView: EmptyViewHandler? = null
- @JvmField
- var speedDialView: SpeedDialView? = null
- @JvmField
- var toolbar: MaterialToolbar? = null
- var swipeRefreshLayout: SwipeRefreshLayout? = null
- var swipeActions: SwipeActions? = null
- private var progressBar: ProgressBar? = null
+ lateinit var recyclerView: EpisodeItemListRecyclerView
+ lateinit var emptyView: EmptyViewHandler
+ lateinit var speedDialView: SpeedDialView
+ lateinit var toolbar: MaterialToolbar
+ lateinit var swipeRefreshLayout: SwipeRefreshLayout
+ lateinit var swipeActions: SwipeActions
+ private lateinit var progressBar: ProgressBar
+ lateinit var listAdapter: EpisodeItemListAdapter
@JvmField
var episodes: MutableList = ArrayList()
protected var disposable: Disposable? = null
- protected var txtvInformation: TextView? = null
+ protected lateinit var txtvInformation: TextView
override fun onStart() {
super.onStart()
@@ -82,24 +79,22 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
override fun onResume() {
super.onResume()
- if (recyclerView != null) registerForContextMenu(recyclerView!!)
+ registerForContextMenu(recyclerView)
}
override fun onPause() {
super.onPause()
- if (getPrefName() != null) recyclerView?.saveScrollPosition(getPrefName())
- if (recyclerView != null) unregisterForContextMenu(recyclerView!!)
+ recyclerView.saveScrollPosition(getPrefName())
+ unregisterForContextMenu(recyclerView)
}
override fun onStop() {
super.onStop()
EventBus.getDefault().unregister(this)
- if (disposable != null) {
- disposable?.dispose()
- }
+ disposable?.dispose()
}
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ @UnstableApi override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (super.onOptionsItemSelected(item)) {
return true
}
@@ -116,17 +111,17 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
override fun onContextItemSelected(item: MenuItem): Boolean {
Log.d(TAG, "onContextItemSelected() called with: item = [$item]")
- if (listAdapter == null || !userVisibleHint || !isVisible || !isMenuVisible) {
+ if (!userVisibleHint || !isVisible || !isMenuVisible) {
// The method is called on all fragments in a ViewPager, so this needs to be ignored in invisible ones.
// Apparently, none of the visibility check method works reliably on its own, so we just use all.
return false
- } else if (listAdapter?.longPressedItem == null) {
+ } else if (listAdapter.longPressedItem == null) {
Log.i(TAG, "Selected item or listAdapter was null, ignoring selection")
return super.onContextItemSelected(item)
- } else if (listAdapter != null && listAdapter!!.onContextItemSelected(item)) {
+ } else if (listAdapter.onContextItemSelected(item)) {
return true
}
- val selectedItem: FeedItem = listAdapter!!.longPressedItem ?: return false
+ val selectedItem: FeedItem = listAdapter.longPressedItem ?: return false
return FeedItemMenuHandler.onMenuItemClicked(this, item.itemId, selectedItem)
}
@@ -135,36 +130,34 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
val root: View = inflater.inflate(R.layout.episodes_list_fragment, container, false)
txtvInformation = root.findViewById(R.id.txtvInformation)
toolbar = root.findViewById(R.id.toolbar)
- toolbar?.setOnMenuItemClickListener(this)
- toolbar?.setOnLongClickListener { v: View? ->
- recyclerView?.scrollToPosition(5)
- recyclerView?.post { recyclerView?.smoothScrollToPosition(0) }
+ toolbar.setOnMenuItemClickListener(this)
+ toolbar.setOnLongClickListener { v: View? ->
+ recyclerView.scrollToPosition(5)
+ recyclerView.post { recyclerView.smoothScrollToPosition(0) }
false
}
displayUpArrow = parentFragmentManager.backStackEntryCount != 0
if (savedInstanceState != null) {
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW)
}
- if (toolbar != null) (activity as MainActivity).setupToolbarToggle(toolbar!!, displayUpArrow)
+ (activity as MainActivity).setupToolbarToggle(toolbar, displayUpArrow)
recyclerView = root.findViewById(R.id.recyclerView)
- recyclerView?.setRecycledViewPool((activity as MainActivity).recycledViewPool)
+ recyclerView.setRecycledViewPool((activity as MainActivity).recycledViewPool)
setupLoadMoreScrollListener()
- recyclerView?.addOnScrollListener(LiftOnScrollListener(root.findViewById(R.id.appbar)))
+ recyclerView.addOnScrollListener(LiftOnScrollListener(root.findViewById(R.id.appbar)))
swipeActions = SwipeActions(this, getFragmentTag()).attachTo(recyclerView)
- swipeActions?.setFilter(getFilter())
-
- if (recyclerView != null) {
- val animator: RecyclerView.ItemAnimator? = recyclerView!!.itemAnimator
- if (animator is SimpleItemAnimator) {
- animator.supportsChangeAnimations = false
- }
+ swipeActions.setFilter(getFilter())
+
+ val animator: RecyclerView.ItemAnimator? = recyclerView.itemAnimator
+ if (animator is SimpleItemAnimator) {
+ animator.supportsChangeAnimations = false
}
swipeRefreshLayout = root.findViewById(R.id.swipeRefresh)
- swipeRefreshLayout?.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
- swipeRefreshLayout?.setOnRefreshListener {
+ swipeRefreshLayout.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
+ swipeRefreshLayout.setOnRefreshListener {
FeedUpdateManager.runOnceOrAsk(requireContext())
}
@@ -180,38 +173,38 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
}
}
}
- listAdapter?.setOnSelectModeListener(this)
- recyclerView?.adapter = listAdapter
+ listAdapter.setOnSelectModeListener(this)
+ recyclerView.adapter = listAdapter
progressBar = root.findViewById(R.id.progressBar)
- progressBar?.visibility = View.VISIBLE
+ progressBar.visibility = View.VISIBLE
emptyView = EmptyViewHandler(context)
- if (recyclerView != null) emptyView?.attachToRecyclerView(recyclerView!!)
- emptyView?.setIcon(R.drawable.ic_feed)
- emptyView?.setTitle(R.string.no_all_episodes_head_label)
- emptyView?.setMessage(R.string.no_all_episodes_label)
- emptyView?.updateAdapter(listAdapter)
- emptyView?.hide()
+ emptyView.attachToRecyclerView(recyclerView)
+ emptyView.setIcon(R.drawable.ic_feed)
+ emptyView.setTitle(R.string.no_all_episodes_head_label)
+ emptyView.setMessage(R.string.no_all_episodes_label)
+ emptyView.updateAdapter(listAdapter)
+ emptyView.hide()
speedDialView = root.findViewById(R.id.fabSD)
- speedDialView?.overlayLayout = root.findViewById(R.id.fabSDOverlay)
- speedDialView?.inflate(R.menu.episodes_apply_action_speeddial)
- speedDialView?.setOnChangeListener(object : SpeedDialView.OnChangeListener {
+ speedDialView.overlayLayout = root.findViewById(R.id.fabSDOverlay)
+ speedDialView.inflate(R.menu.episodes_apply_action_speeddial)
+ speedDialView.setOnChangeListener(object : SpeedDialView.OnChangeListener {
override fun onMainActionSelected(): Boolean {
return false
}
override fun onToggleChanged(open: Boolean) {
- if (open && listAdapter != null && listAdapter!!.selectedCount == 0) {
+ if (open && listAdapter.selectedCount == 0) {
(activity as MainActivity).showSnackbarAbovePlayer(R.string.no_items_selected,
Snackbar.LENGTH_SHORT)
- speedDialView?.close()
+ speedDialView.close()
}
}
})
- speedDialView?.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
+ speedDialView.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
var confirmationString = 0
- if (listAdapter != null && (listAdapter!!.selectedItems.size >= 25 || listAdapter!!.shouldSelectLazyLoadedItems())) {
+ if (listAdapter.selectedItems.size >= 25 || listAdapter.shouldSelectLazyLoadedItems()) {
// Should ask for confirmation
if (actionItem.id == R.id.mark_read_batch) {
confirmationString = R.string.multi_select_mark_played_confirmation
@@ -234,34 +227,32 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
return root
}
- private fun performMultiSelectAction(actionItemId: Int) {
+ @UnstableApi private fun performMultiSelectAction(actionItemId: Int) {
val handler =
EpisodeMultiSelectActionHandler((activity as MainActivity), actionItemId)
Completable.fromAction {
- if (listAdapter != null) {
- handler.handleAction(listAdapter!!.selectedItems.filterIsInstance())
- if (listAdapter!!.shouldSelectLazyLoadedItems()) {
- var applyPage = page + 1
- var nextPage: List
- do {
- nextPage = loadMoreData(applyPage)
- handler.handleAction(nextPage)
- applyPage++
- } while (nextPage.size == EPISODES_PER_PAGE)
- }
+ handler.handleAction(listAdapter.selectedItems.filterIsInstance())
+ if (listAdapter.shouldSelectLazyLoadedItems()) {
+ var applyPage = page + 1
+ var nextPage: List
+ do {
+ nextPage = loadMoreData(applyPage)
+ handler.handleAction(nextPage)
+ applyPage++
+ } while (nextPage.size == EPISODES_PER_PAGE)
}
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe({ listAdapter?.endSelectMode() },
+ .subscribe({ listAdapter.endSelectMode() },
{ error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
private fun setupLoadMoreScrollListener() {
- recyclerView?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
+ recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(view: RecyclerView, deltaX: Int, deltaY: Int) {
super.onScrolled(view, deltaX, deltaY)
- if (!isLoadingMore && hasMoreItems && recyclerView!!.isScrolledToBottom) {
+ if (!isLoadingMore && hasMoreItems && recyclerView.isScrolledToBottom) {
/* The end of the list has been reached. Load more data. */
page++
loadMoreItems()
@@ -272,12 +263,11 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
}
private fun loadMoreItems() {
- if (disposable != null) {
- disposable?.dispose()
- }
+ disposable?.dispose()
+
isLoadingMore = true
- listAdapter?.setDummyViews(1)
- listAdapter?.notifyItemInserted(listAdapter!!.itemCount - 1)
+ listAdapter.setDummyViews(1)
+ listAdapter.notifyItemInserted(listAdapter.itemCount - 1)
disposable = Observable.fromCallable { loadMoreData(page) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@@ -287,33 +277,33 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
hasMoreItems = false
}
episodes.addAll(data)
- listAdapter?.setDummyViews(0)
- listAdapter?.updateItems(episodes)
- if (listAdapter != null && listAdapter!!.shouldSelectLazyLoadedItems()) {
- listAdapter!!.setSelected(episodes.size - data.size, episodes.size, true)
+ listAdapter.setDummyViews(0)
+ listAdapter.updateItems(episodes)
+ if (listAdapter.shouldSelectLazyLoadedItems()) {
+ listAdapter.setSelected(episodes.size - data.size, episodes.size, true)
}
}, { error: Throwable? ->
- listAdapter?.setDummyViews(0)
- listAdapter?.updateItems(emptyList())
+ listAdapter.setDummyViews(0)
+ listAdapter.updateItems(emptyList())
Log.e(TAG, Log.getStackTraceString(error))
}, {
// Make sure to not always load 2 pages at once
- recyclerView?.post { isLoadingMore = false }
+ recyclerView.post { isLoadingMore = false }
})
}
override fun onDestroyView() {
super.onDestroyView()
- listAdapter?.endSelectMode()
+ listAdapter.endSelectMode()
}
override fun onStartSelectMode() {
- speedDialView?.visibility = View.VISIBLE
+ speedDialView.visibility = View.VISIBLE
}
override fun onEndSelectMode() {
- speedDialView?.close()
- speedDialView?.visibility = View.GONE
+ speedDialView.close()
+ speedDialView.visibility = View.GONE
}
@Subscribe(threadMode = ThreadMode.MAIN)
@@ -325,9 +315,9 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
episodes.removeAt(pos)
if (getFilter().matches(item)) {
episodes.add(pos, item)
- listAdapter?.notifyItemChangedCompat(pos)
+ listAdapter.notifyItemChangedCompat(pos)
} else {
- listAdapter?.notifyItemRemoved(pos)
+ listAdapter.notifyItemRemoved(pos)
}
}
}
@@ -335,11 +325,9 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
@UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: PlaybackPositionEvent) {
- if (listAdapter == null) return
- for (i in 0 until listAdapter!!.itemCount) {
- val holder: EpisodeItemViewHolder =
- recyclerView?.findViewHolderForAdapterPosition(i) as EpisodeItemViewHolder
- if (holder != null && holder.isCurrentlyPlayingItem) {
+ for (i in 0 until listAdapter.itemCount) {
+ val holder: EpisodeItemViewHolder = recyclerView.findViewHolderForAdapterPosition(i) as EpisodeItemViewHolder
+ if (holder.isCurrentlyPlayingItem) {
holder.notifyPlaybackPositionUpdated(event)
break
}
@@ -352,8 +340,8 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
return
}
when (event.keyCode) {
- KeyEvent.KEYCODE_T -> recyclerView?.smoothScrollToPosition(0)
- KeyEvent.KEYCODE_B -> recyclerView?.smoothScrollToPosition(listAdapter?.itemCount ?: (0 - 1))
+ KeyEvent.KEYCODE_T -> recyclerView.smoothScrollToPosition(0)
+ KeyEvent.KEYCODE_B -> recyclerView.smoothScrollToPosition(listAdapter.itemCount)
else -> {}
}
}
@@ -363,7 +351,7 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
for (downloadUrl in event.urls) {
val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(episodes, downloadUrl)
if (pos >= 0) {
- listAdapter?.notifyItemChangedCompat(pos)
+ listAdapter.notifyItemChangedCompat(pos)
}
}
}
@@ -397,17 +385,17 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
val restoreScrollPosition = episodes.isEmpty()
episodes = data.first
hasMoreItems = !(page == 1 && episodes.size < EPISODES_PER_PAGE)
- progressBar?.visibility = View.GONE
- listAdapter?.setDummyViews(0)
- listAdapter?.updateItems(episodes)
- listAdapter?.setTotalNumberOfItems(data.second)
- if (restoreScrollPosition && getPrefName() != null) {
- recyclerView?.restoreScrollPosition(getPrefName())
+ progressBar.visibility = View.GONE
+ listAdapter.setDummyViews(0)
+ listAdapter.updateItems(episodes)
+ listAdapter.setTotalNumberOfItems(data.second)
+ if (restoreScrollPosition) {
+ recyclerView.restoreScrollPosition(getPrefName())
}
updateToolbar()
}, { error: Throwable? ->
- listAdapter?.setDummyViews(0)
- listAdapter?.updateItems(emptyList())
+ listAdapter.setDummyViews(0)
+ listAdapter.updateItems(emptyList())
Log.e(TAG, Log.getStackTraceString(error))
})
}
@@ -429,7 +417,7 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: FeedUpdateRunningEvent) {
- swipeRefreshLayout?.isRefreshing = event.isFeedUpdateRunning
+ swipeRefreshLayout.isRefreshing = event.isFeedUpdateRunning
}
override fun onSaveInstanceState(outState: Bundle) {
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/ExternalPlayerFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/ExternalPlayerFragment.kt
index c1ac81a5..4bf2a243 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/ExternalPlayerFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/ExternalPlayerFragment.kt
@@ -37,11 +37,12 @@ import org.greenrobot.eventbus.ThreadMode
* Fragment which is supposed to be displayed outside of the MediaplayerActivity.
*/
class ExternalPlayerFragment : Fragment() {
- private var imgvCover: ImageView? = null
- private var txtvTitle: TextView? = null
- private var butPlay: PlayButton? = null
- private var feedName: TextView? = null
- private var progressBar: ProgressBar? = null
+ private lateinit var imgvCover: ImageView
+ private lateinit var txtvTitle: TextView
+ private lateinit var butPlay: PlayButton
+ private lateinit var feedName: TextView
+ private lateinit var progressBar: ProgressBar
+
private var controller: PlaybackController? = null
private var disposable: Disposable? = null
@@ -73,7 +74,7 @@ class ExternalPlayerFragment : Fragment() {
@UnstableApi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- butPlay!!.setOnClickListener { v: View? ->
+ butPlay.setOnClickListener { v: View? ->
if (controller == null) {
return@setOnClickListener
}
@@ -91,7 +92,7 @@ class ExternalPlayerFragment : Fragment() {
private fun setupPlaybackController(): PlaybackController {
return object : PlaybackController(activity) {
override fun updatePlayButtonShowsPlay(showPlay: Boolean) {
- butPlay!!.setIsShowPlay(showPlay)
+ butPlay.setIsShowPlay(showPlay)
}
override fun loadMediaInfo() {
@@ -116,10 +117,9 @@ class ExternalPlayerFragment : Fragment() {
@UnstableApi
override fun onStop() {
super.onStop()
- if (controller != null) {
- controller!!.release()
- controller = null
- }
+ controller?.release()
+ controller = null
+
EventBus.getDefault().unregister(this)
}
@@ -132,10 +132,10 @@ class ExternalPlayerFragment : Fragment() {
|| controller!!.duration == Playable.INVALID_TIME) {
return
}
- progressBar!!.progress = (controller!!.position.toDouble() / controller!!.duration * 100).toInt()
+ progressBar.progress = (controller!!.position.toDouble() / controller!!.duration * 100).toInt()
}
- @Subscribe(threadMode = ThreadMode.MAIN)
+ @UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
fun onPlaybackServiceChanged(event: PlaybackServiceEvent) {
if (event.action == PlaybackServiceEvent.Action.SERVICE_SHUT_DOWN) {
(activity as MainActivity).setPlayerVisible(false)
@@ -145,17 +145,14 @@ class ExternalPlayerFragment : Fragment() {
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "Fragment is about to be destroyed")
- if (disposable != null) {
- disposable!!.dispose()
- }
+ disposable?.dispose()
+
}
@UnstableApi
override fun onPause() {
super.onPause()
- if (controller != null) {
- controller!!.pause()
- }
+ controller?.pause()
}
@UnstableApi
@@ -166,9 +163,7 @@ class ExternalPlayerFragment : Fragment() {
return
}
- if (disposable != null) {
- disposable!!.dispose()
- }
+ disposable?.dispose()
disposable = Maybe.fromCallable { controller!!.getMedia() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@@ -183,8 +178,8 @@ class ExternalPlayerFragment : Fragment() {
return
}
(activity as MainActivity).setPlayerVisible(true)
- txtvTitle!!.text = media.getEpisodeTitle()
- feedName!!.text = media.getFeedTitle()
+ txtvTitle.text = media.getEpisodeTitle()
+ feedName.text = media.getFeedTitle()
onPositionObserverUpdate(PlaybackPositionEvent(media.getPosition(), media.getDuration()))
val options = RequestOptions()
@@ -199,13 +194,13 @@ class ExternalPlayerFragment : Fragment() {
.load(getFallbackImageLocation(media))
.apply(options))
.apply(options)
- .into(imgvCover!!)
+ .into(imgvCover)
if (controller != null && controller!!.isPlayingVideoLocally) {
(activity as MainActivity).bottomSheet?.setLocked(true)
(activity as MainActivity).bottomSheet?.setState(BottomSheetBehavior.STATE_COLLAPSED)
} else {
- butPlay!!.visibility = View.VISIBLE
+ butPlay.visibility = View.VISIBLE
(activity as MainActivity).bottomSheet?.setLocked(false)
}
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/FeedInfoFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/FeedInfoFragment.kt
index 61f8e068..6d082bb1 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/FeedInfoFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/FeedInfoFragment.kt
@@ -62,17 +62,18 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private var feed: Feed? = null
private var disposable: Disposable? = null
- private var imgvCover: ImageView? = null
- private var txtvTitle: TextView? = null
- private var txtvDescription: TextView? = null
- private var txtvFundingUrl: TextView? = null
- private var lblSupport: TextView? = null
- private var txtvUrl: TextView? = null
- private var txtvAuthorHeader: TextView? = null
- private var imgvBackground: ImageView? = null
- private var infoContainer: View? = null
- private var header: View? = null
- private var toolbar: MaterialToolbar? = null
+
+ private lateinit var imgvCover: ImageView
+ private lateinit var txtvTitle: TextView
+ private lateinit var txtvDescription: TextView
+ private lateinit var txtvFundingUrl: TextView
+ private lateinit var lblSupport: TextView
+ private lateinit var txtvUrl: TextView
+ private lateinit var txtvAuthorHeader: TextView
+ private lateinit var imgvBackground: ImageView
+ private lateinit var infoContainer: View
+ private lateinit var header: View
+ private lateinit var toolbar: MaterialToolbar
private val copyUrlToClipboard = View.OnClickListener {
if (feed != null && feed!!.download_url != null) {
@@ -91,28 +92,26 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
): View {
val root: View = inflater.inflate(R.layout.feedinfo, null)
toolbar = root.findViewById(R.id.toolbar)
- toolbar?.title = ""
- toolbar?.inflateMenu(R.menu.feedinfo)
- toolbar?.setNavigationOnClickListener { v: View? -> parentFragmentManager.popBackStack() }
- toolbar?.setOnMenuItemClickListener(this)
+ toolbar.title = ""
+ toolbar.inflateMenu(R.menu.feedinfo)
+ toolbar.setNavigationOnClickListener { v: View? -> parentFragmentManager.popBackStack() }
+ toolbar.setOnMenuItemClickListener(this)
refreshToolbarState()
val appBar: AppBarLayout = root.findViewById(R.id.appBar)
- val collapsingToolbar: CollapsingToolbarLayout =
- root.findViewById(R.id.collapsing_toolbar)
- if (toolbar != null) {
- val iconTintManager: ToolbarIconTintManager =
- object : ToolbarIconTintManager(requireContext(), toolbar!!, collapsingToolbar) {
- override fun doTint(themedContext: Context?) {
- toolbar!!.menu.findItem(R.id.visit_website_item)
- .setIcon(AppCompatResources.getDrawable(themedContext!!, R.drawable.ic_web))
- toolbar!!.menu.findItem(R.id.share_item)
- .setIcon(AppCompatResources.getDrawable(themedContext, R.drawable.ic_share))
- }
+ val collapsingToolbar: CollapsingToolbarLayout = root.findViewById(R.id.collapsing_toolbar)
+ val iconTintManager: ToolbarIconTintManager =
+ object : ToolbarIconTintManager(requireContext(), toolbar, collapsingToolbar) {
+ override fun doTint(themedContext: Context?) {
+ toolbar.menu.findItem(R.id.visit_website_item)
+ .setIcon(AppCompatResources.getDrawable(themedContext!!, R.drawable.ic_web))
+ toolbar.menu.findItem(R.id.share_item)
+ .setIcon(AppCompatResources.getDrawable(themedContext, R.drawable.ic_share))
}
- iconTintManager.updateTint()
- appBar.addOnOffsetChangedListener(iconTintManager)
- }
+ }
+ iconTintManager.updateTint()
+ appBar.addOnOffsetChangedListener(iconTintManager)
+
imgvCover = root.findViewById(R.id.imgvCover)
txtvTitle = root.findViewById(R.id.txtvTitle)
txtvAuthorHeader = root.findViewById(R.id.txtvAuthor)
@@ -123,14 +122,14 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
root.findViewById(R.id.butShowSettings).visibility = View.INVISIBLE
root.findViewById(R.id.butFilter).visibility = View.INVISIBLE
// https://github.com/bumptech/glide/issues/529
- imgvBackground?.colorFilter = LightingColorFilter(-0x7d7d7e, 0x000000)
+ imgvBackground.colorFilter = LightingColorFilter(-0x7d7d7e, 0x000000)
txtvDescription = root.findViewById(R.id.txtvDescription)
txtvUrl = root.findViewById(R.id.txtvUrl)
lblSupport = root.findViewById(R.id.lblSupport)
txtvFundingUrl = root.findViewById(R.id.txtvFundingUrl)
- txtvUrl?.setOnClickListener(copyUrlToClipboard)
+ txtvUrl.setOnClickListener(copyUrlToClipboard)
val feedId = requireArguments().getLong(EXTRA_FEED_ID)
parentFragmentManager.beginTransaction().replace(R.id.statisticsFragmentContainer,
@@ -165,13 +164,10 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
- if (header == null || infoContainer == null) {
- return
- }
val horizontalSpacing = resources.getDimension(R.dimen.additional_horizontal_spacing).toInt()
- header!!.setPadding(horizontalSpacing, header!!.paddingTop, horizontalSpacing, header!!.paddingBottom)
- infoContainer!!.setPadding(horizontalSpacing, infoContainer!!.paddingTop,
- horizontalSpacing, infoContainer!!.paddingBottom)
+ header.setPadding(horizontalSpacing, header.paddingTop, horizontalSpacing, header.paddingBottom)
+ infoContainer.setPadding(horizontalSpacing, infoContainer.paddingTop,
+ horizontalSpacing, infoContainer.paddingBottom)
}
private fun showFeed() {
@@ -179,42 +175,42 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
Log.d(TAG, "Language is " + feed!!.language)
Log.d(TAG, "Author is " + feed!!.author)
Log.d(TAG, "URL is " + feed!!.download_url)
- if (imgvCover != null) Glide.with(this)
+ Glide.with(this)
.load(feed!!.imageUrl)
.apply(RequestOptions()
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.fitCenter()
.dontAnimate())
- .into(imgvCover!!)
- if (imgvBackground != null) Glide.with(this)
+ .into(imgvCover)
+ Glide.with(this)
.load(feed!!.imageUrl)
.apply(RequestOptions()
.placeholder(R.color.image_readability_tint)
.error(R.color.image_readability_tint)
.transform(FastBlurTransformation())
.dontAnimate())
- .into(imgvBackground!!)
+ .into(imgvBackground)
- txtvTitle?.text = feed!!.title
- txtvTitle?.setMaxLines(6)
+ txtvTitle.text = feed!!.title
+ txtvTitle.setMaxLines(6)
val description: String = HtmlToPlainText.getPlainText(feed!!.description)?:""
- txtvDescription?.text = description
+ txtvDescription.text = description
- if (!TextUtils.isEmpty(feed!!.author)) {
- txtvAuthorHeader?.text = feed!!.author
+ if (!feed!!.author.isNullOrEmpty()) {
+ txtvAuthorHeader.text = feed!!.author
}
- txtvUrl?.text = feed!!.download_url
- txtvUrl?.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_paperclip, 0)
+ txtvUrl.text = feed!!.download_url
+ txtvUrl.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_paperclip, 0)
if (feed!!.paymentLinks.isEmpty()) {
- lblSupport?.visibility = View.GONE
- txtvFundingUrl?.visibility = View.GONE
+ lblSupport.visibility = View.GONE
+ txtvFundingUrl.visibility = View.GONE
} else {
- lblSupport?.visibility = View.VISIBLE
+ lblSupport.visibility = View.VISIBLE
val fundingList: ArrayList = feed!!.paymentLinks
// Filter for duplicates, but keep items in the order that they have in the feed.
@@ -238,7 +234,7 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
str.append("\n")
}
str = StringBuilder(StringUtils.trim(str.toString()))
- txtvFundingUrl?.text = str.toString()
+ txtvFundingUrl.text = str.toString()
}
refreshToolbarState()
@@ -250,12 +246,12 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
private fun refreshToolbarState() {
- toolbar?.menu?.findItem(R.id.reconnect_local_folder)?.setVisible(feed != null && feed!!.isLocalFeed)
- toolbar?.menu?.findItem(R.id.share_item)?.setVisible(feed != null && !feed!!.isLocalFeed)
- toolbar?.menu?.findItem(R.id.visit_website_item)
+ toolbar.menu?.findItem(R.id.reconnect_local_folder)?.setVisible(feed != null && feed!!.isLocalFeed)
+ toolbar.menu?.findItem(R.id.share_item)?.setVisible(feed != null && !feed!!.isLocalFeed)
+ toolbar.menu?.findItem(R.id.visit_website_item)
?.setVisible(feed != null && feed!!.link != null && IntentUtils.isCallable(requireContext(),
Intent(Intent.ACTION_VIEW, Uri.parse(feed!!.link))))
- toolbar?.menu?.findItem(R.id.edit_feed_url_item)?.setVisible(feed != null && !feed!!.isLocalFeed)
+ toolbar.menu?.findItem(R.id.edit_feed_url_item)?.setVisible(feed != null && !feed!!.isLocalFeed)
}
override fun onMenuItemClick(item: MenuItem): Boolean {
@@ -264,33 +260,39 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
R.string.please_wait_for_data, Toast.LENGTH_LONG)
return false
}
- if (item.itemId == R.id.visit_website_item) {
- if (feed!!.link != null) IntentUtils.openInBrowser(requireContext(), feed!!.link!!)
- } else if (item.itemId == R.id.share_item) {
- ShareUtils.shareFeedLink(requireContext(), feed!!)
- } else if (item.itemId == R.id.reconnect_local_folder) {
- val alert = MaterialAlertDialogBuilder(requireContext())
- alert.setMessage(R.string.reconnect_local_folder_warning)
- alert.setPositiveButton(string.ok
- ) { dialog: DialogInterface?, which: Int ->
- try {
- addLocalFolderLauncher.launch(null)
- } catch (e: ActivityNotFoundException) {
- Log.e(TAG, "No activity found. Should never happen...")
- }
+ when (item.itemId) {
+ R.id.visit_website_item -> {
+ if (feed!!.link != null) IntentUtils.openInBrowser(requireContext(), feed!!.link!!)
+ }
+ R.id.share_item -> {
+ ShareUtils.shareFeedLink(requireContext(), feed!!)
}
- alert.setNegativeButton(string.cancel, null)
- alert.show()
- } else if (item.itemId == R.id.edit_feed_url_item) {
- object : EditUrlSettingsDialog(activity as Activity, feed!!) {
- override fun setUrl(url: String?) {
- feed!!.download_url = url
- txtvUrl?.text = feed!!.download_url
- txtvUrl?.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_paperclip, 0)
+ R.id.reconnect_local_folder -> {
+ val alert = MaterialAlertDialogBuilder(requireContext())
+ alert.setMessage(R.string.reconnect_local_folder_warning)
+ alert.setPositiveButton(string.ok
+ ) { dialog: DialogInterface?, which: Int ->
+ try {
+ addLocalFolderLauncher.launch(null)
+ } catch (e: ActivityNotFoundException) {
+ Log.e(TAG, "No activity found. Should never happen...")
+ }
}
- }.show()
- } else {
- return false
+ alert.setNegativeButton(string.cancel, null)
+ alert.show()
+ }
+ R.id.edit_feed_url_item -> {
+ object : EditUrlSettingsDialog(activity as Activity, feed!!) {
+ override fun setUrl(url: String?) {
+ feed!!.download_url = url
+ txtvUrl.text = feed!!.download_url
+ txtvUrl.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_paperclip, 0)
+ }
+ }.show()
+ }
+ else -> {
+ return false
+ }
}
return true
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/FeedItemlistFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/FeedItemlistFragment.kt
index 6b95cc88..67cb4567 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/FeedItemlistFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/FeedItemlistFragment.kt
@@ -69,16 +69,18 @@ import java.util.concurrent.ExecutionException
*/
class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolbar.OnMenuItemClickListener,
SelectableAdapter.OnSelectModeListener {
- private var adapter: FeedItemListAdapter? = null
- private var swipeActions: SwipeActions? = null
- private var nextPageLoader: MoreContentListFooterUtil? = null
+
+ private lateinit var adapter: FeedItemListAdapter
+ private lateinit var swipeActions: SwipeActions
+ private lateinit var viewBinding: FeedItemListFragmentBinding
+ private lateinit var speedDialBinding: MultiSelectSpeedDialBinding
+ private lateinit var nextPageLoader: MoreContentListFooterUtil
+
private var displayUpArrow = false
private var feedID: Long = 0
private var feed: Feed? = null
private var headerCreated = false
private var disposable: Disposable? = null
- private var viewBinding: FeedItemListFragmentBinding? = null
- private var speedDialBinding: MultiSelectSpeedDialBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -91,65 +93,65 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
savedInstanceState: Bundle?
): View {
viewBinding = FeedItemListFragmentBinding.inflate(inflater)
- speedDialBinding = MultiSelectSpeedDialBinding.bind(viewBinding!!.root)
- viewBinding!!.toolbar.inflateMenu(R.menu.feedlist)
- viewBinding!!.toolbar.setOnMenuItemClickListener(this)
- viewBinding!!.toolbar.setOnLongClickListener { v: View? ->
- viewBinding!!.recyclerView.scrollToPosition(5)
- viewBinding!!.recyclerView.post { viewBinding!!.recyclerView.smoothScrollToPosition(0) }
- viewBinding!!.appBar.setExpanded(true)
+ speedDialBinding = MultiSelectSpeedDialBinding.bind(viewBinding.root)
+ viewBinding.toolbar.inflateMenu(R.menu.feedlist)
+ viewBinding.toolbar.setOnMenuItemClickListener(this)
+ viewBinding.toolbar.setOnLongClickListener { v: View? ->
+ viewBinding.recyclerView.scrollToPosition(5)
+ viewBinding.recyclerView.post { viewBinding.recyclerView.smoothScrollToPosition(0) }
+ viewBinding.appBar.setExpanded(true)
false
}
displayUpArrow = parentFragmentManager.backStackEntryCount != 0
if (savedInstanceState != null) {
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW)
}
- (activity as MainActivity).setupToolbarToggle(viewBinding!!.toolbar, displayUpArrow)
+ (activity as MainActivity).setupToolbarToggle(viewBinding.toolbar, displayUpArrow)
updateToolbar()
- viewBinding!!.recyclerView.setRecycledViewPool((activity as MainActivity).recycledViewPool)
+ viewBinding.recyclerView.setRecycledViewPool((activity as MainActivity).recycledViewPool)
adapter = FeedItemListAdapter(activity as MainActivity)
- adapter?.setOnSelectModeListener(this)
- viewBinding!!.recyclerView.adapter = adapter
- swipeActions = SwipeActions(this, TAG).attachTo(viewBinding!!.recyclerView)
- viewBinding!!.progressBar.visibility = View.VISIBLE
+ adapter.setOnSelectModeListener(this)
+ viewBinding.recyclerView.adapter = adapter
+ swipeActions = SwipeActions(this, TAG).attachTo(viewBinding.recyclerView)
+ viewBinding.progressBar.visibility = View.VISIBLE
val iconTintManager: ToolbarIconTintManager = object : ToolbarIconTintManager(
- requireContext(), viewBinding!!.toolbar, viewBinding!!.collapsingToolbar) {
+ requireContext(), viewBinding.toolbar, viewBinding.collapsingToolbar) {
override fun doTint(themedContext: Context?) {
- viewBinding!!.toolbar.menu.findItem(R.id.refresh_item)
+ viewBinding.toolbar.menu.findItem(R.id.refresh_item)
.setIcon(AppCompatResources.getDrawable(themedContext!!, R.drawable.ic_refresh))
- viewBinding!!.toolbar.menu.findItem(R.id.action_search)
+ viewBinding.toolbar.menu.findItem(R.id.action_search)
.setIcon(AppCompatResources.getDrawable(themedContext, R.drawable.ic_search))
}
}
iconTintManager.updateTint()
- viewBinding!!.appBar.addOnOffsetChangedListener(iconTintManager)
+ viewBinding.appBar.addOnOffsetChangedListener(iconTintManager)
- nextPageLoader = MoreContentListFooterUtil(viewBinding!!.moreContent.moreContentListFooter)
- nextPageLoader?.setClickListener(object : MoreContentListFooterUtil.Listener {
+ nextPageLoader = MoreContentListFooterUtil(viewBinding.moreContent.moreContentListFooter)
+ nextPageLoader.setClickListener(object : MoreContentListFooterUtil.Listener {
override fun onClick() {
if (feed != null) {
FeedUpdateManager.runOnce(context, feed, true)
}
}
})
- viewBinding!!.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
+ viewBinding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(view: RecyclerView, deltaX: Int, deltaY: Int) {
super.onScrolled(view, deltaX, deltaY)
val hasMorePages = feed != null && feed!!.isPaged && feed!!.nextPageLink != null
- val pageLoaderVisible = viewBinding!!.recyclerView.isScrolledToBottom && hasMorePages
- nextPageLoader?.root?.visibility = if (pageLoaderVisible) View.VISIBLE else View.GONE
- viewBinding!!.recyclerView.setPadding(
- viewBinding!!.recyclerView.paddingLeft, 0, viewBinding!!.recyclerView.paddingRight,
- if (pageLoaderVisible && nextPageLoader != null) nextPageLoader!!.root.measuredHeight else 0)
+ val pageLoaderVisible = viewBinding.recyclerView.isScrolledToBottom && hasMorePages
+ nextPageLoader.root.visibility = if (pageLoaderVisible) View.VISIBLE else View.GONE
+ viewBinding.recyclerView.setPadding(
+ viewBinding.recyclerView.paddingLeft, 0, viewBinding.recyclerView.paddingRight,
+ if (pageLoaderVisible) nextPageLoader.root.measuredHeight else 0)
}
})
EventBus.getDefault().register(this)
- viewBinding!!.swipeRefresh.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
- viewBinding!!.swipeRefresh.setOnRefreshListener {
+ viewBinding.swipeRefresh.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
+ viewBinding.swipeRefresh.setOnRefreshListener {
FeedUpdateManager.runOnceOrAsk(requireContext(),
feed)
}
@@ -157,28 +159,28 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
loadItems()
// Init action UI (via a FAB Speed Dial)
- speedDialBinding!!.fabSD.overlayLayout = speedDialBinding!!.fabSDOverlay
- speedDialBinding!!.fabSD.inflate(R.menu.episodes_apply_action_speeddial)
- speedDialBinding!!.fabSD.setOnChangeListener(object : SpeedDialView.OnChangeListener {
+ speedDialBinding.fabSD.overlayLayout = speedDialBinding.fabSDOverlay
+ speedDialBinding.fabSD.inflate(R.menu.episodes_apply_action_speeddial)
+ speedDialBinding.fabSD.setOnChangeListener(object : SpeedDialView.OnChangeListener {
override fun onMainActionSelected(): Boolean {
return false
}
override fun onToggleChanged(open: Boolean) {
- if (open && adapter!!.selectedCount == 0) {
+ if (open && adapter.selectedCount == 0) {
(activity as MainActivity).showSnackbarAbovePlayer(R.string.no_items_selected,
Snackbar.LENGTH_SHORT)
- speedDialBinding!!.fabSD.close()
+ speedDialBinding.fabSD.close()
}
}
})
- speedDialBinding!!.fabSD.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
+ speedDialBinding.fabSD.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
EpisodeMultiSelectActionHandler((activity as MainActivity), actionItem.id)
- .handleAction(adapter!!.selectedItems.filterIsInstance())
- adapter?.endSelectMode()
+ .handleAction(adapter.selectedItems.filterIsInstance())
+ adapter.endSelectMode()
true
}
- return viewBinding!!.root
+ return viewBinding.root
}
override fun onDestroyView() {
@@ -186,7 +188,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
EventBus.getDefault().unregister(this)
disposable?.dispose()
- adapter?.endSelectMode()
+ adapter.endSelectMode()
}
override fun onSaveInstanceState(outState: Bundle) {
@@ -198,22 +200,22 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
if (feed == null) {
return
}
- viewBinding!!.toolbar.menu.findItem(R.id.visit_website_item).setVisible(feed!!.link != null)
- viewBinding!!.toolbar.menu.findItem(R.id.refresh_complete_item).setVisible(feed!!.isPaged)
+ viewBinding.toolbar.menu.findItem(R.id.visit_website_item).setVisible(feed!!.link != null)
+ viewBinding.toolbar.menu.findItem(R.id.refresh_complete_item).setVisible(feed!!.isPaged)
if (StringUtils.isBlank(feed!!.link)) {
- viewBinding!!.toolbar.menu.findItem(R.id.visit_website_item).setVisible(false)
+ viewBinding.toolbar.menu.findItem(R.id.visit_website_item).setVisible(false)
}
if (feed!!.isLocalFeed) {
- viewBinding!!.toolbar.menu.findItem(R.id.share_item).setVisible(false)
+ viewBinding.toolbar.menu.findItem(R.id.share_item).setVisible(false)
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
val horizontalSpacing = resources.getDimension(R.dimen.additional_horizontal_spacing).toInt()
- viewBinding!!.header.headerContainer.setPadding(
- horizontalSpacing, viewBinding!!.header.headerContainer.paddingTop,
- horizontalSpacing, viewBinding!!.header.headerContainer.paddingBottom)
+ viewBinding.header.headerContainer.setPadding(
+ horizontalSpacing, viewBinding.header.headerContainer.paddingTop,
+ horizontalSpacing, viewBinding.header.headerContainer.paddingBottom)
}
@UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
@@ -270,12 +272,12 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
}
override fun onContextItemSelected(item: MenuItem): Boolean {
- val selectedItem: FeedItem? = adapter!!.longPressedItem
+ val selectedItem: FeedItem? = adapter.longPressedItem
if (selectedItem == null) {
Log.i(TAG, "Selected item at current position was null, ignoring selection")
return super.onContextItemSelected(item)
}
- if (adapter!!.onContextItemSelected(item)) {
+ if (adapter.onContextItemSelected(item)) {
return true
}
return FeedItemMenuHandler.onMenuItemClicked(this, item.itemId, selectedItem)
@@ -311,7 +313,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
if (pos >= 0) {
feed?.items?.removeAt(pos)
feed?.items?.add(pos, item)
- adapter?.notifyItemChangedCompat(pos)
+ adapter.notifyItemChangedCompat(pos)
}
i++
}
@@ -325,16 +327,16 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
for (downloadUrl in event.urls) {
val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(feed!!.items, downloadUrl)
if (pos >= 0) {
- adapter?.notifyItemChangedCompat(pos)
+ adapter.notifyItemChangedCompat(pos)
}
}
}
@UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: PlaybackPositionEvent) {
- for (i in 0 until adapter!!.itemCount) {
+ for (i in 0 until adapter.itemCount) {
val holder: EpisodeItemViewHolder? =
- viewBinding!!.recyclerView.findViewHolderForAdapterPosition(i) as EpisodeItemViewHolder?
+ viewBinding.recyclerView.findViewHolderForAdapterPosition(i) as EpisodeItemViewHolder?
if (holder != null && holder.isCurrentlyPlayingItem) {
holder.notifyPlaybackPositionUpdated(event)
break
@@ -355,19 +357,19 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
}
override fun onStartSelectMode() {
- swipeActions?.detach()
+ swipeActions.detach()
if (feed != null && feed!!.isLocalFeed) {
- speedDialBinding!!.fabSD.removeActionItemById(R.id.download_batch)
+ speedDialBinding.fabSD.removeActionItemById(R.id.download_batch)
}
- speedDialBinding!!.fabSD.removeActionItemById(R.id.remove_all_inbox_item)
- speedDialBinding!!.fabSD.visibility = View.VISIBLE
+ speedDialBinding.fabSD.removeActionItemById(R.id.remove_all_inbox_item)
+ speedDialBinding.fabSD.visibility = View.VISIBLE
updateToolbar()
}
override fun onEndSelectMode() {
- speedDialBinding!!.fabSD.close()
- speedDialBinding!!.fabSD.visibility = View.GONE
- swipeActions?.attachTo(viewBinding!!.recyclerView)
+ speedDialBinding.fabSD.close()
+ speedDialBinding.fabSD.visibility = View.GONE
+ swipeActions.attachTo(viewBinding.recyclerView)
}
@UnstableApi private fun updateUi() {
@@ -396,51 +398,51 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: FeedUpdateRunningEvent) {
- nextPageLoader?.setLoadingState(event.isFeedUpdateRunning)
+ nextPageLoader.setLoadingState(event.isFeedUpdateRunning)
if (!event.isFeedUpdateRunning) {
- nextPageLoader?.root?.visibility = View.GONE
+ nextPageLoader.root.visibility = View.GONE
}
- viewBinding!!.swipeRefresh.isRefreshing = event.isFeedUpdateRunning
+ viewBinding.swipeRefresh.isRefreshing = event.isFeedUpdateRunning
}
@UnstableApi private fun refreshHeaderView() {
setupHeaderView()
- if (viewBinding == null || feed == null) {
+ if (feed == null) {
Log.e(TAG, "Unable to refresh header view")
return
}
loadFeedImage()
- if (feed != null && feed!!.hasLastUpdateFailed()) {
- viewBinding!!.header.txtvFailure.visibility = View.VISIBLE
+ if (feed!!.hasLastUpdateFailed()) {
+ viewBinding.header.txtvFailure.visibility = View.VISIBLE
} else {
- viewBinding!!.header.txtvFailure.visibility = View.GONE
+ viewBinding.header.txtvFailure.visibility = View.GONE
}
- if (feed != null && feed!!.preferences != null && !feed!!.preferences!!.keepUpdated) {
- viewBinding!!.header.txtvUpdatesDisabled.text = ("{md-pause-circle-outline} "
+ if (feed!!.preferences != null && !feed!!.preferences!!.keepUpdated) {
+ viewBinding.header.txtvUpdatesDisabled.text = ("{md-pause-circle-outline} "
+ this.getString(R.string.updates_disabled_label))
- Iconify.addIcons(viewBinding!!.header.txtvUpdatesDisabled)
- viewBinding!!.header.txtvUpdatesDisabled.visibility = View.VISIBLE
+ Iconify.addIcons(viewBinding.header.txtvUpdatesDisabled)
+ viewBinding.header.txtvUpdatesDisabled.visibility = View.VISIBLE
} else {
- viewBinding!!.header.txtvUpdatesDisabled.visibility = View.GONE
+ viewBinding.header.txtvUpdatesDisabled.visibility = View.GONE
}
- viewBinding!!.header.txtvTitle.text = feed!!.title
- viewBinding!!.header.txtvAuthor.text = feed!!.author
+ viewBinding.header.txtvTitle.text = feed!!.title
+ viewBinding.header.txtvAuthor.text = feed!!.author
if (feed != null && feed!!.itemFilter != null) {
val filter: FeedItemFilter? = feed!!.itemFilter
if (filter != null && filter.values.isNotEmpty()) {
- viewBinding!!.header.txtvInformation.text = ("{md-info-outline} "
+ viewBinding.header.txtvInformation.text = ("{md-info-outline} "
+ this.getString(R.string.filtered_label))
- Iconify.addIcons(viewBinding!!.header.txtvInformation)
- viewBinding!!.header.txtvInformation.setOnClickListener { l: View? ->
+ Iconify.addIcons(viewBinding.header.txtvInformation)
+ viewBinding.header.txtvInformation.setOnClickListener { l: View? ->
FeedItemFilterDialog.newInstance(feed!!).show(
childFragmentManager, null)
}
- viewBinding!!.header.txtvInformation.visibility = View.VISIBLE
+ viewBinding.header.txtvInformation.visibility = View.VISIBLE
} else {
- viewBinding!!.header.txtvInformation.visibility = View.GONE
+ viewBinding.header.txtvInformation.visibility = View.GONE
}
} else {
- viewBinding!!.header.txtvInformation.visibility = View.GONE
+ viewBinding.header.txtvInformation.visibility = View.GONE
}
}
@@ -450,19 +452,19 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
}
// https://github.com/bumptech/glide/issues/529
- viewBinding!!.imgvBackground.colorFilter = LightingColorFilter(-0x99999a, 0x000000)
- viewBinding!!.header.butShowInfo.setOnClickListener { v: View? -> showFeedInfo() }
- viewBinding!!.header.imgvCover.setOnClickListener { v: View? -> showFeedInfo() }
- viewBinding!!.header.butShowSettings.setOnClickListener { v: View? ->
+ viewBinding.imgvBackground.colorFilter = LightingColorFilter(-0x99999a, 0x000000)
+ viewBinding.header.butShowInfo.setOnClickListener { v: View? -> showFeedInfo() }
+ viewBinding.header.imgvCover.setOnClickListener { v: View? -> showFeedInfo() }
+ viewBinding.header.butShowSettings.setOnClickListener { v: View? ->
if (feed != null) {
val fragment = FeedSettingsFragment.newInstance(feed!!)
(activity as MainActivity).loadChildFragment(fragment, TransitionEffect.SLIDE)
}
}
- viewBinding!!.header.butFilter.setOnClickListener { v: View? ->
+ viewBinding.header.butFilter.setOnClickListener { v: View? ->
if (feed != null) FeedItemFilterDialog.newInstance(feed!!).show(childFragmentManager, null)
}
- viewBinding!!.header.txtvFailure.setOnClickListener { v: View? -> showErrorDetails() }
+ viewBinding.header.txtvFailure.setOnClickListener { v: View? -> showErrorDetails() }
headerCreated = true
}
@@ -502,7 +504,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
.error(R.color.image_readability_tint)
.transform(FastBlurTransformation())
.dontAnimate())
- .into(viewBinding!!.imgvBackground)
+ .into(viewBinding.imgvBackground)
Glide.with(this)
.load(feed!!.imageUrl)
@@ -511,7 +513,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
.error(R.color.light_gray)
.fitCenter()
.dontAnimate())
- .into(viewBinding!!.header.imgvCover)
+ .into(viewBinding.header.imgvCover)
}
@UnstableApi private fun loadItems() {
@@ -524,17 +526,17 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
{ result: Feed? ->
feed = result
Log.d(TAG, "loadItems subscribe called ${feed?.title}")
- swipeActions?.setFilter(feed?.itemFilter)
+ swipeActions.setFilter(feed?.itemFilter)
refreshHeaderView()
- viewBinding!!.progressBar.visibility = View.GONE
- adapter?.setDummyViews(0)
- if (feed != null && feed!!.items.isNotEmpty()) adapter?.updateItems(feed!!.items)
+ viewBinding.progressBar.visibility = View.GONE
+ adapter.setDummyViews(0)
+ if (feed != null && feed!!.items.isNotEmpty()) adapter.updateItems(feed!!.items)
updateToolbar()
}, { error: Throwable? ->
feed = null
refreshHeaderView()
- adapter?.setDummyViews(0)
- adapter?.updateItems(emptyList())
+ adapter.setDummyViews(0)
+ adapter.updateItems(emptyList())
updateToolbar()
Log.e(TAG, Log.getStackTraceString(error))
})
@@ -560,8 +562,8 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
return
}
when (event.keyCode) {
- KeyEvent.KEYCODE_T -> viewBinding!!.recyclerView.smoothScrollToPosition(0)
- KeyEvent.KEYCODE_B -> viewBinding!!.recyclerView.smoothScrollToPosition(adapter!!.itemCount - 1)
+ KeyEvent.KEYCODE_T -> viewBinding.recyclerView.smoothScrollToPosition(0)
+ KeyEvent.KEYCODE_B -> viewBinding.recyclerView.smoothScrollToPosition(adapter.itemCount - 1)
else -> {}
}
}
@@ -576,8 +578,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
if (!inActionMode()) {
menu.findItem(R.id.multi_select).setVisible(true)
}
- MenuItemUtils.setOnClickListeners(menu
- ) { item: MenuItem ->
+ MenuItemUtils.setOnClickListeners(menu) { item: MenuItem ->
this@FeedItemlistFragment.onContextItemSelected(item)
}
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/FeedSettingsFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/FeedSettingsFragment.kt
index c12f3cbf..77da53bb 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/FeedSettingsFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/FeedSettingsFragment.kt
@@ -43,6 +43,8 @@ import ac.mdiq.podvinci.model.feed.FeedPreferences.AutoDeleteAction
import ac.mdiq.podvinci.model.feed.FeedPreferences.NewEpisodesAction
import ac.mdiq.podvinci.model.feed.VolumeAdaptionSetting
import ac.mdiq.podvinci.storage.preferences.UserPreferences.isEnableAutodownload
+import androidx.annotation.OptIn
+import androidx.media3.common.util.UnstableApi
import io.reactivex.Maybe
import io.reactivex.MaybeEmitter
import io.reactivex.MaybeOnSubscribe
@@ -100,7 +102,7 @@ class FeedSettingsFragment : Fragment() {
var notificationPermissionDenied: Boolean = false
private val requestPermissionLauncher =
- registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
+ registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
return@registerForActivityResult
}
@@ -123,7 +125,7 @@ class FeedSettingsFragment : Fragment() {
return view
}
- override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ @OptIn(UnstableApi::class) override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.feed_settings)
// To prevent displaying partially loaded data
findPreference(PREF_SCREEN)!!.isVisible = false
@@ -181,7 +183,7 @@ class FeedSettingsFragment : Fragment() {
object : FeedPreferenceSkipDialog(context,
feedPreferences!!.feedSkipIntro,
feedPreferences!!.feedSkipEnding) {
- override fun onConfirmed(skipIntro: Int, skipEnding: Int) {
+ @UnstableApi override fun onConfirmed(skipIntro: Int, skipEnding: Int) {
feedPreferences!!.feedSkipIntro = skipIntro
feedPreferences!!.feedSkipEnding = skipEnding
DBWriter.setFeedPreferences(feedPreferences!!)
@@ -195,7 +197,7 @@ class FeedSettingsFragment : Fragment() {
}
}
- private fun setupPlaybackSpeedPreference() {
+ @UnstableApi private fun setupPlaybackSpeedPreference() {
val feedPlaybackSpeedPreference = findPreference(PREF_FEED_PLAYBACK_SPEED)
feedPlaybackSpeedPreference!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { preference: Preference ->
@@ -237,7 +239,7 @@ class FeedSettingsFragment : Fragment() {
findPreference(PREF_EPISODE_FILTER)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { preference: Preference ->
object : EpisodeFilterDialog(context, feedPreferences!!.filter) {
- override fun onConfirmed(filter: FeedFilter) {
+ @UnstableApi override fun onConfirmed(filter: FeedFilter) {
feedPreferences!!.filter = filter
DBWriter.setFeedPreferences(feedPreferences!!)
}
@@ -253,7 +255,7 @@ class FeedSettingsFragment : Fragment() {
object : AuthenticationDialog(context,
R.string.authentication_label, true,
feedPreferences!!.username, feedPreferences!!.password) {
- override fun onConfirmed(username: String, password: String) {
+ @UnstableApi override fun onConfirmed(username: String, password: String) {
feedPreferences!!.username = username
feedPreferences!!.password = password
val setPreferencesFuture = DBWriter.setFeedPreferences(feedPreferences!!)
@@ -274,7 +276,7 @@ class FeedSettingsFragment : Fragment() {
}
}
- private fun setupAutoDeletePreference() {
+ @UnstableApi private fun setupAutoDeletePreference() {
if (feedPreferences == null) return
findPreference(PREF_AUTO_DELETE)!!.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { preference: Preference?, newValue: Any? ->
@@ -310,7 +312,7 @@ class FeedSettingsFragment : Fragment() {
}
}
- private fun setupVolumeAdaptationPreferences() {
+ @UnstableApi private fun setupVolumeAdaptationPreferences() {
if (feedPreferences == null) return
val volumeAdaptationPreference = findPreference("volumeReduction")
volumeAdaptationPreference!!.onPreferenceChangeListener =
@@ -348,7 +350,7 @@ class FeedSettingsFragment : Fragment() {
}
}
- private fun setupNewEpisodesAction() {
+ @OptIn(UnstableApi::class) private fun setupNewEpisodesAction() {
if (feedPreferences == null) return
findPreference(PREF_NEW_EPISODES_ACTION)!!.onPreferenceChangeListener =
@@ -374,14 +376,14 @@ class FeedSettingsFragment : Fragment() {
}
}
- private fun setupKeepUpdatedPreference() {
+ @OptIn(UnstableApi::class) private fun setupKeepUpdatedPreference() {
if (feedPreferences == null) return
val pref = findPreference("keepUpdated")
pref!!.isChecked = feedPreferences!!.keepUpdated
pref.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { preference: Preference?, newValue: Any ->
- val checked = newValue === java.lang.Boolean.TRUE
+ val checked = newValue == true
feedPreferences!!.keepUpdated = checked
DBWriter.setFeedPreferences(feedPreferences!!)
pref.isChecked = checked
@@ -399,7 +401,7 @@ class FeedSettingsFragment : Fragment() {
}
}
- private fun setupAutoDownloadPreference() {
+ @OptIn(UnstableApi::class) private fun setupAutoDownloadPreference() {
if (feedPreferences == null) return
val pref = findPreference("autoDownload")
@@ -413,7 +415,7 @@ class FeedSettingsFragment : Fragment() {
pref.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { preference: Preference?, newValue: Any ->
- val checked = newValue === java.lang.Boolean.TRUE
+ val checked = newValue == true
feedPreferences!!.autoDownload = checked
DBWriter.setFeedPreferences(feedPreferences!!)
updateAutoDownloadEnabled()
@@ -439,7 +441,7 @@ class FeedSettingsFragment : Fragment() {
}
}
- private fun setupEpisodeNotificationPreference() {
+ @OptIn(UnstableApi::class) private fun setupEpisodeNotificationPreference() {
val pref = findPreference("episodeNotification")
pref!!.isChecked = feedPreferences!!.showEpisodeNotification
@@ -451,7 +453,7 @@ class FeedSettingsFragment : Fragment() {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
return@OnPreferenceChangeListener false
}
- val checked = newValue === java.lang.Boolean.TRUE
+ val checked = newValue == true
feedPreferences!!.showEpisodeNotification = checked
if (feedPreferences != null) DBWriter.setFeedPreferences(feedPreferences!!)
pref.isChecked = checked
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/InboxFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/InboxFragment.kt
index 5a06b6d7..803f61b5 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/InboxFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/InboxFragment.kt
@@ -22,6 +22,7 @@ import ac.mdiq.podvinci.model.feed.FeedItem
import ac.mdiq.podvinci.model.feed.FeedItemFilter
import ac.mdiq.podvinci.model.feed.SortOrder
import ac.mdiq.podvinci.storage.preferences.UserPreferences
+import androidx.annotation.OptIn
import org.greenrobot.eventbus.EventBus
/**
@@ -39,16 +40,16 @@ class InboxFragment : EpisodesListFragment() {
@UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val root = super.onCreateView(inflater, container, savedInstanceState)
- toolbar?.inflateMenu(R.menu.inbox)
- toolbar?.setTitle(R.string.inbox_label)
+ toolbar.inflateMenu(R.menu.inbox)
+ toolbar.setTitle(R.string.inbox_label)
prefs = requireActivity().getSharedPreferences(getPrefName(), Context.MODE_PRIVATE)
updateToolbar()
- emptyView?.setIcon(R.drawable.ic_inbox)
- emptyView?.setTitle(R.string.no_inbox_head_label)
- emptyView?.setMessage(R.string.no_inbox_label)
- speedDialView?.removeActionItemById(R.id.mark_unread_batch)
- speedDialView?.removeActionItemById(R.id.remove_from_queue_batch)
- speedDialView?.removeActionItemById(R.id.delete_batch)
+ emptyView.setIcon(R.drawable.ic_inbox)
+ emptyView.setTitle(R.string.no_inbox_head_label)
+ emptyView.setMessage(R.string.no_inbox_label)
+ speedDialView.removeActionItemById(R.id.mark_unread_batch)
+ speedDialView.removeActionItemById(R.id.remove_from_queue_batch)
+ speedDialView.removeActionItemById(R.id.delete_batch)
return root
}
@@ -56,7 +57,7 @@ class InboxFragment : EpisodesListFragment() {
return FeedItemFilter(FeedItemFilter.NEW)
}
- override fun onMenuItemClick(item: MenuItem): Boolean {
+ @OptIn(UnstableApi::class) override fun onMenuItemClick(item: MenuItem): Boolean {
if (super.onOptionsItemSelected(item)) {
return true
}
@@ -88,7 +89,7 @@ class InboxFragment : EpisodesListFragment() {
return DBReader.getTotalEpisodeCount(FeedItemFilter(FeedItemFilter.NEW))
}
- private fun removeAllFromInbox() {
+ @OptIn(UnstableApi::class) private fun removeAllFromInbox() {
DBWriter.removeAllNewFlags()
(activity as MainActivity).showSnackbarAbovePlayer(R.string.removed_all_inbox_msg, Toast.LENGTH_SHORT)
}
@@ -102,8 +103,7 @@ class InboxFragment : EpisodesListFragment() {
val checkNeverAskAgain: CheckBox = view.findViewById(R.id.checkbox_do_not_show_again)
builder.setView(view)
- builder.setPositiveButton(R.string.confirm_label
- ) { dialog: DialogInterface, which: Int ->
+ builder.setPositiveButton(R.string.confirm_label) { dialog: DialogInterface, which: Int ->
dialog.dismiss()
removeAllFromInbox()
prefs?.edit()?.putBoolean(PREF_DO_NOT_PROMPT_REMOVE_ALL_FROM_INBOX, checkNeverAskAgain.isChecked)
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/ItemDescriptionFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/ItemDescriptionFragment.kt
index 686858e0..ea66dd22 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/ItemDescriptionFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/ItemDescriptionFragment.kt
@@ -27,7 +27,7 @@ import io.reactivex.schedulers.Schedulers
*/
@UnstableApi
class ItemDescriptionFragment : Fragment() {
- private var webvDescription: ShownotesWebView? = null
+ private lateinit var webvDescription: ShownotesWebView
private var webViewLoader: Disposable? = null
private var controller: PlaybackController? = null
@@ -35,41 +35,39 @@ class ItemDescriptionFragment : Fragment() {
Log.d(TAG, "Creating view")
val root = inflater.inflate(R.layout.item_description_fragment, container, false)
webvDescription = root.findViewById(R.id.webview)
- webvDescription?.setTimecodeSelectedListener { time: Int? ->
+ webvDescription.setTimecodeSelectedListener { time: Int? ->
if (controller != null) {
controller!!.seekTo(time!!)
}
}
- webvDescription?.setPageFinishedListener {
+ webvDescription.setPageFinishedListener {
// Restoring the scroll position might not always work
- webvDescription!!.postDelayed({ this@ItemDescriptionFragment.restoreFromPreference() }, 50)
+ webvDescription.postDelayed({ this@ItemDescriptionFragment.restoreFromPreference() }, 50)
}
root.addOnLayoutChangeListener(object : OnLayoutChangeListener {
override fun onLayoutChange(v: View, left: Int, top: Int, right: Int,
bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int
) {
- if (root.measuredHeight != webvDescription?.minimumHeight) {
- webvDescription?.setMinimumHeight(root.measuredHeight)
+ if (root.measuredHeight != webvDescription.minimumHeight) {
+ webvDescription.setMinimumHeight(root.measuredHeight)
}
root.removeOnLayoutChangeListener(this)
}
})
- if (webvDescription != null) registerForContextMenu(webvDescription!!)
+ registerForContextMenu(webvDescription)
return root
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "Fragment destroyed")
- if (webvDescription != null) {
- webvDescription!!.removeAllViews()
- webvDescription!!.destroy()
- }
+ webvDescription.removeAllViews()
+ webvDescription.destroy()
}
override fun onContextItemSelected(item: MenuItem): Boolean {
- return webvDescription!!.onContextItemSelected(item)
+ return webvDescription.onContextItemSelected(item)
}
@UnstableApi private fun load() {
@@ -85,11 +83,10 @@ class ItemDescriptionFragment : Fragment() {
return@create
}
if (media is FeedMedia) {
- val feedMedia = media
- if (feedMedia.getItem() == null) {
- feedMedia.setItem(DBReader.getFeedItem(feedMedia.itemId))
+ if (media.getItem() == null) {
+ media.setItem(DBReader.getFeedItem(media.itemId))
}
- if (feedMedia.getItem() != null) DBReader.loadDescriptionOfFeedItem(feedMedia.getItem()!!)
+ if (media.getItem() != null) DBReader.loadDescriptionOfFeedItem(media.getItem()!!)
}
val shownotesCleaner = ShownotesCleaner(context, media.getDescription()?:"", media.getDuration())
emitter.onSuccess(shownotesCleaner.processShownotes())
@@ -97,7 +94,7 @@ class ItemDescriptionFragment : Fragment() {
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ data: String? ->
- webvDescription!!.loadDataWithBaseURL("https://127.0.0.1", data!!, "text/html",
+ webvDescription.loadDataWithBaseURL("https://127.0.0.1", data!!, "text/html",
"utf-8", "about:blank")
Log.d(TAG, "Webview loaded")
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
@@ -112,9 +109,9 @@ class ItemDescriptionFragment : Fragment() {
Log.d(TAG, "Saving preferences")
val prefs = requireActivity().getSharedPreferences(PREF, Activity.MODE_PRIVATE)
val editor = prefs.edit()
- if (controller != null && controller!!.getMedia() != null && webvDescription != null) {
- Log.d(TAG, "Saving scroll position: " + webvDescription!!.scrollY)
- editor.putInt(PREF_SCROLL_Y, webvDescription!!.scrollY)
+ if (controller?.getMedia() != null) {
+ Log.d(TAG, "Saving scroll position: " + webvDescription.scrollY)
+ editor.putInt(PREF_SCROLL_Y, webvDescription.scrollY)
editor.putString(PREF_PLAYABLE_ID, controller!!.getMedia()!!.getIdentifier()
.toString())
} else {
@@ -132,9 +129,9 @@ class ItemDescriptionFragment : Fragment() {
val prefs = activity.getSharedPreferences(PREF, Activity.MODE_PRIVATE)
val id = prefs.getString(PREF_PLAYABLE_ID, "")
val scrollY = prefs.getInt(PREF_SCROLL_Y, -1)
- if (controller != null && scrollY != -1 && controller!!.getMedia() != null && id == controller!!.getMedia()!!.getIdentifier().toString() && webvDescription != null) {
+ if (controller != null && scrollY != -1 && controller!!.getMedia() != null && id == controller!!.getMedia()!!.getIdentifier().toString()) {
Log.d(TAG, "Restored scroll Position: $scrollY")
- webvDescription!!.scrollTo(webvDescription!!.scrollX, scrollY)
+ webvDescription.scrollTo(webvDescription.scrollX, scrollY)
return true
}
}
@@ -142,7 +139,7 @@ class ItemDescriptionFragment : Fragment() {
}
fun scrollToTop() {
- webvDescription!!.scrollTo(0, 0)
+ webvDescription.scrollTo(0, 0)
savePreference()
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/ItemFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/ItemFragment.kt
index 16133a59..58e65f8b 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/ItemFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/ItemFragment.kt
@@ -46,6 +46,7 @@ import ac.mdiq.podvinci.storage.preferences.UserPreferences
import ac.mdiq.podvinci.ui.common.CircularProgressBar
import ac.mdiq.podvinci.ui.common.ThemeUtils
import ac.mdiq.podvinci.view.ShownotesWebView
+import androidx.annotation.OptIn
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
@@ -65,24 +66,25 @@ class ItemFragment : Fragment() {
private var item: FeedItem? = null
private var webviewData: String? = null
- private var root: ViewGroup? = null
- private var webvDescription: ShownotesWebView? = null
- private var txtvPodcast: TextView? = null
- private var txtvTitle: TextView? = null
- private var txtvDuration: TextView? = null
- private var txtvPublished: TextView? = null
- private var imgvCover: ImageView? = null
- private var progbarDownload: CircularProgressBar? = null
- private var progbarLoading: ProgressBar? = null
- private var butAction1Text: TextView? = null
- private var butAction2Text: TextView? = null
- private var butAction1Icon: ImageView? = null
- private var butAction2Icon: ImageView? = null
- private var butAction1: View? = null
- private var butAction2: View? = null
+ private lateinit var root: ViewGroup
+ private lateinit var webvDescription: ShownotesWebView
+ private lateinit var txtvPodcast: TextView
+ private lateinit var txtvTitle: TextView
+ private lateinit var txtvDuration: TextView
+ private lateinit var txtvPublished: TextView
+ private lateinit var imgvCover: ImageView
+ private lateinit var progbarDownload: CircularProgressBar
+ private lateinit var progbarLoading: ProgressBar
+ private lateinit var butAction1Text: TextView
+ private lateinit var butAction2Text: TextView
+ private lateinit var butAction1Icon: ImageView
+ private lateinit var butAction2Icon: ImageView
+ private lateinit var butAction1: View
+ private lateinit var butAction2: View
+ private lateinit var noMediaLabel: View
+
private var actionButton1: ItemActionButton? = null
private var actionButton2: ItemActionButton? = null
- private var noMediaLabel: View? = null
private var disposable: Disposable? = null
private var controller: PlaybackController? = null
@@ -100,16 +102,16 @@ class ItemFragment : Fragment() {
root = layout.findViewById(R.id.content_root)
txtvPodcast = layout.findViewById(R.id.txtvPodcast)
- txtvPodcast?.setOnClickListener { v: View? -> openPodcast() }
+ txtvPodcast.setOnClickListener { v: View? -> openPodcast() }
txtvTitle = layout.findViewById(R.id.txtvTitle)
if (Build.VERSION.SDK_INT >= 23) {
- txtvTitle?.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL)
+ txtvTitle.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL)
}
txtvDuration = layout.findViewById(R.id.txtvDuration)
txtvPublished = layout.findViewById(R.id.txtvPublished)
- txtvTitle?.ellipsize = TextUtils.TruncateAt.END
+ txtvTitle.ellipsize = TextUtils.TruncateAt.END
webvDescription = layout.findViewById(R.id.webvDescription)
- webvDescription?.setTimecodeSelectedListener { time: Int? ->
+ webvDescription.setTimecodeSelectedListener { time: Int? ->
if (controller != null && item != null && item!!.media != null && controller!!.getMedia() != null &&
item!!.media!!.getIdentifier() == controller!!.getMedia()!!.getIdentifier()) {
controller!!.seekTo(time ?: 0)
@@ -118,10 +120,10 @@ class ItemFragment : Fragment() {
Snackbar.LENGTH_LONG)
}
}
- if (webvDescription != null) registerForContextMenu(webvDescription!!)
+ registerForContextMenu(webvDescription)
imgvCover = layout.findViewById(R.id.imgvCover)
- imgvCover?.setOnClickListener { v: View? -> openPodcast() }
+ imgvCover.setOnClickListener { v: View? -> openPodcast() }
progbarDownload = layout.findViewById(R.id.circularProgressBar)
progbarLoading = layout.findViewById(R.id.progbarLoading)
butAction1 = layout.findViewById(R.id.butAction1)
@@ -132,7 +134,7 @@ class ItemFragment : Fragment() {
butAction2Text = layout.findViewById(R.id.butAction2Text)
noMediaLabel = layout.findViewById(R.id.noMediaLabel)
- butAction1?.setOnClickListener(View.OnClickListener { v: View? ->
+ butAction1.setOnClickListener(View.OnClickListener { v: View? ->
if (actionButton1 is StreamActionButton && !UserPreferences.isStreamOverDownload
&& UsageStatistics.hasSignificantBiasTo(UsageStatistics.ACTION_STREAM)) {
showOnDemandConfigBalloon(true)
@@ -142,7 +144,7 @@ class ItemFragment : Fragment() {
}
actionButton1?.onClick(requireContext())
})
- butAction2?.setOnClickListener(View.OnClickListener { v: View? ->
+ butAction2.setOnClickListener(View.OnClickListener { v: View? ->
if (actionButton2 is DownloadActionButton && UserPreferences.isStreamOverDownload
&& UsageStatistics.hasSignificantBiasTo(UsageStatistics.ACTION_DOWNLOAD)) {
showOnDemandConfigBalloon(false)
@@ -155,7 +157,7 @@ class ItemFragment : Fragment() {
return layout
}
- private fun showOnDemandConfigBalloon(offerStreaming: Boolean) {
+ @OptIn(UnstableApi::class) private fun showOnDemandConfigBalloon(offerStreaming: Boolean) {
val isLocaleRtl = (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL)
val balloon: Balloon = Balloon.Builder(requireContext())
.setArrowOrientation(ArrowOrientation.TOP)
@@ -186,7 +188,7 @@ class ItemFragment : Fragment() {
UsageStatistics.doNotAskAgain(UsageStatistics.ACTION_STREAM) // Type does not matter. Both are silenced.
balloon.dismiss()
}
- balloon.showAlignBottom(butAction1!!, 0, (-12 * resources.displayMetrics.density).toInt())
+ balloon.showAlignBottom(butAction1, 0, (-12 * resources.displayMetrics.density).toInt())
}
@UnstableApi override fun onStart() {
@@ -204,7 +206,7 @@ class ItemFragment : Fragment() {
@UnstableApi override fun onResume() {
super.onResume()
if (itemsLoaded) {
- progbarLoading?.visibility = View.GONE
+ progbarLoading.visibility = View.GONE
updateAppearance()
}
}
@@ -218,16 +220,13 @@ class ItemFragment : Fragment() {
override fun onDestroyView() {
super.onDestroyView()
disposable?.dispose()
-
- if (webvDescription != null && root != null) {
- root!!.removeView(webvDescription)
- webvDescription!!.destroy()
- }
+ root.removeView(webvDescription)
+ webvDescription.destroy()
}
@UnstableApi private fun onFragmentLoaded() {
if (webviewData != null && !itemsLoaded) {
- webvDescription?.loadDataWithBaseURL("https://127.0.0.1", webviewData!!, "text/html", "utf-8", "about:blank")
+ webvDescription.loadDataWithBaseURL("https://127.0.0.1", webviewData!!, "text/html", "utf-8", "about:blank")
}
updateAppearance()
}
@@ -237,13 +236,13 @@ class ItemFragment : Fragment() {
Log.d(TAG, "updateAppearance item is null")
return
}
- if (item!!.feed != null) txtvPodcast?.text = item!!.feed!!.title
- txtvTitle?.text = item!!.title
+ if (item!!.feed != null) txtvPodcast.text = item!!.feed!!.title
+ txtvTitle.text = item!!.title
if (item?.pubDate != null) {
val pubDateStr = DateFormatter.formatAbbrev(activity, item!!.pubDate)
- txtvPublished?.text = pubDateStr
- txtvPublished?.setContentDescription(DateFormatter.formatForAccessibility(item!!.pubDate))
+ txtvPublished.text = pubDateStr
+ txtvPublished.setContentDescription(DateFormatter.formatForAccessibility(item!!.pubDate))
}
val options: RequestOptions = RequestOptions()
@@ -252,25 +251,25 @@ class ItemFragment : Fragment() {
RoundedCorners((8 * resources.displayMetrics.density).toInt()))
.dontAnimate()
- if (imgvCover != null) Glide.with(this)
+ Glide.with(this)
.load(item!!.imageLocation)
.error(Glide.with(this)
.load(ImageResourceUtils.getFallbackImageLocation(item!!))
.apply(options))
.apply(options)
- .into(imgvCover!!)
+ .into(imgvCover)
updateButtons()
}
@UnstableApi private fun updateButtons() {
- progbarDownload?.visibility = View.GONE
+ progbarDownload.visibility = View.GONE
val dls = DownloadServiceInterface.get()
if (item != null && item!!.hasMedia() && item!!.media!!.download_url != null) {
val url = item!!.media!!.download_url!!
if (dls != null && dls.isDownloadingEpisode(url)) {
- progbarDownload?.visibility = View.VISIBLE
- progbarDownload?.setPercentage(0.01f * max(1.0, dls.getProgress(url).toDouble()).toFloat(), item)
- progbarDownload?.setIndeterminate(dls.isEpisodeQueued(url))
+ progbarDownload.visibility = View.VISIBLE
+ progbarDownload.setPercentage(0.01f * max(1.0, dls.getProgress(url).toDouble()).toFloat(), item)
+ progbarDownload.setIndeterminate(dls.isEpisodeQueued(url))
}
}
@@ -280,12 +279,12 @@ class ItemFragment : Fragment() {
actionButton1 = MarkAsPlayedActionButton(item!!)
actionButton2 = VisitWebsiteActionButton(item!!)
}
- noMediaLabel!!.visibility = View.VISIBLE
+ noMediaLabel.visibility = View.VISIBLE
} else {
- noMediaLabel!!.visibility = View.GONE
+ noMediaLabel.visibility = View.GONE
if (media.getDuration() > 0) {
- txtvDuration?.text = Converter.getDurationStringLong(media.getDuration())
- txtvDuration?.setContentDescription(
+ txtvDuration.text = Converter.getDurationStringLong(media.getDuration())
+ txtvDuration.setContentDescription(
Converter.getDurationStringLocalized(requireContext(), media.getDuration().toLong()))
}
if (item != null) {
@@ -309,25 +308,25 @@ class ItemFragment : Fragment() {
}
if (actionButton1 != null) {
- butAction1Text?.setText(actionButton1!!.getLabel())
- butAction1Icon?.setImageResource(actionButton1!!.getDrawable())
+ butAction1Text.setText(actionButton1!!.getLabel())
+ butAction1Icon.setImageResource(actionButton1!!.getDrawable())
}
- butAction1Text?.transformationMethod = null
- if (actionButton1 != null) butAction1!!.visibility = actionButton1!!.visibility
+ butAction1Text.transformationMethod = null
+ if (actionButton1 != null) butAction1.visibility = actionButton1!!.visibility
if (actionButton2 != null) {
- butAction2Text?.setText(actionButton2!!.getLabel())
- butAction2Icon?.setImageResource(actionButton2!!.getDrawable())
+ butAction2Text.setText(actionButton2!!.getLabel())
+ butAction2Icon.setImageResource(actionButton2!!.getDrawable())
}
- butAction2Text?.transformationMethod = null
- if (actionButton2 != null) butAction2!!.visibility = actionButton2!!.visibility
+ butAction2Text.transformationMethod = null
+ if (actionButton2 != null) butAction2.visibility = actionButton2!!.visibility
}
override fun onContextItemSelected(item: MenuItem): Boolean {
- return webvDescription?.onContextItemSelected(item)?: false
+ return webvDescription.onContextItemSelected(item)
}
- private fun openPodcast() {
+ @OptIn(UnstableApi::class) private fun openPodcast() {
if (item == null) {
return
}
@@ -374,13 +373,13 @@ class ItemFragment : Fragment() {
disposable?.dispose()
if (!itemsLoaded) {
- progbarLoading?.visibility = View.VISIBLE
+ progbarLoading.visibility = View.VISIBLE
}
disposable = Observable.fromCallable { this.loadInBackground() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ result: FeedItem? ->
- progbarLoading?.visibility = View.GONE
+ progbarLoading.visibility = View.GONE
item = result
onFragmentLoaded()
itemsLoaded = true
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/ItemPagerFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/ItemPagerFragment.kt
index e09dc053..6813aef3 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/ItemPagerFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/ItemPagerFragment.kt
@@ -30,22 +30,22 @@ import kotlin.math.max
* Displays information about a list of FeedItems.
*/
class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
- private var pager: ViewPager2? = null
+ private lateinit var pager: ViewPager2
+ private lateinit var toolbar: MaterialToolbar
private var feedItems: LongArray? = null
private var item: FeedItem? = null
private var disposable: Disposable? = null
- private var toolbar: MaterialToolbar? = null
-
+
@UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
super.onCreateView(inflater, container, savedInstanceState)
val layout: View = inflater.inflate(R.layout.feeditem_pager_fragment, container, false)
toolbar = layout.findViewById(R.id.toolbar)
- toolbar?.title = ""
- toolbar?.inflateMenu(R.menu.feeditem_options)
- toolbar?.setNavigationOnClickListener { v: View? -> parentFragmentManager.popBackStack() }
- toolbar?.setOnMenuItemClickListener(this)
+ toolbar.title = ""
+ toolbar.inflateMenu(R.menu.feeditem_options)
+ toolbar.setNavigationOnClickListener { v: View? -> parentFragmentManager.popBackStack() }
+ toolbar.setOnMenuItemClickListener(this)
feedItems = requireArguments().getLongArray(ARG_FEEDITEMS)
val feedItemPos = max(0.0, requireArguments().getInt(ARG_FEEDITEM_POS).toDouble())
@@ -61,16 +61,18 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
// Restore state by using the same ID as before. ID collisions are prevented in MainActivity.
newId = savedInstanceState.getInt(KEY_PAGER_ID, 0)
}
- pager?.setId(newId)
- pager?.adapter = ItemPagerAdapter(this)
- pager?.setCurrentItem(feedItemPos, false)
- pager?.offscreenPageLimit = 1
- loadItem(feedItems!![feedItemPos])
- pager?.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
- override fun onPageSelected(position: Int) {
- loadItem(feedItems!![position])
- }
- })
+ pager.setId(newId)
+ pager.adapter = ItemPagerAdapter(this)
+ pager.setCurrentItem(feedItemPos, false)
+ pager.offscreenPageLimit = 1
+ if (feedItems != null && feedItems!!.isNotEmpty()) {
+ loadItem(feedItems!![feedItemPos])
+ pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
+ override fun onPageSelected(position: Int) {
+ loadItem(feedItems!![position])
+ }
+ })
+ }
EventBus.getDefault().register(this)
return layout
@@ -78,7 +80,7 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
- if (pager != null) outState.putInt(KEY_PAGER_ID, pager!!.id)
+ outState.putInt(KEY_PAGER_ID, pager.id)
}
override fun onDestroyView() {
@@ -100,19 +102,19 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
@UnstableApi fun refreshToolbarState() {
- if (item == null || toolbar == null) {
+ if (item == null) {
return
}
if (item!!.hasMedia()) {
- FeedItemMenuHandler.onPrepareMenu(toolbar!!.menu, item)
+ FeedItemMenuHandler.onPrepareMenu(toolbar.menu, item)
} else {
// these are already available via button1 and button2
- FeedItemMenuHandler.onPrepareMenu(toolbar!!.menu, item,
+ FeedItemMenuHandler.onPrepareMenu(toolbar.menu, item,
R.id.mark_read_item, R.id.visit_website_item)
}
}
- override fun onMenuItemClick(menuItem: MenuItem): Boolean {
+ @UnstableApi override fun onMenuItemClick(menuItem: MenuItem): Boolean {
if (menuItem.itemId == R.id.open_podcast) {
openPodcast()
return true
@@ -132,7 +134,7 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
}
- private fun openPodcast() {
+ @UnstableApi private fun openPodcast() {
if (item == null) {
return
}
@@ -142,11 +144,11 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private inner class ItemPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
override fun createFragment(position: Int): Fragment {
- return ItemFragment.newInstance(feedItems!![position])
+ return ItemFragment.newInstance(if (feedItems!= null) feedItems!![position] else 0L)
}
override fun getItemCount(): Int {
- return feedItems!!.size
+ return feedItems?.size?:0
}
}
@@ -165,7 +167,7 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
fun newInstance(feeditems: LongArray?, feedItemPos: Int): ItemPagerFragment {
val fragment = ItemPagerFragment()
val args = Bundle()
- args.putLongArray(ARG_FEEDITEMS, feeditems)
+ if (feeditems != null) args.putLongArray(ARG_FEEDITEMS, feeditems)
args.putInt(ARG_FEEDITEM_POS, max(0.0, feedItemPos.toDouble()).toInt())
fragment.arguments = args
return fragment
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/NavDrawerFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/NavDrawerFragment.kt
index 29949df8..55507661 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/NavDrawerFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/NavDrawerFragment.kt
@@ -42,6 +42,8 @@ import ac.mdiq.podvinci.storage.preferences.UserPreferences
import ac.mdiq.podvinci.ui.appstartintent.MainActivityStarter
import ac.mdiq.podvinci.ui.common.ThemeUtils
import ac.mdiq.podvinci.ui.home.HomeFragment
+import androidx.annotation.OptIn
+import androidx.media3.common.util.UnstableApi
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
@@ -56,9 +58,11 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
private var navDrawerData: NavDrawerData? = null
private var flatItemList: List? = null
private var contextPressedItem: NavDrawerData.DrawerItem? = null
- private var navAdapter: NavListAdapter? = null
private var disposable: Disposable? = null
- private var progressBar: ProgressBar? = null
+
+ private lateinit var navAdapter: NavListAdapter
+ private lateinit var progressBar: ProgressBar
+
private var openFolders: MutableSet = HashSet()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
@@ -83,12 +87,13 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
}
val preferences: SharedPreferences = requireContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
+// TODO: what is this?
openFolders = HashSet(preferences.getStringSet(PREF_OPEN_FOLDERS, HashSet())) // Must not modify
progressBar = root.findViewById(R.id.progressBar)
val navList = root.findViewById(R.id.nav_list)
navAdapter = NavListAdapter(itemAccess, requireActivity())
- navAdapter?.setHasStableIds(true)
+ navAdapter.setHasStableIds(true)
navList.adapter = navAdapter
navList.layoutManager = LinearLayoutManager(context)
@@ -161,14 +166,14 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
}
}
- private fun onFeedContextMenuClicked(feed: Feed, item: MenuItem): Boolean {
+ @OptIn(UnstableApi::class) private fun onFeedContextMenuClicked(feed: Feed, item: MenuItem): Boolean {
val itemId = item.itemId
when (itemId) {
R.id.remove_all_inbox_item -> {
val removeAllNewFlagsConfirmationDialog: ConfirmationDialog = object : ConfirmationDialog(requireContext(),
R.string.remove_all_inbox_label,
R.string.remove_all_inbox_confirmation_msg) {
- override fun onConfirmButtonPressed(dialog: DialogInterface) {
+ @OptIn(UnstableApi::class) override fun onConfirmButtonPressed(dialog: DialogInterface) {
dialog.dismiss()
DBWriter.removeFeedNewFlag(feed.id)
}
@@ -253,12 +258,12 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
override fun isSelected(position: Int): Boolean {
val lastNavFragment = getLastNavFragment(context)
- if (position < navAdapter!!.subscriptionOffset) {
- return navAdapter!!.getFragmentTags()[position] == lastNavFragment
+ if (position < navAdapter.subscriptionOffset) {
+ return navAdapter.getFragmentTags()[position] == lastNavFragment
} else if (StringUtils.isNumeric(lastNavFragment)) { // last fragment was not a list, but a feed
val feedId = lastNavFragment.toLong()
if (navDrawerData != null) {
- val itemToCheck: NavDrawerData.DrawerItem = flatItemList!![position - navAdapter!!.subscriptionOffset]
+ val itemToCheck: NavDrawerData.DrawerItem = flatItemList!![position - navAdapter.subscriptionOffset]
if (itemToCheck.type == NavDrawerData.DrawerItem.Type.FEED) {
// When the same feed is displayed multiple times, it should be highlighted multiple times.
return (itemToCheck as NavDrawerData.FeedDrawerItem).feed.id == feedId
@@ -292,15 +297,15 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
return sum
}
- override fun onItemClick(position: Int) {
- val viewType: Int = navAdapter!!.getItemViewType(position)
+ @OptIn(UnstableApi::class) override fun onItemClick(position: Int) {
+ val viewType: Int = navAdapter.getItemViewType(position)
if (viewType != NavListAdapter.VIEW_TYPE_SECTION_DIVIDER) {
- if (position < navAdapter!!.subscriptionOffset) {
- val tag: String = navAdapter!!.getFragmentTags()[position] ?:""
+ if (position < navAdapter.subscriptionOffset) {
+ val tag: String = navAdapter.getFragmentTags()[position] ?:""
(activity as MainActivity).loadFragment(tag, null)
(activity as MainActivity).bottomSheet?.setState(BottomSheetBehavior.STATE_COLLAPSED)
} else {
- val pos: Int = position - navAdapter!!.subscriptionOffset
+ val pos: Int = position - navAdapter.subscriptionOffset
val clickedItem: NavDrawerData.DrawerItem = flatItemList!![pos]
if (clickedItem.type == NavDrawerData.DrawerItem.Type.FEED) {
@@ -327,20 +332,20 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
.subscribe(
{ result: List? ->
flatItemList = result
- navAdapter?.notifyDataSetChanged()
+ navAdapter.notifyDataSetChanged()
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
}
} else if (UserPreferences.subscriptionsFilter.isEnabled
- && navAdapter!!.showSubscriptionList) {
+ && navAdapter.showSubscriptionList) {
SubscriptionsFilterDialog().show(childFragmentManager, "filter")
}
}
override fun onItemLongClick(position: Int): Boolean {
- if (position < navAdapter!!.getFragmentTags().size) {
+ if (position < navAdapter.getFragmentTags().size) {
DrawerPreferencesDialog.show(context!!) {
- navAdapter?.notifyDataSetChanged()
+ navAdapter.notifyDataSetChanged()
if (UserPreferences.hiddenDrawerItems != null && UserPreferences.hiddenDrawerItems!!.contains(
getLastNavFragment(context))) {
MainActivityStarter(context!!)
@@ -351,7 +356,7 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
}
return true
} else {
- contextPressedItem = flatItemList!![position - navAdapter!!.subscriptionOffset]
+ contextPressedItem = flatItemList!![position - navAdapter.subscriptionOffset]
return false
}
}
@@ -372,11 +377,11 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
{ result: Pair> ->
navDrawerData = result.first
flatItemList = result.second
- navAdapter?.notifyDataSetChanged()
- progressBar?.visibility = View.GONE // Stays hidden once there is something in the list
+ navAdapter.notifyDataSetChanged()
+ progressBar.visibility = View.GONE // Stays hidden once there is something in the list
}, { error: Throwable? ->
Log.e(TAG, Log.getStackTraceString(error))
- progressBar?.visibility = View.GONE
+ progressBar.visibility = View.GONE
})
}
@@ -398,7 +403,7 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) {
if (PREF_LAST_FRAGMENT_TAG == key) {
- navAdapter?.notifyDataSetChanged() // Update selection
+ navAdapter.notifyDataSetChanged() // Update selection
}
}
@@ -414,6 +419,7 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
const val TAG: String = "NavDrawerFragment"
@JvmField
+ @UnstableApi
val NAV_DRAWER_TAGS: Array = arrayOf(HomeFragment.TAG,
QueueFragment.TAG,
InboxFragment.TAG,
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/OnlineSearchFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/OnlineSearchFragment.kt
index ceec72eb..494bb608 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/OnlineSearchFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/OnlineSearchFragment.kt
@@ -33,11 +33,12 @@ class OnlineSearchFragment
*/
private var adapter: ItunesAdapter? = null
private var searchProvider: PodcastSearcher? = null
- private var gridView: GridView? = null
- private var progressBar: ProgressBar? = null
- private var txtvError: TextView? = null
- private var butRetry: Button? = null
- private var txtvEmpty: TextView? = null
+
+ private lateinit var gridView: GridView
+ private lateinit var progressBar: ProgressBar
+ private lateinit var txtvError: TextView
+ private lateinit var butRetry: Button
+ private lateinit var txtvEmpty: TextView
/**
* List of podcasts retreived from the search
@@ -65,10 +66,10 @@ class OnlineSearchFragment
val root: View = inflater.inflate(R.layout.fragment_itunes_search, container, false)
gridView = root.findViewById(R.id.gridView)
adapter = ItunesAdapter(requireContext(), ArrayList())
- gridView?.setAdapter(adapter)
+ gridView.setAdapter(adapter)
//Show information about the podcast when the list item is clicked
- gridView?.onItemClickListener =
+ gridView.onItemClickListener =
AdapterView.OnItemClickListener { parent: AdapterView<*>?, view1: View?, position: Int, id: Long ->
val podcast = searchResults!![position]
if (podcast != null) {
@@ -86,7 +87,7 @@ class OnlineSearchFragment
if (searchProvider != null) txtvPoweredBy.text = getString(R.string.search_powered_by, searchProvider!!.name)
setupToolbar(root.findViewById(R.id.toolbar))
- gridView?.setOnScrollListener(object : AbsListView.OnScrollListener {
+ gridView.setOnScrollListener(object : AbsListView.OnScrollListener {
override fun onScrollStateChanged(view: AbsListView, scrollState: Int) {
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
val imm = activity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
@@ -158,29 +159,29 @@ class OnlineSearchFragment
disposable = searchProvider?.search(query)
?.subscribe({ result: List? ->
searchResults = result
- progressBar?.visibility = View.GONE
+ progressBar.visibility = View.GONE
adapter?.clear()
if (searchResults != null) adapter?.addAll(searchResults!!)
adapter?.notifyDataSetInvalidated()
- gridView?.visibility = if (searchResults!!.isNotEmpty()) View.VISIBLE else View.GONE
- txtvEmpty?.visibility = if (searchResults!!.isEmpty()) View.VISIBLE else View.GONE
- txtvEmpty?.text = getString(R.string.no_results_for_query) + query
+ gridView.visibility = if (searchResults!!.isNotEmpty()) View.VISIBLE else View.GONE
+ txtvEmpty.visibility = if (searchResults!!.isEmpty()) View.VISIBLE else View.GONE
+ txtvEmpty.text = getString(R.string.no_results_for_query) + query
}, { error: Throwable ->
Log.e(TAG, Log.getStackTraceString(error))
- progressBar?.visibility = View.GONE
- txtvError?.text = error.toString()
- txtvError?.visibility = View.VISIBLE
- butRetry?.setOnClickListener { v: View? -> search(query) }
- butRetry!!.visibility = View.VISIBLE
+ progressBar.visibility = View.GONE
+ txtvError.text = error.toString()
+ txtvError.visibility = View.VISIBLE
+ butRetry.setOnClickListener { v: View? -> search(query) }
+ butRetry.visibility = View.VISIBLE
})
}
private fun showOnlyProgressBar() {
- gridView?.visibility = View.GONE
- txtvError?.visibility = View.GONE
- butRetry!!.visibility = View.GONE
- txtvEmpty?.visibility = View.GONE
- progressBar?.visibility = View.VISIBLE
+ gridView.visibility = View.GONE
+ txtvError.visibility = View.GONE
+ butRetry.visibility = View.GONE
+ txtvEmpty.visibility = View.GONE
+ progressBar.visibility = View.VISIBLE
}
private fun showInputMethod(view: View) {
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/PlaybackHistoryFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/PlaybackHistoryFragment.kt
index 415b7aca..38647c25 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/PlaybackHistoryFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/PlaybackHistoryFragment.kt
@@ -14,6 +14,7 @@ import ac.mdiq.podvinci.core.storage.DBWriter
import ac.mdiq.podvinci.event.playback.PlaybackHistoryEvent
import ac.mdiq.podvinci.model.feed.FeedItem
import ac.mdiq.podvinci.model.feed.FeedItemFilter
+import androidx.annotation.OptIn
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
@@ -27,19 +28,19 @@ class PlaybackHistoryFragment : EpisodesListFragment() {
@UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val root = super.onCreateView(inflater, container, savedInstanceState)
- toolbar!!.inflateMenu(R.menu.playback_history)
- toolbar!!.setTitle(R.string.playback_history_label)
+ toolbar.inflateMenu(R.menu.playback_history)
+ toolbar.setTitle(R.string.playback_history_label)
updateToolbar()
- emptyView!!.setIcon(R.drawable.ic_history)
- emptyView!!.setTitle(R.string.no_history_head_label)
- emptyView!!.setMessage(R.string.no_history_label)
+ emptyView.setIcon(R.drawable.ic_history)
+ emptyView.setTitle(R.string.no_history_head_label)
+ emptyView.setMessage(R.string.no_history_label)
return root
}
override fun getFilter(): FeedItemFilter {
return FeedItemFilter.unfiltered()
}
- override fun onMenuItemClick(item: MenuItem): Boolean {
+ @OptIn(UnstableApi::class) override fun onMenuItemClick(item: MenuItem): Boolean {
if (super.onOptionsItemSelected(item)) {
return true
}
@@ -62,7 +63,7 @@ class PlaybackHistoryFragment : EpisodesListFragment() {
override fun updateToolbar() {
// Not calling super, as we do not have a refresh button that could be updated
- toolbar!!.menu.findItem(R.id.clear_history_item).setVisible(episodes.isNotEmpty())
+ toolbar.menu.findItem(R.id.clear_history_item).setVisible(episodes.isNotEmpty())
}
@Subscribe(threadMode = ThreadMode.MAIN)
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/QueueFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/QueueFragment.kt
index 1e98e9d5..2d812153 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/QueueFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/QueueFragment.kt
@@ -60,22 +60,21 @@ import java.util.*
* Shows all items in the queue.
*/
class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAdapter.OnSelectModeListener {
- private var infoBar: TextView? = null
- private var recyclerView: EpisodeItemListRecyclerView? = null
- private var recyclerAdapter: QueueRecyclerAdapter? = null
- private var emptyView: EmptyViewHandler? = null
- private var toolbar: MaterialToolbar? = null
- private var swipeRefreshLayout: SwipeRefreshLayout? = null
+ private lateinit var infoBar: TextView
+ private lateinit var recyclerView: EpisodeItemListRecyclerView
+ private lateinit var emptyView: EmptyViewHandler
+ private lateinit var toolbar: MaterialToolbar
+ private lateinit var swipeRefreshLayout: SwipeRefreshLayout
+ private lateinit var swipeActions: SwipeActions
+ private lateinit var prefs: SharedPreferences
+ private lateinit var speedDialView: SpeedDialView
+ private lateinit var progressBar: ProgressBar
+
private var displayUpArrow = false
+ private var queue: MutableList = mutableListOf()
- private var queue: MutableList? = null
-
+ private var recyclerAdapter: QueueRecyclerAdapter? = null
private var disposable: Disposable? = null
- private var swipeActions: SwipeActions? = null
- private var prefs: SharedPreferences? = null
-
- private var speedDialView: SpeedDialView? = null
- private var progressBar: ProgressBar? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -83,10 +82,96 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
prefs = requireActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE)
}
+ @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ super.onCreateView(inflater, container, savedInstanceState)
+ val root: View = inflater.inflate(R.layout.queue_fragment, container, false)
+ toolbar = root.findViewById(R.id.toolbar)
+ toolbar.setOnMenuItemClickListener(this)
+ toolbar.setOnLongClickListener { v: View? ->
+ recyclerView.scrollToPosition(5)
+ recyclerView.post { recyclerView.smoothScrollToPosition(0) }
+ false
+ }
+ displayUpArrow = parentFragmentManager.backStackEntryCount != 0
+ if (savedInstanceState != null) {
+ displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW)
+ }
+ (activity as MainActivity).setupToolbarToggle(toolbar, displayUpArrow)
+ toolbar.inflateMenu(R.menu.queue)
+ refreshToolbarState()
+ progressBar = root.findViewById(R.id.progressBar)
+ progressBar.visibility = View.VISIBLE
+
+ infoBar = root.findViewById(R.id.info_bar)
+ recyclerView = root.findViewById(R.id.recyclerView)
+ val animator: RecyclerView.ItemAnimator? = recyclerView.itemAnimator
+ if (animator != null && animator is SimpleItemAnimator) {
+ animator.supportsChangeAnimations = false
+ }
+ recyclerView.setRecycledViewPool((activity as MainActivity).recycledViewPool)
+ registerForContextMenu(recyclerView)
+ recyclerView.addOnScrollListener(LiftOnScrollListener(root.findViewById(R.id.appbar)))
+
+ swipeActions = QueueSwipeActions()
+ swipeActions.setFilter(FeedItemFilter(FeedItemFilter.QUEUED))
+ swipeActions.attachTo(recyclerView)
+
+ recyclerAdapter = object : QueueRecyclerAdapter(activity as MainActivity, swipeActions) {
+ override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
+ super.onCreateContextMenu(menu, v, menuInfo)
+ MenuItemUtils.setOnClickListeners(menu
+ ) { item: MenuItem -> this@QueueFragment.onContextItemSelected(item) }
+ }
+ }
+ recyclerAdapter?.setOnSelectModeListener(this)
+ recyclerView.adapter = recyclerAdapter
+
+ swipeRefreshLayout = root.findViewById(R.id.swipeRefresh)
+ swipeRefreshLayout.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
+ swipeRefreshLayout.setOnRefreshListener {
+ FeedUpdateManager.runOnceOrAsk(requireContext())
+ }
+
+ emptyView = EmptyViewHandler(context)
+ emptyView.attachToRecyclerView(recyclerView)
+ emptyView.setIcon(R.drawable.ic_playlist_play)
+ emptyView.setTitle(R.string.no_items_header_label)
+ emptyView.setMessage(R.string.no_items_label)
+ emptyView.updateAdapter(recyclerAdapter)
+
+ speedDialView = root.findViewById(R.id.fabSD)
+ speedDialView.overlayLayout = root.findViewById(R.id.fabSDOverlay)
+ speedDialView.inflate(R.menu.episodes_apply_action_speeddial)
+ speedDialView.removeActionItemById(R.id.mark_read_batch)
+ speedDialView.removeActionItemById(R.id.mark_unread_batch)
+ speedDialView.removeActionItemById(R.id.add_to_queue_batch)
+ speedDialView.removeActionItemById(R.id.remove_all_inbox_item)
+ speedDialView.setOnChangeListener(object : SpeedDialView.OnChangeListener {
+ override fun onMainActionSelected(): Boolean {
+ return false
+ }
+
+ override fun onToggleChanged(open: Boolean) {
+ if (open && recyclerAdapter!!.selectedCount == 0) {
+ (activity as MainActivity).showSnackbarAbovePlayer(R.string.no_items_selected,
+ Snackbar.LENGTH_SHORT)
+ speedDialView.close()
+ }
+ }
+ })
+ speedDialView.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
+ EpisodeMultiSelectActionHandler((activity as MainActivity), actionItem.id)
+ .handleAction(recyclerAdapter!!.selectedItems.filterIsInstance())
+ recyclerAdapter?.endSelectMode()
+ true
+ }
+ return root
+ }
+
override fun onStart() {
super.onStart()
- if (queue != null) {
- recyclerView?.restoreScrollPosition(TAG)
+ if (queue.isNotEmpty()) {
+ recyclerView.restoreScrollPosition(TAG)
}
loadItems(true)
EventBus.getDefault().register(this)
@@ -94,7 +179,7 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
override fun onPause() {
super.onPause()
- recyclerView?.saveScrollPosition(TAG)
+ recyclerView.saveScrollPosition(TAG)
}
override fun onStop() {
@@ -106,15 +191,13 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: QueueEvent) {
Log.d(TAG, "onEventMainThread() called with: event = [$event]")
- if (queue == null) {
- return
- } else if (recyclerAdapter == null) {
+ if (recyclerAdapter == null) {
loadItems(true)
return
}
when (event.action) {
QueueEvent.Action.ADDED -> {
- if (event.item != null) queue!!.add(event.position, event.item!!)
+ if (event.item != null) queue.add(event.position, event.item!!)
recyclerAdapter?.notifyItemInserted(event.position)
}
QueueEvent.Action.SET_QUEUE, QueueEvent.Action.SORTED -> {
@@ -125,14 +208,14 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
}
QueueEvent.Action.REMOVED, QueueEvent.Action.IRREVERSIBLE_REMOVED -> {
if (event.item != null) {
- val position: Int = FeedItemUtil.indexOfItemWithId(queue!!.toList(), event.item!!.id)
- queue!!.removeAt(position)
+ val position: Int = FeedItemUtil.indexOfItemWithId(queue.toList(), event.item!!.id)
+ queue.removeAt(position)
recyclerAdapter?.notifyItemRemoved(position)
}
}
QueueEvent.Action.CLEARED -> {
- queue!!.clear()
- recyclerAdapter?.updateItems(queue!!)
+ queue.clear()
+ recyclerAdapter?.updateItems(queue)
}
QueueEvent.Action.MOVED -> return
QueueEvent.Action.ADDED_ITEMS -> return
@@ -140,16 +223,14 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
}
recyclerAdapter?.updateDragDropEnabled()
refreshToolbarState()
- recyclerView?.saveScrollPosition(TAG)
+ recyclerView.saveScrollPosition(TAG)
refreshInfoBar()
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: FeedItemEvent) {
Log.d(TAG, "onEventMainThread() called with: event = [$event]")
- if (queue == null) {
- return
- } else if (recyclerAdapter == null) {
+ if (recyclerAdapter == null) {
loadItems(true)
return
}
@@ -157,10 +238,10 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
val size: Int = event.items.size
while (i < size) {
val item: FeedItem = event.items[i]
- val pos: Int = FeedItemUtil.indexOfItemWithId(queue!!, item.id)
+ val pos: Int = FeedItemUtil.indexOfItemWithId(queue, item.id)
if (pos >= 0) {
- queue!!.removeAt(pos)
- queue!!.add(pos, item)
+ queue.removeAt(pos)
+ queue.add(pos, item)
recyclerAdapter?.notifyItemChangedCompat(pos)
refreshInfoBar()
}
@@ -170,11 +251,8 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: EpisodeDownloadEvent) {
- if (queue == null) {
- return
- }
for (downloadUrl in event.urls) {
- val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(queue!!.toList(), downloadUrl)
+ val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(queue.toList(), downloadUrl)
if (pos >= 0) {
recyclerAdapter?.notifyItemChangedCompat(pos)
}
@@ -185,7 +263,7 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
fun onEventMainThread(event: PlaybackPositionEvent) {
if (recyclerAdapter != null) {
for (i in 0 until recyclerAdapter!!.itemCount) {
- val holder: EpisodeItemViewHolder? = recyclerView?.findViewHolderForAdapterPosition(i) as? EpisodeItemViewHolder
+ val holder: EpisodeItemViewHolder? = recyclerView.findViewHolderForAdapterPosition(i) as? EpisodeItemViewHolder
if (holder != null && holder.isCurrentlyPlayingItem) {
holder.notifyPlaybackPositionUpdated(event)
break
@@ -213,8 +291,8 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
return
}
when (event.keyCode) {
- KeyEvent.KEYCODE_T -> recyclerView!!.smoothScrollToPosition(0)
- KeyEvent.KEYCODE_B -> recyclerView!!.smoothScrollToPosition(recyclerAdapter!!.itemCount - 1)
+ KeyEvent.KEYCODE_T -> recyclerView.smoothScrollToPosition(0)
+ KeyEvent.KEYCODE_B -> recyclerView.smoothScrollToPosition(recyclerAdapter!!.itemCount - 1)
else -> {}
}
}
@@ -224,19 +302,19 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
recyclerAdapter?.endSelectMode()
recyclerAdapter = null
- toolbar?.setOnMenuItemClickListener(null)
- toolbar?.setOnLongClickListener(null)
+ toolbar.setOnMenuItemClickListener(null)
+ toolbar.setOnLongClickListener(null)
}
private fun refreshToolbarState() {
val keepSorted: Boolean = UserPreferences.isQueueKeepSorted
- toolbar?.menu?.findItem(R.id.queue_lock)?.setChecked(UserPreferences.isQueueLocked)
- toolbar?.menu?.findItem(R.id.queue_lock)?.setVisible(!keepSorted)
+ toolbar.menu?.findItem(R.id.queue_lock)?.setChecked(UserPreferences.isQueueLocked)
+ toolbar.menu?.findItem(R.id.queue_lock)?.setVisible(!keepSorted)
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: FeedUpdateRunningEvent) {
- swipeRefreshLayout?.isRefreshing = event.isFeedUpdateRunning
+ swipeRefreshLayout.isRefreshing = event.isFeedUpdateRunning
}
@UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
@@ -282,7 +360,7 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
if (isLocked) {
setQueueLocked(false)
} else {
- val shouldShowLockWarning: Boolean = prefs!!.getBoolean(PREF_SHOW_LOCK_WARNING, true)
+ val shouldShowLockWarning: Boolean = prefs.getBoolean(PREF_SHOW_LOCK_WARNING, true)
if (!shouldShowLockWarning) {
setQueueLocked(true)
} else {
@@ -296,7 +374,7 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
builder.setPositiveButton(R.string.lock_queue
) { dialog: DialogInterface?, which: Int ->
- prefs!!.edit().putBoolean(PREF_SHOW_LOCK_WARNING, !checkDoNotShowAgain.isChecked).apply()
+ prefs.edit().putBoolean(PREF_SHOW_LOCK_WARNING, !checkDoNotShowAgain.isChecked).apply()
setQueueLocked(true)
}
builder.setNegativeButton(R.string.cancel_label, null)
@@ -311,7 +389,7 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
if (recyclerAdapter != null) {
recyclerAdapter?.updateDragDropEnabled()
}
- if (queue!!.size == 0) {
+ if (queue.size == 0) {
if (locked) {
(activity as MainActivity).showSnackbarAbovePlayer(R.string.queue_locked, Snackbar.LENGTH_SHORT)
} else {
@@ -334,126 +412,38 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
return true
}
- if (queue != null) {
- val position: Int = FeedItemUtil.indexOfItemWithId(queue!!.toList(), selectedItem.id)
- if (position < 0) {
- Log.i(TAG, "Selected item no longer exist, ignoring selection")
- return super.onContextItemSelected(item)
- }
-
- val itemId = item.itemId
- if (itemId == R.id.move_to_top_item) {
- queue!!.add(0, queue!!.removeAt(position))
- recyclerAdapter?.notifyItemMoved(position, 0)
- DBWriter.moveQueueItemToTop(selectedItem.id, true)
- return true
- } else if (itemId == R.id.move_to_bottom_item) {
- queue!!.add(queue!!.size - 1, queue!!.removeAt(position))
- recyclerAdapter?.notifyItemMoved(position, queue!!.size - 1)
- DBWriter.moveQueueItemToBottom(selectedItem.id, true)
- return true
- }
- }
- return FeedItemMenuHandler.onMenuItemClicked(this, item.itemId, selectedItem)
- }
-
- @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
- super.onCreateView(inflater, container, savedInstanceState)
- val root: View = inflater.inflate(R.layout.queue_fragment, container, false)
- toolbar = root.findViewById(R.id.toolbar)
- toolbar?.setOnMenuItemClickListener(this)
- toolbar?.setOnLongClickListener { v: View? ->
- recyclerView?.scrollToPosition(5)
- recyclerView?.post { recyclerView?.smoothScrollToPosition(0) }
- false
- }
- displayUpArrow = parentFragmentManager.backStackEntryCount != 0
- if (savedInstanceState != null) {
- displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW)
- }
- if (toolbar != null) (activity as MainActivity).setupToolbarToggle(toolbar!!, displayUpArrow)
- toolbar?.inflateMenu(R.menu.queue)
- refreshToolbarState()
- progressBar = root.findViewById(R.id.progressBar)
- progressBar?.visibility = View.VISIBLE
-
- infoBar = root.findViewById(R.id.info_bar)
- recyclerView = root.findViewById(R.id.recyclerView)
- val animator: RecyclerView.ItemAnimator? = recyclerView!!.itemAnimator
- if (animator != null && animator is SimpleItemAnimator) {
- animator.supportsChangeAnimations = false
- }
- recyclerView?.setRecycledViewPool((activity as MainActivity).recycledViewPool)
- registerForContextMenu(recyclerView!!)
- recyclerView?.addOnScrollListener(LiftOnScrollListener(root.findViewById(R.id.appbar)))
-
- swipeActions = QueueSwipeActions()
- swipeActions?.setFilter(FeedItemFilter(FeedItemFilter.QUEUED))
- swipeActions?.attachTo(recyclerView)
-
- recyclerAdapter = object : QueueRecyclerAdapter(activity as MainActivity, swipeActions!!) {
- override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
- super.onCreateContextMenu(menu, v, menuInfo)
- MenuItemUtils.setOnClickListeners(menu
- ) { item: MenuItem -> this@QueueFragment.onContextItemSelected(item) }
- }
+ val position: Int = FeedItemUtil.indexOfItemWithId(queue.toList(), selectedItem.id)
+ if (position < 0) {
+ Log.i(TAG, "Selected item no longer exist, ignoring selection")
+ return super.onContextItemSelected(item)
}
- recyclerAdapter?.setOnSelectModeListener(this)
- recyclerView?.adapter = recyclerAdapter
- swipeRefreshLayout = root.findViewById(R.id.swipeRefresh)
- swipeRefreshLayout?.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
- swipeRefreshLayout?.setOnRefreshListener {
- FeedUpdateManager.runOnceOrAsk(requireContext())
+ val itemId = item.itemId
+ if (itemId == R.id.move_to_top_item) {
+ queue.add(0, queue.removeAt(position))
+ recyclerAdapter?.notifyItemMoved(position, 0)
+ DBWriter.moveQueueItemToTop(selectedItem.id, true)
+ return true
+ } else if (itemId == R.id.move_to_bottom_item) {
+ queue.add(queue.size - 1, queue.removeAt(position))
+ recyclerAdapter?.notifyItemMoved(position, queue.size - 1)
+ DBWriter.moveQueueItemToBottom(selectedItem.id, true)
+ return true
}
- emptyView = EmptyViewHandler(context)
- emptyView?.attachToRecyclerView(recyclerView!!)
- emptyView?.setIcon(R.drawable.ic_playlist_play)
- emptyView?.setTitle(R.string.no_items_header_label)
- emptyView?.setMessage(R.string.no_items_label)
- emptyView?.updateAdapter(recyclerAdapter)
-
- speedDialView = root.findViewById(R.id.fabSD)
- speedDialView?.overlayLayout = root.findViewById(R.id.fabSDOverlay)
- speedDialView?.inflate(R.menu.episodes_apply_action_speeddial)
- speedDialView?.removeActionItemById(R.id.mark_read_batch)
- speedDialView?.removeActionItemById(R.id.mark_unread_batch)
- speedDialView?.removeActionItemById(R.id.add_to_queue_batch)
- speedDialView?.removeActionItemById(R.id.remove_all_inbox_item)
- speedDialView?.setOnChangeListener(object : SpeedDialView.OnChangeListener {
- override fun onMainActionSelected(): Boolean {
- return false
- }
-
- override fun onToggleChanged(open: Boolean) {
- if (open && recyclerAdapter!!.selectedCount == 0) {
- (activity as MainActivity).showSnackbarAbovePlayer(R.string.no_items_selected,
- Snackbar.LENGTH_SHORT)
- speedDialView?.close()
- }
- }
- })
- speedDialView?.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
- EpisodeMultiSelectActionHandler((activity as MainActivity), actionItem.id)
- .handleAction(recyclerAdapter!!.selectedItems.filterIsInstance())
- recyclerAdapter?.endSelectMode()
- true
- }
- return root
+ return FeedItemMenuHandler.onMenuItemClicked(this, item.itemId, selectedItem)
}
-
+
override fun onSaveInstanceState(outState: Bundle) {
outState.putBoolean(KEY_UP_ARROW, displayUpArrow)
super.onSaveInstanceState(outState)
}
private fun refreshInfoBar() {
- if (queue == null) return
- var info = String.format(Locale.getDefault(), "%d%s", queue!!.size, getString(R.string.episodes_suffix))
- if (queue!!.size > 0) {
+ var info = String.format(Locale.getDefault(), "%d%s", queue.size, getString(R.string.episodes_suffix))
+ if (queue.size > 0) {
var timeLeft: Long = 0
- for (item in queue!!) {
+ for (item in queue) {
var playbackSpeed = 1f
if (UserPreferences.timeRespectsSpeed()) {
playbackSpeed = PlaybackSpeedUtils.getCurrentPlaybackSpeed(item.media)
@@ -467,44 +457,44 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
info += getString(R.string.time_left_label)
info += Converter.getDurationStringLocalized(requireActivity(), timeLeft)
}
- infoBar?.text = info
+ infoBar.text = info
}
private fun loadItems(restoreScrollPosition: Boolean) {
Log.d(TAG, "loadItems()")
disposable?.dispose()
- if (queue == null) {
- emptyView?.hide()
+ if (queue.isEmpty()) {
+ emptyView.hide()
}
disposable =
Observable.fromCallable { DBReader.getQueue().toMutableList() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe({ items: MutableList? ->
+ .subscribe({ items: MutableList ->
queue = items
- progressBar?.visibility = View.GONE
+ progressBar.visibility = View.GONE
recyclerAdapter?.setDummyViews(0)
- if (queue != null) recyclerAdapter?.updateItems(queue!!)
+ recyclerAdapter?.updateItems(queue)
if (restoreScrollPosition) {
- recyclerView?.restoreScrollPosition(TAG)
+ recyclerView.restoreScrollPosition(TAG)
}
refreshInfoBar()
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
override fun onStartSelectMode() {
- swipeActions?.detach()
- speedDialView?.visibility = View.VISIBLE
+ swipeActions.detach()
+ speedDialView.visibility = View.VISIBLE
refreshToolbarState()
- infoBar?.visibility = View.GONE
+ infoBar.visibility = View.GONE
}
override fun onEndSelectMode() {
- speedDialView?.close()
- speedDialView?.visibility = View.GONE
- infoBar?.visibility = View.VISIBLE
- swipeActions?.attachTo(recyclerView)
+ speedDialView.close()
+ speedDialView.visibility = View.GONE
+ infoBar.visibility = View.VISIBLE
+ swipeActions.attachTo(recyclerView)
}
class QueueSortDialog : ItemSortDialog() {
@@ -565,10 +555,10 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
val from = viewHolder.bindingAdapterPosition
val to = target.bindingAdapterPosition
Log.d(TAG, "move($from, $to) in memory")
- if (queue == null || from >= queue!!.size || to >= queue!!.size || from < 0 || to < 0) {
+ if (from >= queue.size || to >= queue.size || from < 0 || to < 0) {
return false
}
- queue!!.add(to, queue!!.removeAt(from))
+ queue.add(to, queue.removeAt(from))
recyclerAdapter?.notifyItemMoved(from, to)
return true
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/QuickFeedDiscoveryFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/QuickFeedDiscoveryFragment.kt
index 53bf2c31..75dd8038 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/QuickFeedDiscoveryFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/QuickFeedDiscoveryFragment.kt
@@ -1,26 +1,27 @@
package ac.mdiq.podvinci.fragment
+import ac.mdiq.podvinci.BuildConfig
+import ac.mdiq.podvinci.R
import ac.mdiq.podvinci.activity.MainActivity
+import ac.mdiq.podvinci.activity.OnlineFeedViewActivity
+import ac.mdiq.podvinci.adapter.FeedDiscoverAdapter
+import ac.mdiq.podvinci.core.storage.DBReader
+import ac.mdiq.podvinci.event.DiscoveryDefaultUpdateEvent
+import ac.mdiq.podvinci.net.discovery.ItunesTopListLoader
+import ac.mdiq.podvinci.net.discovery.PodcastSearchResult
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
-import android.text.TextUtils
import android.util.DisplayMetrics
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
+import androidx.annotation.OptIn
import androidx.fragment.app.Fragment
-import ac.mdiq.podvinci.BuildConfig
-import ac.mdiq.podvinci.R
-import ac.mdiq.podvinci.activity.OnlineFeedViewActivity
-import ac.mdiq.podvinci.adapter.FeedDiscoverAdapter
-import ac.mdiq.podvinci.core.storage.DBReader
-import ac.mdiq.podvinci.event.DiscoveryDefaultUpdateEvent
-import ac.mdiq.podvinci.net.discovery.ItunesTopListLoader
-import ac.mdiq.podvinci.net.discovery.PodcastSearchResult
+import androidx.media3.common.util.UnstableApi
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
@@ -32,14 +33,15 @@ import java.util.*
class QuickFeedDiscoveryFragment : Fragment(), AdapterView.OnItemClickListener {
private var disposable: Disposable? = null
- private var adapter: FeedDiscoverAdapter? = null
- private var discoverGridLayout: GridView? = null
- private var errorTextView: TextView? = null
- private var poweredByTextView: TextView? = null
- private var errorView: LinearLayout? = null
- private var errorRetry: Button? = null
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+
+ private lateinit var adapter: FeedDiscoverAdapter
+ private lateinit var discoverGridLayout: GridView
+ private lateinit var errorTextView: TextView
+ private lateinit var poweredByTextView: TextView
+ private lateinit var errorView: LinearLayout
+ private lateinit var errorRetry: Button
+
+ @OptIn(UnstableApi::class) override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
val root: View = inflater.inflate(R.layout.quick_feed_discovery, container, false)
val discoverMore = root.findViewById(R.id.discover_more)
@@ -52,15 +54,15 @@ class QuickFeedDiscoveryFragment : Fragment(), AdapterView.OnItemClickListener {
poweredByTextView = root.findViewById(R.id.discover_powered_by_itunes)
adapter = FeedDiscoverAdapter(activity as MainActivity)
- discoverGridLayout?.setAdapter(adapter)
- discoverGridLayout?.onItemClickListener = this
+ discoverGridLayout.setAdapter(adapter)
+ discoverGridLayout.onItemClickListener = this
val displayMetrics: DisplayMetrics = requireContext().resources.displayMetrics
val screenWidthDp: Float = displayMetrics.widthPixels / displayMetrics.density
if (screenWidthDp > 600) {
- discoverGridLayout?.numColumns = 6
+ discoverGridLayout.numColumns = 6
} else {
- discoverGridLayout?.numColumns = 4
+ discoverGridLayout.numColumns = 4
}
// Fill with dummy elements to have a fixed height and
@@ -70,7 +72,7 @@ class QuickFeedDiscoveryFragment : Fragment(), AdapterView.OnItemClickListener {
dummies.add(PodcastSearchResult.dummy())
}
- adapter?.updateData(dummies)
+ adapter.updateData(dummies)
loadToplist()
EventBus.getDefault().register(this)
@@ -90,31 +92,31 @@ class QuickFeedDiscoveryFragment : Fragment(), AdapterView.OnItemClickListener {
}
private fun loadToplist() {
- errorView?.visibility = View.GONE
- errorRetry!!.visibility = View.INVISIBLE
- errorRetry?.setText(R.string.retry_label)
- poweredByTextView?.visibility = View.VISIBLE
+ errorView.visibility = View.GONE
+ errorRetry.visibility = View.INVISIBLE
+ errorRetry.setText(R.string.retry_label)
+ poweredByTextView.visibility = View.VISIBLE
val loader = ItunesTopListLoader(requireContext())
val prefs: SharedPreferences = requireActivity().getSharedPreferences(ItunesTopListLoader.PREFS, Context.MODE_PRIVATE)
val countryCode: String = prefs.getString(ItunesTopListLoader.PREF_KEY_COUNTRY_CODE,
Locale.getDefault().country)!!
if (prefs.getBoolean(ItunesTopListLoader.PREF_KEY_HIDDEN_DISCOVERY_COUNTRY, false)) {
- errorTextView?.setText(R.string.discover_is_hidden)
- errorView?.visibility = View.VISIBLE
- discoverGridLayout?.visibility = View.GONE
- errorRetry!!.visibility = View.GONE
- poweredByTextView?.visibility = View.GONE
+ errorTextView.setText(R.string.discover_is_hidden)
+ errorView.visibility = View.VISIBLE
+ discoverGridLayout.visibility = View.GONE
+ errorRetry.visibility = View.GONE
+ poweredByTextView.visibility = View.GONE
return
}
if (BuildConfig.FLAVOR == "free" && prefs.getBoolean(ItunesTopListLoader.PREF_KEY_NEEDS_CONFIRM, true)) {
- errorTextView?.text = ""
- errorView?.visibility = View.VISIBLE
- discoverGridLayout?.visibility = View.VISIBLE
- errorRetry!!.visibility = View.VISIBLE
- errorRetry?.setText(R.string.discover_confirm)
- poweredByTextView?.visibility = View.VISIBLE
- errorRetry!!.setOnClickListener { v: View? ->
+ errorTextView.text = ""
+ errorView.visibility = View.VISIBLE
+ discoverGridLayout.visibility = View.VISIBLE
+ errorRetry.visibility = View.VISIBLE
+ errorRetry.setText(R.string.discover_confirm)
+ poweredByTextView.visibility = View.VISIBLE
+ errorRetry.setOnClickListener { v: View? ->
prefs.edit().putBoolean(ItunesTopListLoader.PREF_KEY_NEEDS_CONFIRM, false).apply()
loadToplist()
}
@@ -130,32 +132,32 @@ class QuickFeedDiscoveryFragment : Fragment(), AdapterView.OnItemClickListener {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ podcasts: List ->
- errorView?.visibility = View.GONE
+ errorView.visibility = View.GONE
if (podcasts.isEmpty()) {
- errorTextView?.text = resources.getText(R.string.search_status_no_results)
- errorView?.visibility = View.VISIBLE
- discoverGridLayout?.visibility = View.INVISIBLE
+ errorTextView.text = resources.getText(R.string.search_status_no_results)
+ errorView.visibility = View.VISIBLE
+ discoverGridLayout.visibility = View.INVISIBLE
} else {
- discoverGridLayout?.visibility = View.VISIBLE
- adapter?.updateData(podcasts)
+ discoverGridLayout.visibility = View.VISIBLE
+ adapter.updateData(podcasts)
}
}, { error: Throwable ->
Log.e(TAG, Log.getStackTraceString(error))
- errorTextView?.text = error.localizedMessage
- errorView?.visibility = View.VISIBLE
- discoverGridLayout?.visibility = View.INVISIBLE
- errorRetry!!.visibility = View.VISIBLE
- errorRetry?.setOnClickListener { v: View? -> loadToplist() }
+ errorTextView.text = error.localizedMessage
+ errorView.visibility = View.VISIBLE
+ discoverGridLayout.visibility = View.INVISIBLE
+ errorRetry.visibility = View.VISIBLE
+ errorRetry.setOnClickListener { v: View? -> loadToplist() }
})
}
override fun onItemClick(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
- val podcast: PodcastSearchResult = adapter!!.getItem(position)
- if (TextUtils.isEmpty(podcast.feedUrl)) {
+ val podcast: PodcastSearchResult? = adapter.getItem(position)
+ if (podcast?.feedUrl.isNullOrEmpty()) {
return
}
val intent = Intent(activity, OnlineFeedViewActivity::class.java)
- intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, podcast.feedUrl)
+ intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, podcast!!.feedUrl)
startActivity(intent)
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/SearchFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/SearchFragment.kt
index 83f47d42..62932f6c 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/SearchFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/SearchFragment.kt
@@ -55,18 +55,20 @@ import org.greenrobot.eventbus.ThreadMode
* Performs a search operation on all feeds or one specific feed and displays the search result.
*/
class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
- private var adapter: EpisodeItemListAdapter? = null
- private var adapterFeeds: HorizontalFeedListAdapter? = null
+ private lateinit var adapter: EpisodeItemListAdapter
+ private lateinit var adapterFeeds: HorizontalFeedListAdapter
+ private lateinit var progressBar: ProgressBar
+ private lateinit var emptyViewHandler: EmptyViewHandler
+ private lateinit var recyclerView: EpisodeItemListRecyclerView
+ private lateinit var searchView: SearchView
+ private lateinit var speedDialBinding: MultiSelectSpeedDialBinding
+ private lateinit var chip: Chip
+ private lateinit var automaticSearchDebouncer: Handler
+
+ private var results: MutableList = mutableListOf()
+
private var disposable: Disposable? = null
- private var progressBar: ProgressBar? = null
- private var emptyViewHandler: EmptyViewHandler? = null
- private var recyclerView: EpisodeItemListRecyclerView? = null
- private var results: MutableList? = null
- private var chip: Chip? = null
- private var searchView: SearchView? = null
- private var automaticSearchDebouncer: Handler? = null
private var lastQueryChange: Long = 0
- private var speedDialBinding: MultiSelectSpeedDialBinding? = null
private var isOtherViewInFoucus = false
@@ -89,8 +91,8 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
speedDialBinding = MultiSelectSpeedDialBinding.bind(layout)
progressBar = layout.findViewById(R.id.progressBar)
recyclerView = layout.findViewById(R.id.recyclerView)
- recyclerView?.setRecycledViewPool((activity as MainActivity).recycledViewPool)
- registerForContextMenu(recyclerView!!)
+ recyclerView.setRecycledViewPool((activity as MainActivity).recycledViewPool)
+ registerForContextMenu(recyclerView)
adapter = object : EpisodeItemListAdapter(activity as MainActivity) {
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
super.onCreateContextMenu(menu, v, menuInfo)
@@ -101,9 +103,9 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
) { item: MenuItem -> this@SearchFragment.onContextItemSelected(item) }
}
}
- adapter?.setOnSelectModeListener(this)
- recyclerView?.adapter = adapter
- recyclerView?.addOnScrollListener(LiftOnScrollListener(layout.findViewById(R.id.appbar)))
+ adapter.setOnSelectModeListener(this)
+ recyclerView.adapter = adapter
+ recyclerView.addOnScrollListener(LiftOnScrollListener(layout.findViewById(R.id.appbar)))
val recyclerViewFeeds = layout.findViewById(R.id.recyclerViewFeeds)
val layoutManagerFeeds = LinearLayoutManager(activity)
@@ -121,28 +123,28 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
recyclerViewFeeds.adapter = adapterFeeds
emptyViewHandler = EmptyViewHandler(context)
- emptyViewHandler?.attachToRecyclerView(recyclerView!!)
- emptyViewHandler?.setIcon(R.drawable.ic_search)
- emptyViewHandler?.setTitle(R.string.search_status_no_results)
- emptyViewHandler?.setMessage(R.string.type_to_search)
+ emptyViewHandler.attachToRecyclerView(recyclerView)
+ emptyViewHandler.setIcon(R.drawable.ic_search)
+ emptyViewHandler.setTitle(R.string.search_status_no_results)
+ emptyViewHandler.setMessage(R.string.type_to_search)
EventBus.getDefault().register(this)
chip = layout.findViewById(R.id.feed_title_chip)
- chip?.setOnCloseIconClickListener { v: View? ->
+ chip.setOnCloseIconClickListener { v: View? ->
requireArguments().putLong(ARG_FEED, 0)
searchWithProgressBar()
}
- chip?.visibility = if ((requireArguments().getLong(ARG_FEED, 0) == 0L)) View.GONE else View.VISIBLE
- chip?.text = requireArguments().getString(ARG_FEED_NAME, "")
+ chip.visibility = if ((requireArguments().getLong(ARG_FEED, 0) == 0L)) View.GONE else View.VISIBLE
+ chip.text = requireArguments().getString(ARG_FEED_NAME, "")
if (requireArguments().getString(ARG_QUERY, null) != null) {
search()
}
- searchView!!.setOnQueryTextFocusChangeListener { view: View, hasFocus: Boolean ->
+ searchView.setOnQueryTextFocusChangeListener { view: View, hasFocus: Boolean ->
if (hasFocus && !isOtherViewInFoucus) {
showInputMethod(view.findFocus())
}
}
- recyclerView?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
+ recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
@@ -151,24 +153,24 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
}
}
})
- speedDialBinding!!.fabSD.overlayLayout = speedDialBinding!!.fabSDOverlay
- speedDialBinding!!.fabSD.inflate(R.menu.episodes_apply_action_speeddial)
- speedDialBinding!!.fabSD.setOnChangeListener(object : SpeedDialView.OnChangeListener {
+ speedDialBinding.fabSD.overlayLayout = speedDialBinding.fabSDOverlay
+ speedDialBinding.fabSD.inflate(R.menu.episodes_apply_action_speeddial)
+ speedDialBinding.fabSD.setOnChangeListener(object : SpeedDialView.OnChangeListener {
override fun onMainActionSelected(): Boolean {
return false
}
override fun onToggleChanged(open: Boolean) {
- if (open && adapter!!.selectedCount == 0) {
+ if (open && adapter.selectedCount == 0) {
(activity as MainActivity).showSnackbarAbovePlayer(R.string.no_items_selected, Snackbar.LENGTH_SHORT)
- speedDialBinding!!.fabSD.close()
+ speedDialBinding.fabSD.close()
}
}
})
- speedDialBinding!!.fabSD.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
+ speedDialBinding.fabSD.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
EpisodeMultiSelectActionHandler(activity as MainActivity, actionItem.id)
- .handleAction(adapter!!.selectedItems.filterIsInstance())
- adapter?.endSelectMode()
+ .handleAction(adapter.selectedItems.filterIsInstance())
+ adapter.endSelectMode()
true
}
@@ -187,24 +189,24 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
val item: MenuItem = toolbar.menu.findItem(R.id.action_search)
item.expandActionView()
- searchView = item.actionView as SearchView?
- searchView!!.queryHint = getString(R.string.search_label)
- searchView!!.setQuery(requireArguments().getString(ARG_QUERY), true)
- searchView!!.requestFocus()
- searchView!!.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
+ searchView = item.actionView as SearchView
+ searchView.queryHint = getString(R.string.search_label)
+ searchView.setQuery(requireArguments().getString(ARG_QUERY), true)
+ searchView.requestFocus()
+ searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
@UnstableApi override fun onQueryTextSubmit(s: String): Boolean {
- searchView!!.clearFocus()
+ searchView.clearFocus()
searchWithProgressBar()
return true
}
@UnstableApi override fun onQueryTextChange(s: String): Boolean {
- automaticSearchDebouncer!!.removeCallbacksAndMessages(null)
+ automaticSearchDebouncer.removeCallbacksAndMessages(null)
if (s.isEmpty() || s.endsWith(" ") || (lastQueryChange != 0L
&& System.currentTimeMillis() > lastQueryChange + SEARCH_DEBOUNCE_INTERVAL)) {
search()
} else {
- automaticSearchDebouncer!!.postDelayed({
+ automaticSearchDebouncer.postDelayed({
search()
lastQueryChange = 0 // Don't search instantly with first symbol after some pause
}, (SEARCH_DEBOUNCE_INTERVAL / 2).toLong())
@@ -226,14 +228,14 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
}
override fun onContextItemSelected(item: MenuItem): Boolean {
- val selectedFeedItem: Feed? = adapterFeeds?.longPressedItem
+ val selectedFeedItem: Feed? = adapterFeeds.longPressedItem
if (selectedFeedItem != null
&& FeedMenuHandler.onMenuItemClicked(this, item.itemId, selectedFeedItem) {}) {
return true
}
- val selectedItem: FeedItem? = adapter?.longPressedItem
+ val selectedItem: FeedItem? = adapter.longPressedItem
if (selectedItem != null) {
- if (adapter!!.onContextItemSelected(item)) {
+ if (adapter.onContextItemSelected(item)) {
return true
}
if (FeedItemMenuHandler.onMenuItemClicked(this, item.itemId, selectedItem)) {
@@ -256,21 +258,16 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
@UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: FeedItemEvent) {
Log.d(TAG, "onEventMainThread() called with: event = [$event]")
- if (results == null) {
- return
- } else if (adapter == null) {
- search()
- return
- }
+
var i = 0
val size: Int = event.items.size
while (i < size) {
val item: FeedItem = event.items[i]
- val pos: Int = FeedItemUtil.indexOfItemWithId(results!!, item.id)
+ val pos: Int = FeedItemUtil.indexOfItemWithId(results, item.id)
if (pos >= 0) {
- results!!.removeAt(pos)
- results!!.add(pos, item)
- adapter!!.notifyItemChangedCompat(pos)
+ results.removeAt(pos)
+ results.add(pos, item)
+ adapter.notifyItemChangedCompat(pos)
}
i++
}
@@ -278,27 +275,22 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: EpisodeDownloadEvent) {
- if (results == null) {
- return
- }
for (downloadUrl in event.urls) {
- val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(results!!, downloadUrl)
+ val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(results, downloadUrl)
if (pos >= 0) {
- adapter?.notifyItemChangedCompat(pos)
+ adapter.notifyItemChangedCompat(pos)
}
}
}
@UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: PlaybackPositionEvent) {
- if (adapter != null) {
- for (i in 0 until adapter!!.itemCount) {
- val holder: EpisodeItemViewHolder =
- recyclerView!!.findViewHolderForAdapterPosition(i) as EpisodeItemViewHolder
- if (holder.isCurrentlyPlayingItem) {
- holder.notifyPlaybackPositionUpdated(event)
- break
- }
+ for (i in 0 until adapter.itemCount) {
+ val holder: EpisodeItemViewHolder =
+ recyclerView.findViewHolderForAdapterPosition(i) as EpisodeItemViewHolder
+ if (holder.isCurrentlyPlayingItem) {
+ holder.notifyPlaybackPositionUpdated(event)
+ break
}
}
}
@@ -309,40 +301,40 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
}
@UnstableApi private fun searchWithProgressBar() {
- progressBar?.visibility = View.VISIBLE
- emptyViewHandler?.hide()
+ progressBar.visibility = View.VISIBLE
+ emptyViewHandler.hide()
search()
}
@UnstableApi private fun search() {
disposable?.dispose()
- adapterFeeds?.setEndButton(R.string.search_online) { this.searchOnline() }
- chip?.visibility = if ((requireArguments().getLong(ARG_FEED, 0) == 0L)) View.GONE else View.VISIBLE
+ adapterFeeds.setEndButton(R.string.search_online) { this.searchOnline() }
+ chip.visibility = if ((requireArguments().getLong(ARG_FEED, 0) == 0L)) View.GONE else View.VISIBLE
disposable = Observable.fromCallable { this.performSearch() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ results: Pair?, List?> ->
- progressBar?.visibility = View.GONE
+ progressBar.visibility = View.GONE
if (results.first != null) {
this.results = results.first!!.toMutableList()
- adapter?.updateItems(results.first!!)
+ adapter.updateItems(results.first!!)
}
if (requireArguments().getLong(ARG_FEED, 0) == 0L) {
- if (results.second != null) adapterFeeds?.updateData(results.second!!.filterNotNull())
+ if (results.second != null) adapterFeeds.updateData(results.second!!.filterNotNull())
} else {
- adapterFeeds?.updateData(emptyList())
+ adapterFeeds.updateData(emptyList())
}
- if (searchView!!.query.toString().isEmpty()) {
- emptyViewHandler?.setMessage(R.string.type_to_search)
+ if (searchView.query.toString().isEmpty()) {
+ emptyViewHandler.setMessage(R.string.type_to_search)
} else {
- emptyViewHandler?.setMessage(getString(R.string.no_results_for_query) + searchView!!.query)
+ emptyViewHandler.setMessage(getString(R.string.no_results_for_query) + searchView.query)
}
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
@UnstableApi private fun performSearch(): Pair?, List?> {
- val query = searchView!!.query.toString()
+ val query = searchView.query.toString()
if (query.isEmpty()) {
return Pair?, List?>(emptyList(), emptyList())
}
@@ -358,10 +350,10 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
}
@UnstableApi private fun searchOnline() {
- searchView!!.clearFocus()
+ searchView.clearFocus()
val inVal = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
- inVal.hideSoftInputFromWindow(searchView!!.windowToken, 0)
- val query = searchView!!.query.toString()
+ inVal.hideSoftInputFromWindow(searchView.windowToken, 0)
+ val query = searchView.query.toString()
if (query.matches("http[s]?://.*".toRegex())) {
val intent = Intent(activity, OnlineFeedViewActivity::class.java)
intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, query)
@@ -374,26 +366,26 @@ class SearchFragment : Fragment(), SelectableAdapter.OnSelectModeListener {
override fun onStartSelectMode() {
searchViewFocusOff()
- speedDialBinding!!.fabSD.removeActionItemById(R.id.remove_from_inbox_batch)
- speedDialBinding!!.fabSD.removeActionItemById(R.id.remove_from_queue_batch)
- speedDialBinding!!.fabSD.removeActionItemById(R.id.delete_batch)
- speedDialBinding!!.fabSD.visibility = View.VISIBLE
+ speedDialBinding.fabSD.removeActionItemById(R.id.remove_from_inbox_batch)
+ speedDialBinding.fabSD.removeActionItemById(R.id.remove_from_queue_batch)
+ speedDialBinding.fabSD.removeActionItemById(R.id.delete_batch)
+ speedDialBinding.fabSD.visibility = View.VISIBLE
}
override fun onEndSelectMode() {
- speedDialBinding!!.fabSD.close()
- speedDialBinding!!.fabSD.visibility = View.GONE
+ speedDialBinding.fabSD.close()
+ speedDialBinding.fabSD.visibility = View.GONE
searchViewFocusOn()
}
private fun searchViewFocusOff() {
isOtherViewInFoucus = true
- searchView!!.clearFocus()
+ searchView.clearFocus()
}
private fun searchViewFocusOn() {
isOtherViewInFoucus = false
- searchView!!.requestFocus()
+ searchView.requestFocus()
}
companion object {
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/SubscriptionFragment.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/SubscriptionFragment.kt
index b9b5f4b3..c64fb89b 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/SubscriptionFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/SubscriptionFragment.kt
@@ -52,22 +52,21 @@ import java.util.*
* Fragment for displaying feed subscriptions
*/
class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAdapter.OnSelectModeListener {
- private var subscriptionRecycler: RecyclerView? = null
- private var subscriptionAdapter: SubscriptionsRecyclerAdapter? = null
- private var emptyView: EmptyViewHandler? = null
- private var feedsFilteredMsg: LinearLayout? = null
- private var toolbar: MaterialToolbar? = null
- private var swipeRefreshLayout: SwipeRefreshLayout? = null
- private var progressBar: ProgressBar? = null
- private var displayedFolder: String? = null
+ private lateinit var subscriptionRecycler: RecyclerView
+ private lateinit var subscriptionAdapter: SubscriptionsRecyclerAdapter
+ private lateinit var emptyView: EmptyViewHandler
+ private lateinit var feedsFilteredMsg: LinearLayout
+ private lateinit var toolbar: MaterialToolbar
+ private lateinit var swipeRefreshLayout: SwipeRefreshLayout
+ private lateinit var progressBar: ProgressBar
+ private lateinit var displayedFolder: String
+ private lateinit var prefs: SharedPreferences
+ private lateinit var speedDialView: SpeedDialView
+
private var displayUpArrow = false
private var disposable: Disposable? = null
- private var prefs: SharedPreferences? = null
-
- private var speedDialView: SpeedDialView? = null
-
- private var listItems: List? = null
+ private var listItems: List = mutableListOf()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -81,36 +80,34 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
): View {
val root: View = inflater.inflate(R.layout.fragment_subscriptions, container, false)
toolbar = root.findViewById(R.id.toolbar)
- toolbar?.setOnMenuItemClickListener(this)
- toolbar?.setOnLongClickListener { v: View? ->
- subscriptionRecycler!!.scrollToPosition(5)
- subscriptionRecycler!!.post { subscriptionRecycler!!.smoothScrollToPosition(0) }
+ toolbar.setOnMenuItemClickListener(this)
+ toolbar.setOnLongClickListener { v: View? ->
+ subscriptionRecycler.scrollToPosition(5)
+ subscriptionRecycler.post { subscriptionRecycler.smoothScrollToPosition(0) }
false
}
displayUpArrow = parentFragmentManager.backStackEntryCount != 0
if (savedInstanceState != null) {
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW)
}
- if (toolbar != null) (activity as MainActivity).setupToolbarToggle(toolbar!!, displayUpArrow)
- toolbar?.inflateMenu(R.menu.subscriptions)
+ (activity as MainActivity).setupToolbarToggle(toolbar, displayUpArrow)
+ toolbar.inflateMenu(R.menu.subscriptions)
for (i in COLUMN_CHECKBOX_IDS.indices) {
// Do this in Java to localize numbers
- toolbar?.menu?.findItem(COLUMN_CHECKBOX_IDS[i])
+ toolbar.menu?.findItem(COLUMN_CHECKBOX_IDS[i])
?.setTitle(String.format(Locale.getDefault(), "%d", i + MIN_NUM_COLUMNS))
}
refreshToolbarState()
if (arguments != null) {
displayedFolder = requireArguments().getString(ARGUMENT_FOLDER, null)
- if (displayedFolder != null) {
- toolbar?.title = displayedFolder
- }
+ toolbar.title = displayedFolder
}
subscriptionRecycler = root.findViewById(R.id.subscriptions_grid)
- subscriptionRecycler?.addItemDecoration(SubscriptionsRecyclerAdapter.GridDividerItemDecorator())
- if (subscriptionRecycler != null) registerForContextMenu(subscriptionRecycler!!)
- subscriptionRecycler?.addOnScrollListener(LiftOnScrollListener(root.findViewById(R.id.appbar)))
+ subscriptionRecycler.addItemDecoration(SubscriptionsRecyclerAdapter.GridDividerItemDecorator())
+ registerForContextMenu(subscriptionRecycler)
+ subscriptionRecycler.addOnScrollListener(LiftOnScrollListener(root.findViewById(R.id.appbar)))
subscriptionAdapter = object : SubscriptionsRecyclerAdapter(activity as MainActivity) {
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
super.onCreateContextMenu(menu, v, menuInfo)
@@ -120,13 +117,13 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
}
}
}
- setColumnNumber(prefs!!.getInt(PREF_NUM_COLUMNS, defaultNumOfColumns))
- subscriptionAdapter?.setOnSelectModeListener(this)
- subscriptionRecycler?.adapter = subscriptionAdapter
+ setColumnNumber(prefs.getInt(PREF_NUM_COLUMNS, defaultNumOfColumns))
+ subscriptionAdapter.setOnSelectModeListener(this)
+ subscriptionRecycler.adapter = subscriptionAdapter
setupEmptyView()
progressBar = root.findViewById(R.id.progressBar)
- progressBar?.visibility = View.VISIBLE
+ progressBar.visibility = View.VISIBLE
val subscriptionAddButton: FloatingActionButton =
root.findViewById(R.id.subscriptions_add)
@@ -137,21 +134,21 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
}
feedsFilteredMsg = root.findViewById(R.id.feeds_filtered_message)
- feedsFilteredMsg?.setOnClickListener { l: View? ->
+ feedsFilteredMsg.setOnClickListener { l: View? ->
SubscriptionsFilterDialog().show(
childFragmentManager, "filter")
}
swipeRefreshLayout = root.findViewById(R.id.swipeRefresh)
- swipeRefreshLayout?.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
- swipeRefreshLayout?.setOnRefreshListener {
+ swipeRefreshLayout.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
+ swipeRefreshLayout.setOnRefreshListener {
FeedUpdateManager.runOnceOrAsk(requireContext())
}
speedDialView = root.findViewById(R.id.fabSD)
- speedDialView?.overlayLayout = root.findViewById(R.id.fabSDOverlay)
- speedDialView?.inflate(R.menu.nav_feed_action_speeddial)
- speedDialView?.setOnChangeListener(object : SpeedDialView.OnChangeListener {
+ speedDialView.overlayLayout = root.findViewById(R.id.fabSDOverlay)
+ speedDialView.inflate(R.menu.nav_feed_action_speeddial)
+ speedDialView.setOnChangeListener(object : SpeedDialView.OnChangeListener {
override fun onMainActionSelected(): Boolean {
return false
}
@@ -159,9 +156,9 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
override fun onToggleChanged(isOpen: Boolean) {
}
})
- speedDialView?.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
+ speedDialView.setOnActionSelectedListener { actionItem: SpeedDialActionItem ->
FeedMultiSelectActionHandler(activity as MainActivity,
- subscriptionAdapter!!.selectedItems.filterIsInstance()).handleAction(actionItem.id)
+ subscriptionAdapter.selectedItems.filterIsInstance()).handleAction(actionItem.id)
true
}
@@ -174,13 +171,13 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
}
private fun refreshToolbarState() {
- val columns: Int = prefs!!.getInt(PREF_NUM_COLUMNS, defaultNumOfColumns)
- toolbar?.menu?.findItem(COLUMN_CHECKBOX_IDS[columns - MIN_NUM_COLUMNS])?.setChecked(true)
+ val columns: Int = prefs.getInt(PREF_NUM_COLUMNS, defaultNumOfColumns)
+ toolbar.menu?.findItem(COLUMN_CHECKBOX_IDS[columns - MIN_NUM_COLUMNS])?.setChecked(true)
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: FeedUpdateRunningEvent) {
- swipeRefreshLayout?.isRefreshing = event.isFeedUpdateRunning
+ swipeRefreshLayout.isRefreshing = event.isFeedUpdateRunning
}
@UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
@@ -229,18 +226,18 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
private fun setColumnNumber(columns: Int) {
val gridLayoutManager = GridLayoutManager(context,
columns, RecyclerView.VERTICAL, false)
- subscriptionAdapter?.setColumnCount(columns)
- subscriptionRecycler!!.layoutManager = gridLayoutManager
- prefs!!.edit().putInt(PREF_NUM_COLUMNS, columns).apply()
+ subscriptionAdapter.setColumnCount(columns)
+ subscriptionRecycler.layoutManager = gridLayoutManager
+ prefs.edit().putInt(PREF_NUM_COLUMNS, columns).apply()
refreshToolbarState()
}
private fun setupEmptyView() {
emptyView = EmptyViewHandler(context)
- emptyView?.setIcon(R.drawable.ic_subscriptions)
- emptyView?.setTitle(R.string.no_subscriptions_head_label)
- emptyView?.setMessage(R.string.no_subscriptions_label)
- if (subscriptionRecycler != null) emptyView?.attachToRecyclerView(subscriptionRecycler!!)
+ emptyView.setIcon(R.drawable.ic_subscriptions)
+ emptyView.setTitle(R.string.no_subscriptions_head_label)
+ emptyView.setMessage(R.string.no_subscriptions_label)
+ emptyView.attachToRecyclerView(subscriptionRecycler)
}
override fun onStart() {
@@ -253,13 +250,12 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
super.onStop()
EventBus.getDefault().unregister(this)
disposable?.dispose()
- subscriptionAdapter?.endSelectMode()
+ subscriptionAdapter.endSelectMode()
}
private fun loadSubscriptions() {
disposable?.dispose()
-
- emptyView?.hide()
+ emptyView.hide()
disposable = Observable.fromCallable {
val data: NavDrawerData = DBReader.getNavDrawerData(UserPreferences.subscriptionsFilter)
val items: List = data.items
@@ -273,23 +269,23 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
- { result: List ->
- if (listItems != null && listItems!!.size > result.size) {
+ { result: List ->
+ if ( listItems.size > result.size) {
// We have fewer items. This can result in items being selected that are no longer visible.
- subscriptionAdapter?.endSelectMode()
+ subscriptionAdapter.endSelectMode()
}
listItems = result
- progressBar?.visibility = View.GONE
- subscriptionAdapter?.setItems(result.filterNotNull())
- emptyView?.updateVisibility()
+ progressBar.visibility = View.GONE
+ subscriptionAdapter.setItems(result)
+ emptyView.updateVisibility()
}, { error: Throwable? ->
Log.e(TAG, Log.getStackTraceString(error))
})
if (UserPreferences.subscriptionsFilter.isEnabled) {
- feedsFilteredMsg?.visibility = View.VISIBLE
+ feedsFilteredMsg.visibility = View.VISIBLE
} else {
- feedsFilteredMsg?.visibility = View.GONE
+ feedsFilteredMsg.visibility = View.GONE
}
}
@@ -297,7 +293,7 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
get() = resources.getInteger(R.integer.subscriptions_default_num_of_columns)
override fun onContextItemSelected(item: MenuItem): Boolean {
- val drawerItem: NavDrawerData.DrawerItem = subscriptionAdapter!!.getSelectedItem() ?: return false
+ val drawerItem: NavDrawerData.DrawerItem = subscriptionAdapter.getSelectedItem() ?: return false
val itemId = item.itemId
if (drawerItem.type == NavDrawerData.DrawerItem.Type.TAG && itemId == R.id.rename_folder_item) {
RenameItemDialog(activity as Activity, drawerItem).show()
@@ -306,8 +302,8 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
val feed: Feed = (drawerItem as NavDrawerData.FeedDrawerItem).feed
if (itemId == R.id.multi_select) {
- speedDialView?.visibility = View.VISIBLE
- return subscriptionAdapter!!.onContextItemSelected(item)
+ speedDialView.visibility = View.VISIBLE
+ return subscriptionAdapter.onContextItemSelected(item)
}
return FeedMenuHandler.onMenuItemClicked(this, item.itemId, feed) { this.loadSubscriptions() }
}
@@ -323,20 +319,19 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
}
override fun onEndSelectMode() {
- speedDialView?.close()
- speedDialView?.visibility = View.GONE
- if (listItems != null) subscriptionAdapter?.setItems(listItems!!.filterNotNull())
+ speedDialView.close()
+ speedDialView.visibility = View.GONE
+ subscriptionAdapter.setItems(listItems)
}
override fun onStartSelectMode() {
val feedsOnly: MutableList = ArrayList()
- if (listItems != null) for (item in listItems!!) {
- if (item == null) continue
+ for (item in listItems) {
if (item.type == NavDrawerData.DrawerItem.Type.FEED) {
feedsOnly.add(item)
}
}
- subscriptionAdapter?.setItems(feedsOnly)
+ subscriptionAdapter.setItems(feedsOnly)
}
companion object {
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/actions/EpisodeMultiSelectActionHandler.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/actions/EpisodeMultiSelectActionHandler.kt
index b0095bb1..27e6faea 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/actions/EpisodeMultiSelectActionHandler.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/actions/EpisodeMultiSelectActionHandler.kt
@@ -10,7 +10,9 @@ import ac.mdiq.podvinci.core.util.LongList
import ac.mdiq.podvinci.model.feed.FeedItem
import ac.mdiq.podvinci.net.download.serviceinterface.DownloadServiceInterface
import ac.mdiq.podvinci.view.LocalDeleteModal
+import androidx.media3.common.util.UnstableApi
+@UnstableApi
class EpisodeMultiSelectActionHandler(private val activity: MainActivity, private val actionId: Int) {
private var totalNumItems = 0
private var snackbar: Snackbar? = null
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/actions/FeedMultiSelectActionHandler.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/actions/FeedMultiSelectActionHandler.kt
index 81c073b2..794322d0 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/actions/FeedMultiSelectActionHandler.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/actions/FeedMultiSelectActionHandler.kt
@@ -17,8 +17,10 @@ import ac.mdiq.podvinci.fragment.preferences.dialog.PreferenceListDialog
import ac.mdiq.podvinci.fragment.preferences.dialog.PreferenceSwitchDialog
import ac.mdiq.podvinci.model.feed.Feed
import ac.mdiq.podvinci.model.feed.FeedPreferences
+import androidx.media3.common.util.UnstableApi
import java.util.*
+@UnstableApi
class FeedMultiSelectActionHandler(private val activity: MainActivity, private val selectedItems: List) {
fun handleAction(id: Int) {
@@ -56,7 +58,7 @@ class FeedMultiSelectActionHandler(private val activity: MainActivity, private v
activity.getString(R.string.episode_notification_summary))
preferenceSwitchDialog.setOnPreferenceChangedListener(object: PreferenceSwitchDialog.OnPreferenceChangedListener {
- override fun preferenceChanged(enabled: Boolean) {
+ @UnstableApi override fun preferenceChanged(enabled: Boolean) {
saveFeedPreferences { feedPreferences: FeedPreferences ->
feedPreferences.showEpisodeNotification = enabled
}
@@ -69,7 +71,7 @@ class FeedMultiSelectActionHandler(private val activity: MainActivity, private v
val preferenceSwitchDialog = PreferenceSwitchDialog(activity,
activity.getString(R.string.auto_download_settings_label),
activity.getString(R.string.auto_download_label))
- preferenceSwitchDialog.setOnPreferenceChangedListener(object: PreferenceSwitchDialog.OnPreferenceChangedListener {
+ preferenceSwitchDialog.setOnPreferenceChangedListener(@UnstableApi object: PreferenceSwitchDialog.OnPreferenceChangedListener {
override fun preferenceChanged(enabled: Boolean) {
saveFeedPreferences { feedPreferences: FeedPreferences -> feedPreferences.autoDownload = enabled }
}
@@ -77,7 +79,7 @@ class FeedMultiSelectActionHandler(private val activity: MainActivity, private v
preferenceSwitchDialog.openDialog()
}
- private fun playbackSpeedPrefHandler() {
+ @UnstableApi private fun playbackSpeedPrefHandler() {
val viewBinding =
PlaybackSpeedFeedSettingDialogBinding.inflate(activity.layoutInflater)
viewBinding.seekBar.setProgressChangedListener { speed: Float? ->
@@ -110,7 +112,7 @@ class FeedMultiSelectActionHandler(private val activity: MainActivity, private v
val items: Array = activity.resources.getStringArray(R.array.spnAutoDeleteItems)
preferenceListDialog.openDialog(items)
preferenceListDialog.setOnPreferenceChangedListener(object: PreferenceListDialog.OnPreferenceChangedListener {
- override fun preferenceChanged(which: Int) {
+ @UnstableApi override fun preferenceChanged(which: Int) {
val autoDeleteAction: FeedPreferences.AutoDeleteAction = FeedPreferences.AutoDeleteAction.fromCode(which)
saveFeedPreferences { feedPreferences: FeedPreferences ->
feedPreferences.currentAutoDelete = autoDeleteAction
@@ -124,7 +126,7 @@ class FeedMultiSelectActionHandler(private val activity: MainActivity, private v
activity.getString(R.string.kept_updated),
activity.getString(R.string.keep_updated_summary))
preferenceSwitchDialog.setOnPreferenceChangedListener(object: PreferenceSwitchDialog.OnPreferenceChangedListener {
- override fun preferenceChanged(keepUpdated: Boolean) {
+ @UnstableApi override fun preferenceChanged(keepUpdated: Boolean) {
saveFeedPreferences { feedPreferences: FeedPreferences ->
feedPreferences.keepUpdated = keepUpdated
}
@@ -133,12 +135,12 @@ class FeedMultiSelectActionHandler(private val activity: MainActivity, private v
preferenceSwitchDialog.openDialog()
}
- private fun showMessage(@PluralsRes msgId: Int, numItems: Int) {
+ @UnstableApi private fun showMessage(@PluralsRes msgId: Int, numItems: Int) {
activity.showSnackbarAbovePlayer(activity.resources
.getQuantityString(msgId, numItems, numItems), Snackbar.LENGTH_LONG)
}
- private fun saveFeedPreferences(preferencesConsumer: Consumer) {
+ @UnstableApi private fun saveFeedPreferences(preferencesConsumer: Consumer) {
for (feed in selectedItems) {
if (feed.preferences == null) continue
preferencesConsumer.accept(feed.preferences)
diff --git a/app/src/main/java/ac/mdiq/podvinci/fragment/swipeactions/DeleteSwipeAction.kt b/app/src/main/java/ac/mdiq/podvinci/fragment/swipeactions/DeleteSwipeAction.kt
index f88f28aa..08dfee50 100644
--- a/app/src/main/java/ac/mdiq/podvinci/fragment/swipeactions/DeleteSwipeAction.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/fragment/swipeactions/DeleteSwipeAction.kt
@@ -30,9 +30,8 @@ class DeleteSwipeAction : SwipeAction {
if (!item.isDownloaded && !item.feed!!.isLocalFeed) {
return
}
- showLocalFeedDeleteWarningIfNecessary(
- fragment.requireContext(), listOf(item)
- ) { DBWriter.deleteFeedMediaOfItem(fragment.requireContext(), item.media!!.id) }
+ showLocalFeedDeleteWarningIfNecessary(fragment.requireContext(), listOf(item)) {
+ DBWriter.deleteFeedMediaOfItem(fragment.requireContext(), item.media!!.id) }
}
override fun willRemove(filter: FeedItemFilter, item: FeedItem): Boolean {
diff --git a/app/src/main/java/ac/mdiq/podvinci/menuhandler/FeedItemMenuHandler.kt b/app/src/main/java/ac/mdiq/podvinci/menuhandler/FeedItemMenuHandler.kt
index 24b59ad4..e40a3a98 100644
--- a/app/src/main/java/ac/mdiq/podvinci/menuhandler/FeedItemMenuHandler.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/menuhandler/FeedItemMenuHandler.kt
@@ -21,11 +21,13 @@ import ac.mdiq.podvinci.model.feed.FeedItem
import ac.mdiq.podvinci.model.feed.FeedMedia
import ac.mdiq.podvinci.net.sync.model.EpisodeAction
import ac.mdiq.podvinci.view.LocalDeleteModal
+import androidx.annotation.OptIn
import kotlin.math.ceil
/**
* Handles interactions with the FeedItemMenu.
*/
+@OptIn(UnstableApi::class)
object FeedItemMenuHandler {
private const val TAG = "FeedItemMenuHandler"
@@ -115,7 +117,7 @@ object FeedItemMenuHandler {
return false
}
val rc = onPrepareMenu(menu, selectedItem)
- if (rc && excludeIds != null) {
+ if (rc && excludeIds.isNotEmpty()) {
for (id in excludeIds) {
setItemVisibility(menu, id, false)
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeFragment.kt b/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeFragment.kt
index 55ae0a7c..efce2e89 100644
--- a/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeFragment.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeFragment.kt
@@ -29,6 +29,7 @@ import ac.mdiq.podvinci.storage.preferences.UserPreferences
import ac.mdiq.podvinci.ui.echo.EchoActivity
import ac.mdiq.podvinci.ui.home.sections.*
import ac.mdiq.podvinci.view.LiftOnScrollListener
+import androidx.media3.common.util.UnstableApi
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
@@ -43,33 +44,32 @@ import java.util.*
*/
class HomeFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private var displayUpArrow = false
- private var viewBinding: HomeFragmentBinding? = null
private var disposable: Disposable? = null
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ private lateinit var viewBinding: HomeFragmentBinding
+
+ @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
viewBinding = HomeFragmentBinding.inflate(inflater)
- viewBinding!!.toolbar.inflateMenu(R.menu.home)
- viewBinding!!.toolbar.setOnMenuItemClickListener(this)
- if (savedInstanceState != null) {
- displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW)
- }
- viewBinding!!.homeScrollView.setOnScrollChangeListener(LiftOnScrollListener(
- viewBinding!!.appbar))
- (requireActivity() as MainActivity).setupToolbarToggle(viewBinding!!.toolbar, displayUpArrow)
+ viewBinding.toolbar.inflateMenu(R.menu.home)
+ viewBinding.toolbar.setOnMenuItemClickListener(this)
+ displayUpArrow = savedInstanceState?.getBoolean(KEY_UP_ARROW)?:false
+
+ viewBinding.homeScrollView.setOnScrollChangeListener(LiftOnScrollListener(viewBinding.appbar))
+ (requireActivity() as MainActivity).setupToolbarToggle(viewBinding.toolbar, displayUpArrow)
populateSectionList()
updateWelcomeScreenVisibility()
- viewBinding!!.swipeRefresh.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
- viewBinding!!.swipeRefresh.setOnRefreshListener {
+ viewBinding.swipeRefresh.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
+ viewBinding.swipeRefresh.setOnRefreshListener {
FeedUpdateManager.runOnceOrAsk(requireContext())
}
- return viewBinding!!.root
+ return viewBinding.root
}
private fun populateSectionList() {
- viewBinding!!.homeContainer.removeAllViews()
+ viewBinding.homeContainer.removeAllViews()
val prefs: SharedPreferences = requireContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
if (Build.VERSION.SDK_INT >= 33 && ContextCompat.checkSelfPermission(requireContext(),
@@ -78,8 +78,10 @@ class HomeFragment : Fragment(), Toolbar.OnMenuItemClickListener {
addSection(AllowNotificationsSection())
}
}
- if (Calendar.getInstance()[Calendar.YEAR] == EchoActivity.RELEASE_YEAR && Calendar.getInstance()[Calendar.MONTH] == Calendar.DECEMBER && Calendar.getInstance()[Calendar.DAY_OF_MONTH] >= 10 && prefs.getInt(
- PREF_HIDE_ECHO, 0) != EchoActivity.RELEASE_YEAR) {
+ if (Calendar.getInstance()[Calendar.YEAR] == EchoActivity.RELEASE_YEAR &&
+ Calendar.getInstance()[Calendar.MONTH] == Calendar.DECEMBER &&
+ Calendar.getInstance()[Calendar.DAY_OF_MONTH] >= 10 &&
+ prefs.getInt(PREF_HIDE_ECHO, 0) != EchoActivity.RELEASE_YEAR) {
addSection(EchoSection())
}
@@ -96,8 +98,8 @@ class HomeFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private fun addSection(section: Fragment?) {
val containerView = FragmentContainerView(requireContext())
containerView.id = View.generateViewId()
- viewBinding!!.homeContainer.addView(containerView)
- childFragmentManager.beginTransaction().add(containerView.id, section!!).commit()
+ viewBinding.homeContainer.addView(containerView)
+ if (section != null) childFragmentManager.beginTransaction().add(containerView.id, section).commit()
}
private fun getSection(tag: String): Fragment? {
@@ -113,10 +115,10 @@ class HomeFragment : Fragment(), Toolbar.OnMenuItemClickListener {
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: FeedUpdateRunningEvent) {
- viewBinding!!.swipeRefresh.isRefreshing = event.isFeedUpdateRunning
+ viewBinding.swipeRefresh.isRefreshing = event.isFeedUpdateRunning
}
- override fun onMenuItemClick(item: MenuItem): Boolean {
+ @UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
when (item.itemId) {
R.id.homesettings_items -> {
HomeSectionsSettingsDialog.open(requireContext()
@@ -128,7 +130,7 @@ class HomeFragment : Fragment(), Toolbar.OnMenuItemClickListener {
return true
}
R.id.action_search -> {
- (activity as MainActivity?)?.loadChildFragment(SearchFragment.newInstance())
+ (activity as MainActivity).loadChildFragment(SearchFragment.newInstance())
return true
}
else -> return super.onOptionsItemSelected(item)
@@ -156,16 +158,14 @@ class HomeFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
private fun updateWelcomeScreenVisibility() {
- if (disposable != null) {
- disposable?.dispose()
- }
- disposable =
- Observable.fromCallable { DBReader.getNavDrawerData(UserPreferences.subscriptionsFilter).items.size }
+ disposable?.dispose()
+
+ disposable = Observable.fromCallable { DBReader.getNavDrawerData(UserPreferences.subscriptionsFilter).items.size }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ numSubscriptions: Int ->
- viewBinding!!.welcomeContainer.visibility = if (numSubscriptions == 0) View.VISIBLE else View.GONE
- viewBinding!!.homeContainer.visibility = if (numSubscriptions == 0) View.GONE else View.VISIBLE
+ viewBinding.welcomeContainer.visibility = if (numSubscriptions == 0) View.VISIBLE else View.GONE
+ viewBinding.homeContainer.visibility = if (numSubscriptions == 0) View.GONE else View.VISIBLE
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeSection.kt b/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeSection.kt
index 138ebe71..6365adb8 100644
--- a/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeSection.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeSection.kt
@@ -24,28 +24,25 @@ import java.util.*
* Section on the HomeFragment
*/
abstract class HomeSection : Fragment(), OnCreateContextMenuListener {
- @JvmField
- protected var viewBinding: HomeSectionBinding? = null
+ protected lateinit var viewBinding: HomeSectionBinding
- override fun onCreateView(inflater: LayoutInflater,
- container: ViewGroup?, savedInstanceState: Bundle?
- ): View {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
viewBinding = HomeSectionBinding.inflate(inflater)
- viewBinding!!.titleLabel.text = sectionTitle
+ viewBinding.titleLabel.text = sectionTitle
if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_LTR) {
- viewBinding!!.moreButton.text = "$moreLinkTitle\u00A0»"
+ viewBinding.moreButton.text = "$moreLinkTitle\u00A0»"
} else {
- viewBinding!!.moreButton.text = "«\u00A0$moreLinkTitle"
+ viewBinding.moreButton.text = "«\u00A0$moreLinkTitle"
}
- viewBinding!!.moreButton.setOnClickListener { view: View? -> handleMoreClick() }
+ viewBinding.moreButton.setOnClickListener { view: View? -> handleMoreClick() }
if (TextUtils.isEmpty(moreLinkTitle)) {
- viewBinding!!.moreButton.visibility = View.INVISIBLE
+ viewBinding.moreButton.visibility = View.INVISIBLE
}
// Dummies are necessary to ensure height, but do not animate them
- viewBinding!!.recyclerView.itemAnimator = null
- viewBinding!!.recyclerView.postDelayed(
- { viewBinding!!.recyclerView.itemAnimator = DefaultItemAnimator() }, 500)
- return viewBinding!!.root
+ viewBinding.recyclerView.itemAnimator = null
+ viewBinding.recyclerView.postDelayed(
+ { viewBinding.recyclerView.itemAnimator = DefaultItemAnimator() }, 500)
+ return viewBinding.root
}
override fun onContextItemSelected(item: MenuItem): Boolean {
@@ -54,19 +51,19 @@ abstract class HomeSection : Fragment(), OnCreateContextMenuListener {
// Apparently, none of the visibility check method works reliably on its own, so we just use all.
return false
}
- if (viewBinding!!.recyclerView.adapter is HorizontalFeedListAdapter) {
- val adapter = viewBinding!!.recyclerView.adapter as HorizontalFeedListAdapter?
- val selectedFeed = adapter!!.longPressedItem
- return (selectedFeed != null
- && FeedMenuHandler.onMenuItemClicked(this, item.itemId, selectedFeed) {})
+ if (viewBinding.recyclerView.adapter is HorizontalFeedListAdapter) {
+ val adapter = viewBinding.recyclerView.adapter as? HorizontalFeedListAdapter
+ val selectedFeed = adapter?.longPressedItem
+ return (selectedFeed != null && FeedMenuHandler.onMenuItemClicked(this, item.itemId, selectedFeed) {})
}
+
var longPressedItem: FeedItem? = null
- if (viewBinding!!.recyclerView.adapter is EpisodeItemListAdapter) {
- val adapter = viewBinding!!.recyclerView.adapter as EpisodeItemListAdapter?
- if (adapter != null) longPressedItem = adapter.longPressedItem
- } else if (viewBinding!!.recyclerView.adapter is HorizontalItemListAdapter) {
- val adapter = viewBinding!!.recyclerView.adapter as HorizontalItemListAdapter?
- if (adapter != null) longPressedItem = adapter.longPressedItem
+ if (viewBinding.recyclerView.adapter is EpisodeItemListAdapter) {
+ val adapter = viewBinding.recyclerView.adapter as? EpisodeItemListAdapter
+ longPressedItem = adapter?.longPressedItem
+ } else if (viewBinding.recyclerView.adapter is HorizontalItemListAdapter) {
+ val adapter = viewBinding.recyclerView.adapter as HorizontalItemListAdapter?
+ longPressedItem = adapter?.longPressedItem
} else {
return false
}
@@ -81,13 +78,13 @@ abstract class HomeSection : Fragment(), OnCreateContextMenuListener {
override fun onStart() {
super.onStart()
EventBus.getDefault().register(this)
- registerForContextMenu(viewBinding!!.recyclerView)
+ registerForContextMenu(viewBinding.recyclerView)
}
override fun onStop() {
super.onStop()
EventBus.getDefault().unregister(this)
- unregisterForContextMenu(viewBinding!!.recyclerView)
+ unregisterForContextMenu(viewBinding.recyclerView)
}
protected abstract val sectionTitle: String?
diff --git a/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeSectionsSettingsDialog.kt b/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeSectionsSettingsDialog.kt
index 8fa85617..783a1c5d 100644
--- a/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeSectionsSettingsDialog.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/ui/home/HomeSectionsSettingsDialog.kt
@@ -22,8 +22,7 @@ object HomeSectionsSettingsDialog {
val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(R.string.configure_home)
- builder.setMultiChoiceItems(sectionLabels,
- checked) { dialog: DialogInterface?, which: Int, isChecked: Boolean ->
+ builder.setMultiChoiceItems(sectionLabels, checked) { dialog: DialogInterface?, which: Int, isChecked: Boolean ->
if (isChecked) {
hiddenSections.remove(sectionTags[which])
} else {
diff --git a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/AllowNotificationsSection.kt b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/AllowNotificationsSection.kt
index 054443d6..af9b8b57 100644
--- a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/AllowNotificationsSection.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/AllowNotificationsSection.kt
@@ -19,37 +19,39 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import ac.mdiq.podvinci.R
import ac.mdiq.podvinci.databinding.HomeSectionNotificationBinding
import ac.mdiq.podvinci.ui.home.HomeFragment
+import androidx.media3.common.util.UnstableApi
+@UnstableApi
class AllowNotificationsSection : Fragment() {
- var viewBinding: HomeSectionNotificationBinding? = null
+ lateinit var viewBinding: HomeSectionNotificationBinding
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
(activity as MainActivity).loadFragment(HomeFragment.TAG, null)
} else {
- viewBinding!!.openSettingsButton.visibility = View.VISIBLE
- viewBinding!!.allowButton.visibility = View.GONE
+ viewBinding.openSettingsButton.visibility = View.VISIBLE
+ viewBinding.allowButton.visibility = View.GONE
Toast.makeText(context, R.string.notification_permission_denied, Toast.LENGTH_LONG).show()
}
}
- override fun onCreateView(inflater: LayoutInflater,
- container: ViewGroup?, savedInstanceState: Bundle?
+ @UnstableApi override fun onCreateView(inflater: LayoutInflater,
+ container: ViewGroup?, savedInstanceState: Bundle?
): View {
viewBinding = HomeSectionNotificationBinding.inflate(inflater)
- viewBinding!!.allowButton.setOnClickListener { v: View? ->
+ viewBinding.allowButton.setOnClickListener { v: View? ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
}
- viewBinding!!.openSettingsButton.setOnClickListener { view: View? ->
+ viewBinding.openSettingsButton.setOnClickListener { view: View? ->
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri = Uri.fromParts("package", requireContext().packageName, null)
intent.setData(uri)
startActivity(intent)
}
- viewBinding!!.denyButton.setOnClickListener { v: View? ->
+ viewBinding.denyButton.setOnClickListener { v: View? ->
val builder = MaterialAlertDialogBuilder(requireContext())
builder.setMessage(R.string.notification_permission_deny_warning)
builder.setPositiveButton(R.string.deny_label
@@ -61,6 +63,6 @@ class AllowNotificationsSection : Fragment() {
builder.setNegativeButton(R.string.cancel_label, null)
builder.show()
}
- return viewBinding!!.root
+ return viewBinding.root
}
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/DownloadsSection.kt b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/DownloadsSection.kt
index 34213dbc..b1149693 100644
--- a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/DownloadsSection.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/DownloadsSection.kt
@@ -32,17 +32,15 @@ import org.greenrobot.eventbus.ThreadMode
class DownloadsSection : HomeSection() {
private var adapter: EpisodeItemListAdapter? = null
- private var items: List? = null
private var disposable: Disposable? = null
- @UnstableApi override fun onCreateView(inflater: LayoutInflater,
- container: ViewGroup?, savedInstanceState: Bundle?
+ @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
val view: View = super.onCreateView(inflater, container, savedInstanceState)
- viewBinding?.recyclerView?.setPadding(0, 0, 0, 0)
- viewBinding?.recyclerView?.setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER)
- viewBinding?.recyclerView?.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
- viewBinding?.recyclerView?.setRecycledViewPool((requireActivity() as MainActivity).recycledViewPool)
+ viewBinding.recyclerView.setPadding(0, 0, 0, 0)
+ viewBinding.recyclerView.setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER)
+ viewBinding.recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
+ viewBinding.recyclerView.setRecycledViewPool((requireActivity() as MainActivity).recycledViewPool)
adapter = object : EpisodeItemListAdapter(requireActivity() as MainActivity) {
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
super.onCreateContextMenu(menu, v, menuInfo)
@@ -53,10 +51,10 @@ class DownloadsSection : HomeSection() {
}
}
adapter?.setDummyViews(NUM_EPISODES)
- if (adapter != null) viewBinding?.recyclerView?.adapter = adapter
+ viewBinding.recyclerView.adapter = adapter
val swipeActions = SwipeActions(this, CompletedDownloadsFragment.TAG)
- if (viewBinding != null) swipeActions.attachTo(viewBinding!!.recyclerView)
+ swipeActions.attachTo(viewBinding.recyclerView)
swipeActions.setFilter(FeedItemFilter(FeedItemFilter.DOWNLOADED))
return view
}
@@ -66,7 +64,7 @@ class DownloadsSection : HomeSection() {
loadItems()
}
- override fun handleMoreClick() {
+ @UnstableApi override fun handleMoreClick() {
(requireActivity() as MainActivity).loadChildFragment(CompletedDownloadsFragment())
}
@@ -77,11 +75,11 @@ class DownloadsSection : HomeSection() {
@UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(event: PlaybackPositionEvent) {
- if (viewBinding == null || adapter == null) {
+ if (adapter == null) {
return
}
for (i in 0 until adapter!!.itemCount) {
- val holder: EpisodeItemViewHolder? = viewBinding!!.recyclerView.findViewHolderForAdapterPosition(i) as? EpisodeItemViewHolder
+ val holder: EpisodeItemViewHolder? = viewBinding.recyclerView.findViewHolderForAdapterPosition(i) as? EpisodeItemViewHolder
if (holder != null && holder.isCurrentlyPlayingItem) {
holder.notifyPlaybackPositionUpdated(event)
break
@@ -119,9 +117,8 @@ class DownloadsSection : HomeSection() {
if (downloads.size > NUM_EPISODES) {
downloads = downloads.subList(0, NUM_EPISODES)
}
- items = downloads
adapter?.setDummyViews(0)
- if (items != null) adapter?.updateItems(items!!)
+ adapter?.updateItems(downloads)
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/EchoSection.kt b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/EchoSection.kt
index 0fc33594..64198fcd 100644
--- a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/EchoSection.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/EchoSection.kt
@@ -13,28 +13,30 @@ import ac.mdiq.podvinci.core.storage.DBReader
import ac.mdiq.podvinci.databinding.HomeSectionEchoBinding
import ac.mdiq.podvinci.ui.echo.EchoActivity
import ac.mdiq.podvinci.ui.home.HomeFragment
+import androidx.media3.common.util.UnstableApi
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.util.*
+@UnstableApi
class EchoSection : Fragment() {
- private var viewBinding: HomeSectionEchoBinding? = null
+ private lateinit var viewBinding: HomeSectionEchoBinding
private var disposable: Disposable? = null
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View {
viewBinding = HomeSectionEchoBinding.inflate(inflater)
- viewBinding!!.titleLabel.text = getString(R.string.podvinci_echo_year, EchoActivity.RELEASE_YEAR)
- viewBinding!!.echoButton.setOnClickListener { v: View? ->
+ viewBinding.titleLabel.text = getString(R.string.podvinci_echo_year, EchoActivity.RELEASE_YEAR)
+ viewBinding.echoButton.setOnClickListener { v: View? ->
startActivity(Intent(context,
EchoActivity::class.java))
}
- viewBinding!!.closeButton.setOnClickListener { v: View? -> hideThisYear() }
+ viewBinding.closeButton.setOnClickListener { v: View? -> hideThisYear() }
updateVisibility()
- return viewBinding!!.root
+ return viewBinding.root
}
private fun jan1(): Long {
@@ -64,10 +66,9 @@ class EchoSection : Fragment() {
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ totalTime: Long ->
val shouldShow = (totalTime >= 3600 * 10)
- viewBinding!!.root.visibility = if (shouldShow) View.VISIBLE else View.GONE
- if (!shouldShow) {
- hideThisYear()
- }
+ viewBinding.root.visibility = if (shouldShow) View.VISIBLE else View.GONE
+ if (!shouldShow) hideThisYear()
+
}, { obj: Throwable -> obj.printStackTrace() })
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/EpisodesSurpriseSection.kt b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/EpisodesSurpriseSection.kt
index 99402a62..1ac6f007 100644
--- a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/EpisodesSurpriseSection.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/EpisodesSurpriseSection.kt
@@ -37,10 +37,10 @@ class EpisodesSurpriseSection : HomeSection() {
container: ViewGroup?, savedInstanceState: Bundle?
): View {
val view: View = super.onCreateView(inflater, container, savedInstanceState)
- viewBinding?.shuffleButton?.setVisibility(View.VISIBLE)
- viewBinding?.shuffleButton?.setOnClickListener { v: View? ->
+ viewBinding.shuffleButton.setVisibility(View.VISIBLE)
+ viewBinding.shuffleButton.setOnClickListener { v: View? ->
seed = Random().nextInt()
- viewBinding?.recyclerView?.scrollToPosition(0)
+ viewBinding.recyclerView.scrollToPosition(0)
loadItems()
}
listAdapter = object : HorizontalItemListAdapter(activity as MainActivity) {
@@ -53,13 +53,12 @@ class EpisodesSurpriseSection : HomeSection() {
}
}
listAdapter?.setDummyViews(NUM_EPISODES)
- viewBinding?.recyclerView?.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
- viewBinding?.recyclerView?.adapter = listAdapter
+ viewBinding.recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
+ viewBinding.recyclerView.adapter = listAdapter
val paddingHorizontal: Int = (12 * resources.displayMetrics.density).toInt()
- viewBinding?.recyclerView?.setPadding(paddingHorizontal, 0, paddingHorizontal, 0)
- if (seed == 0) {
- seed = Random().nextInt()
- }
+ viewBinding.recyclerView.setPadding(paddingHorizontal, 0, paddingHorizontal, 0)
+ if (seed == 0) seed = Random().nextInt()
+
return view
}
@@ -68,7 +67,7 @@ class EpisodesSurpriseSection : HomeSection() {
loadItems()
}
- override fun handleMoreClick() {
+ @UnstableApi override fun handleMoreClick() {
(requireActivity() as MainActivity).loadChildFragment(AllEpisodesFragment())
}
@@ -105,9 +104,8 @@ class EpisodesSurpriseSection : HomeSection() {
fun onEventMainThread(event: EpisodeDownloadEvent) {
for (downloadUrl in event.urls) {
val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(episodes, downloadUrl)
- if (pos >= 0) {
- listAdapter?.notifyItemChangedCompat(pos)
- }
+ if (pos >= 0) listAdapter?.notifyItemChangedCompat(pos)
+
}
}
@@ -117,7 +115,7 @@ class EpisodesSurpriseSection : HomeSection() {
return
}
for (i in 0 until listAdapter!!.itemCount) {
- val holder: HorizontalItemViewHolder? = viewBinding?.recyclerView?.findViewHolderForAdapterPosition(i) as? HorizontalItemViewHolder
+ val holder: HorizontalItemViewHolder? = viewBinding.recyclerView.findViewHolderForAdapterPosition(i) as? HorizontalItemViewHolder
if (holder != null && holder.isCurrentlyPlayingItem) {
holder.notifyPlaybackPositionUpdated(event)
break
@@ -128,10 +126,7 @@ class EpisodesSurpriseSection : HomeSection() {
private fun loadItems() {
disposable?.dispose()
- disposable = Observable.fromCallable {
- DBReader.getRandomEpisodes(
- NUM_EPISODES, seed)
- }
+ disposable = Observable.fromCallable { DBReader.getRandomEpisodes(NUM_EPISODES, seed) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ episodes: List ->
diff --git a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/InboxSection.kt b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/InboxSection.kt
index 8dda016a..4c5f41c1 100644
--- a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/InboxSection.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/InboxSection.kt
@@ -40,10 +40,10 @@ class InboxSection : HomeSection() {
container: ViewGroup?, savedInstanceState: Bundle?
): View {
val view: View = super.onCreateView(inflater, container, savedInstanceState)
- viewBinding?.recyclerView?.setPadding(0, 0, 0, 0)
- viewBinding?.recyclerView?.setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER)
- viewBinding?.recyclerView?.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
- viewBinding?.recyclerView?.setRecycledViewPool((requireActivity() as MainActivity).recycledViewPool)
+ viewBinding.recyclerView.setPadding(0, 0, 0, 0)
+ viewBinding.recyclerView.setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER)
+ viewBinding.recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
+ viewBinding.recyclerView.setRecycledViewPool((requireActivity() as MainActivity).recycledViewPool)
adapter = object : EpisodeItemListAdapter(requireActivity() as MainActivity) {
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
super.onCreateContextMenu(menu, v, menuInfo)
@@ -52,10 +52,10 @@ class InboxSection : HomeSection() {
}
}
adapter?.setDummyViews(NUM_EPISODES)
- if (adapter != null) viewBinding?.recyclerView?.adapter = adapter
+ viewBinding.recyclerView.adapter = adapter
val swipeActions = SwipeActions(this, InboxFragment.TAG)
- if (viewBinding != null) swipeActions.attachTo(viewBinding!!.recyclerView)
+ swipeActions.attachTo(viewBinding.recyclerView)
swipeActions.setFilter(FeedItemFilter(FeedItemFilter.NEW))
return view
}
@@ -65,7 +65,7 @@ class InboxSection : HomeSection() {
loadItems()
}
- override fun handleMoreClick() {
+ @UnstableApi override fun handleMoreClick() {
(requireActivity() as MainActivity).loadChildFragment(InboxFragment())
}
@@ -114,11 +114,11 @@ class InboxSection : HomeSection() {
items = data.first
adapter?.setDummyViews(0)
adapter?.updateItems(items)
- viewBinding?.numNewItemsLabel?.visibility = View.VISIBLE
+ viewBinding.numNewItemsLabel.visibility = View.VISIBLE
if (data.second >= 100) {
- viewBinding?.numNewItemsLabel?.text = String.format(Locale.getDefault(), "%d+", 99)
+ viewBinding.numNewItemsLabel.text = String.format(Locale.getDefault(), "%d+", 99)
} else {
- viewBinding?.numNewItemsLabel?.text = String.format(Locale.getDefault(), "%d", data.second)
+ viewBinding.numNewItemsLabel.text = String.format(Locale.getDefault(), "%d", data.second)
}
}, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) })
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/QueueSection.kt b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/QueueSection.kt
index 4fc10a63..e3aecf1e 100644
--- a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/QueueSection.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/QueueSection.kt
@@ -1,13 +1,7 @@
package ac.mdiq.podvinci.ui.home.sections
-import ac.mdiq.podvinci.activity.MainActivity
-import android.os.Bundle
-import android.util.Log
-import android.view.*
-import androidx.media3.common.util.UnstableApi
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
import ac.mdiq.podvinci.R
+import ac.mdiq.podvinci.activity.MainActivity
import ac.mdiq.podvinci.adapter.HorizontalItemListAdapter
import ac.mdiq.podvinci.core.menuhandler.MenuItemUtils
import ac.mdiq.podvinci.core.storage.DBReader
@@ -21,13 +15,18 @@ import ac.mdiq.podvinci.fragment.QueueFragment
import ac.mdiq.podvinci.model.feed.FeedItem
import ac.mdiq.podvinci.ui.home.HomeSection
import ac.mdiq.podvinci.view.viewholder.HorizontalItemViewHolder
+import android.os.Bundle
+import android.util.Log
+import android.view.*
+import androidx.media3.common.util.UnstableApi
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
-import java.util.concurrent.Callable
class QueueSection : HomeSection() {
private var listAdapter: HorizontalItemListAdapter? = null
@@ -46,10 +45,10 @@ class QueueSection : HomeSection() {
}
}
listAdapter?.setDummyViews(NUM_EPISODES)
- viewBinding?.recyclerView?.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
- viewBinding?.recyclerView?.adapter = listAdapter
+ viewBinding.recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
+ viewBinding.recyclerView.adapter = listAdapter
val paddingHorizontal: Int = (12 * resources.displayMetrics.density).toInt()
- viewBinding?.recyclerView?.setPadding(paddingHorizontal, 0, paddingHorizontal, 0)
+ viewBinding.recyclerView.setPadding(paddingHorizontal, 0, paddingHorizontal, 0)
return view
}
@@ -58,7 +57,7 @@ class QueueSection : HomeSection() {
loadItems()
}
- override fun handleMoreClick() {
+ @UnstableApi override fun handleMoreClick() {
(requireActivity() as MainActivity).loadChildFragment(QueueFragment())
}
@@ -112,7 +111,7 @@ class QueueSection : HomeSection() {
var currentlyPlayingItemIsFirst = true
for (i in 0 until listAdapter!!.itemCount) {
val holder: HorizontalItemViewHolder =
- viewBinding?.recyclerView?.findViewHolderForAdapterPosition(i) as? HorizontalItemViewHolder ?: continue
+ viewBinding.recyclerView.findViewHolderForAdapterPosition(i) as? HorizontalItemViewHolder ?: continue
if (holder.isCurrentlyPlayingItem) {
holder.notifyPlaybackPositionUpdated(event)
foundCurrentlyPlayingItem = true
diff --git a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/SubscriptionsSection.kt b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/SubscriptionsSection.kt
index a954e9a6..c5f32807 100644
--- a/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/SubscriptionsSection.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/ui/home/sections/SubscriptionsSection.kt
@@ -34,7 +34,7 @@ class SubscriptionsSection : HomeSection() {
container: ViewGroup?, savedInstanceState: Bundle?
): View {
val view: View = super.onCreateView(inflater, container, savedInstanceState)
- viewBinding?.recyclerView?.layoutManager = LinearLayoutManager(activity, RecyclerView.HORIZONTAL, false)
+ viewBinding.recyclerView.layoutManager = LinearLayoutManager(activity, RecyclerView.HORIZONTAL, false)
listAdapter = object : HorizontalFeedListAdapter(activity as MainActivity) {
override fun onCreateContextMenu(contextMenu: ContextMenu, view: View, contextMenuInfo: ContextMenu.ContextMenuInfo?
) {
@@ -46,9 +46,9 @@ class SubscriptionsSection : HomeSection() {
}
}
listAdapter?.setDummyViews(NUM_FEEDS)
- viewBinding?.recyclerView?.adapter = listAdapter
+ viewBinding.recyclerView.adapter = listAdapter
val paddingHorizontal: Int = (12 * resources.displayMetrics.density).toInt()
- viewBinding?.recyclerView?.setPadding(paddingHorizontal, 0, paddingHorizontal, 0)
+ viewBinding.recyclerView.setPadding(paddingHorizontal, 0, paddingHorizontal, 0)
return view
}
@@ -78,11 +78,8 @@ class SubscriptionsSection : HomeSection() {
val prefs: SharedPreferences =
requireContext().getSharedPreferences(StatisticsFragment.PREF_NAME, Context.MODE_PRIVATE)
val includeMarkedAsPlayed: Boolean = prefs.getBoolean(StatisticsFragment.PREF_INCLUDE_MARKED_PLAYED, false)
- disposable = Observable.fromCallable> {
- DBReader.getStatistics(includeMarkedAsPlayed,
- 0,
- Long.MAX_VALUE).feedTime
- }
+ disposable = Observable.fromCallable>
+ { DBReader.getStatistics(includeMarkedAsPlayed, 0, Long.MAX_VALUE).feedTime }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ statisticsData: List ->
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/AspectRatioVideoView.kt b/app/src/main/java/ac/mdiq/podvinci/view/AspectRatioVideoView.kt
index e24357b3..e651bb82 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/AspectRatioVideoView.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/AspectRatioVideoView.kt
@@ -9,6 +9,7 @@ class AspectRatioVideoView @JvmOverloads constructor(context: Context?,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : VideoView(context, attrs, defStyle) {
+
private var mVideoWidth = 0
private var mVideoHeight = 0
private var mAvailableWidth = -1f
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/ChapterSeekBar.kt b/app/src/main/java/ac/mdiq/podvinci/view/ChapterSeekBar.kt
index 09600783..d41dd336 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/ChapterSeekBar.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/ChapterSeekBar.kt
@@ -53,7 +53,7 @@ class ChapterSeekBar : AppCompatSeekBar {
if (dividerPos != null) {
this.dividerPos = FloatArray(dividerPos.size + 2)
this.dividerPos!![0] = 0f
- System.arraycopy(dividerPos, 0, this.dividerPos, 1, dividerPos.size)
+ System.arraycopy(dividerPos, 0, this.dividerPos!!, 1, dividerPos.size)
this.dividerPos!![this.dividerPos!!.size - 1] = 1f
} else {
this.dividerPos = null
@@ -104,30 +104,32 @@ class ChapterSeekBar : AppCompatSeekBar {
canvas.translate(paddingLeft.toFloat(), paddingTop.toFloat())
- for (i in 1 until dividerPos!!.size) {
- val right = dividerPos!![i] * width - chapterMargin
- val left = dividerPos!![i - 1] * width
- val rightCurr = dividerPos!![currChapter] * width - chapterMargin
- val leftCurr = dividerPos!![currChapter - 1] * width
-
- canvas.drawRect(left, top, right, bottom, paintBackground)
-
- if (progressSecondary > 0 && progressSecondary < width) {
- if (right < progressSecondary) {
- canvas.drawRect(left, top, right, bottom, paintBackground)
- } else if (progressSecondary > left) {
- canvas.drawRect(left, top, progressSecondary, bottom, paintBackground)
+ if (dividerPos != null && dividerPos!!.isNotEmpty()) {
+ for (i in 1 until dividerPos!!.size) {
+ val right = dividerPos!![i] * width - chapterMargin
+ val left = dividerPos!![i - 1] * width
+ val rightCurr = dividerPos!![currChapter] * width - chapterMargin
+ val leftCurr = dividerPos!![currChapter - 1] * width
+
+ canvas.drawRect(left, top, right, bottom, paintBackground)
+
+ if (progressSecondary > 0 && progressSecondary < width) {
+ if (right < progressSecondary) {
+ canvas.drawRect(left, top, right, bottom, paintBackground)
+ } else if (progressSecondary > left) {
+ canvas.drawRect(left, top, progressSecondary, bottom, paintBackground)
+ }
}
- }
- if (right < progressPrimary) {
- currChapter = i + 1
- canvas.drawRect(left, top, right, bottom, paintProgressPrimary)
- } else if (isHighlighted || isPressed) {
- canvas.drawRect(leftCurr, topExpanded, rightCurr, bottomExpanded, paintBackground)
- canvas.drawRect(leftCurr, topExpanded, progressPrimary, bottomExpanded, paintProgressPrimary)
- } else {
- canvas.drawRect(leftCurr, top, progressPrimary, bottom, paintProgressPrimary)
+ if (right < progressPrimary) {
+ currChapter = i + 1
+ canvas.drawRect(left, top, right, bottom, paintProgressPrimary)
+ } else if (isHighlighted || isPressed) {
+ canvas.drawRect(leftCurr, topExpanded, rightCurr, bottomExpanded, paintBackground)
+ canvas.drawRect(leftCurr, topExpanded, progressPrimary, bottomExpanded, paintProgressPrimary)
+ } else {
+ canvas.drawRect(leftCurr, top, progressPrimary, bottom, paintProgressPrimary)
+ }
}
}
canvas.restoreToCount(saveCount)
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/EmptyViewHandler.kt b/app/src/main/java/ac/mdiq/podvinci/view/EmptyViewHandler.kt
index 45777ee0..ccbd2c39 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/EmptyViewHandler.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/EmptyViewHandler.kt
@@ -58,38 +58,41 @@ class EmptyViewHandler(context: Context?) {
}
private fun addToParentView(view: View) {
- var parent = (view.parent as ViewGroup)
+ var parent = view.parent as? ViewGroup
while (parent != null) {
- if (parent is RelativeLayout) {
- parent.addView(emptyView)
- val layoutParams =
- emptyView.layoutParams as RelativeLayout.LayoutParams
- layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE)
- emptyView.layoutParams = layoutParams
- break
- } else if (parent is FrameLayout) {
- parent.addView(emptyView)
- val layoutParams =
- emptyView.layoutParams as FrameLayout.LayoutParams
- layoutParams.gravity = Gravity.CENTER
- emptyView.layoutParams = layoutParams
- break
- } else if (parent is CoordinatorLayout) {
- parent.addView(emptyView)
- val layoutParams =
- emptyView.layoutParams as CoordinatorLayout.LayoutParams
- layoutParams.gravity = Gravity.CENTER
- emptyView.layoutParams = layoutParams
- break
+ when (parent) {
+ is RelativeLayout -> {
+ parent.addView(emptyView)
+ val layoutParams =
+ emptyView.layoutParams as RelativeLayout.LayoutParams
+ layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE)
+ emptyView.layoutParams = layoutParams
+ break
+ }
+ is FrameLayout -> {
+ parent.addView(emptyView)
+ val layoutParams =
+ emptyView.layoutParams as FrameLayout.LayoutParams
+ layoutParams.gravity = Gravity.CENTER
+ emptyView.layoutParams = layoutParams
+ break
+ }
+ is CoordinatorLayout -> {
+ parent.addView(emptyView)
+ val layoutParams =
+ emptyView.layoutParams as CoordinatorLayout.LayoutParams
+ layoutParams.gravity = Gravity.CENTER
+ emptyView.layoutParams = layoutParams
+ break
+ }
}
- parent = parent.parent as ViewGroup
+ parent = parent.parent as? ViewGroup
}
}
fun updateAdapter(adapter: RecyclerView.Adapter<*>?) {
- if (this.recyclerAdapter != null) {
- recyclerAdapter!!.unregisterAdapterDataObserver(adapterObserver)
- }
+ recyclerAdapter?.unregisterAdapterDataObserver(adapterObserver)
+
this.recyclerAdapter = adapter
adapter?.registerAdapterDataObserver(adapterObserver)
updateVisibility()
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/EpisodeItemListRecyclerView.kt b/app/src/main/java/ac/mdiq/podvinci/view/EpisodeItemListRecyclerView.kt
index ae759b0d..2d1640b4 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/EpisodeItemListRecyclerView.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/EpisodeItemListRecyclerView.kt
@@ -10,28 +10,28 @@ import androidx.recyclerview.widget.RecyclerView
import ac.mdiq.podvinci.R
class EpisodeItemListRecyclerView : RecyclerView {
- private var layoutManager: LinearLayoutManager? = null
+ private lateinit var layoutManager: LinearLayoutManager
- constructor(context: Context?) : super(ContextThemeWrapper(context, R.style.FastScrollRecyclerView)) {
+ constructor(context: Context) : super(ContextThemeWrapper(context, R.style.FastScrollRecyclerView)) {
setup()
}
- constructor(context: Context?, attrs: AttributeSet?) : super(ContextThemeWrapper(context,
+ constructor(context: Context, attrs: AttributeSet?) : super(ContextThemeWrapper(context,
R.style.FastScrollRecyclerView), attrs) {
setup()
}
- constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(ContextThemeWrapper(context,
+ constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(ContextThemeWrapper(context,
R.style.FastScrollRecyclerView), attrs, defStyleAttr) {
setup()
}
private fun setup() {
layoutManager = LinearLayoutManager(context)
- layoutManager!!.recycleChildrenOnDetach = true
+ layoutManager.recycleChildrenOnDetach = true
setLayoutManager(layoutManager)
setHasFixedSize(true)
- addItemDecoration(DividerItemDecoration(context, layoutManager!!.orientation))
+ addItemDecoration(DividerItemDecoration(context, layoutManager.orientation))
clipToPadding = false
}
@@ -42,8 +42,8 @@ class EpisodeItemListRecyclerView : RecyclerView {
}
fun saveScrollPosition(tag: String) {
- val firstItem = layoutManager!!.findFirstVisibleItemPosition()
- val firstItemView = layoutManager!!.findViewByPosition(firstItem)
+ val firstItem = layoutManager.findFirstVisibleItemPosition()
+ val firstItemView = layoutManager.findViewByPosition(firstItem)
val topOffset = firstItemView?.top?.toFloat() ?: 0f
context.getSharedPreferences(TAG, Context.MODE_PRIVATE).edit()
@@ -57,15 +57,15 @@ class EpisodeItemListRecyclerView : RecyclerView {
val position = prefs.getInt(PREF_PREFIX_SCROLL_POSITION + tag, 0)
val offset = prefs.getInt(PREF_PREFIX_SCROLL_OFFSET + tag, 0)
if (position > 0 || offset > 0) {
- layoutManager!!.scrollToPositionWithOffset(position, offset)
+ layoutManager.scrollToPositionWithOffset(position, offset)
}
}
val isScrolledToBottom: Boolean
get() {
val visibleEpisodeCount = childCount
- val totalEpisodeCount = layoutManager!!.itemCount
- val firstVisibleEpisode = layoutManager!!.findFirstVisibleItemPosition()
+ val totalEpisodeCount = layoutManager.itemCount
+ val firstVisibleEpisode = layoutManager.findFirstVisibleItemPosition()
return (totalEpisodeCount - visibleEpisodeCount) <= (firstVisibleEpisode + 3)
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/LiftOnScrollListener.kt b/app/src/main/java/ac/mdiq/podvinci/view/LiftOnScrollListener.kt
index fc2c6935..ff8ced20 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/LiftOnScrollListener.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/LiftOnScrollListener.kt
@@ -22,14 +22,13 @@ class LiftOnScrollListener(appBar: View) : RecyclerView.OnScrollListener(), Nest
}
private fun isScrolled(recyclerView: RecyclerView): Boolean {
- val firstItem =
- (recyclerView.layoutManager as LinearLayoutManager?)!!.findFirstVisibleItemPosition()
+ val firstItem = (recyclerView.layoutManager as? LinearLayoutManager)?.findFirstVisibleItemPosition()?:-1
if (firstItem < 0) {
return false
} else if (firstItem > 0) {
return true
}
- val firstItemView = recyclerView.layoutManager!!.findViewByPosition(firstItem)
+ val firstItemView = recyclerView.layoutManager?.findViewByPosition(firstItem)
return if (firstItemView == null) {
false
} else {
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/LocalDeleteModal.kt b/app/src/main/java/ac/mdiq/podvinci/view/LocalDeleteModal.kt
index 59bf51f7..e6785839 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/LocalDeleteModal.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/LocalDeleteModal.kt
@@ -7,9 +7,8 @@ import ac.mdiq.podvinci.model.feed.FeedItem
import ac.mdiq.podvinci.ui.i18n.R
object LocalDeleteModal {
- fun showLocalFeedDeleteWarningIfNecessary(context: Context?, items: Iterable,
- deleteCommand: Runnable
- ) {
+ fun showLocalFeedDeleteWarningIfNecessary(context: Context, items: Iterable,
+ deleteCommand: Runnable) {
var anyLocalFeed = false
for (item in items) {
if (item.feed?.isLocalFeed == true) {
@@ -23,7 +22,7 @@ object LocalDeleteModal {
return
}
- MaterialAlertDialogBuilder(context!!)
+ MaterialAlertDialogBuilder(context)
.setTitle(R.string.delete_episode_label)
.setMessage(R.string.delete_local_feed_warning_body)
.setPositiveButton(R.string.delete_label) { dialog: DialogInterface?, which: Int -> deleteCommand.run() }
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/NestedScrollableHost.kt b/app/src/main/java/ac/mdiq/podvinci/view/NestedScrollableHost.kt
index 789250b0..9c405bae 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/NestedScrollableHost.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/NestedScrollableHost.kt
@@ -69,10 +69,7 @@ class NestedScrollableHost : FrameLayout {
}
private fun setAttributes(context: Context, attrs: AttributeSet?) {
- val a = context.theme.obtainStyledAttributes(
- attrs,
- R.styleable.NestedScrollableHost,
- 0, 0)
+ val a = context.theme.obtainStyledAttributes(attrs, R.styleable.NestedScrollableHost, 0, 0)
try {
preferHorizontal = a.getInteger(R.styleable.NestedScrollableHost_preferHorizontal, 1)
@@ -89,11 +86,11 @@ class NestedScrollableHost : FrameLayout {
viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
- var v = parent as View
+ var v = parent as? View
while (v != null && v !is ViewPager2 || isntSameDirection(v)) {
- v = v.parent as View
+ v = v!!.parent as? View
}
- parentViewPager = v as ViewPager2
+ parentViewPager = v as? ViewPager2
viewTreeObserver.removeOnPreDrawListener(this)
return false
@@ -146,7 +143,6 @@ class NestedScrollableHost : FrameLayout {
return
}
-
if (e.action == MotionEvent.ACTION_DOWN) {
initialX = e.x
initialY = e.y
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/PlayButton.kt b/app/src/main/java/ac/mdiq/podvinci/view/PlayButton.kt
index a4a5c70d..72f2faab 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/PlayButton.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/PlayButton.kt
@@ -24,20 +24,23 @@ class PlayButton : AppCompatImageButton {
if (this.isShowPlay != showPlay) {
this.isShowPlay = showPlay
contentDescription = context.getString(if (showPlay) R.string.play_label else R.string.pause_label)
- if (isVideoScreen) {
- setImageResource(if (showPlay) R.drawable.ic_play_video_white else R.drawable.ic_pause_video_white)
- } else if (!isShown) {
- setImageResource(if (showPlay) R.drawable.ic_play_48dp else R.drawable.ic_pause)
- } else if (showPlay) {
- val drawable = AnimatedVectorDrawableCompat.create(
- context, R.drawable.ic_animate_pause_play)
- setImageDrawable(drawable)
- drawable!!.start()
- } else {
- val drawable = AnimatedVectorDrawableCompat.create(
- context, R.drawable.ic_animate_play_pause)
- setImageDrawable(drawable)
- drawable!!.start()
+ when {
+ isVideoScreen -> {
+ setImageResource(if (showPlay) R.drawable.ic_play_video_white else R.drawable.ic_pause_video_white)
+ }
+ !isShown -> {
+ setImageResource(if (showPlay) R.drawable.ic_play_48dp else R.drawable.ic_pause)
+ }
+ showPlay -> {
+ val drawable = AnimatedVectorDrawableCompat.create(context, R.drawable.ic_animate_pause_play)
+ setImageDrawable(drawable)
+ drawable?.start()
+ }
+ else -> {
+ val drawable = AnimatedVectorDrawableCompat.create(context, R.drawable.ic_animate_play_pause)
+ setImageDrawable(drawable)
+ drawable?.start()
+ }
}
}
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/PlaybackSpeedSeekBar.kt b/app/src/main/java/ac/mdiq/podvinci/view/PlaybackSpeedSeekBar.kt
index 0bc236ce..f9a09b79 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/PlaybackSpeedSeekBar.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/PlaybackSpeedSeekBar.kt
@@ -10,7 +10,7 @@ import androidx.core.util.Consumer
import ac.mdiq.podvinci.R
class PlaybackSpeedSeekBar : FrameLayout {
- private var seekBar: SeekBar? = null
+ private lateinit var seekBar: SeekBar
private var progressChangedListener: Consumer? = null
constructor(context: Context) : super(context) {
@@ -28,10 +28,10 @@ class PlaybackSpeedSeekBar : FrameLayout {
private fun setup() {
inflate(context, R.layout.playback_speed_seek_bar, this)
seekBar = findViewById(R.id.playback_speed)
- findViewById(R.id.butDecSpeed).setOnClickListener { v: View? -> seekBar?.progress = (seekBar?.progress ?: 0) - 2 }
- findViewById(R.id.butIncSpeed).setOnClickListener { v: View? -> seekBar?.progress = (seekBar?.progress ?: 0) + 2 }
+ findViewById(R.id.butDecSpeed).setOnClickListener { v: View? -> seekBar.progress -= 2 }
+ findViewById(R.id.butIncSpeed).setOnClickListener { v: View? -> seekBar.progress += 2 }
- seekBar?.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
+ seekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
val playbackSpeed = (progress + 10) / 20.0f
if (progressChangedListener != null) {
@@ -48,7 +48,7 @@ class PlaybackSpeedSeekBar : FrameLayout {
}
fun updateSpeed(speedMultiplier: Float) {
- seekBar!!.progress = Math.round((20 * speedMultiplier) - 10)
+ seekBar.progress = Math.round((20 * speedMultiplier) - 10)
}
fun setProgressChangedListener(progressChangedListener: Consumer?) {
@@ -56,11 +56,11 @@ class PlaybackSpeedSeekBar : FrameLayout {
}
val currentSpeed: Float
- get() = (seekBar!!.progress + 10) / 20.0f
+ get() = (seekBar.progress + 10) / 20.0f
override fun setEnabled(enabled: Boolean) {
super.setEnabled(enabled)
- seekBar!!.isEnabled = enabled
+ seekBar.isEnabled = enabled
findViewById(R.id.butDecSpeed).isEnabled = enabled
findViewById(R.id.butIncSpeed).isEnabled = enabled
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/ShownotesWebView.kt b/app/src/main/java/ac/mdiq/podvinci/view/ShownotesWebView.kt
index 4242e5d9..dc8ace41 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/ShownotesWebView.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/ShownotesWebView.kt
@@ -27,6 +27,7 @@ import ac.mdiq.podvinci.core.util.IntentUtils
import ac.mdiq.podvinci.core.util.NetworkUtils
import ac.mdiq.podvinci.core.util.ShareUtils
import ac.mdiq.podvinci.core.util.gui.ShownotesCleaner
+import androidx.media3.common.util.UnstableApi
import kotlin.math.max
class ShownotesWebView : WebView, View.OnLongClickListener {
@@ -80,27 +81,28 @@ class ShownotesWebView : WebView, View.OnLongClickListener {
})
}
- override fun onLongClick(v: View): Boolean {
+ @UnstableApi override fun onLongClick(v: View): Boolean {
val r: HitTestResult = getHitTestResult()
- if (r.type == HitTestResult.SRC_ANCHOR_TYPE) {
- Log.d(TAG, "Link of webview was long-pressed. Extra: " + r.extra)
- selectedUrl = r.extra
- showContextMenu()
- return true
- } else if (r.type == HitTestResult.EMAIL_TYPE) {
- Log.d(TAG, "E-Mail of webview was long-pressed. Extra: " + r.extra)
- ContextCompat.getSystemService(
- context,
- ClipboardManager::class.java)?.setPrimaryClip(ClipData.newPlainText("PodVinci", r.extra))
- if (Build.VERSION.SDK_INT <= 32 && this.context is MainActivity) {
- (this.context as MainActivity).showSnackbarAbovePlayer(
- resources.getString(R.string.copied_to_clipboard),
- Snackbar.LENGTH_SHORT)
+ when (r.type) {
+ HitTestResult.SRC_ANCHOR_TYPE -> {
+ Log.d(TAG, "Link of webview was long-pressed. Extra: " + r.extra)
+ selectedUrl = r.extra
+ showContextMenu()
+ return true
+ }
+ HitTestResult.EMAIL_TYPE -> {
+ Log.d(TAG, "E-Mail of webview was long-pressed. Extra: " + r.extra)
+ ContextCompat.getSystemService(context, ClipboardManager::class.java)?.setPrimaryClip(ClipData.newPlainText("PodVinci", r.extra))
+ if (Build.VERSION.SDK_INT <= 32 && this.context is MainActivity) {
+ (this.context as MainActivity).showSnackbarAbovePlayer(resources.getString(R.string.copied_to_clipboard), Snackbar.LENGTH_SHORT)
+ }
+ return true
+ }
+ else -> {
+ selectedUrl = null
+ return false
}
- return true
}
- selectedUrl = null
- return false
}
fun onContextItemSelected(item: MenuItem): Boolean {
@@ -109,29 +111,34 @@ class ShownotesWebView : WebView, View.OnLongClickListener {
}
val itemId = item.itemId
- if (itemId == R.id.open_in_browser_item) {
- if (selectedUrl != null) IntentUtils.openInBrowser(context, selectedUrl!!)
- } else if (itemId == R.id.share_url_item) {
- if (selectedUrl != null) ShareUtils.shareLink(context, selectedUrl!!)
- } else if (itemId == R.id.copy_url_item) {
- val clipData: ClipData = ClipData.newPlainText(selectedUrl, selectedUrl)
- val cm = context
- .getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
- cm.setPrimaryClip(clipData)
- if (Build.VERSION.SDK_INT < 32) {
- val s: Snackbar = Snackbar.make(this, R.string.copied_to_clipboard, Snackbar.LENGTH_LONG)
- s.view.elevation = 100f
- s.show()
+ when (itemId) {
+ R.id.open_in_browser_item -> {
+ if (selectedUrl != null) IntentUtils.openInBrowser(context, selectedUrl!!)
}
- } else if (itemId == R.id.go_to_position_item) {
- if (ShownotesCleaner.isTimecodeLink(selectedUrl) && timecodeSelectedListener != null) {
- timecodeSelectedListener!!.accept(ShownotesCleaner.getTimecodeLinkTime(selectedUrl))
- } else {
- Log.e(TAG, "Selected go_to_position_item, but URL was no timecode link: $selectedUrl")
+ R.id.share_url_item -> {
+ if (selectedUrl != null) ShareUtils.shareLink(context, selectedUrl!!)
+ }
+ R.id.copy_url_item -> {
+ val clipData: ClipData = ClipData.newPlainText(selectedUrl, selectedUrl)
+ val cm = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
+ cm.setPrimaryClip(clipData)
+ if (Build.VERSION.SDK_INT < 32) {
+ val s: Snackbar = Snackbar.make(this, R.string.copied_to_clipboard, Snackbar.LENGTH_LONG)
+ s.view.elevation = 100f
+ s.show()
+ }
+ }
+ R.id.go_to_position_item -> {
+ if (ShownotesCleaner.isTimecodeLink(selectedUrl) && timecodeSelectedListener != null) {
+ timecodeSelectedListener!!.accept(ShownotesCleaner.getTimecodeLinkTime(selectedUrl))
+ } else {
+ Log.e(TAG, "Selected go_to_position_item, but URL was no timecode link: $selectedUrl")
+ }
+ }
+ else -> {
+ selectedUrl = null
+ return false
}
- } else {
- selectedUrl = null
- return false
}
selectedUrl = null
return true
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/ToolbarIconTintManager.kt b/app/src/main/java/ac/mdiq/podvinci/view/ToolbarIconTintManager.kt
index b8953aea..54c945c5 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/ToolbarIconTintManager.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/ToolbarIconTintManager.kt
@@ -40,9 +40,7 @@ abstract class ToolbarIconTintManager(private val context: Context,
}
private fun safeSetColorFilter(icon: Drawable?, filter: PorterDuffColorFilter?) {
- if (icon != null) {
- icon.colorFilter = filter
- }
+ icon?.colorFilter = filter
}
/**
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/viewholder/DownloadLogItemViewHolder.kt b/app/src/main/java/ac/mdiq/podvinci/view/viewholder/DownloadLogItemViewHolder.kt
index 595ff24e..a861cd3d 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/viewholder/DownloadLogItemViewHolder.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/viewholder/DownloadLogItemViewHolder.kt
@@ -15,6 +15,7 @@ import ac.mdiq.podvinci.ui.common.CircularProgressBar
class DownloadLogItemViewHolder(context: Context?, parent: ViewGroup?) :
RecyclerView.ViewHolder(LayoutInflater.from(context).inflate(R.layout.downloadlog_item, parent, false)) {
+
@JvmField
val secondaryActionButton: View = itemView.findViewById(R.id.secondaryActionButton)
@JvmField
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/viewholder/EpisodeItemViewHolder.kt b/app/src/main/java/ac/mdiq/podvinci/view/viewholder/EpisodeItemViewHolder.kt
index bcf2446b..93220007 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/viewholder/EpisodeItemViewHolder.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/viewholder/EpisodeItemViewHolder.kt
@@ -41,8 +41,9 @@ import kotlin.math.max
* Holds the view which shows FeedItems.
*/
@UnstableApi
-class EpisodeItemViewHolder(activity: MainActivity, parent: ViewGroup?) :
+class EpisodeItemViewHolder(private val activity: MainActivity, parent: ViewGroup?) :
RecyclerView.ViewHolder(LayoutInflater.from(activity).inflate(R.layout.feeditemlist_item, parent, false)) {
+
private val container: View = itemView.findViewById(R.id.container)
@JvmField
val dragHandle: ImageView = itemView.findViewById(R.id.drag_handle)
@@ -69,7 +70,6 @@ class EpisodeItemViewHolder(activity: MainActivity, parent: ViewGroup?) :
@JvmField
val coverHolder: CardView
- private val activity: MainActivity = activity
private var item: FeedItem? = null
init {
@@ -269,8 +269,11 @@ class EpisodeItemViewHolder(activity: MainActivity, parent: ViewGroup?) :
* Hides the separator dot between icons and text if there are no icons.
*/
fun hideSeparatorIfNecessary() {
- val hasIcons =
- isInbox.visibility == View.VISIBLE || isInQueue.visibility == View.VISIBLE || isVideo.visibility == View.VISIBLE || isFavorite.visibility == View.VISIBLE || isInbox.visibility == View.VISIBLE
+ val hasIcons = isInbox.visibility == View.VISIBLE ||
+ isInQueue.visibility == View.VISIBLE ||
+ isVideo.visibility == View.VISIBLE ||
+ isFavorite.visibility == View.VISIBLE ||
+ isInbox.visibility == View.VISIBLE
separatorIcons.visibility = if (hasIcons) View.VISIBLE else View.GONE
}
diff --git a/app/src/main/java/ac/mdiq/podvinci/view/viewholder/HorizontalItemViewHolder.kt b/app/src/main/java/ac/mdiq/podvinci/view/viewholder/HorizontalItemViewHolder.kt
index 6d006e13..ce5780fa 100644
--- a/app/src/main/java/ac/mdiq/podvinci/view/viewholder/HorizontalItemViewHolder.kt
+++ b/app/src/main/java/ac/mdiq/podvinci/view/viewholder/HorizontalItemViewHolder.kt
@@ -29,6 +29,7 @@ import kotlin.math.max
class HorizontalItemViewHolder(private val activity: MainActivity, parent: ViewGroup?) :
RecyclerView.ViewHolder(LayoutInflater.from(activity).inflate(R.layout.horizontal_itemlist_item, parent, false)) {
+
@JvmField
val card: CardView = itemView.findViewById(R.id.card)
@@ -110,7 +111,7 @@ class HorizontalItemViewHolder(private val activity: MainActivity, parent: ViewG
}
val isCurrentlyPlayingItem: Boolean
- @UnstableApi get() = item != null && item!!.media != null && PlaybackStatus.isCurrentlyPlaying(item!!.media)
+ @UnstableApi get() = item?.media != null && PlaybackStatus.isCurrentlyPlaying(item!!.media)
fun notifyPlaybackPositionUpdated(event: PlaybackPositionEvent) {
setProgressBar(true, 100.0f * event.position / event.duration)
diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml
index 2c9cbf88..5a5f22b4 100644
--- a/core/src/main/AndroidManifest.xml
+++ b/core/src/main/AndroidManifest.xml
@@ -9,6 +9,8 @@
+
+
@@ -18,10 +20,11 @@
android:supportsRtl="true">
+ android:foregroundServiceType="mediaPlayback"
+ android:label="@string/app_name"
+ android:enabled="true"
+ android:exported="false"
+ tools:ignore="ExportedService">
diff --git a/core/src/main/java/ac/mdiq/podvinci/core/service/playback/ExoPlayerWrapper.kt b/core/src/main/java/ac/mdiq/podvinci/core/service/playback/ExoPlayerWrapper.kt
index 75c0f2bb..a2cf110e 100644
--- a/core/src/main/java/ac/mdiq/podvinci/core/service/playback/ExoPlayerWrapper.kt
+++ b/core/src/main/java/ac/mdiq/podvinci/core/service/playback/ExoPlayerWrapper.kt
@@ -223,6 +223,7 @@ class ExoPlayerWrapper internal constructor(private val context: Context) {
}
fun setPlaybackParams(speed: Float, skipSilence: Boolean) {
+ Log.d(TAG, "setPlaybackParams speed=$speed pitch=${playbackParameters.pitch} skipSilence=$skipSilence")
playbackParameters = PlaybackParameters(speed, playbackParameters.pitch)
exoPlayer.skipSilenceEnabled = skipSilence
exoPlayer.playbackParameters = playbackParameters
diff --git a/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackService.kt b/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackService.kt
index 545c4783..4875e314 100644
--- a/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackService.kt
+++ b/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackService.kt
@@ -166,16 +166,16 @@ class PlaybackService : MediaBrowserServiceCompat() {
notificationBuilder = PlaybackServiceNotificationBuilder(this)
// TODO: this shit doesn't work
-// if (Build.VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
-// registerReceiver(autoStateUpdated, IntentFilter("com.google.android.gms.car.media.STATUS"), RECEIVER_EXPORTED)
-// registerReceiver(shutdownReceiver, IntentFilter(PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE), RECEIVER_EXPORTED)
-// } else {
-// ContextCompat.registerReceiver(applicationContext, autoStateUpdated, IntentFilter("com.google.android.gms.car.media.STATUS"), ContextCompat.RECEIVER_EXPORTED)
-// ContextCompat.registerReceiver(applicationContext, shutdownReceiver, IntentFilter(PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE), ContextCompat.RECEIVER_EXPORTED)
-// }
+ if (Build.VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
+ registerReceiver(autoStateUpdated, IntentFilter("com.google.android.gms.car.media.STATUS"), RECEIVER_NOT_EXPORTED)
+ registerReceiver(shutdownReceiver, IntentFilter(PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE), RECEIVER_NOT_EXPORTED)
+ } else {
+ registerReceiver(autoStateUpdated, IntentFilter("com.google.android.gms.car.media.STATUS"))
+ registerReceiver(shutdownReceiver, IntentFilter(PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE))
+ }
- registerReceiver(autoStateUpdated, IntentFilter("com.google.android.gms.car.media.STATUS"))
- registerReceiver(shutdownReceiver, IntentFilter(PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE))
+// registerReceiver(autoStateUpdated, IntentFilter("com.google.android.gms.car.media.STATUS"))
+// registerReceiver(shutdownReceiver, IntentFilter(PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE))
registerReceiver(headsetDisconnected, IntentFilter(Intent.ACTION_HEADSET_PLUG))
registerReceiver(bluetoothStateUpdated, IntentFilter(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED))
@@ -272,13 +272,13 @@ class PlaybackService : MediaBrowserServiceCompat() {
cancelPositionObserver()
mediaSession?.release()
mediaSession = null
+ mediaPlayer?.shutdown()
unregisterReceiver(autoStateUpdated)
unregisterReceiver(headsetDisconnected)
unregisterReceiver(shutdownReceiver)
unregisterReceiver(bluetoothStateUpdated)
unregisterReceiver(audioBecomingNoisy)
- mediaPlayer?.shutdown()
taskManager.shutdown()
EventBus.getDefault().unregister(this)
}
@@ -699,7 +699,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
}
else -> {
Log.d(TAG, "Unhandled key code: $keycode")
- if (info?.playable != null && info?.playerStatus == PlayerStatus.PLAYING) { // only notify the user about an unknown key event if it is actually doing something
+ if (info?.playable != null && info.playerStatus == PlayerStatus.PLAYING) { // only notify the user about an unknown key event if it is actually doing something
val message = String.format(resources.getString(R.string.unknown_media_key), keycode)
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
diff --git a/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackServiceStateManager.kt b/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackServiceStateManager.kt
index ee6de9ca..1851b944 100644
--- a/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackServiceStateManager.kt
+++ b/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackServiceStateManager.kt
@@ -2,6 +2,8 @@ package ac.mdiq.podvinci.core.service.playback
import android.annotation.SuppressLint
import android.app.Notification
+import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
+import android.os.Build
import android.util.Log
import androidx.core.app.ServiceCompat
import kotlin.concurrent.Volatile
@@ -13,11 +15,13 @@ internal class PlaybackServiceStateManager(private val playbackService: Playback
@Volatile
private var hasReceivedValidStartCommand = false
- @SuppressLint("ForegroundServiceType")
- fun startForeground(notificationId: Int, notification: Notification?) {
+ fun startForeground(notificationId: Int, notification: Notification) {
Log.d(TAG, "startForeground")
- // TODO: need to add declaration in manifest
- playbackService.startForeground(notificationId, notification)
+ if (Build.VERSION.SDK_INT >= 29) {
+ playbackService.startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK)
+ } else {
+ playbackService.startForeground(notificationId, notification)
+ }
isInForeground = true
}
diff --git a/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackServiceTaskManager.kt b/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackServiceTaskManager.kt
index 0f47a846..2b07b92f 100644
--- a/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackServiceTaskManager.kt
+++ b/core/src/main/java/ac/mdiq/podvinci/core/service/playback/PlaybackServiceTaskManager.kt
@@ -242,10 +242,8 @@ class PlaybackServiceTaskManager(private val context: Context,
cancelWidgetUpdater()
disableSleepTimer()
- if (chapterLoaderFuture != null) {
- chapterLoaderFuture!!.dispose()
- chapterLoaderFuture = null
- }
+ chapterLoaderFuture?.dispose()
+ chapterLoaderFuture = null
}
/**
diff --git a/core/src/main/java/ac/mdiq/podvinci/core/storage/DBReader.kt b/core/src/main/java/ac/mdiq/podvinci/core/storage/DBReader.kt
index a0c5b53f..2522d338 100644
--- a/core/src/main/java/ac/mdiq/podvinci/core/storage/DBReader.kt
+++ b/core/src/main/java/ac/mdiq/podvinci/core/storage/DBReader.kt
@@ -646,7 +646,11 @@ object DBReader {
@JvmStatic
fun loadChaptersOfFeedItem(item: FeedItem): List? {
Log.d(TAG, "loadChaptersOfFeedItem() called with: item = [$item]")
-
+// TODO: need to find out who are often calling this
+// val stackTraceElements = Thread.currentThread().stackTrace
+// stackTraceElements.forEach { element ->
+// println(element)
+// }
val adapter = getInstance()
adapter!!.open()
try {
diff --git a/core/src/main/java/ac/mdiq/podvinci/core/storage/DBWriter.kt b/core/src/main/java/ac/mdiq/podvinci/core/storage/DBWriter.kt
index 09812798..2f960896 100644
--- a/core/src/main/java/ac/mdiq/podvinci/core/storage/DBWriter.kt
+++ b/core/src/main/java/ac/mdiq/podvinci/core/storage/DBWriter.kt
@@ -205,7 +205,7 @@ import java.util.concurrent.TimeUnit
removedFromQueue.add(item)
}
if (item.media != null) {
- if (item.media!!.id == currentlyPlayingFeedMediaId) {
+ if (item.media?.id == currentlyPlayingFeedMediaId) {
// Applies to both downloaded and streamed media
writeNoMediaPlaying()
sendLocalBroadcast(context, PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE)
diff --git a/core/src/main/java/ac/mdiq/podvinci/core/util/FeedItemUtil.kt b/core/src/main/java/ac/mdiq/podvinci/core/util/FeedItemUtil.kt
index 34f0e7c1..344be077 100644
--- a/core/src/main/java/ac/mdiq/podvinci/core/util/FeedItemUtil.kt
+++ b/core/src/main/java/ac/mdiq/podvinci/core/util/FeedItemUtil.kt
@@ -10,7 +10,7 @@ object FeedItemUtil {
fun indexOfItemWithId(items: List, id: Long): Int {
for (i in items.indices) {
val item = items[i]
- if (item != null && item.id == id) {
+ if (item?.id == id) {
return i
}
}
@@ -21,7 +21,7 @@ object FeedItemUtil {
fun indexOfItemWithDownloadUrl(items: List, downloadUrl: String): Int {
for (i in items.indices) {
val item = items[i]
- if (item?.media != null && item.media!!.download_url == downloadUrl) {
+ if (item?.media?.download_url == downloadUrl) {
return i
}
}
@@ -30,7 +30,7 @@ object FeedItemUtil {
@JvmStatic
fun getIds(items: List?): LongArray {
- if (items == null || items.isEmpty()) {
+ if (items.isNullOrEmpty()) {
return LongArray(0)
}
val result = LongArray(items.size)
diff --git a/core/src/main/java/ac/mdiq/podvinci/core/util/playback/PlaybackController.kt b/core/src/main/java/ac/mdiq/podvinci/core/util/playback/PlaybackController.kt
index f5d48b1a..b0db8ae4 100644
--- a/core/src/main/java/ac/mdiq/podvinci/core/util/playback/PlaybackController.kt
+++ b/core/src/main/java/ac/mdiq/podvinci/core/util/playback/PlaybackController.kt
@@ -74,19 +74,17 @@ abstract class PlaybackController(private val activity: FragmentActivity?) {
initialized = true
// TODO: this shit doesn't work
-// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
-// activity?.registerReceiver(statusUpdate, IntentFilter(
-// PlaybackService.ACTION_PLAYER_STATUS_CHANGED), Context.RECEIVER_NOT_EXPORTED)
-// activity?.registerReceiver(notificationReceiver, IntentFilter(
-// PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION), Context.RECEIVER_NOT_EXPORTED)
-// } else {
-// ContextCompat.registerReceiver(activity!!, statusUpdate, IntentFilter(
-// PlaybackService.ACTION_PLAYER_STATUS_CHANGED), ContextCompat.RECEIVER_EXPORTED)
-// ContextCompat.registerReceiver(activity, notificationReceiver, IntentFilter(
-// PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION), ContextCompat.RECEIVER_EXPORTED)
-// }
- activity?.registerReceiver(statusUpdate, IntentFilter(PlaybackService.ACTION_PLAYER_STATUS_CHANGED))
- activity?.registerReceiver(notificationReceiver, IntentFilter(PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION))
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ activity?.registerReceiver(statusUpdate, IntentFilter(
+ PlaybackService.ACTION_PLAYER_STATUS_CHANGED), Context.RECEIVER_NOT_EXPORTED)
+ activity?.registerReceiver(notificationReceiver, IntentFilter(
+ PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION), Context.RECEIVER_NOT_EXPORTED)
+ } else {
+ activity?.registerReceiver(statusUpdate, IntentFilter(PlaybackService.ACTION_PLAYER_STATUS_CHANGED))
+ activity?.registerReceiver(notificationReceiver, IntentFilter(PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION))
+ }
+// activity?.registerReceiver(statusUpdate, IntentFilter(PlaybackService.ACTION_PLAYER_STATUS_CHANGED))
+// activity?.registerReceiver(notificationReceiver, IntentFilter(PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION))
if (!released) {
bindToService()
@@ -390,7 +388,7 @@ abstract class PlaybackController(private val activity: FragmentActivity?) {
if (playbackService == null || playbackService!!.audioTracks.isNullOrEmpty()) {
return emptyList()
}
- return playbackService!!.audioTracks!!.filterNotNull().map { it }
+ return playbackService!!.audioTracks.filterNotNull().map { it }
}
val selectedAudioTrack: Int
diff --git a/model/src/main/java/ac/mdiq/podvinci/model/feed/Chapter.kt b/model/src/main/java/ac/mdiq/podvinci/model/feed/Chapter.kt
index 2f0175a6..70752a9f 100644
--- a/model/src/main/java/ac/mdiq/podvinci/model/feed/Chapter.kt
+++ b/model/src/main/java/ac/mdiq/podvinci/model/feed/Chapter.kt
@@ -31,6 +31,6 @@ class Chapter : FeedComponent {
}
override fun toString(): String {
- return "ID3Chapter [title=" + title + ", start=" + start + ", url=" + link + "]"
+ return "ID3Chapter [title=$title, start=$start, url=$link]"
}
}