removed unnecessary net load

This commit is contained in:
Xilin Jia 2024-02-19 15:15:58 +01:00
parent 14d823ad3d
commit 7d5bf3ad98
35 changed files with 228 additions and 154 deletions

View File

@ -22,8 +22,8 @@ android {
// Version code schema: // Version code schema:
// "1.2.3-beta4" -> 1020304 // "1.2.3-beta4" -> 1020304
// "1.2.3" -> 1020395 // "1.2.3" -> 1020395
versionCode 3020097 versionCode 3020098
versionName "3.2.2" versionName "3.2.3"
def commit = "" def commit = ""
try { try {

View File

@ -149,9 +149,22 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
} }
}) })
controller = newPlaybackController()
controller?.init()
loadMediaInfo(false)
EventBus.getDefault().register(this)
return root return root
} }
override fun onDestroyView() {
super.onDestroyView()
controller?.release()
controller = null
EventBus.getDefault().unregister(this)
Log.d(TAG, "Fragment destroyed")
}
private fun setChapterDividers(media: Playable?) { private fun setChapterDividers(media: Playable?) {
if (media == null) { if (media == null) {
return return
@ -241,9 +254,8 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
} }
private fun loadMediaInfo(includingChapters: Boolean) { private fun loadMediaInfo(includingChapters: Boolean) {
if (disposable != null) { disposable?.dispose()
disposable!!.dispose()
}
disposable = Maybe.create<Playable> { emitter: MaybeEmitter<Playable?> -> disposable = Maybe.create<Playable> { emitter: MaybeEmitter<Playable?> ->
val media: Playable? = controller?.getMedia() val media: Playable? = controller?.getMedia()
if (media != null) { if (media != null) {
@ -308,20 +320,20 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
controller = newPlaybackController() // controller = newPlaybackController()
controller?.init() // controller?.init()
loadMediaInfo(false) // loadMediaInfo(false)
EventBus.getDefault().register(this) // EventBus.getDefault().register(this)
txtvRev.text = NumberFormat.getInstance().format(UserPreferences.rewindSecs.toLong()) txtvRev.text = NumberFormat.getInstance().format(UserPreferences.rewindSecs.toLong())
txtvFF.text = NumberFormat.getInstance().format(UserPreferences.fastForwardSecs.toLong()) txtvFF.text = NumberFormat.getInstance().format(UserPreferences.fastForwardSecs.toLong())
} }
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
controller?.release() // controller?.release()
controller = null // controller = null
// EventBus.getDefault().unregister(this)
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)
disposable?.dispose() disposable?.dispose()
} }

View File

@ -91,11 +91,6 @@ class ChaptersFragment : AppCompatDialogFragment() {
CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT) CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT)
recyclerView.layoutParams = wrapHeight recyclerView.layoutParams = wrapHeight
return root
}
override fun onStart() {
super.onStart()
controller = object : PlaybackController(activity) { controller = object : PlaybackController(activity) {
override fun loadMediaInfo() { override fun loadMediaInfo() {
this@ChaptersFragment.loadMediaInfo(false) this@ChaptersFragment.loadMediaInfo(false)
@ -104,14 +99,35 @@ class ChaptersFragment : AppCompatDialogFragment() {
controller?.init() controller?.init()
EventBus.getDefault().register(this) EventBus.getDefault().register(this)
loadMediaInfo(false) loadMediaInfo(false)
return root
}
override fun onDestroyView() {
super.onDestroyView()
controller?.release()
controller = null
EventBus.getDefault().unregister(this)
}
override fun onStart() {
super.onStart()
// controller = object : PlaybackController(activity) {
// override fun loadMediaInfo() {
// this@ChaptersFragment.loadMediaInfo(false)
// }
// }
// controller?.init()
// EventBus.getDefault().register(this)
// loadMediaInfo(false)
} }
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
disposable?.dispose() disposable?.dispose()
controller?.release() // controller?.release()
controller = null // controller = null
EventBus.getDefault().unregister(this) // EventBus.getDefault().unregister(this)
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)

View File

@ -29,6 +29,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.annotation.OptIn
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.graphics.BlendModeColorFilterCompat import androidx.core.graphics.BlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat import androidx.core.graphics.BlendModeCompat
@ -78,9 +79,27 @@ class CoverFragment : Fragment() {
} }
viewBinding.butPrevChapter.setOnClickListener { v: View? -> seekToPrevChapter() } viewBinding.butPrevChapter.setOnClickListener { v: View? -> seekToPrevChapter() }
viewBinding.butNextChapter.setOnClickListener { v: View? -> seekToNextChapter() } viewBinding.butNextChapter.setOnClickListener { v: View? -> seekToNextChapter() }
controller = object : PlaybackController(activity) {
override fun loadMediaInfo() {
this@CoverFragment.loadMediaInfo(false)
}
}
controller?.init()
loadMediaInfo(false)
EventBus.getDefault().register(this)
return viewBinding.root return viewBinding.root
} }
@OptIn(UnstableApi::class) override fun onDestroyView() {
super.onDestroyView()
controller?.release()
controller = null
EventBus.getDefault().unregister(this)
Log.d(TAG, "Fragment destroyed")
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
configureForOrientation(resources.configuration) configureForOrientation(resources.configuration)
} }
@ -231,22 +250,22 @@ class CoverFragment : Fragment() {
@UnstableApi override fun onStart() { @UnstableApi override fun onStart() {
super.onStart() super.onStart()
controller = object : PlaybackController(activity) { // controller = object : PlaybackController(activity) {
override fun loadMediaInfo() { // override fun loadMediaInfo() {
this@CoverFragment.loadMediaInfo(false) // this@CoverFragment.loadMediaInfo(false)
} // }
} // }
controller?.init() // controller?.init()
loadMediaInfo(false) // loadMediaInfo(false)
EventBus.getDefault().register(this) // EventBus.getDefault().register(this)
} }
@UnstableApi override fun onStop() { @UnstableApi override fun onStop() {
super.onStop() super.onStop()
disposable?.dispose() disposable?.dispose()
controller?.release() // controller?.release()
controller = null // controller = null
EventBus.getDefault().unregister(this) // EventBus.getDefault().unregister(this)
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)

View File

@ -25,6 +25,7 @@ import ac.mdiq.podvinci.model.playback.MediaType
import ac.mdiq.podvinci.model.playback.Playable import ac.mdiq.podvinci.model.playback.Playable
import ac.mdiq.podvinci.playback.base.PlayerStatus import ac.mdiq.podvinci.playback.base.PlayerStatus
import ac.mdiq.podvinci.view.PlayButton import ac.mdiq.podvinci.view.PlayButton
import androidx.annotation.OptIn
import io.reactivex.Maybe import io.reactivex.Maybe
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
@ -68,9 +69,19 @@ class ExternalPlayerFragment : Fragment() {
} }
} }
} }
controller = setupPlaybackController()
controller!!.init()
loadMediaInfo()
EventBus.getDefault().register(this)
return root return root
} }
@OptIn(UnstableApi::class) override fun onDestroyView() {
super.onDestroyView()
controller?.release()
controller = null
EventBus.getDefault().unregister(this)
}
@UnstableApi @UnstableApi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -105,22 +116,20 @@ class ExternalPlayerFragment : Fragment() {
} }
} }
@UnstableApi
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
controller = setupPlaybackController() // controller = setupPlaybackController()
controller!!.init() // controller!!.init()
loadMediaInfo() // loadMediaInfo()
EventBus.getDefault().register(this) // EventBus.getDefault().register(this)
} }
@UnstableApi
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
controller?.release() // controller?.release()
controller = null // controller = null
//
EventBus.getDefault().unregister(this) // EventBus.getDefault().unregister(this)
} }
@UnstableApi @UnstableApi
@ -146,7 +155,6 @@ class ExternalPlayerFragment : Fragment() {
super.onDestroy() super.onDestroy()
Log.d(TAG, "Fragment is about to be destroyed") Log.d(TAG, "Fragment is about to be destroyed")
disposable?.dispose() disposable?.dispose()
} }
@UnstableApi @UnstableApi

View File

@ -77,9 +77,9 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
private lateinit var nextPageLoader: MoreContentListFooterUtil private lateinit var nextPageLoader: MoreContentListFooterUtil
private var displayUpArrow = false private var displayUpArrow = false
private var headerCreated = false
private var feedID: Long = 0 private var feedID: Long = 0
private var feed: Feed? = null private var feed: Feed? = null
private var headerCreated = false
private var disposable: Disposable? = null private var disposable: Disposable? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -236,8 +236,8 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
} }
R.id.refresh_complete_item -> { R.id.refresh_complete_item -> {
Thread { Thread {
feed?.nextPageLink = feed!!.download_url feed!!.nextPageLink = feed!!.download_url
feed?.pageNr = 0 feed!!.pageNr = 0
try { try {
DBWriter.resetPagedFeedPage(feed).get() DBWriter.resetPagedFeedPage(feed).get()
FeedUpdateManager.runOnce(context, feed) FeedUpdateManager.runOnce(context, feed)

View File

@ -28,6 +28,7 @@ import io.reactivex.schedulers.Schedulers
@UnstableApi @UnstableApi
class ItemDescriptionFragment : Fragment() { class ItemDescriptionFragment : Fragment() {
private lateinit var webvDescription: ShownotesWebView private lateinit var webvDescription: ShownotesWebView
private var webViewLoader: Disposable? = null private var webViewLoader: Disposable? = null
private var controller: PlaybackController? = null private var controller: PlaybackController? = null
@ -36,9 +37,7 @@ class ItemDescriptionFragment : Fragment() {
val root = inflater.inflate(R.layout.item_description_fragment, container, false) val root = inflater.inflate(R.layout.item_description_fragment, container, false)
webvDescription = root.findViewById(R.id.webview) webvDescription = root.findViewById(R.id.webview)
webvDescription.setTimecodeSelectedListener { time: Int? -> webvDescription.setTimecodeSelectedListener { time: Int? ->
if (controller != null) { controller?.seekTo(time!!)
controller!!.seekTo(time!!)
}
} }
webvDescription.setPageFinishedListener { webvDescription.setPageFinishedListener {
// Restoring the scroll position might not always work // Restoring the scroll position might not always work
@ -56,11 +55,21 @@ class ItemDescriptionFragment : Fragment() {
} }
}) })
registerForContextMenu(webvDescription) registerForContextMenu(webvDescription)
controller = object : PlaybackController(activity) {
override fun loadMediaInfo() {
load()
}
}
controller?.init()
load()
return root return root
} }
override fun onDestroy() { override fun onDestroyView() {
super.onDestroy() super.onDestroyView()
controller?.release()
controller = null
Log.d(TAG, "Fragment destroyed") Log.d(TAG, "Fragment destroyed")
webvDescription.removeAllViews() webvDescription.removeAllViews()
webvDescription.destroy() webvDescription.destroy()
@ -71,13 +80,12 @@ class ItemDescriptionFragment : Fragment() {
} }
@UnstableApi private fun load() { @UnstableApi private fun load() {
Log.d(TAG, "load()") Log.d(TAG, "load() called")
if (webViewLoader != null) { webViewLoader?.dispose()
webViewLoader!!.dispose()
}
val context = context ?: return val context = context ?: return
webViewLoader = Maybe.create { emitter: MaybeEmitter<String?> -> webViewLoader = Maybe.create { emitter: MaybeEmitter<String?> ->
val media = controller!!.getMedia() val media = controller?.getMedia()
if (media == null) { if (media == null) {
emitter.onComplete() emitter.onComplete()
return@create return@create
@ -112,8 +120,7 @@ class ItemDescriptionFragment : Fragment() {
if (controller?.getMedia() != null) { if (controller?.getMedia() != null) {
Log.d(TAG, "Saving scroll position: " + webvDescription.scrollY) Log.d(TAG, "Saving scroll position: " + webvDescription.scrollY)
editor.putInt(PREF_SCROLL_Y, webvDescription.scrollY) editor.putInt(PREF_SCROLL_Y, webvDescription.scrollY)
editor.putString(PREF_PLAYABLE_ID, controller!!.getMedia()!!.getIdentifier() editor.putString(PREF_PLAYABLE_ID, controller!!.getMedia()!!.getIdentifier().toString())
.toString())
} else { } else {
Log.d(TAG, "savePreferences was called while media or webview was null") Log.d(TAG, "savePreferences was called while media or webview was null")
editor.putInt(PREF_SCROLL_Y, -1) editor.putInt(PREF_SCROLL_Y, -1)
@ -145,23 +152,21 @@ class ItemDescriptionFragment : Fragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
controller = object : PlaybackController(activity) { // controller = object : PlaybackController(activity) {
override fun loadMediaInfo() { // override fun loadMediaInfo() {
load() // load()
} // }
} // }
controller?.init() // controller?.init()
load() // load()
} }
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
if (webViewLoader != null) { webViewLoader?.dispose()
webViewLoader!!.dispose() // controller?.release()
} // controller = null
controller!!.release()
controller = null
} }
companion object { companion object {

View File

@ -154,6 +154,16 @@ class ItemFragment : Fragment() {
} }
actionButton2?.onClick(requireContext()) actionButton2?.onClick(requireContext())
}) })
EventBus.getDefault().register(this)
controller = object : PlaybackController(activity) {
override fun loadMediaInfo() {
// Do nothing
}
}
controller?.init()
load()
return layout return layout
} }
@ -193,14 +203,14 @@ class ItemFragment : Fragment() {
@UnstableApi override fun onStart() { @UnstableApi override fun onStart() {
super.onStart() super.onStart()
EventBus.getDefault().register(this) // EventBus.getDefault().register(this)
controller = object : PlaybackController(activity) { // controller = object : PlaybackController(activity) {
override fun loadMediaInfo() { // override fun loadMediaInfo() {
// Do nothing // // Do nothing
} // }
} // }
controller?.init() // controller?.init()
load() // load()
} }
@UnstableApi override fun onResume() { @UnstableApi override fun onResume() {
@ -213,12 +223,14 @@ class ItemFragment : Fragment() {
@UnstableApi override fun onStop() { @UnstableApi override fun onStop() {
super.onStop() super.onStop()
EventBus.getDefault().unregister(this) // EventBus.getDefault().unregister(this)
controller?.release() // controller?.release()
} }
override fun onDestroyView() { @OptIn(UnstableApi::class) override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
EventBus.getDefault().unregister(this)
controller?.release()
disposable?.dispose() disposable?.dispose()
root.removeView(webvDescription) root.removeView(webvDescription)
webvDescription.destroy() webvDescription.destroy()

View File

@ -142,8 +142,8 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
speedDialView = root.findViewById(R.id.fabSD) speedDialView = root.findViewById(R.id.fabSD)
speedDialView.overlayLayout = root.findViewById(R.id.fabSDOverlay) speedDialView.overlayLayout = root.findViewById(R.id.fabSDOverlay)
speedDialView.inflate(R.menu.episodes_apply_action_speeddial) speedDialView.inflate(R.menu.episodes_apply_action_speeddial)
speedDialView.removeActionItemById(R.id.mark_read_batch) // speedDialView.removeActionItemById(R.id.mark_read_batch)
speedDialView.removeActionItemById(R.id.mark_unread_batch) // speedDialView.removeActionItemById(R.id.mark_unread_batch)
speedDialView.removeActionItemById(R.id.add_to_queue_batch) speedDialView.removeActionItemById(R.id.add_to_queue_batch)
speedDialView.removeActionItemById(R.id.remove_all_inbox_item) speedDialView.removeActionItemById(R.id.remove_all_inbox_item)
speedDialView.setOnChangeListener(object : SpeedDialView.OnChangeListener { speedDialView.setOnChangeListener(object : SpeedDialView.OnChangeListener {
@ -337,9 +337,7 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
val conDialog: ConfirmationDialog = object : ConfirmationDialog(requireContext(), val conDialog: ConfirmationDialog = object : ConfirmationDialog(requireContext(),
R.string.clear_queue_label, R.string.clear_queue_label,
R.string.clear_queue_confirmation_msg) { R.string.clear_queue_confirmation_msg) {
@UnstableApi override fun onConfirmButtonPressed( @UnstableApi override fun onConfirmButtonPressed(dialog: DialogInterface) {
dialog: DialogInterface
) {
dialog.dismiss() dialog.dismiss()
DBWriter.clearQueue() DBWriter.clearQueue()
} }
@ -512,11 +510,7 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
return view return view
} }
override fun onAddItem(title: Int, override fun onAddItem(title: Int, ascending: SortOrder, descending: SortOrder, ascendingIsDefault: Boolean) {
ascending: SortOrder,
descending: SortOrder,
ascendingIsDefault: Boolean
) {
if (ascending != SortOrder.EPISODE_FILENAME_A_Z && ascending != SortOrder.SIZE_SMALL_LARGE) { if (ascending != SortOrder.EPISODE_FILENAME_A_Z && ascending != SortOrder.SIZE_SMALL_LARGE) {
super.onAddItem(title, ascending, descending, ascendingIsDefault) super.onAddItem(title, ascending, descending, ascendingIsDefault)
} }

View File

@ -35,7 +35,7 @@ class AutoDownloadPreferencesFragment : PreferenceFragmentCompat() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.pref_automatic_download_title) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.pref_automatic_download_title)
} }
override fun onResume() { override fun onResume() {

View File

@ -32,7 +32,7 @@ class DownloadsPreferencesFragment : PreferenceFragmentCompat(), OnSharedPrefere
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.downloads_pref) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.downloads_pref)
PreferenceManager.getDefaultSharedPreferences(requireContext()).registerOnSharedPreferenceChangeListener( PreferenceManager.getDefaultSharedPreferences(requireContext()).registerOnSharedPreferenceChangeListener(
this) this)
} }
@ -51,7 +51,7 @@ class DownloadsPreferencesFragment : PreferenceFragmentCompat(), OnSharedPrefere
private fun setupNetworkScreen() { private fun setupNetworkScreen() {
findPreference<Preference>(PREF_SCREEN_AUTODL)!!.onPreferenceClickListener = findPreference<Preference>(PREF_SCREEN_AUTODL)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { preference: Preference? -> Preference.OnPreferenceClickListener { preference: Preference? ->
(activity as PreferenceActivity?)!!.openScreen(R.xml.preferences_autodownload) (activity as PreferenceActivity).openScreen(R.xml.preferences_autodownload)
true true
} }
// validate and set correct value: number of downloads between 1 and 50 (inclusive) // validate and set correct value: number of downloads between 1 and 50 (inclusive)

View File

@ -75,7 +75,7 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.import_export_pref) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.import_export_pref)
} }
override fun onStop() { override fun onStop() {

View File

@ -54,39 +54,39 @@ class MainPreferencesFragment : PreferenceFragmentCompat() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.settings_label) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.settings_label)
} }
@SuppressLint("CommitTransaction") @SuppressLint("CommitTransaction")
private fun setupMainScreen() { private fun setupMainScreen() {
findPreference<Preference>(PREF_SCREEN_USER_INTERFACE)!!.onPreferenceClickListener = findPreference<Preference>(PREF_SCREEN_USER_INTERFACE)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { preference: Preference? -> Preference.OnPreferenceClickListener { preference: Preference? ->
(activity as PreferenceActivity?)!!.openScreen(R.xml.preferences_user_interface) (activity as PreferenceActivity).openScreen(R.xml.preferences_user_interface)
true true
} }
findPreference<Preference>(PREF_SCREEN_PLAYBACK)!!.onPreferenceClickListener = findPreference<Preference>(PREF_SCREEN_PLAYBACK)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { preference: Preference? -> Preference.OnPreferenceClickListener { preference: Preference? ->
(activity as PreferenceActivity?)!!.openScreen(R.xml.preferences_playback) (activity as PreferenceActivity).openScreen(R.xml.preferences_playback)
true true
} }
findPreference<Preference>(PREF_SCREEN_DOWNLOADS)!!.onPreferenceClickListener = findPreference<Preference>(PREF_SCREEN_DOWNLOADS)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { preference: Preference? -> Preference.OnPreferenceClickListener { preference: Preference? ->
(activity as PreferenceActivity?)!!.openScreen(R.xml.preferences_downloads) (activity as PreferenceActivity).openScreen(R.xml.preferences_downloads)
true true
} }
findPreference<Preference>(PREF_SCREEN_SYNCHRONIZATION)!!.onPreferenceClickListener = findPreference<Preference>(PREF_SCREEN_SYNCHRONIZATION)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { preference: Preference? -> Preference.OnPreferenceClickListener { preference: Preference? ->
(activity as PreferenceActivity?)!!.openScreen(R.xml.preferences_synchronization) (activity as PreferenceActivity).openScreen(R.xml.preferences_synchronization)
true true
} }
findPreference<Preference>(PREF_SCREEN_IMPORT_EXPORT)!!.onPreferenceClickListener = findPreference<Preference>(PREF_SCREEN_IMPORT_EXPORT)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { preference: Preference? -> Preference.OnPreferenceClickListener { preference: Preference? ->
(activity as PreferenceActivity?)!!.openScreen(R.xml.preferences_import_export) (activity as PreferenceActivity).openScreen(R.xml.preferences_import_export)
true true
} }
findPreference<Preference>(PREF_NOTIFICATION)!!.onPreferenceClickListener = findPreference<Preference>(PREF_NOTIFICATION)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { preference: Preference? -> Preference.OnPreferenceClickListener { preference: Preference? ->
(activity as PreferenceActivity?)!!.openScreen(R.xml.preferences_notifications) (activity as PreferenceActivity).openScreen(R.xml.preferences_notifications)
true true
} }
findPreference<Preference>(PREF_ABOUT)!!.onPreferenceClickListener = findPreference<Preference>(PREF_ABOUT)!!.onPreferenceClickListener =

View File

@ -15,7 +15,7 @@ class NotificationPreferencesFragment : PreferenceFragmentCompat() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.notification_pref_fragment) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.notification_pref_fragment)
} }
private fun setUpScreen() { private fun setUpScreen() {

View File

@ -27,7 +27,7 @@ class PlaybackPreferencesFragment : PreferenceFragmentCompat() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.playback_pref) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.playback_pref)
} }
private fun setupPlaybackScreen() { private fun setupPlaybackScreen() {

View File

@ -58,7 +58,7 @@ class SwipePreferencesFragment : PreferenceFragmentCompat() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.swipeactions_label) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.swipeactions_label)
} }
companion object { companion object {

View File

@ -31,7 +31,7 @@ class UserInterfacePreferencesFragment : PreferenceFragmentCompat() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.user_interface_label) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.user_interface_label)
} }
private fun setupInterfaceScreen() { private fun setupInterfaceScreen() {
@ -78,7 +78,7 @@ class UserInterfacePreferencesFragment : PreferenceFragmentCompat() {
}) })
findPreference<Preference>(PREF_SWIPE) findPreference<Preference>(PREF_SWIPE)
?.setOnPreferenceClickListener { preference: Preference? -> ?.setOnPreferenceClickListener { preference: Preference? ->
(activity as PreferenceActivity?)!!.openScreen(R.xml.preferences_swipe) (activity as PreferenceActivity).openScreen(R.xml.preferences_swipe)
true true
} }

View File

@ -57,6 +57,6 @@ class AboutFragment : PreferenceFragmentCompat() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.about_pref) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.about_pref)
} }
} }

View File

@ -44,7 +44,7 @@ class ContributorsPagerFragment : Fragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.contributors) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.contributors)
} }
class StatisticsPagerAdapter internal constructor(fragment: Fragment) : FragmentStateAdapter(fragment) { class StatisticsPagerAdapter internal constructor(fragment: Fragment) : FragmentStateAdapter(fragment) {

View File

@ -98,13 +98,11 @@ class LicensesFragment : ListFragment() {
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
if (licensesLoader != null) { licensesLoader?.dispose()
licensesLoader!!.dispose()
}
} }
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.licenses) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.licenses)
} }
} }

View File

@ -37,7 +37,7 @@ class SynchronizationPreferencesFragment : PreferenceFragmentCompat() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as PreferenceActivity?)!!.supportActionBar!!.setTitle(R.string.synchronization_pref) (activity as PreferenceActivity).supportActionBar!!.setTitle(R.string.synchronization_pref)
updateScreen() updateScreen()
EventBus.getDefault().register(this) EventBus.getDefault().register(this)
} }
@ -45,7 +45,7 @@ class SynchronizationPreferencesFragment : PreferenceFragmentCompat() {
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
EventBus.getDefault().unregister(this) EventBus.getDefault().unregister(this)
(activity as PreferenceActivity?)!!.supportActionBar!!.subtitle = "" (activity as PreferenceActivity).supportActionBar!!.subtitle = ""
} }
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true) @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
@ -59,7 +59,7 @@ class SynchronizationPreferencesFragment : PreferenceFragmentCompat() {
updateLastSyncReport(SynchronizationSettings.isLastSyncSuccessful, updateLastSyncReport(SynchronizationSettings.isLastSyncSuccessful,
SynchronizationSettings.lastSyncAttempt) SynchronizationSettings.lastSyncAttempt)
} else { } else {
(activity as PreferenceActivity?)!!.supportActionBar!! (activity as PreferenceActivity).supportActionBar!!
.setSubtitle(event.messageResId) .setSubtitle(event.messageResId)
} }
} }
@ -203,7 +203,7 @@ class SynchronizationPreferencesFragment : PreferenceFragmentCompat() {
) R.string.gpodnetsync_pref_report_successful else R.string.gpodnetsync_pref_report_failed), ) R.string.gpodnetsync_pref_report_successful else R.string.gpodnetsync_pref_report_failed),
DateUtils.getRelativeDateTimeString(context, DateUtils.getRelativeDateTimeString(context,
lastTime, DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, DateUtils.FORMAT_SHOW_TIME)) lastTime, DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, DateUtils.FORMAT_SHOW_TIME))
(activity as PreferenceActivity?)!!.supportActionBar!!.subtitle = status (activity as PreferenceActivity).supportActionBar!!.subtitle = status
} }
companion object { companion object {

View File

@ -29,6 +29,7 @@ import ac.mdiq.podvinci.storage.preferences.UserPreferences
import ac.mdiq.podvinci.ui.echo.EchoActivity import ac.mdiq.podvinci.ui.echo.EchoActivity
import ac.mdiq.podvinci.ui.home.sections.* import ac.mdiq.podvinci.ui.home.sections.*
import ac.mdiq.podvinci.view.LiftOnScrollListener import ac.mdiq.podvinci.view.LiftOnScrollListener
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
@ -68,7 +69,7 @@ class HomeFragment : Fragment(), Toolbar.OnMenuItemClickListener {
return viewBinding.root return viewBinding.root
} }
private fun populateSectionList() { @OptIn(UnstableApi::class) private fun populateSectionList() {
viewBinding.homeContainer.removeAllViews() viewBinding.homeContainer.removeAllViews()
val prefs: SharedPreferences = requireContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) val prefs: SharedPreferences = requireContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)

View File

@ -12,7 +12,7 @@
<TextView <TextView
android:id="@+id/titleLabel" android:id="@+id/titleLabel"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:textAlignment="textStart" android:textAlignment="textStart"
@ -27,7 +27,7 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0" app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_default="wrap" app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@id/shuffleButton" app:layout_constraintEnd_toStartOf="@id/shuffleButton"
tools:text="Title" /> tools:text="Title" />

View File

@ -1656,12 +1656,14 @@ class PlaybackService : MediaBrowserServiceCompat() {
positionEventTimer = Observable.interval(POSITION_EVENT_INTERVAL, TimeUnit.SECONDS) positionEventTimer = Observable.interval(POSITION_EVENT_INTERVAL, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { number: Long? -> .subscribe { number: Long? ->
Log.d(TAG, "notificationBuilder.updatePosition currentPosition: $currentPosition, currentPlaybackSpeed: $currentPlaybackSpeed")
EventBus.getDefault().post(PlaybackPositionEvent(currentPosition, duration)) EventBus.getDefault().post(PlaybackPositionEvent(currentPosition, duration))
if (Build.VERSION.SDK_INT < 29) { // TODO: why set SDK_INT < 29
// if (Build.VERSION.SDK_INT < 29) {
notificationBuilder.updatePosition(currentPosition, currentPlaybackSpeed) notificationBuilder.updatePosition(currentPosition, currentPlaybackSpeed)
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager val notificationManager = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager
notificationManager?.notify(R.id.notification_playing, notificationBuilder.build()) notificationManager?.notify(R.id.notification_playing, notificationBuilder.build())
} // }
skipEndingIfNecessary() skipEndingIfNecessary()
} }
} }
@ -1860,6 +1862,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
*/ */
private const val TAG = "PlaybackService" private const val TAG = "PlaybackService"
// TODO: need to experiment this value
private const val POSITION_EVENT_INTERVAL = 10L private const val POSITION_EVENT_INTERVAL = 10L
const val ACTION_PLAYER_STATUS_CHANGED: String = "action.ac.mdiq.podvinci.core.service.playerStatusChanged" const val ACTION_PLAYER_STATUS_CHANGED: String = "action.ac.mdiq.podvinci.core.service.playerStatusChanged"

View File

@ -176,11 +176,9 @@ class PlaybackServiceNotificationBuilder(private val context: Context) {
compactActionList.add(numActions) compactActionList.add(numActions)
numActions++ numActions++
if (UserPreferences.showNextChapterOnFullNotification() && playable!!.getChapters() != null) { if (UserPreferences.showNextChapterOnFullNotification() && playable?.getChapters() != null) {
val nextChapterPendingIntent = getPendingIntentForCustomMediaAction( val nextChapterPendingIntent = getPendingIntentForCustomMediaAction(PlaybackService.CUSTOM_ACTION_NEXT_CHAPTER, numActions)
PlaybackService.CUSTOM_ACTION_NEXT_CHAPTER, numActions) notification.addAction(R.drawable.ic_notification_next_chapter, context.getString(R.string.next_chapter), nextChapterPendingIntent)
notification.addAction(R.drawable.ic_notification_next_chapter, context.getString(R.string.next_chapter),
nextChapterPendingIntent)
numActions++ numActions++
} }

View File

@ -22,10 +22,10 @@ class APQueueCleanupAlgorithm : EpisodeCleanupAlgorithm() {
} }
public override fun performCleanup(context: Context?, numberOfEpisodesToDelete: Int): Int { public override fun performCleanup(context: Context?, numberOfEpisodesToDelete: Int): Int {
val candidates = candidates var candidates = candidates
// in the absence of better data, we'll sort by item publication date // in the absence of better data, we'll sort by item publication date
Collections.sort(candidates) { lhs: FeedItem, rhs: FeedItem -> candidates = candidates.sortedWith { lhs: FeedItem, rhs: FeedItem ->
var l = lhs.getPubDate() var l = lhs.getPubDate()
var r = rhs.getPubDate() var r = rhs.getPubDate()

View File

@ -342,9 +342,9 @@ object DBReader {
i++ i++
} }
itemCursor = adapter.getFeedItemCursor(itemIds.filterNotNull().toTypedArray()) itemCursor = adapter.getFeedItemCursor(itemIds.filterNotNull().toTypedArray())
val items = extractItemlistFromCursor(adapter, itemCursor) val items = extractItemlistFromCursor(adapter, itemCursor).toMutableList()
loadAdditionalFeedItemListData(items) loadAdditionalFeedItemListData(items)
Collections.sort(items, PlaybackCompletionDateComparator()) items.sortWith(PlaybackCompletionDateComparator())
return items return items
} finally { } finally {
mediaCursor?.close() mediaCursor?.close()
@ -378,7 +378,7 @@ object DBReader {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
downloadLog.add(convert(cursor)) downloadLog.add(convert(cursor))
} }
Collections.sort(downloadLog, DownloadResultComparator()) downloadLog.sortWith(DownloadResultComparator())
return downloadLog return downloadLog
} }
} finally { } finally {
@ -404,7 +404,7 @@ object DBReader {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
downloadLog.add(convert(cursor)) downloadLog.add(convert(cursor))
} }
Collections.sort(downloadLog, DownloadResultComparator()) downloadLog.sortWith(DownloadResultComparator())
return downloadLog return downloadLog
} }
} finally { } finally {
@ -621,6 +621,11 @@ object DBReader {
*/ */
fun loadDescriptionOfFeedItem(item: FeedItem) { fun loadDescriptionOfFeedItem(item: FeedItem) {
Log.d(TAG, "loadDescriptionOfFeedItem() called with: item = [$item]") Log.d(TAG, "loadDescriptionOfFeedItem() 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() val adapter = getInstance()
adapter!!.open() adapter!!.open()
try { try {
@ -712,9 +717,9 @@ object DBReader {
adapter!!.open() adapter!!.open()
try { try {
adapter.getFeedItemCursorByUrl(urls!!).use { itemCursor -> adapter.getFeedItemCursorByUrl(urls!!).use { itemCursor ->
val items = extractItemlistFromCursor(adapter, itemCursor) val items = extractItemlistFromCursor(adapter, itemCursor).toMutableList()
loadAdditionalFeedItemListData(items) loadAdditionalFeedItemListData(items)
Collections.sort(items, PlaybackCompletionDateComparator()) items.sortWith(PlaybackCompletionDateComparator())
return items return items
} }
} finally { } finally {
@ -870,7 +875,7 @@ object DBReader {
} }
} }
Collections.sort(feeds, comparator) feeds = feeds.sortedWith(comparator)
val queueSize = adapter.queueSize val queueSize = adapter.queueSize
val numNewItems = getTotalEpisodeCount(FeedItemFilter(FeedItemFilter.NEW)) val numNewItems = getTotalEpisodeCount(FeedItemFilter(FeedItemFilter.NEW))
val numDownloadedItems = getTotalEpisodeCount(FeedItemFilter(FeedItemFilter.DOWNLOADED)) val numDownloadedItems = getTotalEpisodeCount(FeedItemFilter(FeedItemFilter.DOWNLOADED))

View File

@ -211,7 +211,7 @@ import java.util.concurrent.*
} else { } else {
Log.d(TAG, "Feed with title " + newFeed.title + " already exists. Syncing new with existing one.") Log.d(TAG, "Feed with title " + newFeed.title + " already exists. Syncing new with existing one.")
Collections.sort(newFeed.items, FeedItemPubdateComparator()) newFeed.items.sortWith(FeedItemPubdateComparator())
if (newFeed.pageNr == savedFeed.pageNr) { if (newFeed.pageNr == savedFeed.pageNr) {
if (savedFeed.compareWithOther(newFeed)) { if (savedFeed.compareWithOther(newFeed)) {

View File

@ -26,17 +26,17 @@ class ExceptFavoriteCleanupAlgorithm : EpisodeCleanupAlgorithm() {
} }
public override fun performCleanup(context: Context?, numberOfEpisodesToDelete: Int): Int { public override fun performCleanup(context: Context?, numberOfEpisodesToDelete: Int): Int {
val candidates = candidates var candidates = candidates
// in the absence of better data, we'll sort by item publication date // in the absence of better data, we'll sort by item publication date
Collections.sort(candidates) { lhs: FeedItem, rhs: FeedItem -> candidates = candidates.sortedWith { lhs: FeedItem, rhs: FeedItem ->
val l = lhs.getPubDate() val l = lhs.getPubDate()
val r = rhs.getPubDate() val r = rhs.getPubDate()
if (l != null && r != null) { if (l != null && r != null) {
return@sort l.compareTo(r) return@sortedWith l.compareTo(r)
} else { } else {
// No date - compare by id which should be always incremented // No date - compare by id which should be always incremented
return@sort lhs.id.compareTo(rhs.id) return@sortedWith lhs.id.compareTo(rhs.id)
} }
} }

View File

@ -167,8 +167,8 @@ object ChapterUtils {
private fun readId3ChaptersFrom(inVal: CountingInputStream): List<Chapter> { private fun readId3ChaptersFrom(inVal: CountingInputStream): List<Chapter> {
val reader = ChapterReader(inVal) val reader = ChapterReader(inVal)
reader.readInputStream() reader.readInputStream()
val chapters = reader.getChapters() var chapters = reader.getChapters()
Collections.sort(chapters, ChapterStartTimeComparator()) chapters = chapters.sortedWith(ChapterStartTimeComparator())
enumerateEmptyChapterTitles(chapters) enumerateEmptyChapterTitles(chapters)
if (!chaptersValid(chapters)) { if (!chaptersValid(chapters)) {
Log.i(TAG, "Chapter data was invalid") Log.i(TAG, "Chapter data was invalid")
@ -181,8 +181,8 @@ object ChapterUtils {
private fun readOggChaptersFromInputStream(input: InputStream): List<Chapter> { private fun readOggChaptersFromInputStream(input: InputStream): List<Chapter> {
val reader = VorbisCommentChapterReader(BufferedInputStream(input)) val reader = VorbisCommentChapterReader(BufferedInputStream(input))
reader.readInputStream() reader.readInputStream()
val chapters = reader.getChapters() var chapters = reader.getChapters()
Collections.sort(chapters, ChapterStartTimeComparator()) chapters = chapters.sortedWith(ChapterStartTimeComparator())
enumerateEmptyChapterTitles(chapters) enumerateEmptyChapterTitles(chapters)
if (chaptersValid(chapters)) { if (chaptersValid(chapters)) {
return chapters return chapters

View File

@ -139,7 +139,7 @@ object FeedItemPermutors {
val feeds: MutableList<List<FeedItem>> = ArrayList() val feeds: MutableList<List<FeedItem>> = ArrayList()
for ((_, value) in map) { for ((_, value) in map) {
Collections.sort(value, itemComparator) value.sortWith(itemComparator)
feeds.add(value) feeds.add(value)
} }

View File

@ -19,7 +19,6 @@ import android.os.IBinder
import android.util.Log import android.util.Log
import android.util.Pair import android.util.Pair
import android.view.SurfaceHolder import android.view.SurfaceHolder
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
@ -73,7 +72,6 @@ abstract class PlaybackController(private val activity: FragmentActivity?) {
} }
initialized = true initialized = true
// TODO: this shit doesn't work
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
activity?.registerReceiver(statusUpdate, IntentFilter( activity?.registerReceiver(statusUpdate, IntentFilter(
PlaybackService.ACTION_PLAYER_STATUS_CHANGED), Context.RECEIVER_NOT_EXPORTED) PlaybackService.ACTION_PLAYER_STATUS_CHANGED), Context.RECEIVER_NOT_EXPORTED)

View File

@ -48,9 +48,9 @@ internal object DbTestUtils {
"http://example.com", "http://example.com/image.png")) "http://example.com", "http://example.com/image.png"))
} }
} }
f.items?.add(item) f.items.add(item)
} }
Collections.sort(f.items, FeedItemPubdateComparator()) f.items.sortWith(FeedItemPubdateComparator())
adapter.setCompleteFeed(f) adapter.setCompleteFeed(f)
Assert.assertTrue(f.id != 0L) Assert.assertTrue(f.id != 0L)
for (item in f.items!!) { for (item in f.items!!) {

View File

@ -24,10 +24,15 @@ object DownloadResultCursorMapper {
val indexCompletionDate = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_COMPLETION_DATE) val indexCompletionDate = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_COMPLETION_DATE)
val indexReasonDetailed = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_REASON_DETAILED) val indexReasonDetailed = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_REASON_DETAILED)
return DownloadResult(cursor.getLong(indexId), cursor.getString(indexTitle), cursor.getLong(indexFeedFile), return DownloadResult(
cursor.getInt(indexFileFileType), cursor.getInt(indexSuccessful) > 0, cursor.getLong(indexId),
cursor.getString(indexTitle),
cursor.getLong(indexFeedFile),
cursor.getInt(indexFileFileType),
cursor.getInt(indexSuccessful) > 0,
fromCode(cursor.getInt(indexReason)), fromCode(cursor.getInt(indexReason)),
Date(cursor.getLong(indexCompletionDate)), Date(cursor.getLong(indexCompletionDate)),
cursor.getString(indexReasonDetailed)) if (!cursor.isNull(indexReasonDetailed)) cursor.getString(indexReasonDetailed) else ""
)
} }
} }

View File

@ -44,10 +44,10 @@ class FeedStatisticsFragment : Fragment() {
disposable = disposable =
Observable.fromCallable { Observable.fromCallable {
val statisticsData = DBReader.getStatistics(true, 0, Long.MAX_VALUE) val statisticsData = DBReader.getStatistics(true, 0, Long.MAX_VALUE)
Collections.sort(statisticsData.feedTime) { item1: StatisticsItem, item2: StatisticsItem -> statisticsData.feedTime.sortWith(Comparator { item1: StatisticsItem, item2: StatisticsItem ->
java.lang.Long.compare(item2.timePlayed, java.lang.Long.compare(item2.timePlayed,
item1.timePlayed) item1.timePlayed)
} })
for (statisticsItem in statisticsData.feedTime) { for (statisticsItem in statisticsData.feedTime) {
if (statisticsItem.feed.id == feedId) { if (statisticsItem.feed.id == feedId) {