add tv shows support to parser, start implementing account fragment

This commit is contained in:
2020-10-11 23:16:47 +02:00
parent b27a218b51
commit 7b708f5aa0
18 changed files with 330 additions and 65 deletions

View File

@ -79,7 +79,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
Log.i(javaClass.name, "please login!")
LoginDialog(this).positiveButton {
EncryptedPreferences.saveCredentials(email, password, context)
EncryptedPreferences.saveCredentials(login, password, context)
}.negativeButton {
Log.i(javaClass.name, "Login canceled, exiting.")
finish()
@ -88,17 +88,14 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
}
fun showDetailFragment(media: GUIMedia) {
val streams = AoDParser().loadStreams(media.link) // load the streams for the selected media
val streamMedia = AoDParser().loadStreams(media.link) // load the streams for the selected media
val mediaFragment = MediaFragment(media, streams)
val mediaFragment = MediaFragment(media, streamMedia)
supportFragmentManager.commit {
add(R.id.nav_host_fragment, mediaFragment, "MediaFragment")
addToBackStack(null)
show(mediaFragment)
}
println("visible !!!: " + mediaFragment.isVisible)
println(supportFragmentManager.backStackEntryCount)
}
fun startPlayer(streamUrl: String) {

View File

@ -1,11 +1,15 @@
package org.mosad.teapod.parser
import android.util.Log
import com.google.gson.JsonParser
import kotlinx.coroutines.*
import org.jsoup.Connection
import org.jsoup.Jsoup
import org.mosad.teapod.preferences.EncryptedPreferences
import org.mosad.teapod.util.DataTypes.MediaType
import org.mosad.teapod.util.GUIMedia
import org.mosad.teapod.util.StreamMedia
import kotlin.collections.ArrayList
class AoDParser {
@ -60,7 +64,9 @@ class AoDParser {
}
}
// https://www.anime-on-demand.de/animes
/**
* list all animes from the website
*/
fun listAnimes(): ArrayList<GUIMedia> = runBlocking {
if (sessionCookies.isEmpty()) login()
@ -92,12 +98,12 @@ class AoDParser {
/**
* load streams for the media path
*/
fun loadStreams(mediaPath: String): List<String> = runBlocking {
fun loadStreams(mediaPath: String): StreamMedia = runBlocking {
if (sessionCookies.isEmpty()) login()
if (!loginSuccess) {
println("please log in") // TODO
return@runBlocking listOf()
return@runBlocking StreamMedia(MediaType.OTHER)
}
withContext(Dispatchers.Default) {
@ -114,14 +120,20 @@ class AoDParser {
//println("first entry: ${playlists.first()}")
//println("csrf token is: $csrfToken")
return@withContext loadStreamInfo(playlists.first(), csrfToken)
val type = if (res.select("h2").eachText().filter { it == "Episoden" }.any()) {
MediaType.TVSHOW
} else {
MediaType.MOVIE
}
return@withContext loadStreamInfo(playlists.first(), csrfToken, type)
}
}
/**
* load the playlist path and parse it, read the stream info from json
*/
private fun loadStreamInfo(playlistPath: String, csrfToken: String): List<String> = runBlocking {
private fun loadStreamInfo(playlistPath: String, csrfToken: String, type: MediaType): StreamMedia = runBlocking {
withContext(Dispatchers.Default) {
val headers = mutableMapOf(
Pair("Accept", "application/json, text/javascript, */*; q=0.01"),
@ -139,13 +151,37 @@ class AoDParser {
//println(res.body())
// TODO if it's a series there sources for each episode
val sources = JsonParser.parseString(res.body()).asJsonObject
.get("playlist").asJsonArray.first().asJsonObject
.get("sources").asJsonArray
println(type)
return@withContext when (type) {
MediaType.MOVIE -> {
val movie = JsonParser.parseString(res.body()).asJsonObject
.get("playlist").asJsonArray
return@withContext sources.toList().map {
it.asJsonObject.get("file").asString
val streamList = arrayListOf<String>()
movie.first().asJsonObject.get("sources").asJsonArray.toList().forEach {
streamList.add(it.asJsonObject.get("file").asString)
}
StreamMedia(MediaType.MOVIE, streamList)
}
MediaType.TVSHOW -> {
val episodes = JsonParser.parseString(res.body()).asJsonObject
.get("playlist").asJsonArray
val streamList = arrayListOf<String>()
episodes.forEach {
val streamUrl = it.asJsonObject.get("sources").asJsonArray
.first().asJsonObject
.get("file").asString
streamList.add(streamUrl)
}
StreamMedia(MediaType.TVSHOW, streamList)
}
else -> {
Log.e(javaClass.name, "Wrong Type, please report this issue.")
StreamMedia(MediaType.OTHER)
}
}
}
}

View File

@ -1,19 +1,23 @@
package org.mosad.teapod.ui
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.fragment_media.*
import org.mosad.teapod.MainActivity
import org.mosad.teapod.R
import org.mosad.teapod.util.DataTypes.MediaType
import org.mosad.teapod.util.GUIMedia
import java.net.URL
import java.net.URLEncoder
import org.mosad.teapod.util.StreamMedia
class MediaFragment(val media: GUIMedia, val streams: List<String>) : Fragment() {
class MediaFragment(private val guiMedia: GUIMedia, private val streamMedia: StreamMedia) : Fragment() {
private lateinit var adapterEpisodes: ArrayAdapter<String>
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_media, container, false)
@ -22,25 +26,51 @@ class MediaFragment(val media: GUIMedia, val streams: List<String>) : Fragment()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// load poster
Glide.with(requireContext()).load(media.posterLink).into(image_poster)
text_title.text = media.title
text_desc.text = media.shortDesc
// generic gui
Glide.with(requireContext()).load(guiMedia.posterLink).into(image_poster)
text_title.text = guiMedia.title
text_desc.text = guiMedia.shortDesc
println("media streams: $streams")
// specific gui
if (streamMedia.type == MediaType.TVSHOW) {
val episodes = streamMedia.streams.mapIndexed { index, _ ->
"${guiMedia.title} - Ep. ${index + 1}"
}
adapterEpisodes = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, episodes)
list_episodes.adapter = adapterEpisodes
} else if (streamMedia.type == MediaType.MOVIE) {
list_episodes.visibility = View.GONE
}
println("media streams: ${streamMedia.streams}")
initActions()
}
private fun initActions() {
button_play.setOnClickListener { onClickButtonPlay() }
button_play.setOnClickListener {
onClickButtonPlay()
}
list_episodes.setOnItemClickListener { _, _, position, _ ->
playStream(streamMedia.streams[position])
}
}
private fun onClickButtonPlay() {
println("play ${streams.first()}")
when (streamMedia.type) {
MediaType.MOVIE -> playStream(streamMedia.streams.first())
MediaType.TVSHOW -> playStream(streamMedia.streams.first())
MediaType.OTHER -> Log.e(javaClass.name, "Wrong Type, please report this issue.")
}
}
private fun playStream(url: String) {
val mainActivity = activity as MainActivity
mainActivity.startPlayer(streams.first())
mainActivity.startPlayer(url)
}
}

View File

@ -5,8 +5,12 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.afollestad.materialdialogs.MaterialDialog
import kotlinx.android.synthetic.main.fragment_account.*
import org.mosad.teapod.BuildConfig
import org.mosad.teapod.R
import org.mosad.teapod.preferences.EncryptedPreferences
import org.mosad.teapod.ui.components.LoginDialog
class AccountFragment : Fragment() {
@ -17,6 +21,27 @@ class AccountFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
text_account.text = "This is the Account Fragment"
text_account_login.text = EncryptedPreferences.login
text_info_about_desc.text = getString(R.string.info_about_desc, BuildConfig.VERSION_NAME, getString(R.string.build_time))
initActions()
}
private fun initActions() {
linear_account_login.setOnClickListener {
LoginDialog(requireContext()).positiveButton {
EncryptedPreferences.saveCredentials(login, password, context)
}.show {
login = EncryptedPreferences.login
password = ""
}
}
linear_about.setOnClickListener {
MaterialDialog(requireContext())
.title(R.string.info_about)
.message(R.string.info_about_dialog)
.show()
}
}
}

View File

@ -25,8 +25,6 @@ package org.mosad.teapod.ui.components
import android.content.Context
import android.widget.EditText
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.WhichButton
import com.afollestad.materialdialogs.actions.getActionButton
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
import com.afollestad.materialdialogs.bottomsheets.setPeekHeight
import com.afollestad.materialdialogs.customview.customView
@ -40,7 +38,7 @@ class LoginDialog(val context: Context) {
private val editTextLogin: EditText
private val editTextPassword: EditText
var email = ""
var login = ""
var password = ""
init {
@ -61,7 +59,7 @@ class LoginDialog(val context: Context) {
fun positiveButton(func: LoginDialog.() -> Unit): LoginDialog = apply {
dialog.positiveButton {
email = editTextLogin.text.toString()
login = editTextLogin.text.toString()
password = editTextPassword.text.toString()
func()
@ -81,7 +79,7 @@ class LoginDialog(val context: Context) {
fun show(func: LoginDialog.() -> Unit): LoginDialog = apply {
func()
editTextLogin.setText(email)
editTextLogin.setText(login)
editTextPassword.setText(password)
show()

View File

@ -19,7 +19,5 @@ class HomeFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
text_home.text = "This is the home fragment"
println("HomeFragment created")
}
}

View File

@ -48,10 +48,8 @@ class SearchFragment : Fragment() {
}
override fun onQueryTextChange(newText: String?): Boolean {
println("new text is: $newText")
adapter.filter.filter(newText)
adapter.notifyDataSetChanged()
return false
}
})

View File

@ -20,10 +20,6 @@ class CustomAdapter(val context: Context, private val originalMedia: ArrayList<G
private var filteredMedia = originalMedia.map { it.copy() }
private val customFilter = CustomFilter()
init {
println("initial filtered size is: ${filteredMedia.size}")
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: LayoutInflater.from(context).inflate(R.layout.linear_media, parent, false)
@ -68,8 +64,6 @@ class CustomAdapter(val context: Context, private val originalMedia: ArrayList<G
results.values = filteredList
results.count = filteredList.size
println("filtered size is: ${results.count}")
return results
}

View File

@ -1,7 +1,17 @@
package org.mosad.teapod.util
class DataTypes {
enum class MediaType {
OTHER,
MOVIE,
TVSHOW
}
}
data class GUIMedia(val title: String, val posterLink: String, val shortDesc : String, val link: String) {
override fun toString(): String {
return title
}
}
}
data class StreamMedia(val type: DataTypes.MediaType, val streams: ArrayList<String> = arrayListOf())