added episode description and is watched status to MediaFragment
This commit is contained in:
		| @ -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<Episode> = runBlocking { | ||||
|     private fun loadStreamInfo(playlistPath: String, csrfToken: String, type: MediaType, episodes: List<Episode>): List<Episode> = 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 | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -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() | ||||
|  | ||||
| @ -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 | ||||
| ) | ||||
|  | ||||
| @ -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<Episode>, private val context: Context) : RecyclerView.Adapter<EpisodesAdapter.MyViewHolder>() { | ||||
| class EpisodesAdapter(private val episodes: List<Episode>, private val context: Context) : RecyclerView.Adapter<EpisodesAdapter.MyViewHolder>() { | ||||
|  | ||||
|     var onItemClick: ((String, Int) -> Unit)? = null | ||||
|  | ||||
| @ -20,21 +20,30 @@ class EpisodesAdapter(private val data: List<Episode>, 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) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
							
								
								
									
										10
									
								
								app/src/main/res/drawable/ic_baseline_check_circle_24.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								app/src/main/res/drawable/ic_baseline_check_circle_24.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24" | ||||
|     android:tint="?attr/colorControlNormal"> | ||||
|   <path | ||||
|       android:fillColor="@android:color/white" | ||||
|       android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/> | ||||
| </vector> | ||||
| @ -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" /> | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/text_episode_title" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_width="0dp" | ||||
|             android:layout_height="match_parent" | ||||
|             android:layout_marginStart="7dp" | ||||
|             android:layout_weight="1" | ||||
|             android:text="TextView" | ||||
|             android:text="@string/component_episode_title" | ||||
|             android:textSize="16sp" /> | ||||
|  | ||||
|         <ImageView | ||||
|             android:id="@+id/image_watched" | ||||
|             android:layout_width="30dp" | ||||
|             android:layout_height="30dp" | ||||
|             android:layout_margin="2dp" | ||||
|             android:contentDescription="@string/component_watched_desc" | ||||
|             app:srcCompat="@drawable/ic_baseline_check_circle_24" /> | ||||
|     </LinearLayout> | ||||
|  | ||||
|     <TextView | ||||
|         android:id="@+id/text_episode_desc" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" /> | ||||
|         android:layout_height="wrap_content" | ||||
|         android:maxLines="2" | ||||
|         android:ellipsize="end"/> | ||||
| </LinearLayout> | ||||
| @ -12,6 +12,7 @@ | ||||
|     <string name="button_play">Abspielen</string> | ||||
|     <string name="text_episodes_count">%1$d Episoden</string> | ||||
|     <string name="text_runtime">%1$d Minuten</string> | ||||
|     <string name="component_episode_title">Episode %1$d %2$s</string> | ||||
|  | ||||
|     <!-- settings fragment --> | ||||
|     <string name="account">Account</string> | ||||
|  | ||||
| @ -16,6 +16,9 @@ | ||||
|     <string name="text_age_ex" translatable="false">6</string> | ||||
|     <string name="text_episodes_count">%1$d episodes</string> | ||||
|     <string name="text_runtime">%1$d Minutes</string> | ||||
|     <string name="component_episode_title">Episode %1$d %2$s</string> | ||||
|     <string name="component_poster_desc" translatable="false">episode poster</string> | ||||
|     <string name="component_watched_desc" translatable="false">already watched</string> | ||||
|  | ||||
|     <!-- settings fragment --> | ||||
|     <string name="account">Account</string> | ||||
|  | ||||
		Reference in New Issue
	
	Block a user