fix #9 & replace my list checkbox with layout for easier gui building

This commit is contained in:
Jannik 2020-10-16 18:24:34 +02:00
parent d912ed34a3
commit 5458b43354
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
8 changed files with 81 additions and 67 deletions

View File

@ -11,7 +11,6 @@ import org.mosad.teapod.util.Episode
import org.mosad.teapod.util.Media import org.mosad.teapod.util.Media
import java.io.IOException import java.io.IOException
import java.util.* import java.util.*
import kotlin.collections.ArrayList
/** /**
* maybe AoDParser as object would be useful * maybe AoDParser as object would be useful
@ -43,8 +42,8 @@ class AoDParser {
val authenticityToken = resAuth.parse().select("meta[name=csrf-token]").attr("content") val authenticityToken = resAuth.parse().select("meta[name=csrf-token]").attr("content")
val authCookies = resAuth.cookies() val authCookies = resAuth.cookies()
Log.i(javaClass.name, "Received authenticity token: $authenticityToken") //Log.d(javaClass.name, "Received authenticity token: $authenticityToken")
Log.i(javaClass.name, "Received authenticity cookies: $authCookies") //Log.d(javaClass.name, "Received authenticity cookies: $authCookies")
val data = mapOf( val data = mapOf(
Pair("user[login]", EncryptedPreferences.login), Pair("user[login]", EncryptedPreferences.login),
@ -62,6 +61,7 @@ class AoDParser {
.execute() .execute()
//println(resLogin.body()) //println(resLogin.body())
sessionCookies = resLogin.cookies() sessionCookies = resLogin.cookies()
loginSuccess = resLogin.body().contains("Hallo, du bist jetzt angemeldet.") loginSuccess = resLogin.body().contains("Hallo, du bist jetzt angemeldet.")
Log.i(javaClass.name, "Status: ${resLogin.statusCode()} (${resLogin.statusMessage()}), login successful: $loginSuccess") Log.i(javaClass.name, "Status: ${resLogin.statusCode()} (${resLogin.statusMessage()}), login successful: $loginSuccess")
@ -167,14 +167,12 @@ class AoDParser {
if (csrfToken.isEmpty()) { if (csrfToken.isEmpty()) {
csrfToken = res.select("meta[name=csrf-token]").attr("content") csrfToken = res.select("meta[name=csrf-token]").attr("content")
//Log.i(javaClass.name, "New csrf token is $csrfToken")
} }
// has attr data-lag (ger or jap) // TODO has attr data-lag (ger or jap)
val playlists = res.select("input.streamstarter_html5").eachAttr("data-playlist") val playlists = res.select("input.streamstarter_html5").eachAttr("data-playlist")
//println("first entry: ${playlists.first()}")
//println("csrf token is: $csrfToken")
return@withContext if (playlists.size > 0) { return@withContext if (playlists.size > 0) {
loadStreamInfo(playlists.first(), csrfToken, media.type, episodes) loadStreamInfo(playlists.first(), csrfToken, media.type, episodes)
} else { } else {
@ -197,7 +195,7 @@ class AoDParser {
Pair("X-Requested-With", "XMLHttpRequest"), Pair("X-Requested-With", "XMLHttpRequest"),
) )
println("loading streaminfo with cstf: $csrfToken") //println("loading streaminfo with cstf: $csrfToken")
val res = Jsoup.connect(baseUrl + playlistPath) val res = Jsoup.connect(baseUrl + playlistPath)
.ignoreContentType(true) .ignoreContentType(true)
@ -262,13 +260,15 @@ class AoDParser {
) )
try { try {
Jsoup.connect(baseUrl + callbackPath) withContext(Dispatchers.IO) {
.ignoreContentType(true) Jsoup.connect(baseUrl + callbackPath)
.cookies(sessionCookies) .ignoreContentType(true)
.headers(headers) .cookies(sessionCookies)
.execute() .headers(headers)
.execute()
}
} catch (ex: IOException) { } catch (ex: IOException) {
Log.e(javaClass.name, "Callback for $callbackPath failed.") Log.e(javaClass.name, "Callback for $callbackPath failed.", ex)
} }
} }

View File

@ -4,10 +4,10 @@ import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.fragment.app.Fragment
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 androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
@ -17,11 +17,11 @@ import kotlinx.android.synthetic.main.fragment_media.*
import org.mosad.teapod.MainActivity import org.mosad.teapod.MainActivity
import org.mosad.teapod.R import org.mosad.teapod.R
import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.parser.AoDParser
import org.mosad.teapod.util.StorageController
import org.mosad.teapod.util.DataTypes.MediaType import org.mosad.teapod.util.DataTypes.MediaType
import org.mosad.teapod.util.adapter.EpisodeItemAdapter
import org.mosad.teapod.util.Media import org.mosad.teapod.util.Media
import org.mosad.teapod.util.StorageController
import org.mosad.teapod.util.TMDBResponse import org.mosad.teapod.util.TMDBResponse
import org.mosad.teapod.util.adapter.EpisodeItemAdapter
class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) : Fragment() { class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) : Fragment() {
@ -60,11 +60,15 @@ class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) :
text_year.text = media.info.year.toString() text_year.text = media.info.year.toString()
text_age.text = media.info.age.toString() text_age.text = media.info.age.toString()
text_overview.text = media.info.shortDesc text_overview.text = media.info.shortDesc
check_my_list.isChecked = StorageController.myList.contains(media.link) if (StorageController.myList.contains(media.link)) {
Glide.with(requireContext()).load(R.drawable.ic_baseline_check_24).into(image_my_list_action)
} else {
Glide.with(requireContext()).load(R.drawable.ic_baseline_add_24).into(image_my_list_action)
}
// specific gui // specific gui
if (media.type == MediaType.TVSHOW) { if (media.type == MediaType.TVSHOW) {
adapterRecEpisodes = EpisodeItemAdapter(media.episodes, requireContext()) adapterRecEpisodes = EpisodeItemAdapter(media.episodes)
viewManager = LinearLayoutManager(context) viewManager = LinearLayoutManager(context)
recycler_episodes.layoutManager = viewManager recycler_episodes.layoutManager = viewManager
recycler_episodes.adapter = adapterRecEpisodes recycler_episodes.adapter = adapterRecEpisodes
@ -91,15 +95,16 @@ class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) :
} }
// add or remove media from myList // add or remove media from myList
check_my_list.setOnCheckedChangeListener { _, isChecked -> linear_my_list_action.setOnClickListener {
if (isChecked) { if (StorageController.myList.contains(media.link)) {
StorageController.myList.add(media.link)
} else {
StorageController.myList.remove(media.link) StorageController.myList.remove(media.link)
Glide.with(requireContext()).load(R.drawable.ic_baseline_add_24).into(image_my_list_action)
} else {
StorageController.myList.add(media.link)
Glide.with(requireContext()).load(R.drawable.ic_baseline_check_24).into(image_my_list_action)
} }
StorageController.saveMyList(requireContext())
// TODO notify home fragment on change // notify home fragment on change
parentFragmentManager.findFragmentByTag("HomeFragment")?.let { parentFragmentManager.findFragmentByTag("HomeFragment")?.let {
(it as HomeFragment).updateMyListMedia() (it as HomeFragment).updateMyListMedia()
} }
@ -119,11 +124,8 @@ class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) :
} }
private fun playStream(url: String) { private fun playStream(url: String) {
val mainActivity = activity as MainActivity Log.d(javaClass.name, "Playing stream: $url")
(activity as MainActivity).startPlayer(url)
println("url is: $url")
mainActivity.startPlayer(url)
} }
} }

View File

@ -1,9 +1,9 @@
package org.mosad.teapod.util.adapter package org.mosad.teapod.util.adapter
import android.content.Context
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 androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
@ -12,7 +12,7 @@ import kotlinx.android.synthetic.main.item_episode.view.*
import org.mosad.teapod.R import org.mosad.teapod.R
import org.mosad.teapod.util.Episode import org.mosad.teapod.util.Episode
class EpisodeItemAdapter(private val episodes: List<Episode>, private val context: Context) : RecyclerView.Adapter<EpisodeItemAdapter.MyViewHolder>() { class EpisodeItemAdapter(private val episodes: List<Episode>) : RecyclerView.Adapter<EpisodeItemAdapter.MyViewHolder>() {
var onItemClick: ((String, Int) -> Unit)? = null var onItemClick: ((String, Int) -> Unit)? = null
var onImageClick: ((String, Int) -> Unit)? = null var onImageClick: ((String, Int) -> Unit)? = null
@ -24,6 +24,8 @@ class EpisodeItemAdapter(private val episodes: List<Episode>, private val contex
} }
override fun onBindViewHolder(holder: MyViewHolder, position: Int) { override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val context = holder.view.context
holder.view.text_episode_title.text = context.getString( holder.view.text_episode_title.text = context.getString(
R.string.component_episode_title, R.string.component_episode_title,
episodes[position].number, episodes[position].number,
@ -37,7 +39,11 @@ class EpisodeItemAdapter(private val episodes: List<Episode>, private val contex
.into(holder.view.image_episode) .into(holder.view.image_episode)
} }
if (!episodes[position].watched) { if (episodes[position].watched) {
holder.view.image_watched.setImageDrawable(
ContextCompat.getDrawable(context, R.drawable.ic_baseline_check_circle_24)
)
} else {
holder.view.image_watched.setImageDrawable(null) holder.view.image_watched.setImageDrawable(null)
} }
} }

View File

@ -6,5 +6,5 @@
android:tint="?attr/colorControlNormal"> android:tint="?attr/colorControlNormal">
<path <path
android:fillColor="@android:color/white" android:fillColor="@android:color/white"
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/> android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector> </vector>

View 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="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>

View File

@ -1,10 +0,0 @@
<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="M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3 4.42,3 2,5.42 2,8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5 22,5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1 -0.1,-0.1C7.14,14.24 4,11.39 4,8.5 4,6.5 5.5,5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5 0,2.89 -3.14,5.74 -7.9,10.05z"/>
</vector>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/ic_baseline_favorite_border_24"
android:state_checked="false" />
<item
android:drawable="@drawable/ic_baseline_favorite_24"
android:state_checked="true" />
<item
android:drawable="@drawable/ic_baseline_favorite_border_24" />
</selector>

View File

@ -113,19 +113,36 @@
android:layout_marginEnd="12dp" android:layout_marginEnd="12dp"
android:text="@string/text_overview_ex" /> android:text="@string/text_overview_ex" />
<CheckBox <LinearLayout
android:id="@+id/check_my_list" android:id="@+id/linear_actions"
android:layout_width="48dp" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="match_parent"
android:layout_marginStart="12dp"
android:layout_marginStart="31dp"
android:layout_marginTop="7dp" android:layout_marginTop="7dp"
android:layout_marginEnd="7dp" android:layout_marginEnd="12dp"
android:layout_marginBottom="7dp" android:orientation="horizontal">
android:button="@drawable/sl_favourite_24dp"
android:scaleX="2.0" <LinearLayout
android:scaleY="2.0" android:id="@+id/linear_my_list_action"
app:buttonTint="#4A4141" /> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/image_my_list_action"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_baseline_add_24"
app:tint="#4A4141" />
<TextView
android:id="@+id/text_my_list_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/my_list" />
</LinearLayout>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_episodes" android:id="@+id/recycler_episodes"