Touch: use OfflineItemView and fix loading and deleting-behaviour in Download-List

This commit is contained in:
Felix 2019-04-30 19:25:02 +02:00
parent 91d3c300fc
commit cbe2874394
10 changed files with 95 additions and 39 deletions

View file

@ -147,6 +147,12 @@ class OfflineItemManager(context: Context,
} }
} }
fun deleteOfflineItem(guid: String){
offlineEventDao.getByEventGuidSync(guid)?.let {
deleteOfflineItem(it)
}
}
fun deleteOfflineItem(item: OfflineEvent) { fun deleteOfflineItem(item: OfflineEvent) {
downloadManager.remove(item.downloadReference) downloadManager.remove(item.downloadReference)
val file = File(item.localPath) val file = File(item.localPath)

View file

@ -0,0 +1,11 @@
package de.nicidienase.chaosflix.common
import android.content.Context
import android.content.res.Resources
import android.support.annotation.StringRes
class ResourcesFacade(context: Context) {
private val resources: Resources = context.applicationContext.resources
fun getString(@StringRes id: Int, vararg any: Any): String = resources.getString(id,any)
}

View file

@ -3,9 +3,11 @@ package de.nicidienase.chaosflix.common.viewmodel
import android.arch.lifecycle.LiveData import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel import android.arch.lifecycle.ViewModel
import de.nicidienase.chaosflix.R
import de.nicidienase.chaosflix.common.ChaosflixDatabase import de.nicidienase.chaosflix.common.ChaosflixDatabase
import de.nicidienase.chaosflix.common.OfflineItemManager import de.nicidienase.chaosflix.common.OfflineItemManager
import de.nicidienase.chaosflix.common.PreferencesManager import de.nicidienase.chaosflix.common.PreferencesManager
import de.nicidienase.chaosflix.common.ResourcesFacade
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.ConferenceGroup import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.ConferenceGroup
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
@ -16,6 +18,7 @@ import de.nicidienase.chaosflix.common.mediadata.sync.Downloader
import de.nicidienase.chaosflix.common.userdata.entities.download.OfflineEvent import de.nicidienase.chaosflix.common.userdata.entities.download.OfflineEvent
import de.nicidienase.chaosflix.common.util.LiveDataMerger import de.nicidienase.chaosflix.common.util.LiveDataMerger
import de.nicidienase.chaosflix.common.util.LiveEvent import de.nicidienase.chaosflix.common.util.LiveEvent
import de.nicidienase.chaosflix.common.util.SingleLiveEvent
import de.nicidienase.chaosflix.common.util.ThreadHandler import de.nicidienase.chaosflix.common.util.ThreadHandler
import retrofit2.Response import retrofit2.Response
import java.io.IOException import java.io.IOException
@ -25,9 +28,16 @@ class BrowseViewModel(
val database: ChaosflixDatabase, val database: ChaosflixDatabase,
recordingApi: RecordingService, recordingApi: RecordingService,
val streamingApi: StreamingService, val streamingApi: StreamingService,
val preferencesManager: PreferencesManager val preferencesManager: PreferencesManager,
private val resources: ResourcesFacade
) : ViewModel() { ) : ViewModel() {
val state: SingleLiveEvent<LiveEvent<State, Event, String>> = SingleLiveEvent()
enum class State {
ShowEventDetails
}
val downloader = Downloader(recordingApi, database) val downloader = Downloader(recordingApi, database)
private val handler = ThreadHandler() private val handler = ThreadHandler()
@ -151,6 +161,22 @@ class BrowseViewModel(
} }
} }
fun showDetailsForEvent(guid: String) {
handler.runOnBackgroundThread {
val event = database.eventDao().findEventByGuidSync(guid)
if(event != null){
state.postValue(LiveEvent(State.ShowEventDetails,event))
} else {
state.postValue(LiveEvent(State.ShowEventDetails,error = resources.getString(R.string.error_event_not_found)))
}
}
}
fun deleteOfflineItem(guid: String) {
handler.runOnBackgroundThread {
offlineItemManager.deleteOfflineItem(guid)
}
}
fun getAutoselectStream() = preferencesManager.getAutoselectStream() fun getAutoselectStream() = preferencesManager.getAutoselectStream()
} }

View file

@ -8,27 +8,29 @@ import android.preference.PreferenceManager
import de.nicidienase.chaosflix.common.DatabaseFactory import de.nicidienase.chaosflix.common.DatabaseFactory
import de.nicidienase.chaosflix.common.OfflineItemManager import de.nicidienase.chaosflix.common.OfflineItemManager
import de.nicidienase.chaosflix.common.PreferencesManager import de.nicidienase.chaosflix.common.PreferencesManager
import de.nicidienase.chaosflix.common.ResourcesFacade
import de.nicidienase.chaosflix.common.mediadata.network.ApiFactory import de.nicidienase.chaosflix.common.mediadata.network.ApiFactory
import de.nicidienase.chaosflix.common.mediadata.sync.Downloader import de.nicidienase.chaosflix.common.mediadata.sync.Downloader
class ViewModelFactory(context: Context) : ViewModelProvider.Factory { class ViewModelFactory(context: Context) : ViewModelProvider.Factory {
val apiFactory = ApiFactory(context.resources) private val apiFactory = ApiFactory(context.resources)
val database = DatabaseFactory.getInstance(context) private val database by lazy { DatabaseFactory.getInstance(context) }
val recordingApi = apiFactory.recordingApi private val recordingApi = apiFactory.recordingApi
val streamingApi = apiFactory.streamingApi private val streamingApi = apiFactory.streamingApi
val preferencesManager = private val preferencesManager =
PreferencesManager(PreferenceManager.getDefaultSharedPreferences(context.applicationContext)) PreferencesManager(PreferenceManager.getDefaultSharedPreferences(context.applicationContext))
val offlineItemManager = private val offlineItemManager =
OfflineItemManager(context.applicationContext, database.offlineEventDao(),preferencesManager) OfflineItemManager(context.applicationContext, database.offlineEventDao(),preferencesManager)
val downloader by lazy { Downloader(recordingApi, database) } private val downloader by lazy { Downloader(recordingApi, database) }
val externalFilesDir = Environment.getExternalStorageDirectory() private val externalFilesDir = Environment.getExternalStorageDirectory()
private val resourcesFacade by lazy { ResourcesFacade(context) }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T { override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(BrowseViewModel::class.java)) { if (modelClass.isAssignableFrom(BrowseViewModel::class.java)) {
return BrowseViewModel(offlineItemManager, database, recordingApi, streamingApi, preferencesManager) as T return BrowseViewModel(offlineItemManager, database, recordingApi, streamingApi, preferencesManager,resourcesFacade) as T
} else if (modelClass.isAssignableFrom(PlayerViewModel::class.java)) { } else if (modelClass.isAssignableFrom(PlayerViewModel::class.java)) {
return PlayerViewModel(database) as T return PlayerViewModel(database) as T
} else if (modelClass.isAssignableFrom(DetailsViewModel::class.java)) { } else if (modelClass.isAssignableFrom(DetailsViewModel::class.java)) {
@ -38,7 +40,7 @@ class ViewModelFactory(context: Context) : ViewModelProvider.Factory {
} else { } else {
throw UnsupportedOperationException("The requested ViewModel is currently unsupported. " + throw UnsupportedOperationException("The requested ViewModel is currently unsupported. " +
"Please make sure to implement are correct creation of it. " + "Please make sure to implement are correct creation of it. " +
" Request: ${modelClass.getCanonicalName()}"); " Request: ${modelClass.canonicalName}");
} }
} }

View file

@ -48,4 +48,5 @@
<string name="settings_choose_recording">Automatically choose recording</string> <string name="settings_choose_recording">Automatically choose recording</string>
<string name="export_favorites">Export Favorites</string> <string name="export_favorites">Export Favorites</string>
<string name="import_favorites">Import Favorites</string> <string name="import_favorites">Import Favorites</string>
<string name="error_event_not_found">Event not found</string>
</resources> </resources>

View file

@ -1,5 +1,6 @@
package de.nicidienase.chaosflix.touch.browse package de.nicidienase.chaosflix.touch.browse
import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModelProviders import android.arch.lifecycle.ViewModelProviders
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
@ -86,6 +87,23 @@ class BrowseActivity : AppCompatActivity(),
showConferencesFragment() showConferencesFragment()
} }
viewModel = ViewModelProviders.of(this, ViewModelFactory(this)).get(BrowseViewModel::class.java) viewModel = ViewModelProviders.of(this, ViewModelFactory(this)).get(BrowseViewModel::class.java)
viewModel.state.observe(this, Observer { event ->
if(event == null){
return@Observer
}
val errorMessage = event.error
if(errorMessage != null){
Snackbar.make(binding.root, errorMessage, Snackbar.LENGTH_SHORT).show()
}
when(event.state){
BrowseViewModel.State.ShowEventDetails -> {
event.data?.let {
EventDetailsActivity.launch(this, it)
}
}
}
})
} }
fun setupDrawerToggle(toolbar: Toolbar?) { fun setupDrawerToggle(toolbar: Toolbar?) {

View file

@ -32,7 +32,7 @@ class DownloadsListFragment : BrowseFragment() {
setupToolbar(incToolbar.toolbar, R.string.downloads) setupToolbar(incToolbar.toolbar, R.string.downloads)
overlay = incOverlay.loadingOverlay overlay = incOverlay.loadingOverlay
val offlineEventAdapter = OfflineEventAdapter(viewModel.offlineItemManager, viewModel::deleteOfflineItem) { val offlineEventAdapter = OfflineEventAdapter(viewModel.offlineItemManager, viewModel::deleteOfflineItem) {
EventDetailsActivity.launch(requireContext(), it) viewModel.showDetailsForEvent(it)
} }
list.adapter = offlineEventAdapter list.adapter = offlineEventAdapter
if (columnCount <= 1) { if (columnCount <= 1) {
@ -40,16 +40,10 @@ class DownloadsListFragment : BrowseFragment() {
} else { } else {
list.layoutManager = GridLayoutManager(context, columnCount - 1) list.layoutManager = GridLayoutManager(context, columnCount - 1)
} }
// viewModel.getOfflineEvents().observe(this@DownloadsListFragment, Observer { events ->
// if (events != null) {
// offlineEventAdapter.items = viewModel.mapOfflineEvents(events)
// } else {
// offlineEventAdapter.items = emptyList()
// }
// setLoadingOverlayVisibility(false)
// })
viewModel.getOfflineDisplayEvents().observe(this@DownloadsListFragment, Observer { viewModel.getOfflineDisplayEvents().observe(this@DownloadsListFragment, Observer {
Log.d(TAG,"size: ${it?.size}") if (it != null){
offlineEventAdapter.items = it
}
}) })
return root return root
} }

View file

@ -9,18 +9,15 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import de.nicidienase.chaosflix.common.OfflineItemManager import de.nicidienase.chaosflix.common.OfflineItemManager
import de.nicidienase.chaosflix.touch.R import de.nicidienase.chaosflix.touch.R
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event import de.nicidienase.chaosflix.common.userdata.entities.download.OfflineEventView
import de.nicidienase.chaosflix.common.userdata.entities.download.OfflineEvent
import de.nicidienase.chaosflix.touch.databinding.ItemOfflineEventBinding import de.nicidienase.chaosflix.touch.databinding.ItemOfflineEventBinding
import de.nicidienase.chaosflix.touch.OnEventSelectedListener
import de.nicidienase.chaosflix.common.viewmodel.BrowseViewModel
class OfflineEventAdapter(private val offlineItemManager: OfflineItemManager, class OfflineEventAdapter(private val offlineItemManager: OfflineItemManager,
private val eventDeleteListener: (OfflineEvent) -> Unit, private val eventDeleteListener: (String) -> Unit,
private val eventSelectedListener: (Event)->Unit) : private val eventSelectedListener: (String)->Unit) :
RecyclerView.Adapter<OfflineEventAdapter.ViewHolder>() { RecyclerView.Adapter<OfflineEventAdapter.ViewHolder>() {
var items: List<Pair<OfflineEvent, Event>> = emptyList() var items: List<OfflineEventView> = emptyList()
set(value) { set(value) {
field = value field = value
notifyDataSetChanged() notifyDataSetChanged()
@ -29,19 +26,19 @@ class OfflineEventAdapter(private val offlineItemManager: OfflineItemManager,
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items[position] val item = items[position]
holder.binding.event = item.second holder.binding.item = item
Glide.with(holder.thumbnail) Glide.with(holder.thumbnail)
.load(item.second.thumbUrl) .load(item.thumbUrl)
.apply(RequestOptions().fitCenter()) .apply(RequestOptions().fitCenter())
.into(holder.thumbnail) .into(holder.thumbnail)
with(holder.binding){ with(holder.binding){
downloadStatus = offlineItemManager.downloadStatus[item.first.downloadReference] downloadStatus = offlineItemManager.downloadStatus[item.downloadReference]
buttonDelete.setOnClickListener { buttonDelete.setOnClickListener {
eventDeleteListener(item.first) eventDeleteListener(item.eventGuid)
} }
content?.setOnClickListener { _ -> content?.setOnClickListener { _ ->
eventSelectedListener(item.second) eventSelectedListener(item.eventGuid)
} }
} }
} }

View file

@ -214,6 +214,7 @@ class EventDetailsActivity : AppCompatActivity(),
private const val EXTRA_EVENT = "extra_event" private const val EXTRA_EVENT = "extra_event"
private const val EXTRA_URI = "extra_uri" private const val EXTRA_URI = "extra_uri"
private const val EXTRA_GUID = "extra_guid"
private const val WRITE_PERMISSION_REQUEST = 23 private const val WRITE_PERMISSION_REQUEST = 23
private val TAG = EventDetailsActivity::class.java.simpleName private val TAG = EventDetailsActivity::class.java.simpleName

View file

@ -7,12 +7,12 @@
<import type="android.view.View"/> <import type="android.view.View"/>
<variable <variable
name="downloadStatus" name="item"
type="de.nicidienase.chaosflix.common.OfflineItemManager.DownloadStatus"/> type="de.nicidienase.chaosflix.common.userdata.entities.download.OfflineEventView"/>
<variable <variable
name="event" name="downloadStatus"
type="de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event"/> type="de.nicidienase.chaosflix.common.OfflineItemManager.DownloadStatus"/>
</data> </data>
<LinearLayout <LinearLayout
@ -62,7 +62,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_weight="1" android:layout_weight="1"
android:text="@{event.title}" android:text="@{item.title}"
android:textAppearance="@style/TextAppearance.AppCompat.Title" android:textAppearance="@style/TextAppearance.AppCompat.Title"
tools:text="Title"/> tools:text="Title"/>
@ -71,7 +71,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="@{event.subtitle}" android:text="@{item.subtitle}"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Small" android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
tools:text="Subtitle"/> tools:text="Subtitle"/>