show AoD highlights on home fragment
This commit is contained in:
parent
a390bc9686
commit
6775a4da2e
|
@ -47,6 +47,7 @@ object AoDParser {
|
|||
|
||||
private val mediaList = arrayListOf<Media>()
|
||||
val itemMediaList = arrayListOf<ItemMedia>()
|
||||
val highlightsList = arrayListOf<ItemMedia>()
|
||||
val newEpisodesList = arrayListOf<ItemMedia>()
|
||||
|
||||
fun login(): Boolean = runBlocking {
|
||||
|
@ -95,7 +96,7 @@ object AoDParser {
|
|||
*/
|
||||
fun initialLoading() = runBlocking {
|
||||
val newEPJob = GlobalScope.async {
|
||||
listNewEpisodes()
|
||||
loadHome()
|
||||
}
|
||||
|
||||
val listJob = GlobalScope.async {
|
||||
|
@ -182,9 +183,9 @@ object AoDParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* load all new episodes from AoD into newEpisodesList
|
||||
* load new episodes and highlights
|
||||
*/
|
||||
private fun listNewEpisodes() = runBlocking {
|
||||
private fun loadHome() = runBlocking {
|
||||
if (sessionCookies.isEmpty()) login()
|
||||
|
||||
withContext(Dispatchers.Default) {
|
||||
|
@ -192,6 +193,7 @@ object AoDParser {
|
|||
.cookies(sessionCookies)
|
||||
.get()
|
||||
|
||||
// get all new episodes from AoD
|
||||
newEpisodesList.clear()
|
||||
resHome.select("div.jcarousel-container-new").select("li").forEach {
|
||||
if (it.select("span").hasClass("neweps")) {
|
||||
|
@ -204,6 +206,18 @@ object AoDParser {
|
|||
}
|
||||
}
|
||||
|
||||
// get highlights from AoD
|
||||
highlightsList.clear()
|
||||
resHome.select("#aod-highlights").select("div.news-item").forEach {
|
||||
val mediaId = it.select("div.news-item-text").select("a.serienlink")
|
||||
.attr("href").substringAfterLast("/").toInt()
|
||||
val mediaTitle = it.select("div.news-title").select("h2").text()
|
||||
val mediaImage = it.select("img").attr("src")
|
||||
|
||||
highlightsList.add(ItemMedia(mediaId, mediaTitle, mediaImage))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
package org.mosad.teapod.ui.fragments
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.mosad.teapod.MainActivity
|
||||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.databinding.FragmentHomeBinding
|
||||
import org.mosad.teapod.parser.AoDParser
|
||||
import org.mosad.teapod.util.ItemMedia
|
||||
import org.mosad.teapod.util.StorageController
|
||||
import org.mosad.teapod.util.adapter.MediaItemAdapter
|
||||
import org.mosad.teapod.util.decoration.MediaItemDecoration
|
||||
|
@ -22,6 +29,8 @@ class HomeFragment : Fragment() {
|
|||
private lateinit var adapterMyList: MediaItemAdapter
|
||||
private lateinit var adapterNewEpisodes: MediaItemAdapter
|
||||
|
||||
private lateinit var highlightMedia: ItemMedia
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
binding = FragmentHomeBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
|
@ -30,24 +39,89 @@ class HomeFragment : Fragment() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
GlobalScope.launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
context?.let {
|
||||
binding.recyclerMyList.addItemDecoration(MediaItemDecoration(9))
|
||||
|
||||
updateMyListMedia()
|
||||
|
||||
adapterNewEpisodes = MediaItemAdapter(AoDParser.newEpisodesList)
|
||||
binding.recyclerNewEpisodes.adapter = adapterNewEpisodes
|
||||
binding.recyclerNewEpisodes.addItemDecoration(MediaItemDecoration(9))
|
||||
|
||||
initActions()
|
||||
}
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
context?.let {
|
||||
initHighlight()
|
||||
initRecyclerViews()
|
||||
initActions()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO recreating the adapter on list change is not a good solution
|
||||
private fun initHighlight() {
|
||||
highlightMedia = AoDParser.highlightsList[0]
|
||||
|
||||
binding.textHighlightTitle.text = highlightMedia.title
|
||||
Glide.with(requireContext()).load(highlightMedia.posterUrl)
|
||||
.into(binding.imageHighlight)
|
||||
|
||||
if (StorageController.myList.contains(highlightMedia.id)) {
|
||||
loadIntoCompoundDrawable(R.drawable.ic_baseline_check_24, binding.textHighlightMyList)
|
||||
} else {
|
||||
loadIntoCompoundDrawable(R.drawable.ic_baseline_add_24, binding.textHighlightMyList)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initRecyclerViews() {
|
||||
binding.recyclerMyList.addItemDecoration(MediaItemDecoration(9))
|
||||
binding.recyclerNewEpisodes.addItemDecoration(MediaItemDecoration(9))
|
||||
|
||||
// my list
|
||||
val myListMedia = StorageController.myList.map { elementId ->
|
||||
AoDParser.itemMediaList.first {
|
||||
elementId == it.id
|
||||
}
|
||||
}
|
||||
adapterMyList = MediaItemAdapter(myListMedia)
|
||||
adapterMyList.onItemClick = { mediaId, _ ->
|
||||
(activity as MainActivity).showFragment(MediaFragment(mediaId))
|
||||
}
|
||||
binding.recyclerMyList.adapter = adapterMyList
|
||||
|
||||
// new episodes
|
||||
adapterNewEpisodes = MediaItemAdapter(AoDParser.newEpisodesList)
|
||||
binding.recyclerNewEpisodes.adapter = adapterNewEpisodes
|
||||
}
|
||||
|
||||
private fun initActions() {
|
||||
binding.buttonPlayHighlight.setOnClickListener {
|
||||
// TODO get next episode
|
||||
GlobalScope.launch {
|
||||
val media = AoDParser.getMediaById(highlightMedia.id)
|
||||
|
||||
Log.d(javaClass.name, "Starting Player with mediaId: ${media.id}")
|
||||
(activity as MainActivity).startPlayer(media.id, media.episodes.first().id)
|
||||
}
|
||||
}
|
||||
|
||||
binding.textHighlightMyList.setOnClickListener {
|
||||
if (StorageController.myList.contains(highlightMedia.id)) {
|
||||
StorageController.myList.remove(highlightMedia.id)
|
||||
loadIntoCompoundDrawable(R.drawable.ic_baseline_add_24, binding.textHighlightMyList)
|
||||
} else {
|
||||
StorageController.myList.add(highlightMedia.id)
|
||||
loadIntoCompoundDrawable(R.drawable.ic_baseline_check_24, binding.textHighlightMyList)
|
||||
}
|
||||
StorageController.saveMyList(requireContext())
|
||||
|
||||
updateMyListMedia() // update my list, since it has changed
|
||||
}
|
||||
|
||||
binding.textHighlightInfo.setOnClickListener {
|
||||
(activity as MainActivity).showFragment(MediaFragment(highlightMedia.id))
|
||||
}
|
||||
|
||||
adapterNewEpisodes.onItemClick = { mediaId, _ ->
|
||||
(activity as MainActivity).showFragment(MediaFragment(mediaId))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update my media list
|
||||
* TODO
|
||||
* * auto call when StorageController.myList is changed
|
||||
* * only update actual change and not all data (performance)
|
||||
*/
|
||||
fun updateMyListMedia() {
|
||||
val myListMedia = StorageController.myList.map { elementId ->
|
||||
AoDParser.itemMediaList.first {
|
||||
|
@ -55,17 +129,22 @@ class HomeFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
adapterMyList = MediaItemAdapter(myListMedia)
|
||||
adapterMyList.onItemClick = { mediaId, _ ->
|
||||
(activity as MainActivity).showFragment(MediaFragment(mediaId))
|
||||
}
|
||||
|
||||
binding.recyclerMyList.adapter = adapterMyList
|
||||
adapterMyList.updateMediaList(myListMedia)
|
||||
adapterMyList.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun initActions() {
|
||||
adapterNewEpisodes.onItemClick = { mediaId, _ ->
|
||||
(activity as MainActivity).showFragment(MediaFragment(mediaId))
|
||||
}
|
||||
private fun loadIntoCompoundDrawable(drawable: Int, textView: TextView) {
|
||||
Glide.with(requireContext())
|
||||
.load(drawable)
|
||||
.into(object : CustomTarget<Drawable>(48, 48) {
|
||||
override fun onLoadCleared(drawable: Drawable?) {
|
||||
textView.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null)
|
||||
}
|
||||
|
||||
override fun onResourceReady(res: Drawable, transition: Transition<in Drawable>?) {
|
||||
textView.setCompoundDrawablesWithIntrinsicBounds(null, res, null, null)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
|
@ -10,11 +10,11 @@ import org.mosad.teapod.databinding.ItemMediaBinding
|
|||
import org.mosad.teapod.util.ItemMedia
|
||||
import java.util.*
|
||||
|
||||
class MediaItemAdapter(private val media: List<ItemMedia>) : RecyclerView.Adapter<MediaItemAdapter.MediaViewHolder>(), Filterable {
|
||||
class MediaItemAdapter(private val initMedia: List<ItemMedia>) : RecyclerView.Adapter<MediaItemAdapter.MediaViewHolder>(), Filterable {
|
||||
|
||||
var onItemClick: ((Int, Int) -> Unit)? = null
|
||||
private val filter = MediaFilter()
|
||||
private var filteredMedia = media.map { it.copy() }
|
||||
private var filteredMedia = initMedia.map { it.copy() }
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MediaItemAdapter.MediaViewHolder {
|
||||
return MediaViewHolder(ItemMediaBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
|
@ -35,6 +35,10 @@ class MediaItemAdapter(private val media: List<ItemMedia>) : RecyclerView.Adapte
|
|||
return filter
|
||||
}
|
||||
|
||||
fun updateMediaList(mediaList: List<ItemMedia>) {
|
||||
filteredMedia = mediaList
|
||||
}
|
||||
|
||||
inner class MediaViewHolder(val binding: ItemMediaBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
binding.root.setOnClickListener {
|
||||
|
@ -49,9 +53,9 @@ class MediaItemAdapter(private val media: List<ItemMedia>) : RecyclerView.Adapte
|
|||
val results = FilterResults()
|
||||
|
||||
val filteredList = if (filterTerm.isEmpty()) {
|
||||
media
|
||||
initMedia
|
||||
} else {
|
||||
media.filter {
|
||||
initMedia.filter {
|
||||
it.title.toLowerCase(Locale.ROOT).contains(filterTerm)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="7dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:text="@string/info_about_dialog"
|
||||
android:text="@string/about_info"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -18,6 +18,97 @@
|
|||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear_highlight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="7dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_highlight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/highlight_media"
|
||||
app:layout_constraintDimensionRatio="H,16:9"
|
||||
tools:src="@drawable/ic_launcher_background" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_highlight_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="7dp"
|
||||
android:text="@string/text_title_ex"
|
||||
android:textAlignment="center"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="7dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_highlight_my_list"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/my_list"
|
||||
android:textColor="?textSecondary"
|
||||
android:textSize="12sp"
|
||||
app:drawableTint="?buttonBackground"
|
||||
app:drawableTopCompat="@drawable/ic_baseline_add_24" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_play_highlight"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/button_play"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?themePrimary"
|
||||
android:textSize="16sp"
|
||||
app:backgroundTint="?buttonBackground"
|
||||
app:icon="@drawable/ic_baseline_play_arrow_24"
|
||||
app:iconGravity="textStart"
|
||||
app:iconTint="?themePrimary" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_highlight_info"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/info"
|
||||
android:textColor="?textSecondary"
|
||||
android:textSize="12sp"
|
||||
app:drawableTint="?buttonBackground"
|
||||
app:drawableTopCompat="@drawable/ic_baseline_info_24" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear_my_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
|
@ -45,6 +136,7 @@
|
|||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear_new_episodes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<string name="title_account">Account</string>
|
||||
|
||||
<!-- home fragment -->
|
||||
<string name="highlight_media">Highlight</string>
|
||||
<string name="my_list">Meine Liste</string>
|
||||
<string name="new_episodes">Neue Episoden</string>
|
||||
|
||||
|
@ -24,13 +25,6 @@
|
|||
<string name="account_login_desc">Zum bearbeiten tippen</string>
|
||||
<string name="info">Info</string>
|
||||
<string name="info_about_desc">Version %1$s (%2$s)</string>
|
||||
<string name="info_about_dialog">
|
||||
Teapod ist eine inoffizielle App für Anime on Demand.
|
||||
Sie wird unter den Bedingungen der GNU GPL 3 oder höher zur Verfügung gestellt.
|
||||
\n\n
|
||||
© 2020 seil0@mosad.xyz
|
||||
</string>
|
||||
<string name="licenses">Lizenzen</string>
|
||||
<string name="settings">Einstellungen</string>
|
||||
<string name="settings_secondary">Bevorzuge alternativen Stream</string>
|
||||
<string name="settings_secondary_desc">Untertitle-Stream verwenden, sofern vorhanden</string>
|
||||
|
@ -41,6 +35,12 @@
|
|||
<string name="theme_dark">Dunkel</string>
|
||||
|
||||
<!-- about fragment -->
|
||||
<string name="about_info">
|
||||
Teapod ist eine inoffizielle App für Anime on Demand.
|
||||
Sie wird unter den Bedingungen der GNU GPL 3 oder höher zur Verfügung gestellt.
|
||||
\n\n
|
||||
© 2020 seil0@mosad.xyz
|
||||
</string>
|
||||
<string name="third_party_heading">Lizenzen von Drittanbietern</string>
|
||||
<string name="third_party_component_desc">© %1$s %2$s unter %3$s</string>
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<string name="title_account">Account</string>
|
||||
|
||||
<!-- home fragment -->
|
||||
<string name="highlight_media">Highlight</string>
|
||||
<string name="my_list">My list</string>
|
||||
<string name="new_episodes">New episodes</string>
|
||||
|
||||
|
@ -33,12 +34,6 @@
|
|||
<string name="info">Info</string>
|
||||
<string name="info_about" translatable="false">Teapod by @Seil0</string>
|
||||
<string name="info_about_desc">Version %1$s (%2$s)</string>
|
||||
<string name="info_about_dialog">
|
||||
Teapod is an unofficial app for anime on demand.
|
||||
It is published under the terms and conditions of the GNU GPL 3 or later.
|
||||
\n\n
|
||||
© 2020 seil0@mosad.xyz</string>
|
||||
<string name="licenses">Licenses</string>
|
||||
<string name="settings">Settings</string>
|
||||
<string name="settings_secondary">Prefer secondary (sub) stream</string>
|
||||
<string name="settings_secondary_desc">Use the subtitles stream if present</string>
|
||||
|
@ -49,8 +44,14 @@
|
|||
<string name="theme_dark">Dark</string>
|
||||
|
||||
<!-- about fragment -->
|
||||
<string name="teapod_repo" translatable="false">git.mosad.xyz/Seil0/teapod</string>
|
||||
<string name="about_info">
|
||||
Teapod is an unofficial app for anime on demand.
|
||||
It is published under the terms and conditions of the GNU GPL 3 or later.
|
||||
\n\n
|
||||
© 2020 seil0@mosad.xyz
|
||||
</string>
|
||||
<string name="tmdb_notice" translatable="false">This product uses the TMDb API but is not endorsed or certified by TMDb.</string>
|
||||
<string name="teapod_repo" translatable="false">git.mosad.xyz/Seil0/teapod</string>
|
||||
<string name="third_party_heading">Third Party Licenses</string>
|
||||
<string name="third_party_component_desc">© %1$s %2$s under %3$s</string>
|
||||
|
||||
|
|
Loading…
Reference in New Issue