play offline file if one exists and other download-related updates
|
@ -8,7 +8,7 @@ buildscript {
|
|||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.0'
|
||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package de.nicidienase.chaosflix.touch
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.arch.lifecycle.LiveData
|
||||
import android.arch.lifecycle.MutableLiveData
|
||||
import android.arch.lifecycle.Observer
|
||||
import android.content.Context
|
||||
import android.databinding.ObservableField
|
||||
import de.nicidienase.chaosflix.common.entities.download.OfflineEvent
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.io.File
|
||||
|
||||
class OfflineItemManager(downloadRefs: List<Long>?) {
|
||||
|
||||
val downloadStatus: MutableMap<Long, DownloadStatus>
|
||||
|
||||
val downloadManager: DownloadManager
|
||||
= ChaosflixApplication.APPLICATION_CONTEXT
|
||||
.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||
|
||||
init {
|
||||
downloadStatus = HashMap()
|
||||
downloadRefs?.map { downloadStatus.put(it, DownloadStatus()) }
|
||||
}
|
||||
|
||||
fun updateDownloadStatus(offlineEvents: LiveData<List<OfflineEvent>>) {
|
||||
Completable.fromAction {
|
||||
offlineEvents.observeForever(Observer {
|
||||
if (it != null && it.size > 0) {
|
||||
val downloadRef = it.map { it.downloadReference }.toTypedArray().toLongArray() ?: longArrayOf()
|
||||
val cursor = downloadManager.query(DownloadManager.Query().setFilterById(*downloadRef))
|
||||
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
val columnId = cursor.getColumnIndex(DownloadManager.COLUMN_ID)
|
||||
val id = cursor.getLong(columnId)
|
||||
val columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
|
||||
val status = cursor.getInt(columnIndex)
|
||||
val bytesSoFarIndex = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
|
||||
val bytesSoFar = cursor.getInt(bytesSoFarIndex)
|
||||
val bytesTotalIndex = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
|
||||
val bytesTotal = cursor.getInt(bytesTotalIndex)
|
||||
|
||||
val statusText: String =
|
||||
when (status) {
|
||||
DownloadManager.STATUS_RUNNING -> "Running"
|
||||
DownloadManager.STATUS_FAILED -> "Failed"
|
||||
DownloadManager.STATUS_PAUSED -> "Paused"
|
||||
DownloadManager.STATUS_SUCCESSFUL -> "Successful"
|
||||
DownloadManager.STATUS_PENDING -> "Pending"
|
||||
else -> "UNKNOWN"
|
||||
}
|
||||
if (downloadStatus.containsKey(id)) {
|
||||
val item = downloadStatus[id]
|
||||
item?.statusText?.set(statusText)
|
||||
item?.currentBytes?.set(bytesSoFar)
|
||||
item?.totalBytes?.set(bytesTotal)
|
||||
} else {
|
||||
downloadStatus.put(id, DownloadStatus(statusText, bytesSoFar, bytesTotal))
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
}
|
||||
})
|
||||
}.subscribeOn(Schedulers.io()).subscribe()
|
||||
}
|
||||
|
||||
fun deleteOfflineItem(item: OfflineEvent): LiveData<Boolean> {
|
||||
val result = MutableLiveData<Boolean>()
|
||||
Completable.fromAction {
|
||||
val file = File(item.localPath)
|
||||
if (file.exists()) file.delete()
|
||||
result.postValue(true)
|
||||
}.subscribeOn(Schedulers.io()).subscribe()
|
||||
return result
|
||||
}
|
||||
|
||||
inner class DownloadStatus(status: String = "", currentBytes: Int = 0, totalBytes: Int = 0) {
|
||||
val statusText: ObservableField<String> = ObservableField()
|
||||
val currentBytes: ObservableField<Int> = ObservableField()
|
||||
val totalBytes: ObservableField<Int> = ObservableField()
|
||||
|
||||
init {
|
||||
this.statusText.set(status)
|
||||
this.currentBytes.set(currentBytes)
|
||||
this.totalBytes.set(totalBytes)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +1,13 @@
|
|||
package de.nicidienase.chaosflix.touch.browse
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.arch.lifecycle.LiveData
|
||||
import android.arch.lifecycle.Observer
|
||||
import android.arch.lifecycle.ViewModel
|
||||
import android.content.Context
|
||||
import android.databinding.ObservableField
|
||||
import android.os.Environment
|
||||
import de.nicidienase.chaosflix.common.entities.ChaosflixDatabase
|
||||
import de.nicidienase.chaosflix.common.entities.download.OfflineEvent
|
||||
import de.nicidienase.chaosflix.common.network.RecordingService
|
||||
import de.nicidienase.chaosflix.common.network.StreamingService
|
||||
import de.nicidienase.chaosflix.touch.ChaosflixApplication
|
||||
import de.nicidienase.chaosflix.touch.OfflineItemManager
|
||||
import de.nicidienase.chaosflix.touch.sync.Downloader
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
@ -24,12 +20,14 @@ class BrowseViewModel(
|
|||
) : ViewModel() {
|
||||
|
||||
val downloader = Downloader(recordingApi, database)
|
||||
lateinit var offlineItemManager: OfflineItemManager
|
||||
|
||||
val downloadManager: DownloadManager
|
||||
= ChaosflixApplication.APPLICATION_CONTEXT
|
||||
.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||
|
||||
val downloadStatus: MutableMap<Long, DownloadStatus> = HashMap()
|
||||
init {
|
||||
getOfflineEvents().observeForever(Observer {
|
||||
val downloadRefs = it?.map { it.downloadReference } ?: emptyList()
|
||||
offlineItemManager = OfflineItemManager(downloadRefs)
|
||||
})
|
||||
}
|
||||
|
||||
fun getConferenceGroups()
|
||||
= database.conferenceGroupDao().getAll()
|
||||
|
@ -64,77 +62,13 @@ class BrowseViewModel(
|
|||
|
||||
fun getRecordingByid(recordingId: Long) = database.recordingDao().findRecordingById(recordingId)
|
||||
|
||||
init {
|
||||
getOfflineEvents().observeForever(Observer {
|
||||
val downloadRef = it?.map { it.downloadReference }?.map { downloadStatus.put(it, DownloadStatus()) }
|
||||
})
|
||||
}
|
||||
|
||||
fun updateDownloadStatus() {
|
||||
Completable.fromAction {
|
||||
getOfflineEvents().observeForever(Observer {
|
||||
if (it != null && it.size > 0) {
|
||||
val downloadRef = it.map { it.downloadReference }.toTypedArray().toLongArray() ?: longArrayOf()
|
||||
val cursor = downloadManager.query(DownloadManager.Query().setFilterById(*downloadRef))
|
||||
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
val columnId = cursor.getColumnIndex(DownloadManager.COLUMN_ID)
|
||||
val id = cursor.getLong(columnId)
|
||||
val columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
|
||||
val status = cursor.getInt(columnIndex)
|
||||
val bytesSoFarIndex = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
|
||||
val bytesSoFar = cursor.getInt(bytesSoFarIndex)
|
||||
val bytesTotalIndex = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
|
||||
val bytesTotal = cursor.getInt(bytesTotalIndex)
|
||||
|
||||
val statusText: String =
|
||||
when (status) {
|
||||
DownloadManager.STATUS_RUNNING -> "Running"
|
||||
DownloadManager.STATUS_FAILED -> "Failed"
|
||||
DownloadManager.STATUS_PAUSED -> "Paused"
|
||||
DownloadManager.STATUS_SUCCESSFUL -> "Successful"
|
||||
DownloadManager.STATUS_PENDING -> "Pending"
|
||||
else -> "UNKNOWN"
|
||||
}
|
||||
if (downloadStatus.containsKey(id)) {
|
||||
val item = downloadStatus[id]
|
||||
item?.statusText?.set(statusText)
|
||||
item?.currentBytes?.set(bytesSoFar)
|
||||
item?.totalBytes?.set(bytesTotal)
|
||||
} else {
|
||||
downloadStatus.put(id, DownloadStatus(statusText, bytesSoFar, bytesTotal))
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
}
|
||||
})
|
||||
}.subscribeOn(Schedulers.io()).subscribe()
|
||||
}
|
||||
|
||||
inner class DownloadStatus(status: String = "", currentBytes: Int = 0, totalBytes: Int = 0) {
|
||||
val statusText: ObservableField<String> = ObservableField()
|
||||
val currentBytes: ObservableField<Int> = ObservableField()
|
||||
val totalBytes: ObservableField<Int> = ObservableField()
|
||||
|
||||
init {
|
||||
this.statusText.set(status)
|
||||
this.currentBytes.set(currentBytes)
|
||||
this.totalBytes.set(totalBytes)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getUriForEvent(item: OfflineEvent): String {
|
||||
val directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
|
||||
val uri = "${directory.toURI()}chaosflix/${item.localPath}"
|
||||
return uri
|
||||
offlineItemManager.updateDownloadStatus(getOfflineEvents())
|
||||
}
|
||||
|
||||
fun deleteOfflineItem(item: OfflineEvent) {
|
||||
Completable.fromAction {
|
||||
val directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
|
||||
val file = File("${directory.path}/chaosflix/${item.localPath}")
|
||||
val file = File(item.localPath)
|
||||
if (file.exists()) file.delete()
|
||||
database.offlineEventDao().deleteById(item.id)
|
||||
}.subscribeOn(Schedulers.io()).subscribe()
|
||||
|
|
|
@ -57,6 +57,6 @@ open class EventRecyclerViewAdapter(val listener: OnEventSelectedListener) :
|
|||
ViewCompat.setTransitionName(holder.mIcon,
|
||||
resources.getString(R.string.thumbnail) + event.eventId)
|
||||
|
||||
holder.mView.setOnClickListener({ v: View -> listener.onEventSelected(items[position]) })
|
||||
holder.mView.setOnClickListener({ _: View -> listener.onEventSelected(items[position]) })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package de.nicidienase.chaosflix.touch.browse.download
|
||||
|
||||
import android.arch.lifecycle.Observer
|
||||
import android.databinding.DataBindingUtil
|
||||
import android.os.Environment
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v7.widget.PopupMenu
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -15,7 +11,6 @@ import de.nicidienase.chaosflix.common.entities.download.OfflineEvent
|
|||
import de.nicidienase.chaosflix.databinding.ItemOfflineEventBinding
|
||||
import de.nicidienase.chaosflix.touch.OnEventSelectedListener
|
||||
import de.nicidienase.chaosflix.touch.browse.BrowseViewModel
|
||||
import de.nicidienase.chaosflix.touch.playback.PlayerActivity
|
||||
|
||||
class OfflineEventAdapter(var items: List<OfflineEvent>, val viewModel: BrowseViewModel, val listener: OnEventSelectedListener) :
|
||||
RecyclerView.Adapter<OfflineEventAdapter.ViewHolder>() {
|
||||
|
@ -37,44 +32,17 @@ class OfflineEventAdapter(var items: List<OfflineEvent>, val viewModel: BrowseVi
|
|||
}
|
||||
)
|
||||
|
||||
holder.binding.downloadStatus = viewModel.downloadStatus[item.downloadReference]
|
||||
holder.binding.card.setOnClickListener { view ->
|
||||
// item.event?.let {
|
||||
// listener.onEventSelected(it)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// holder.binding.textViewOptions.setOnClickListener {
|
||||
// holder.binding.card.setOnClickListener {
|
||||
val menu = PopupMenu(holder.view.context, holder.binding.card)
|
||||
menu.inflate(R.menu.offline_menu)
|
||||
menu.setOnMenuItemClickListener { menuItem ->
|
||||
when (menuItem.itemId) {
|
||||
R.id.item_open -> {
|
||||
item.event?.let {
|
||||
listener.onEventSelected(it)
|
||||
}
|
||||
true
|
||||
}
|
||||
R.id.item_play -> {
|
||||
PlayerActivity.launch(view.context, item.event!!, viewModel.getUriForEvent(item))
|
||||
true
|
||||
}
|
||||
R.id.item_delete -> {
|
||||
viewModel.deleteOfflineItem(item)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
holder.binding.downloadStatus = viewModel.offlineItemManager.downloadStatus[item.downloadReference]
|
||||
holder.binding.buttonDelete.setOnClickListener {
|
||||
viewModel.deleteOfflineItem(item)
|
||||
}
|
||||
holder.binding.content.setOnClickListener {
|
||||
item.event?.let {
|
||||
listener.onEventSelected(it)
|
||||
}
|
||||
menu.show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.size
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import de.nicidienase.chaosflix.touch.ChaosflixApplication
|
|||
import de.nicidienase.chaosflix.touch.sync.Downloader
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.io.File
|
||||
|
||||
class DetailsViewModel(
|
||||
val database: ChaosflixDatabase,
|
||||
|
@ -80,7 +81,7 @@ class DetailsViewModel(
|
|||
Completable.fromAction {
|
||||
database.offlineEventDao().insert(
|
||||
OfflineEvent(eventId = event.eventId, recordingId = recording.recordingId,
|
||||
localPath = recording.filename, downloadReference = downloadReference))
|
||||
localPath = getDownloadDir() + recording.filename, downloadReference = downloadReference))
|
||||
result.postValue(true)
|
||||
}.subscribeOn(Schedulers.io()).subscribe()
|
||||
} else {
|
||||
|
@ -90,8 +91,30 @@ class DetailsViewModel(
|
|||
return result
|
||||
}
|
||||
|
||||
fun getOfflineItem(eventId: Long) = database.offlineEventDao().getByEventId(eventId)
|
||||
|
||||
fun offlineItemExists(eventId: Long): LiveData<Boolean> {
|
||||
val result = MutableLiveData<Boolean>()
|
||||
getOfflineItem(eventId).observeForever({ event: OfflineEvent? ->
|
||||
result.postValue(if (event != null) File(event.localPath).exists() else false)
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
fun deleteOfflineItem(item: OfflineEvent) {
|
||||
Completable.fromAction {
|
||||
val file = File(item.localPath)
|
||||
if (file.exists()) file.delete()
|
||||
database.offlineEventDao().deleteById(item.id)
|
||||
}.subscribeOn(Schedulers.io()).subscribe()
|
||||
}
|
||||
|
||||
private fun getDownloadDir(): String {
|
||||
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).path + DOWNLOAD_DIR;
|
||||
}
|
||||
|
||||
companion object {
|
||||
val DOWNLOAD_DIR = "chaosflix/"
|
||||
val DOWNLOAD_DIR = "/chaosflix/"
|
||||
val TAG = DetailsViewModel::class.simpleName
|
||||
}
|
||||
}
|
|
@ -19,7 +19,6 @@ import de.nicidienase.chaosflix.touch.playback.PlayerActivity
|
|||
class EventDetailsActivity : AppCompatActivity(),
|
||||
EventDetailsFragment.OnEventDetailsFragmentInteractionListener,
|
||||
OnEventSelectedListener {
|
||||
|
||||
override fun onEventSelected(event: PersistentEvent) {
|
||||
showFragmentForEvent(event.eventId, true)
|
||||
}
|
||||
|
@ -65,6 +64,10 @@ class EventDetailsActivity : AppCompatActivity(),
|
|||
PlayerActivity.launch(this, event, recording)
|
||||
}
|
||||
|
||||
override fun playItem(event: PersistentEvent, uri: String) {
|
||||
PlayerActivity.launch(this,event,uri)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val EXTRA_EVENT = "extra_event"
|
||||
|
||||
|
|
|
@ -125,16 +125,20 @@ class EventDetailsFragment : Fragment() {
|
|||
|
||||
private fun play() {
|
||||
listener?.let {
|
||||
val event = this.event
|
||||
if (event != null) {
|
||||
|
||||
viewModel.getRecordingForEvent(eventId)
|
||||
.observe(this, Observer { persistentRecordings ->
|
||||
if (persistentRecordings != null) {
|
||||
listener!!.playItem(event, Util.getOptimalStream(persistentRecordings))
|
||||
}
|
||||
})
|
||||
}
|
||||
viewModel.getOfflineItem(eventId).observe(this, Observer { offlineEvent ->
|
||||
if(offlineEvent != null){
|
||||
Log.d(TAG,"Playing offline file")
|
||||
listener?.playItem(event,offlineEvent.localPath)
|
||||
} else {
|
||||
viewModel.getRecordingForEvent(eventId)
|
||||
.observe(this, Observer { persistentRecordings ->
|
||||
if (persistentRecordings != null) {
|
||||
Log.d(TAG,"Playing network file")
|
||||
listener!!.playItem(event, Util.getOptimalStream(persistentRecordings))
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,6 +170,16 @@ class EventDetailsFragment : Fragment() {
|
|||
menu.findItem(R.id.action_unbookmark).isVisible = false
|
||||
}
|
||||
menu.findItem(R.id.action_download).isVisible = viewModel.writeExternalStorageAllowed
|
||||
viewModel.offlineItemExists(eventId).observe(this,
|
||||
Observer { itemExists ->
|
||||
itemExists?.let {
|
||||
menu.findItem(R.id.action_download).isVisible =
|
||||
viewModel.writeExternalStorageAllowed && !itemExists
|
||||
menu.findItem(R.id.action_delete_offline_item).isVisible =
|
||||
viewModel.writeExternalStorageAllowed && itemExists
|
||||
}
|
||||
})
|
||||
|
||||
menu.findItem(R.id.action_play).isVisible = appBarExpanded
|
||||
}
|
||||
|
||||
|
@ -200,12 +214,21 @@ class EventDetailsFragment : Fragment() {
|
|||
R.id.action_download -> {
|
||||
viewModel.getRecordingForEvent(eventId).observeForever {
|
||||
viewModel.download(event, Util.getOptimalStream(it!!)).observe(this, Observer {
|
||||
if(it != null){
|
||||
val message = if(it) "Download started" else "Error starting download"
|
||||
Snackbar.make(view!!,message, Snackbar.LENGTH_LONG).show()
|
||||
if (it != null) {
|
||||
val message = if (it) "Download started" else "Error starting download"
|
||||
Snackbar.make(view!!, message, Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
})
|
||||
}
|
||||
activity?.invalidateOptionsMenu()
|
||||
return true
|
||||
}
|
||||
R.id.action_delete_offline_item -> {
|
||||
viewModel.getOfflineItem(eventId).observeForever {
|
||||
if (it != null) {
|
||||
viewModel.deleteOfflineItem(it)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
|
@ -217,6 +240,7 @@ class EventDetailsFragment : Fragment() {
|
|||
fun onToolbarStateChange()
|
||||
fun invalidateOptionsMenu()
|
||||
fun playItem(event: PersistentEvent, recording: PersistentRecording)
|
||||
fun playItem(event: PersistentEvent, uri: String)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -20,10 +20,10 @@ class Downloader(val recordingApi: RecordingService,
|
|||
|
||||
private fun updateEverything() {
|
||||
updateConferencesAndGroups { conferenceIds ->
|
||||
for (id in conferenceIds) {
|
||||
updateEventsForConference(id) { eventIds ->
|
||||
for (id in eventIds) {
|
||||
updateRecordingsForEvent(id)
|
||||
for (confId in conferenceIds) {
|
||||
updateEventsForConference(confId) { eventIds ->
|
||||
for (eventId in eventIds) {
|
||||
updateRecordingsForEvent(eventId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
BIN
touch/src/main/res/drawable-hdpi/ic_delete.png
Normal file
After Width: | Height: | Size: 227 B |
BIN
touch/src/main/res/drawable-hdpi/ic_delete_dark.png
Normal file
After Width: | Height: | Size: 257 B |
BIN
touch/src/main/res/drawable-mdpi/ic_delete.png
Normal file
After Width: | Height: | Size: 178 B |
BIN
touch/src/main/res/drawable-mdpi/ic_delete_dark.png
Normal file
After Width: | Height: | Size: 197 B |
BIN
touch/src/main/res/drawable-xhdpi/ic_delete.png
Normal file
After Width: | Height: | Size: 255 B |
BIN
touch/src/main/res/drawable-xhdpi/ic_delete_dark.png
Normal file
After Width: | Height: | Size: 279 B |
BIN
touch/src/main/res/drawable-xxhdpi/ic_delete.png
Normal file
After Width: | Height: | Size: 418 B |
BIN
touch/src/main/res/drawable-xxhdpi/ic_delete_dark.png
Normal file
After Width: | Height: | Size: 474 B |
|
@ -1,10 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<import type="de.nicidienase.chaosflix.touch.browse.BrowseViewModel.DownloadStatus"/>
|
||||
<import type="de.nicidienase.chaosflix.touch.OfflineItemManager.DownloadStatus"/>
|
||||
|
||||
<import type="de.nicidienase.chaosflix.common.entities.recording.persistence.PersistentEvent"/>
|
||||
|
||||
|
@ -49,6 +50,7 @@
|
|||
android:scaleType="fitCenter"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
|
@ -82,11 +84,18 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="bottom|right"
|
||||
android:paddingRight="8dp"
|
||||
android:text="@{downloadStatus.statusText}"
|
||||
tools:text="Tag"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/button_delete"
|
||||
android:layout_width="@dimen/del_button_size"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/button_rect_normal"
|
||||
app:srcCompat="@drawable/ic_delete_dark"/>
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
|
@ -15,11 +16,17 @@
|
|||
<item
|
||||
android:id="@+id/action_unbookmark"
|
||||
android:icon="@drawable/ic_bookmark"
|
||||
android:title="Remove Bookmark"
|
||||
android:title="@string/remove_bookmark"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/action_download"
|
||||
android:title="@string/download"
|
||||
android:icon="@drawable/ic_download"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/action_delete_offline_item"
|
||||
android:title="@string/delete_local_file"
|
||||
android:icon="@drawable/ic_delete"
|
||||
android:visible="false"
|
||||
app:showAsAction="always"/>
|
||||
</menu>
|
|
@ -6,4 +6,5 @@
|
|||
<dimen name="margin_content">120dp</dimen>
|
||||
<dimen name="details_text_margin">8dp</dimen>
|
||||
<dimen name="details_title_margin">25dp</dimen>
|
||||
<dimen name="del_button_size">64dp</dimen>
|
||||
</resources>
|
|
@ -33,4 +33,6 @@
|
|||
<string name="drawer_close">Drawer closed</string>
|
||||
<string name="about_description">TODO: Description</string>
|
||||
<string name="about_title">Chaosflix</string>
|
||||
<string name="remove_bookmark">Remove Bookmark</string>
|
||||
<string name="delete_local_file">Delete local File</string>
|
||||
</resources>
|