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 = val dur: Long =
data.getLongExtra(VLC_EXTRA_DURATION_OUT, -1) //Last position in media when player exited data.getLongExtra(VLC_EXTRA_DURATION_OUT, -1) //Last position in media when player exited
val id = getKey<Int>(VLC_LAST_ID_KEY) val id = getKey<Int>(VLC_LAST_ID_KEY)
println("SET KEY $id at $pos / $dur")
if (dur > 0 && pos > 0) { if (dur > 0 && pos > 0) {
setViewPos(id, pos, dur) setViewPos(id, pos, dur)
} }

View file

@ -1,31 +1,81 @@
package com.lagradost.cloudstream3.ui.download package com.lagradost.cloudstream3.ui.download
import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.LinearLayout
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.R 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() { 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( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
notificationsViewModel = downloadsViewModel =
ViewModelProvider(this).get(DownloadViewModel::class.java) ViewModelProvider(this).get(DownloadViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_notifications, container, false) observe(downloadsViewModel.noDownloadsText) {
val textView: TextView = root.findViewById(R.id.text_notifications) text_no_downloads.text = it
notificationsViewModel.text.observe(viewLifecycleOwner, Observer { }
textView.text = it observe(downloadsViewModel.headerCards) {
}) (download_list?.adapter as DownloadHeaderAdapter? ?: return@observe).cardList = it
return root (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 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.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel 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() { class DownloadViewModel : ViewModel() {
private val _text = MutableLiveData<String>().apply { private val _noDownloadsText = MutableLiveData<String>().apply {
value = "This is notifications Fragment" 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, episodeClick.data.index,
eps, eps,
sortUrls(currentLinks ?: return), sortUrls(currentLinks ?: return),
currentSubs ?: return, currentSubs ?: ArrayList(),
startTime = episodeClick.data.getRealPosition(), startTime = episodeClick.data.getRealPosition(),
startIndex = startIndex startIndex = startIndex
) )
@ -548,7 +548,7 @@ class ResultFragment : Fragment() {
vlcIntent.putExtra("position", position) vlcIntent.putExtra("position", position)
vlcIntent.component = VLC_COMPONENT 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) activity?.startActivityForResult(vlcIntent, VLC_REQUEST_CODE)
} }

View file

@ -146,7 +146,7 @@ class SearchFragment : Fragment() {
allApi.providersActive = requireActivity().getApiSettings() allApi.providersActive = requireActivity().getApiSettings()
//searchViewModel.search("iron man") //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() (requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.enter_anim, .setCustomAnimations(R.anim.enter_anim,

View file

@ -53,11 +53,12 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
</TextView> </TextView>
</LinearLayout> </LinearLayout>
<!--
android:background="?selectableItemBackgroundBorderless"-->
<ImageView <ImageView
android:layout_marginStart="-40dp" android:layout_marginStart="-40dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_width="30dp" android:layout_width="30dp"
android:background="?selectableItemBackgroundBorderless"
android:layout_gravity="center_vertical|end" android:layout_gravity="center_vertical|end"
android:src="@drawable/ic_baseline_keyboard_arrow_right_24" android:src="@drawable/ic_baseline_keyboard_arrow_right_24"
android:contentDescription="@string/download_descript"/> 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:id="@+id/navigation_notifications"
android:name="com.lagradost.cloudstream3.ui.download.DownloadFragment" android:name="com.lagradost.cloudstream3.ui.download.DownloadFragment"
android:label="@string/title_downloads" android:label="@string/title_downloads"
tools:layout="@layout/fragment_notifications"/> tools:layout="@layout/fragment_downloads"/>
<fragment <fragment
android:id="@+id/navigation_settings" android:id="@+id/navigation_settings"
android:layout_height="match_parent" android:layout_height="match_parent"

View file

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

View file

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