download headers

This commit is contained in:
LagradOst 2021-07-18 15:02:30 +02:00
parent 8a519176ca
commit ddd722f19e
12 changed files with 295 additions and 62 deletions

View file

@ -113,6 +113,7 @@ class MainActivity : AppCompatActivity() {
val dur: Long =
data.getLongExtra(VLC_EXTRA_DURATION_OUT, -1) //Last position in media when player exited
val id = getKey<Int>(VLC_LAST_ID_KEY)
println("SET KEY $id at $pos / $dur")
if (dur > 0 && pos > 0) {
setViewPos(id, pos, dur)
}

View file

@ -1,31 +1,81 @@
package com.lagradost.cloudstream3.ui.download
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.LinearLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.mvvm.observe
import kotlinx.android.synthetic.main.fragment_downloads.*
import kotlinx.android.synthetic.main.fragment_result.*
class DownloadFragment : Fragment() {
private lateinit var notificationsViewModel: DownloadViewModel
private lateinit var downloadsViewModel: DownloadViewModel
private fun getBytesAsText(bytes: Long): String {
return "%.1f".format(bytes / 1000000000f)
}
private fun View.setLayoutWidth(weight: Long) {
val param = LinearLayout.LayoutParams(
0,
LinearLayout.LayoutParams.MATCH_PARENT,
maxOf((weight / 1000000000f), 0.1f) // 100mb
)
this.layoutParams = param
}
@SuppressLint("SetTextI18n")
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
notificationsViewModel =
downloadsViewModel =
ViewModelProvider(this).get(DownloadViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_notifications, container, false)
val textView: TextView = root.findViewById(R.id.text_notifications)
notificationsViewModel.text.observe(viewLifecycleOwner, Observer {
textView.text = it
})
return root
observe(downloadsViewModel.noDownloadsText) {
text_no_downloads.text = it
}
observe(downloadsViewModel.headerCards) {
(download_list?.adapter as DownloadHeaderAdapter? ?: return@observe).cardList = it
(download_list?.adapter as DownloadHeaderAdapter? ?: return@observe).notifyDataSetChanged()
}
observe(downloadsViewModel.availableBytes) {
download_free_txt?.text = "Free • ${getBytesAsText(it)}GB"
download_free?.setLayoutWidth(it)
}
observe(downloadsViewModel.usedBytes) {
download_used_txt?.text = "Used • ${getBytesAsText(it)}GB"
download_used?.setLayoutWidth(it)
}
observe(downloadsViewModel.downloadBytes) {
download_app_txt?.text = "App • ${getBytesAsText(it)}GB"
download_app?.setLayoutWidth(it)
}
return inflater.inflate(R.layout.fragment_downloads, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
DownloadHeaderAdapter(
ArrayList(),
) { click ->
}
download_list.adapter = adapter
download_list.layoutManager = GridLayoutManager(context, 1)
downloadsViewModel.updateList(requireContext())
activity?.fixPaddingStatusbar(download_root)
}
}

View file

@ -1,13 +1,95 @@
package com.lagradost.cloudstream3.ui.download
import android.content.Context
import android.os.Environment
import android.os.StatFs
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.getKeys
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
import com.lagradost.cloudstream3.utils.VideoDownloadManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class DownloadViewModel : ViewModel() {
private val _text = MutableLiveData<String>().apply {
value = "This is notifications Fragment"
private val _noDownloadsText = MutableLiveData<String>().apply {
value = ""
}
val noDownloadsText: LiveData<String> = _noDownloadsText
private val _headerCards =
MutableLiveData<List<VisualDownloadHeaderCached>>().apply { listOf<VisualDownloadHeaderCached>() }
val headerCards: LiveData<List<VisualDownloadHeaderCached>> = _headerCards
private val _usedBytes = MutableLiveData<Long>()
private val _availableBytes = MutableLiveData<Long>()
private val _downloadBytes = MutableLiveData<Long>()
val usedBytes: LiveData<Long> = _usedBytes
val availableBytes: LiveData<Long> = _availableBytes
val downloadBytes: LiveData<Long> = _downloadBytes
fun updateList(context: Context) = viewModelScope.launch {
val children = withContext(Dispatchers.IO) {
val headers = context.getKeys(DOWNLOAD_EPISODE_CACHE)
headers.mapNotNull { context.getKey<VideoDownloadHelper.DownloadEpisodeCached>(it) }
}
// parentId : bytes
val bytesUsedByChild = HashMap<Int, Long>()
// parentId : downloadsCount
val totalDownloads = HashMap<Int, Int>()
// Gets all children downloads
withContext(Dispatchers.IO) {
for (c in children) {
val childFile = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(context, c.id)
val len = childFile?.totalBytes ?: continue
if (bytesUsedByChild.containsKey(c.parentId)) {
bytesUsedByChild[c.parentId] = bytesUsedByChild[c.parentId]?.plus(len) ?: len
} else {
bytesUsedByChild[c.parentId] = len
}
if (totalDownloads.containsKey(c.parentId)) {
totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1
} else {
totalDownloads[c.parentId] = 1
}
}
}
val cached = withContext(Dispatchers.IO) {
val headers = context.getKeys(DOWNLOAD_HEADER_CACHE)
headers.mapNotNull { context.getKey<VideoDownloadHelper.DownloadHeaderCached>(it) }
}
val visual = withContext(Dispatchers.IO) {
cached.mapNotNull { // TODO FIX
val downloads = totalDownloads[it.id] ?: 0
val bytes = bytesUsedByChild[it.id] ?: 0
if(bytes <= 0 || downloads <= 0) return@mapNotNull null
VisualDownloadHeaderCached(0, downloads, bytes, it)
}
}
val stat = StatFs(Environment.getExternalStorageDirectory().path)
val localBytesAvailable = stat.availableBytes//stat.blockSizeLong * stat.blockCountLong
val localTotalBytes = stat.blockSizeLong * stat.blockCountLong
val localDownloadedBytes = visual.sumOf { it.totalBytes }
_usedBytes.postValue(localTotalBytes - localBytesAvailable - localDownloadedBytes)
_availableBytes.postValue(localBytesAvailable)
_downloadBytes.postValue(localDownloadedBytes)
_headerCards.postValue(visual)
}
val text: LiveData<String> = _text
}

View file

@ -352,7 +352,7 @@ class ResultFragment : Fragment() {
episodeClick.data.index,
eps,
sortUrls(currentLinks ?: return),
currentSubs ?: return,
currentSubs ?: ArrayList(),
startTime = episodeClick.data.getRealPosition(),
startIndex = startIndex
)
@ -548,7 +548,7 @@ class ResultFragment : Fragment() {
vlcIntent.putExtra("position", position)
vlcIntent.component = VLC_COMPONENT
requireContext().setKey(VLC_LAST_ID_KEY, currentId)
requireContext().setKey(VLC_LAST_ID_KEY, episodeClick.data.id)
activity?.startActivityForResult(vlcIntent, VLC_REQUEST_CODE)
}

View file

@ -146,7 +146,7 @@ class SearchFragment : Fragment() {
allApi.providersActive = requireActivity().getApiSettings()
//searchViewModel.search("iron man")
(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")
//(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")
/*
(requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.enter_anim,

View file

@ -53,11 +53,12 @@
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
<!--
android:background="?selectableItemBackgroundBorderless"-->
<ImageView
android:layout_marginStart="-40dp"
android:layout_height="match_parent"
android:layout_width="30dp"
android:background="?selectableItemBackgroundBorderless"
android:layout_gravity="center_vertical|end"
android:src="@drawable/ic_baseline_keyboard_arrow_right_24"
android:contentDescription="@string/download_descript"/>

View file

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/download_root"
android:orientation="vertical"
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.download.DownloadFragment">
<LinearLayout
android:layout_margin="10dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_marginBottom="5dp"
android:text="@string/download_storage_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<LinearLayout
android:layout_marginBottom="5dp"
android:layout_width="fill_parent"
android:layout_height="12dp"
android:orientation="horizontal">
<View
android:layout_weight="0.5"
android:id="@+id/download_used"
android:background="@color/usedStorageColor"
android:layout_width="0dp"
android:layout_height="match_parent"/>
<View
android:id="@+id/download_app"
android:layout_weight="0.10"
android:background="?attr/colorPrimary"
android:layout_width="0dp"
android:layout_height="match_parent"/>
<View
android:id="@+id/download_free"
android:layout_weight="0.10"
android:background="@color/freeStorageColor"
android:layout_width="0dp"
android:layout_height="match_parent"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_marginEnd="5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_gravity="center_vertical"
android:background="@color/usedStorageColor"
android:layout_width="10dp"
android:layout_height="10dp"/>
<TextView
android:id="@+id/download_used_txt"
android:layout_gravity="center_vertical"
tools:text="Used • 30.58GB"
android:textSize="12sp"
android:textColor="?attr/textColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<View
android:layout_margin="5dp"
android:layout_gravity="center_vertical"
android:background="?attr/colorPrimary"
android:layout_width="10dp"
android:layout_height="10dp"/>
<TextView
android:id="@+id/download_app_txt"
android:layout_gravity="center_vertical"
tools:text="App • 30.58GB"
android:textSize="12sp"
android:textColor="?attr/textColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<View
android:layout_margin="5dp"
android:layout_gravity="center_vertical"
android:background="@color/freeStorageColor"
android:layout_width="10dp"
android:layout_height="10dp"/>
<TextView
android:id="@+id/download_free_txt"
android:textSize="12sp"
android:layout_gravity="center_vertical"
tools:text="Free • 30.58GB"
android:textColor="?attr/textColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:layout_margin="10dp"
android:id="@+id/download_list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
<TextView
android:id="@+id/text_no_downloads"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</LinearLayout>

View file

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.download.DownloadFragment">
<TextView
android:id="@+id/text_notifications"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -21,7 +21,7 @@
android:id="@+id/navigation_notifications"
android:name="com.lagradost.cloudstream3.ui.download.DownloadFragment"
android:label="@string/title_downloads"
tools:layout="@layout/fragment_notifications"/>
tools:layout="@layout/fragment_downloads"/>
<fragment
android:id="@+id/navigation_settings"
android:layout_height="match_parent"

View file

@ -38,4 +38,7 @@
<color name="videoColorPrimary">@color/colorPrimary</color> <!--0e09df 617EFF 3d50fa-->
<color name="iconColor">#9ba0a6</color>
<color name="usedStorageColor">#FFF</color>
<color name="freeStorageColor">#676767</color>
</resources>

View file

@ -40,4 +40,5 @@
<string name="need_storage">Allow to download episodes</string>
<string name="download_descript">Download</string>
<string name="error_loading_links">Error Loading Links</string>
<string name="download_storage_text">Internal Storage</string>
</resources>