add info bars and thematic icons
This commit is contained in:
parent
de261e2825
commit
063af37362
|
@ -149,8 +149,8 @@ android {
|
|||
// Version code schema (not used):
|
||||
// "1.2.3-beta4" -> 1020304
|
||||
// "1.2.3" -> 1020395
|
||||
versionCode 3020108
|
||||
versionName "4.2.5"
|
||||
versionCode 3020109
|
||||
versionName "4.2.6"
|
||||
|
||||
def commit = ""
|
||||
try {
|
||||
|
|
|
@ -193,7 +193,7 @@ class UITestUtils(private val context: Context) {
|
|||
adapter.setCompleteFeed(*hostedFeeds.toTypedArray<Feed>())
|
||||
adapter.setQueue(queue)
|
||||
adapter.close()
|
||||
EventBus.getDefault().post(ac.mdiq.podcini.util.event.FeedListUpdateEvent(hostedFeeds))
|
||||
EventBus.getDefault().post(FeedListUpdateEvent(hostedFeeds))
|
||||
EventBus.getDefault().post(setQueue(queue))
|
||||
}
|
||||
|
||||
|
|
|
@ -10,14 +10,14 @@ import org.greenrobot.eventbus.Subscribe
|
|||
*
|
||||
*/
|
||||
class FeedItemEventListener {
|
||||
private val events: MutableList<ac.mdiq.podcini.util.event.FeedItemEvent> = ArrayList()
|
||||
private val events: MutableList<FeedItemEvent> = ArrayList()
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: ac.mdiq.podcini.util.event.FeedItemEvent) {
|
||||
fun onEvent(event: FeedItemEvent) {
|
||||
events.add(event)
|
||||
}
|
||||
|
||||
fun getEvents(): List<ac.mdiq.podcini.util.event.FeedItemEvent> {
|
||||
fun getEvents(): List<FeedItemEvent> {
|
||||
return events
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import ac.mdiq.podcini.ui.gui.NotificationUtils
|
|||
import ac.mdiq.podcini.storage.model.playback.Playable
|
||||
import ac.mdiq.podcini.playback.base.PlayerStatus
|
||||
import ac.mdiq.podcini.preferences.UserPreferences
|
||||
import ac.mdiq.podcini.util.Converter
|
||||
import org.apache.commons.lang3.ArrayUtils
|
||||
import java.util.concurrent.ExecutionException
|
||||
|
||||
|
@ -52,7 +53,7 @@ class PlaybackServiceNotificationBuilder(private val context: Context) {
|
|||
|
||||
fun updatePosition(position: Int, speed: Float) {
|
||||
val converter = TimeSpeedConverter(speed)
|
||||
this.position = ac.mdiq.podcini.util.Converter.getDurationStringLong(converter.convert(position))
|
||||
this.position = Converter.getDurationStringLong(converter.convert(position))
|
||||
}
|
||||
|
||||
val isIconCached: Boolean
|
||||
|
|
|
@ -25,6 +25,7 @@ import ac.mdiq.podcini.storage.database.PodDBAdapter
|
|||
import ac.mdiq.podcini.storage.database.PodDBAdapter.Companion.getInstance
|
||||
import ac.mdiq.podcini.storage.database.mapper.FeedCursorMapper.convert
|
||||
import ac.mdiq.podcini.preferences.UserPreferences.newEpisodesAction
|
||||
import ac.mdiq.podcini.util.event.FeedListUpdateEvent
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import java.util.*
|
||||
import java.util.concurrent.*
|
||||
|
@ -352,9 +353,9 @@ import java.util.concurrent.*
|
|||
adapter.close()
|
||||
|
||||
if (savedFeed != null) {
|
||||
EventBus.getDefault().post(ac.mdiq.podcini.util.event.FeedListUpdateEvent(savedFeed))
|
||||
EventBus.getDefault().post(FeedListUpdateEvent(savedFeed))
|
||||
} else {
|
||||
EventBus.getDefault().post(ac.mdiq.podcini.util.event.FeedListUpdateEvent(emptyList()))
|
||||
EventBus.getDefault().post(FeedListUpdateEvent(emptyList()))
|
||||
}
|
||||
|
||||
return resultFeed
|
||||
|
|
|
@ -74,8 +74,7 @@ class SubscriptionsFilter(private val properties: Array<String>) {
|
|||
|
||||
if (showIfCounterGreaterZero) {
|
||||
for (i in result.indices.reversed()) {
|
||||
if (!feedCounters.containsKey(result[i].id)
|
||||
|| feedCounters[result[i].id]!! <= 0) {
|
||||
if (!feedCounters.containsKey(result[i].id) || feedCounters[result[i].id]!! <= 0) {
|
||||
result.removeAt(i)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import ac.mdiq.podcini.ui.fragment.*
|
|||
import ac.mdiq.podcini.ui.statistics.StatisticsFragment
|
||||
import ac.mdiq.podcini.ui.view.LockableBottomSheetBehavior
|
||||
import ac.mdiq.podcini.util.event.EpisodeDownloadEvent
|
||||
import ac.mdiq.podcini.util.event.FeedUpdateRunningEvent
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
|
@ -73,7 +74,6 @@ import kotlin.math.min
|
|||
*/
|
||||
@UnstableApi
|
||||
class MainActivity : CastEnabledActivity() {
|
||||
// some device doesn't have a drawer
|
||||
private var drawerLayout: DrawerLayout? = null
|
||||
|
||||
private lateinit var binding: MainActivityBinding
|
||||
|
@ -183,7 +183,7 @@ class MainActivity : CastEnabledActivity() {
|
|||
}
|
||||
}
|
||||
}
|
||||
EventBus.getDefault().postSticky(ac.mdiq.podcini.util.event.FeedUpdateRunningEvent(isRefreshingFeeds))
|
||||
EventBus.getDefault().postSticky(FeedUpdateRunningEvent(isRefreshingFeeds))
|
||||
}
|
||||
WorkManager.getInstance(this)
|
||||
.getWorkInfosByTagLiveData(DownloadServiceInterface.WORK_TAG)
|
||||
|
|
|
@ -89,22 +89,6 @@ open class EpisodeItemListAdapter(mainActivity: MainActivity) :
|
|||
}
|
||||
}
|
||||
|
||||
// holder.infoCard.setOnClickListener {
|
||||
// if (inActionMode()) {
|
||||
// toggleSelection(holder.bindingAdapterPosition)
|
||||
// } else {
|
||||
// longPressedItem = item
|
||||
// longPressedPosition = holder.bindingAdapterPosition
|
||||
// it.showContextMenu()
|
||||
// }
|
||||
// }
|
||||
|
||||
// holder.infoCard.setOnCreateContextMenuListener(this)
|
||||
// holder.infoCard.setOnLongClickListener {
|
||||
// longPressedItem = item
|
||||
// longPressedPosition = holder.bindingAdapterPosition
|
||||
// false
|
||||
// }
|
||||
holder.coverHolder.setOnClickListener {
|
||||
val activity: MainActivity? = mainActivityRef.get()
|
||||
if (!inActionMode()) {
|
||||
|
|
|
@ -85,24 +85,6 @@ open class SubscriptionsRecyclerAdapter(mainActivity: MainActivity) :
|
|||
true
|
||||
}
|
||||
|
||||
// holder.infoCard.setOnClickListener {
|
||||
// if (inActionMode()) {
|
||||
// holder.selectCheckbox.setChecked(!isSelected(holder.bindingAdapterPosition))
|
||||
// } else {
|
||||
// longPressedPosition = holder.bindingAdapterPosition
|
||||
// selectedItem = drawerItem
|
||||
// it.showContextMenu()
|
||||
// }
|
||||
// }
|
||||
// holder.infoCard.setOnCreateContextMenuListener(this)
|
||||
// holder.infoCard.setOnLongClickListener {
|
||||
// if (!inActionMode()) {
|
||||
// longPressedPosition = holder.bindingAdapterPosition
|
||||
// selectedItem = drawerItem
|
||||
// }
|
||||
// false
|
||||
// }
|
||||
|
||||
holder.itemView.setOnTouchListener { _: View?, e: MotionEvent ->
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (e.isFromSource(InputDevice.SOURCE_MOUSE)
|
||||
|
|
|
@ -35,8 +35,7 @@ class SubscriptionsFilterDialog : BottomSheetDialogFragment() {
|
|||
for (item in SubscriptionsFilterGroup.entries) {
|
||||
val binding = FilterDialogRowBinding.inflate(inflater)
|
||||
binding.root.addOnButtonCheckedListener { _: MaterialButtonToggleGroup?, _: Int, _: Boolean ->
|
||||
updateFilter(
|
||||
filterValues)
|
||||
updateFilter(filterValues)
|
||||
}
|
||||
binding.buttonGroup.weightSum = item.values.size.toFloat()
|
||||
binding.filterButton1.setText(item.values[0].displayName)
|
||||
|
|
|
@ -7,6 +7,7 @@ import ac.mdiq.podcini.storage.DBWriter
|
|||
import ac.mdiq.podcini.storage.model.feed.FeedPreferences
|
||||
import ac.mdiq.podcini.ui.adapter.SimpleChipAdapter
|
||||
import ac.mdiq.podcini.ui.view.ItemOffsetDecoration
|
||||
import ac.mdiq.podcini.util.event.FeedTagsChangedEvent
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
|
@ -21,6 +22,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import java.io.Serializable
|
||||
|
||||
class TagSettingsDialog : DialogFragment() {
|
||||
|
@ -79,6 +81,7 @@ class TagSettingsDialog : DialogFragment() {
|
|||
addTag(viewBinding.newTagEditText.text.toString().trim { it <= ' ' })
|
||||
updatePreferencesTags(feedPreferencesList, commonTags)
|
||||
DBReader.buildTags()
|
||||
EventBus.getDefault().post(FeedTagsChangedEvent())
|
||||
}
|
||||
dialog.setNegativeButton(R.string.cancel_label, null)
|
||||
return dialog.create()
|
||||
|
|
|
@ -64,7 +64,6 @@ class ChaptersFragment : AppCompatDialogFragment() {
|
|||
|
||||
fun onCreateView(inflater: LayoutInflater): View {
|
||||
val viewBinding = SimpleListFragmentBinding.inflate(inflater)
|
||||
// val root = inflater.inflate(R.layout.simple_list_fragment, null, false)
|
||||
viewBinding.toolbar.visibility = View.GONE
|
||||
|
||||
Log.d(TAG, "fragment onCreateView")
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.leinardi.android.speeddial.SpeedDialView
|
|||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.databinding.MultiSelectSpeedDialBinding
|
||||
import ac.mdiq.podcini.databinding.SimpleListFragmentBinding
|
||||
import ac.mdiq.podcini.feed.util.PlaybackSpeedUtils
|
||||
import ac.mdiq.podcini.ui.adapter.EpisodeItemListAdapter
|
||||
import ac.mdiq.podcini.ui.adapter.SelectableAdapter
|
||||
import ac.mdiq.podcini.ui.adapter.actionbutton.DeleteActionButton
|
||||
|
@ -37,6 +38,9 @@ import ac.mdiq.podcini.ui.view.EmptyViewHandler
|
|||
import ac.mdiq.podcini.ui.view.EpisodeItemListRecyclerView
|
||||
import ac.mdiq.podcini.ui.view.LiftOnScrollListener
|
||||
import ac.mdiq.podcini.ui.view.viewholder.EpisodeItemViewHolder
|
||||
import ac.mdiq.podcini.util.Converter
|
||||
import ac.mdiq.podcini.util.event.FeedItemEvent
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import io.reactivex.Observable
|
||||
|
@ -46,6 +50,9 @@ import io.reactivex.schedulers.Schedulers
|
|||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
/**
|
||||
* Displays all completed downloads and provides a button to delete them.
|
||||
|
@ -54,6 +61,7 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
private var runningDownloads: Set<String>? = HashSet()
|
||||
private var items: MutableList<FeedItem> = mutableListOf()
|
||||
|
||||
private lateinit var infoBar: TextView
|
||||
private lateinit var adapter: CompletedDownloadsListAdapter
|
||||
private lateinit var toolbar: MaterialToolbar
|
||||
private lateinit var recyclerView: EpisodeItemListRecyclerView
|
||||
|
@ -69,11 +77,10 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
@UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
val viewBinding = SimpleListFragmentBinding.inflate(inflater)
|
||||
// val root: View = inflater.inflate(R.layout.simple_list_fragment, container, false)
|
||||
val binding = SimpleListFragmentBinding.inflate(inflater)
|
||||
|
||||
Log.d(TAG, "fragment onCreateView")
|
||||
toolbar = viewBinding.toolbar
|
||||
toolbar = binding.toolbar
|
||||
toolbar.setTitle(R.string.downloads_label)
|
||||
toolbar.inflateMenu(R.menu.downloads_completed)
|
||||
toolbar.setOnMenuItemClickListener(this)
|
||||
|
@ -88,12 +95,12 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
}
|
||||
(activity as MainActivity).setupToolbarToggle(toolbar, displayUpArrow)
|
||||
|
||||
recyclerView = viewBinding.recyclerView
|
||||
recyclerView = binding.recyclerView
|
||||
recyclerView.setRecycledViewPool((activity as MainActivity).recycledViewPool)
|
||||
adapter = CompletedDownloadsListAdapter(activity as MainActivity)
|
||||
adapter.setOnSelectModeListener(this)
|
||||
recyclerView.adapter = adapter
|
||||
recyclerView.addOnScrollListener(LiftOnScrollListener(viewBinding.appbar))
|
||||
recyclerView.addOnScrollListener(LiftOnScrollListener(binding.appbar))
|
||||
swipeActions = SwipeActions(this, TAG).attachTo(recyclerView)
|
||||
swipeActions.setFilter(FeedItemFilter(FeedItemFilter.DOWNLOADED))
|
||||
|
||||
|
@ -102,10 +109,12 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
animator.supportsChangeAnimations = false
|
||||
}
|
||||
|
||||
progressBar = viewBinding.progLoading
|
||||
progressBar = binding.progLoading
|
||||
progressBar.visibility = View.VISIBLE
|
||||
|
||||
val multiSelectDial = MultiSelectSpeedDialBinding.bind(viewBinding.root)
|
||||
infoBar = binding.infoBar
|
||||
|
||||
val multiSelectDial = MultiSelectSpeedDialBinding.bind(binding.root)
|
||||
speedDialView = multiSelectDial.fabSD
|
||||
speedDialView.overlayLayout = multiSelectDial.fabSDOverlay
|
||||
speedDialView.inflate(R.menu.episodes_apply_action_speeddial)
|
||||
|
@ -113,7 +122,6 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
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
|
||||
|
@ -144,7 +152,7 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
|
||||
loadItems()
|
||||
|
||||
return viewBinding.root
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
|
@ -227,7 +235,7 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(event: ac.mdiq.podcini.util.event.FeedItemEvent) {
|
||||
fun onEventMainThread(event: FeedItemEvent) {
|
||||
Log.d(TAG, "onEventMainThread() called with: event = [$event]")
|
||||
|
||||
var i = 0
|
||||
|
@ -252,6 +260,7 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
adapter.setDummyViews(0)
|
||||
adapter.updateItems(items)
|
||||
}
|
||||
refreshInfoBar()
|
||||
}
|
||||
|
||||
@UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
|
||||
|
@ -264,6 +273,7 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
break
|
||||
}
|
||||
}
|
||||
refreshInfoBar()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
|
@ -312,6 +322,7 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
adapter.setDummyViews(0)
|
||||
progressBar.visibility = View.GONE
|
||||
adapter.updateItems(result)
|
||||
refreshInfoBar()
|
||||
}, { error: Throwable? ->
|
||||
adapter.setDummyViews(0)
|
||||
adapter.updateItems(emptyList())
|
||||
|
@ -319,6 +330,18 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
|||
})
|
||||
}
|
||||
|
||||
private fun refreshInfoBar() {
|
||||
var info = String.format(Locale.getDefault(), "%d%s", items.size, getString(R.string.episodes_suffix))
|
||||
if (items.isNotEmpty()) {
|
||||
var sizeMB: Long = 0
|
||||
for (item in items) {
|
||||
sizeMB += item.media?.size?:0
|
||||
}
|
||||
info += " • " + getString(R.string.size) + " : " + (sizeMB / 1000000) + " MB"
|
||||
}
|
||||
infoBar.text = info
|
||||
}
|
||||
|
||||
override fun onStartSelectMode() {
|
||||
swipeActions.detach()
|
||||
speedDialView.visibility = View.VISIBLE
|
||||
|
|
|
@ -17,9 +17,11 @@ import ac.mdiq.podcini.ui.common.CircularProgressBar
|
|||
import ac.mdiq.podcini.ui.common.ThemeUtils
|
||||
import ac.mdiq.podcini.ui.gui.ShownotesCleaner
|
||||
import ac.mdiq.podcini.ui.view.ShownotesWebView
|
||||
import ac.mdiq.podcini.util.Converter
|
||||
import ac.mdiq.podcini.util.DateFormatter
|
||||
import ac.mdiq.podcini.util.PlaybackStatus
|
||||
import ac.mdiq.podcini.util.event.EpisodeDownloadEvent
|
||||
import ac.mdiq.podcini.util.event.FeedItemEvent
|
||||
import ac.mdiq.podcini.util.event.UnreadItemsUpdateEvent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
|
@ -277,9 +279,9 @@ class ItemFragment : Fragment() {
|
|||
} else {
|
||||
noMediaLabel.visibility = View.GONE
|
||||
if (media.getDuration() > 0) {
|
||||
txtvDuration.text = ac.mdiq.podcini.util.Converter.getDurationStringLong(media.getDuration())
|
||||
txtvDuration.text = Converter.getDurationStringLong(media.getDuration())
|
||||
txtvDuration.setContentDescription(
|
||||
ac.mdiq.podcini.util.Converter.getDurationStringLocalized(requireContext(), media.getDuration().toLong()))
|
||||
Converter.getDurationStringLocalized(requireContext(), media.getDuration().toLong()))
|
||||
}
|
||||
if (item != null) {
|
||||
actionButton1 = if (PlaybackStatus.isCurrentlyPlaying(media)) {
|
||||
|
@ -329,7 +331,7 @@ class ItemFragment : Fragment() {
|
|||
}
|
||||
|
||||
@UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(event: ac.mdiq.podcini.util.event.FeedItemEvent) {
|
||||
fun onEventMainThread(event: FeedItemEvent) {
|
||||
Log.d(TAG, "onEventMainThread() called with: event = [$event]")
|
||||
if (this.item == null) return
|
||||
for (item in event.items) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import ac.mdiq.podcini.storage.DBReader
|
|||
import ac.mdiq.podcini.storage.model.feed.FeedItem
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.ui.menuhandler.FeedItemMenuHandler
|
||||
import ac.mdiq.podcini.util.event.FeedItemEvent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
|
@ -128,7 +129,7 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
|
|||
}
|
||||
|
||||
@UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(event: ac.mdiq.podcini.util.event.FeedItemEvent) {
|
||||
fun onEventMainThread(event: FeedItemEvent) {
|
||||
for (item in event.items) {
|
||||
if (this.item != null && this.item!!.id == item.id) {
|
||||
this.item = item
|
||||
|
|
|
@ -15,6 +15,7 @@ import ac.mdiq.podcini.ui.common.ThemeUtils
|
|||
import ac.mdiq.podcini.ui.dialog.*
|
||||
import ac.mdiq.podcini.ui.menuhandler.MenuItemUtils
|
||||
import ac.mdiq.podcini.ui.statistics.StatisticsFragment
|
||||
import ac.mdiq.podcini.util.event.FeedListUpdateEvent
|
||||
import android.R.attr
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
|
@ -197,7 +198,7 @@ class NavDrawerFragment : Fragment(), SharedPreferences.OnSharedPreferenceChange
|
|||
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onFeedListChanged(event: ac.mdiq.podcini.util.event.FeedListUpdateEvent?) {
|
||||
fun onFeedListChanged(event: FeedListUpdateEvent?) {
|
||||
loadData()
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ import ac.mdiq.podcini.ui.view.EmptyViewHandler
|
|||
import ac.mdiq.podcini.ui.view.EpisodeItemListRecyclerView
|
||||
import ac.mdiq.podcini.ui.view.LiftOnScrollListener
|
||||
import ac.mdiq.podcini.ui.view.viewholder.EpisodeItemViewHolder
|
||||
import ac.mdiq.podcini.util.Converter
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
|
@ -456,7 +457,7 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
|
|||
}
|
||||
info += " • "
|
||||
info += getString(R.string.time_left_label)
|
||||
info += ac.mdiq.podcini.util.Converter.getDurationStringLocalized(requireActivity(), timeLeft)
|
||||
info += Converter.getDurationStringLocalized(requireActivity(), timeLeft)
|
||||
}
|
||||
infoBar.text = info
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ import ac.mdiq.podcini.ui.menuhandler.MenuItemUtils
|
|||
import ac.mdiq.podcini.ui.view.EmptyViewHandler
|
||||
import ac.mdiq.podcini.ui.view.LiftOnScrollListener
|
||||
import ac.mdiq.podcini.util.event.FeedListUpdateEvent
|
||||
import ac.mdiq.podcini.util.event.FeedTagsChangedEvent
|
||||
import ac.mdiq.podcini.util.event.FeedUpdateRunningEvent
|
||||
import ac.mdiq.podcini.util.event.UnreadItemsUpdateEvent
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
|
@ -26,10 +28,7 @@ import android.os.Bundle
|
|||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.*
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
|
@ -53,17 +52,19 @@ import java.util.*
|
|||
* Fragment for displaying feed subscriptions
|
||||
*/
|
||||
class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAdapter.OnSelectModeListener {
|
||||
|
||||
private lateinit var subscriptionRecycler: RecyclerView
|
||||
private lateinit var subscriptionAdapter: SubscriptionsRecyclerAdapter
|
||||
private lateinit var emptyView: EmptyViewHandler
|
||||
private lateinit var feedsFilteredMsg: LinearLayout
|
||||
private lateinit var feedsInfoMsg: LinearLayout
|
||||
private lateinit var feedsFilteredMsg: TextView
|
||||
private lateinit var feedCount: TextView
|
||||
private lateinit var toolbar: MaterialToolbar
|
||||
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
|
||||
private lateinit var progressBar: ProgressBar
|
||||
private lateinit var prefs: SharedPreferences
|
||||
private lateinit var speedDialView: SpeedDialView
|
||||
|
||||
private val tags: MutableList<String> = mutableListOf()
|
||||
private var tagFilterIndex = 1
|
||||
private var displayedFolder: String = ""
|
||||
private var displayUpArrow = false
|
||||
|
@ -81,10 +82,10 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
|
||||
@UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View {
|
||||
val viewBinding = FragmentSubscriptionsBinding.inflate(inflater)
|
||||
val binding = FragmentSubscriptionsBinding.inflate(inflater)
|
||||
|
||||
Log.d(TAG, "fragment onCreateView")
|
||||
toolbar = viewBinding.toolbar
|
||||
toolbar = binding.toolbar
|
||||
toolbar.setOnMenuItemClickListener(this)
|
||||
toolbar.setOnLongClickListener {
|
||||
subscriptionRecycler.scrollToPosition(5)
|
||||
|
@ -103,10 +104,10 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
toolbar.title = displayedFolder
|
||||
}
|
||||
|
||||
subscriptionRecycler = viewBinding.subscriptionsGrid
|
||||
subscriptionRecycler = binding.subscriptionsGrid
|
||||
subscriptionRecycler.addItemDecoration(SubscriptionsRecyclerAdapter.GridDividerItemDecorator())
|
||||
registerForContextMenu(subscriptionRecycler)
|
||||
subscriptionRecycler.addOnScrollListener(LiftOnScrollListener(viewBinding.appbar))
|
||||
subscriptionRecycler.addOnScrollListener(LiftOnScrollListener(binding.appbar))
|
||||
subscriptionAdapter = object : SubscriptionsRecyclerAdapter(activity as MainActivity) {
|
||||
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo)
|
||||
|
@ -123,14 +124,13 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
subscriptionRecycler.adapter = subscriptionAdapter
|
||||
setupEmptyView()
|
||||
|
||||
tags.add("Untagged")
|
||||
tags.add("All")
|
||||
tags.addAll(DBReader.getTags())
|
||||
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, tags)
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
val catSpinner = viewBinding.categorySpinner
|
||||
catSpinner.setAdapter(adapter)
|
||||
catSpinner.setSelection(adapter.getPosition("All"))
|
||||
resetTags()
|
||||
|
||||
val catAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, tags)
|
||||
catAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
val catSpinner = binding.categorySpinner
|
||||
catSpinner.setAdapter(catAdapter)
|
||||
catSpinner.setSelection(catAdapter.getPosition("All"))
|
||||
catSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
|
||||
tagFilterIndex = position
|
||||
|
@ -140,7 +140,7 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
|
||||
val searchBox = viewBinding.searchBox
|
||||
val searchBox = binding.searchBox
|
||||
searchBox.setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||
val text = searchBox.text.toString().lowercase(Locale.getDefault())
|
||||
|
@ -155,29 +155,32 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
}
|
||||
}
|
||||
|
||||
progressBar = viewBinding.progressBar
|
||||
progressBar = binding.progressBar
|
||||
progressBar.visibility = View.VISIBLE
|
||||
|
||||
val subscriptionAddButton: FloatingActionButton = viewBinding.subscriptionsAdd
|
||||
val subscriptionAddButton: FloatingActionButton = binding.subscriptionsAdd
|
||||
subscriptionAddButton.setOnClickListener {
|
||||
if (activity is MainActivity) {
|
||||
(activity as MainActivity).loadChildFragment(AddFeedFragment())
|
||||
}
|
||||
}
|
||||
|
||||
feedsFilteredMsg = viewBinding.feedsFilteredMessage
|
||||
feedsFilteredMsg.setOnClickListener {
|
||||
SubscriptionsFilterDialog().show(
|
||||
childFragmentManager, "filter")
|
||||
}
|
||||
feedsInfoMsg = binding.feedsInfoMessage
|
||||
// feedsInfoMsg.setOnClickListener {
|
||||
// SubscriptionsFilterDialog().show(
|
||||
// childFragmentManager, "filter")
|
||||
// }
|
||||
feedsFilteredMsg = binding.feedsFilteredMessage
|
||||
feedCount = binding.count
|
||||
feedCount.text = feedListFiltered.size.toString() + " / " + feedList.size.toString()
|
||||
|
||||
swipeRefreshLayout = viewBinding.swipeRefresh
|
||||
swipeRefreshLayout = binding.swipeRefresh
|
||||
swipeRefreshLayout.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
FeedUpdateManager.runOnceOrAsk(requireContext())
|
||||
}
|
||||
|
||||
val speedDialBinding = MultiSelectSpeedDialBinding.bind(viewBinding.root)
|
||||
val speedDialBinding = MultiSelectSpeedDialBinding.bind(binding.root)
|
||||
|
||||
speedDialView = speedDialBinding.fabSD
|
||||
speedDialView.overlayLayout = speedDialBinding.fabSDOverlay
|
||||
|
@ -199,7 +202,7 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
EventBus.getDefault().register(this)
|
||||
loadSubscriptions()
|
||||
|
||||
return viewBinding.root
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -215,29 +218,31 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
|
||||
fun filterOnTag() {
|
||||
when (tagFilterIndex) {
|
||||
// All feeds
|
||||
1 -> {
|
||||
// All feeds
|
||||
feedListFiltered = feedList
|
||||
}
|
||||
// feeds without tag
|
||||
0 -> {
|
||||
// feeds without tag
|
||||
feedListFiltered = feedList.filter {
|
||||
val tags = it.feed.preferences?.getTags()
|
||||
tags.isNullOrEmpty() || (tags.size == 1 && tags.toList()[0] == "#root")
|
||||
}
|
||||
}
|
||||
// feeds with the chosen tag
|
||||
else -> {
|
||||
// feeds with the chosen tag
|
||||
val tag = tags[tagFilterIndex]
|
||||
feedListFiltered = feedList.filter {
|
||||
it.feed.preferences?.getTags()?.contains(tag) ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
feedCount.text = feedListFiltered.size.toString() + " / " + feedList.size.toString()
|
||||
subscriptionAdapter.setItems(feedListFiltered)
|
||||
}
|
||||
|
||||
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(event: ac.mdiq.podcini.util.event.FeedUpdateRunningEvent) {
|
||||
fun onEventMainThread(event: FeedUpdateRunningEvent) {
|
||||
swipeRefreshLayout.isRefreshing = event.isFeedUpdateRunning
|
||||
}
|
||||
|
||||
|
@ -297,6 +302,7 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
filterOnTag()
|
||||
progressBar.visibility = View.GONE
|
||||
subscriptionAdapter.setItems(feedListFiltered)
|
||||
feedCount.text = feedListFiltered.size.toString() + " / " + feedList.size.toString()
|
||||
emptyView.updateVisibility()
|
||||
}, { error: Throwable? ->
|
||||
Log.e(TAG, Log.getStackTraceString(error))
|
||||
|
@ -332,6 +338,11 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
loadSubscriptions()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onFeedTagsChanged(event: FeedTagsChangedEvent?) {
|
||||
resetTags()
|
||||
}
|
||||
|
||||
override fun onEndSelectMode() {
|
||||
speedDialView.close()
|
||||
speedDialView.visibility = View.GONE
|
||||
|
@ -353,6 +364,8 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
private const val KEY_UP_ARROW = "up_arrow"
|
||||
private const val ARGUMENT_FOLDER = "folder"
|
||||
|
||||
private val tags: MutableList<String> = mutableListOf()
|
||||
|
||||
fun newInstance(folderTitle: String?): SubscriptionFragment {
|
||||
val fragment = SubscriptionFragment()
|
||||
val args = Bundle()
|
||||
|
@ -360,5 +373,12 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select
|
|||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
|
||||
fun resetTags() {
|
||||
tags.clear()
|
||||
tags.add("Untagged")
|
||||
tags.add("All")
|
||||
tags.addAll(DBReader.getTags())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,10 @@ import ac.mdiq.podcini.ui.fragment.preferences.dialog.PreferenceListDialog
|
|||
import ac.mdiq.podcini.ui.fragment.preferences.dialog.PreferenceSwitchDialog
|
||||
import ac.mdiq.podcini.storage.model.feed.Feed
|
||||
import ac.mdiq.podcini.storage.model.feed.FeedPreferences
|
||||
import ac.mdiq.podcini.ui.fragment.SubscriptionFragment
|
||||
import ac.mdiq.podcini.util.event.FeedTagsChangedEvent
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import java.util.*
|
||||
|
||||
@UnstableApi
|
||||
|
|
|
@ -26,6 +26,7 @@ import ac.mdiq.podcini.util.IntentUtils
|
|||
import ac.mdiq.podcini.util.NetworkUtils
|
||||
import ac.mdiq.podcini.util.ShareUtils
|
||||
import ac.mdiq.podcini.ui.gui.ShownotesCleaner
|
||||
import ac.mdiq.podcini.util.Converter
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import kotlin.math.max
|
||||
|
||||
|
@ -151,7 +152,7 @@ class ShownotesWebView : WebView, View.OnLongClickListener {
|
|||
|
||||
if (ShownotesCleaner.isTimecodeLink(selectedUrl)) {
|
||||
menu.add(Menu.NONE, R.id.go_to_position_item, Menu.NONE, R.string.go_to_position_label)
|
||||
menu.setHeaderTitle(ac.mdiq.podcini.util.Converter.getDurationStringLong(ShownotesCleaner.getTimecodeLinkTime(selectedUrl)))
|
||||
menu.setHeaderTitle(Converter.getDurationStringLong(ShownotesCleaner.getTimecodeLinkTime(selectedUrl)))
|
||||
} else {
|
||||
val uri = Uri.parse(selectedUrl)
|
||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
package ac.mdiq.podcini.util.event
|
||||
|
||||
class FeedTagsChangedEvent
|
|
@ -8,13 +8,13 @@
|
|||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="?attr/colorPrimary"
|
||||
android:strokeColor="?attr/action_icon_color"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M21,15l-4,4l-4,-4m4,4v-14"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="?attr/colorPrimary"
|
||||
android:strokeColor="?attr/action_icon_color"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#000000"
|
||||
<vector android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"/>
|
||||
<path android:fillColor="?attr/action_icon_color" android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#000000"
|
||||
<vector android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M4,12l1.41,1.41L11,7.83V20h2V7.83l5.58,5.59L20,12l-8,-8 -8,8z"/>
|
||||
<path android:fillColor="?attr/action_icon_color" android:pathData="M4,12l1.41,1.41L11,7.83V20h2V7.83l5.58,5.59L20,12l-8,-8 -8,8z"/>
|
||||
</vector>
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
app:navigationIcon="?homeAsUpIndicator" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/feeds_filtered_message"
|
||||
android:id="@+id/feeds_info_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="60dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:layout_marginTop="-12dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
|
@ -39,10 +39,23 @@
|
|||
android:src="@drawable/ic_info" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/feeds_filtered_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:text="@string/subscriptions_are_filtered" />
|
||||
android:text="@string/filtered_label" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="12sp"
|
||||
android:text="12 Podcasts" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="match_parent" xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/simple_list_fragment">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
|
@ -19,6 +19,18 @@
|
|||
app:navigationContentDescription="@string/toolbar_back_button_content_description"
|
||||
app:navigationIcon="?homeAsUpIndicator" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/info_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/toolbar"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginTop="-12dp"
|
||||
android:layout_marginLeft="60dp"
|
||||
android:layout_marginStart="60dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
tools:text="12 Episodes - Size: 40 MB" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<ac.mdiq.podcini.ui.view.EpisodeItemListRecyclerView
|
||||
|
|
|
@ -8,11 +8,6 @@
|
|||
custom:showAsAction="collapseActionView">
|
||||
</item>
|
||||
|
||||
<!-- <item-->
|
||||
<!-- android:id="@+id/remove_inbox_item"-->
|
||||
<!-- custom:showAsAction="collapseActionView"-->
|
||||
<!-- android:title="@string/remove_inbox_label" />-->
|
||||
|
||||
<item
|
||||
android:id="@+id/mark_read_item"
|
||||
custom:showAsAction="collapseActionView"
|
||||
|
|
|
@ -5,11 +5,6 @@
|
|||
android:menuCategory="container"
|
||||
android:title="@string/skip_episode_label" />
|
||||
|
||||
<!-- <item-->
|
||||
<!-- android:id="@+id/remove_inbox_item"-->
|
||||
<!-- android:menuCategory="container"-->
|
||||
<!-- android:title="@string/remove_inbox_label" />-->
|
||||
|
||||
<item
|
||||
android:id="@+id/mark_read_item"
|
||||
android:menuCategory="container"
|
||||
|
|
|
@ -79,3 +79,10 @@
|
|||
* operations are only on the selected (single or multiple)
|
||||
* popup menus for single item operation are disabled
|
||||
* in podcast view, the title bar no longer scrolls off screen
|
||||
|
||||
## 4.2.6
|
||||
|
||||
* corrected action icons for themes
|
||||
* revealed info bar in Downloads view
|
||||
* revealed info bar in Subscriptions view
|
||||
* reset tags list in Subscriptions when new tag is added
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
Version 4.2.6 brings several changes:
|
||||
|
||||
* corrected action icons for themes
|
||||
* revealed info bar in Downloads view
|
||||
* revealed info bar in Subscriptions view
|
||||
* reset tags list in Subscriptions when new tag is added
|
Loading…
Reference in New Issue