diff --git a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt index 1981a33..5552012 100644 --- a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt +++ b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt @@ -131,14 +131,24 @@ class AoDParser { "episodenanzahl" -> media.info.episodesCount = it.select("td").text().toInt() } } + /** * TODO tv show specific for each episode (div.episodebox) - * * episode id (div.flip-front -> id.substringafter("-")) - * * watched (if div.status-icon-orange present = true) * * watchedCallback - * * episodebox-shorttext */ + val episodes = if (media.type == MediaType.TVSHOW) { + res.select("div.three-box-container > div.episodebox").map { episodebox -> + val episodeId = episodebox.select("div.flip-front").attr("id").substringAfter("-").toInt() + val episodeWatched = episodebox.select("div.episodebox-icons > div").hasClass("status-icon-orange") + val episodeShortDesc = episodebox.select("p.episodebox-shorttext").text() + Episode(id = episodeId, watched = episodeWatched, shortDesc = episodeShortDesc) + } + } else { + listOf(Episode()) + } + + // has attr data-lag (ger or jap) val playlists = res.select("input.streamstarter_html5").eachAttr("data-playlist") val csrfToken = res.select("meta[name=csrf-token]").attr("content") @@ -146,7 +156,7 @@ class AoDParser { //println("csrf token is: $csrfToken") return@withContext if (playlists.size > 0) { - loadStreamInfo(playlists.first(), csrfToken, media.type) + loadStreamInfo(playlists.first(), csrfToken, media.type, episodes) } else { listOf() } @@ -155,8 +165,9 @@ class AoDParser { /** * load the playlist path and parse it, read the stream info from json + * @param episodes is used as call ba reference, additionally it is passed a return value */ - private fun loadStreamInfo(playlistPath: String, csrfToken: String, type: MediaType): List = runBlocking { + private fun loadStreamInfo(playlistPath: String, csrfToken: String, type: MediaType, episodes: List): List = runBlocking { withContext(Dispatchers.Default) { val headers = mutableMapOf( Pair("Accept", "application/json, text/javascript, */*; q=0.01"), @@ -174,44 +185,48 @@ class AoDParser { //println(res.body()) - return@withContext when (type) { + when (type) { MediaType.MOVIE -> { val movie = JsonParser.parseString(res.body()).asJsonObject .get("playlist").asJsonArray - movie.first().asJsonObject.get("sources").asJsonArray.toList().map { - Episode(streamUrl = it.asJsonObject.get("file").asString) + movie.first().asJsonObject.get("sources").asJsonArray.toList().forEach { + episodes.first().streamUrl = it.asJsonObject.get("file").asString } } + MediaType.TVSHOW -> { val episodesJson = JsonParser.parseString(res.body()).asJsonObject .get("playlist").asJsonArray - episodesJson.map { - val episodeStream = it.asJsonObject.get("sources").asJsonArray + episodesJson.forEach { jsonElement -> + val episodeId = jsonElement.asJsonObject.get("mediaid") + val episodeStream = jsonElement.asJsonObject.get("sources").asJsonArray .first().asJsonObject .get("file").asString - val episodeTitle = it.asJsonObject.get("title").asString - val episodePoster = it.asJsonObject.get("image").asString - val episodeDescription = it.asJsonObject.get("description").asString + val episodeTitle = jsonElement.asJsonObject.get("title").asString + val episodePoster = jsonElement.asJsonObject.get("image").asString + val episodeDescription = jsonElement.asJsonObject.get("description").asString val episodeNumber = episodeTitle.substringAfter(", Ep. ").toInt() - Episode( - episodeTitle, - episodeStream, - episodePoster, - episodeDescription, - episodeNumber - ) + episodes.first { it.id == episodeId.asInt }.apply { + this.title = episodeTitle + this.posterLink = episodePoster + this.streamUrl = episodeStream + this.description = episodeDescription + this.number = episodeNumber + } } } + else -> { Log.e(javaClass.name, "Wrong Type, please report this issue.") - listOf() } } + + return@withContext episodes } } diff --git a/app/src/main/java/org/mosad/teapod/ui/search/SearchFragment.kt b/app/src/main/java/org/mosad/teapod/ui/search/SearchFragment.kt index 847ef48..4faf86b 100644 --- a/app/src/main/java/org/mosad/teapod/ui/search/SearchFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/search/SearchFragment.kt @@ -16,7 +16,7 @@ import org.mosad.teapod.util.Media class SearchFragment : Fragment() { - private lateinit var adapter : CustomAdapter + private var adapter : CustomAdapter? = null override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_search, container, false) @@ -45,14 +45,14 @@ class SearchFragment : Fragment() { private fun initActions() { search_text.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { - adapter.filter.filter(query) - adapter.notifyDataSetChanged() + adapter?.filter?.filter(query) + adapter?.notifyDataSetChanged() return false } override fun onQueryTextChange(newText: String?): Boolean { - adapter.filter.filter(newText) - adapter.notifyDataSetChanged() + adapter?.filter?.filter(newText) + adapter?.notifyDataSetChanged() return false } }) @@ -61,7 +61,7 @@ class SearchFragment : Fragment() { search_text.clearFocus() // remove focus from the SearchView runBlocking { - val media = adapter.getItem(position) as Media + val media = adapter?.getItem(position) as Media println("selected item is: ${media.title}") (activity as MainActivity).showDetailFragment(media).join() diff --git a/app/src/main/java/org/mosad/teapod/util/DataTypes.kt b/app/src/main/java/org/mosad/teapod/util/DataTypes.kt index b94c854..cdc40cf 100644 --- a/app/src/main/java/org/mosad/teapod/util/DataTypes.kt +++ b/app/src/main/java/org/mosad/teapod/util/DataTypes.kt @@ -24,10 +24,12 @@ data class Info( ) data class Episode( - val title: String = "", - val streamUrl: String = "", - val posterLink: String = "", + val id: Int = 0, + var title: String = "", + var streamUrl: String = "", + var posterLink: String = "", var description: String = "", + var shortDesc: String = "", var number: Int = 0, var watched: Boolean = false ) diff --git a/app/src/main/java/org/mosad/teapod/util/EpisodesAdapter.kt b/app/src/main/java/org/mosad/teapod/util/EpisodesAdapter.kt index e271226..27762ee 100644 --- a/app/src/main/java/org/mosad/teapod/util/EpisodesAdapter.kt +++ b/app/src/main/java/org/mosad/teapod/util/EpisodesAdapter.kt @@ -9,7 +9,7 @@ import com.bumptech.glide.Glide import kotlinx.android.synthetic.main.component_episode.view.* import org.mosad.teapod.R -class EpisodesAdapter(private val data: List, private val context: Context) : RecyclerView.Adapter() { +class EpisodesAdapter(private val episodes: List, private val context: Context) : RecyclerView.Adapter() { var onItemClick: ((String, Int) -> Unit)? = null @@ -20,21 +20,30 @@ class EpisodesAdapter(private val data: List, private val context: Cont } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { - holder.view.text_episode_title.text = "Episode ${data[position].number} ${data[position].description}" + holder.view.text_episode_title.text = context.getString( + R.string.component_episode_title, + episodes[position].number, + episodes[position].description + ) + holder.view.text_episode_desc.text = episodes[position].shortDesc - if (data[position].posterLink.isNotEmpty()) { - Glide.with(context).load(data[position].posterLink).into(holder.view.image_episode) + if (episodes[position].posterLink.isNotEmpty()) { + Glide.with(context).load(episodes[position].posterLink).into(holder.view.image_episode) + } + + if (!episodes[position].watched) { + holder.view.image_watched.setImageDrawable(null) } } override fun getItemCount(): Int { - return data.size + return episodes.size } inner class MyViewHolder(val view: View) : RecyclerView.ViewHolder(view) { init { view.setOnClickListener { - onItemClick?.invoke(data[adapterPosition].title, adapterPosition) + onItemClick?.invoke(episodes[adapterPosition].title, adapterPosition) } } } diff --git a/app/src/main/res/drawable/ic_baseline_check_circle_24.xml b/app/src/main/res/drawable/ic_baseline_check_circle_24.xml new file mode 100644 index 0000000..5e111ca --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_check_circle_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/component_episode.xml b/app/src/main/res/layout/component_episode.xml index b02a8f5..1060d76 100644 --- a/app/src/main/res/layout/component_episode.xml +++ b/app/src/main/res/layout/component_episode.xml @@ -18,20 +18,31 @@ android:id="@+id/image_episode" android:layout_width="128dp" android:layout_height="72dp" + android:contentDescription="@string/component_poster_desc" app:srcCompat="@drawable/ic_baseline_account_box_24" /> + + + android:layout_height="wrap_content" + android:maxLines="2" + android:ellipsize="end"/> \ No newline at end of file diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index d744835..a177454 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -12,6 +12,7 @@ Abspielen %1$d Episoden %1$d Minuten + Episode %1$d %2$s Account diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0176503..63f1dc7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,6 +16,9 @@ 6 %1$d episodes %1$d Minutes + Episode %1$d %2$s + episode poster + already watched Account