diff --git a/app/build.gradle b/app/build.gradle index 11b8dd6..6051734 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,6 +14,7 @@ android { versionName "0.1-alpha1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + resValue "string", "build_time", buildTime() setProperty("archivesBaseName", "teapod-$versionName") } @@ -62,4 +63,8 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' +} + +static def buildTime() { + return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC")) } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/MainActivity.kt b/app/src/main/java/org/mosad/teapod/MainActivity.kt index 9ad41d5..48ffbe2 100644 --- a/app/src/main/java/org/mosad/teapod/MainActivity.kt +++ b/app/src/main/java/org/mosad/teapod/MainActivity.kt @@ -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) { 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 705ceeb..04600eb 100644 --- a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt +++ b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt @@ -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 = runBlocking { if (sessionCookies.isEmpty()) login() @@ -92,12 +98,12 @@ class AoDParser { /** * load streams for the media path */ - fun loadStreams(mediaPath: String): List = 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 = 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() + 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() + 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) + } } } } diff --git a/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt b/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt index 8fba103..dd91182 100644 --- a/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt @@ -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) : Fragment() { +class MediaFragment(private val guiMedia: GUIMedia, private val streamMedia: StreamMedia) : Fragment() { + + private lateinit var adapterEpisodes: ArrayAdapter 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) : 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) } } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/ui/account/AccountFragment.kt b/app/src/main/java/org/mosad/teapod/ui/account/AccountFragment.kt index b3b3c7f..0f0713e 100644 --- a/app/src/main/java/org/mosad/teapod/ui/account/AccountFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/account/AccountFragment.kt @@ -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() + } } } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/ui/components/LoginDialog.kt b/app/src/main/java/org/mosad/teapod/ui/components/LoginDialog.kt index 4466c0a..b521c21 100644 --- a/app/src/main/java/org/mosad/teapod/ui/components/LoginDialog.kt +++ b/app/src/main/java/org/mosad/teapod/ui/components/LoginDialog.kt @@ -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() diff --git a/app/src/main/java/org/mosad/teapod/ui/home/HomeFragment.kt b/app/src/main/java/org/mosad/teapod/ui/home/HomeFragment.kt index c936b14..1aa3936 100644 --- a/app/src/main/java/org/mosad/teapod/ui/home/HomeFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/home/HomeFragment.kt @@ -19,7 +19,5 @@ class HomeFragment : Fragment() { super.onViewCreated(view, savedInstanceState) text_home.text = "This is the home fragment" - - println("HomeFragment created") } } \ No newline at end of file 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 8a3aab0..bd4e46a 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 @@ -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 } }) diff --git a/app/src/main/java/org/mosad/teapod/util/CustomAdapter.kt b/app/src/main/java/org/mosad/teapod/util/CustomAdapter.kt index ebcb3fa..4be1472 100644 --- a/app/src/main/java/org/mosad/teapod/util/CustomAdapter.kt +++ b/app/src/main/java/org/mosad/teapod/util/CustomAdapter.kt @@ -20,10 +20,6 @@ class CustomAdapter(val context: Context, private val originalMedia: ArrayList = arrayListOf()) \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_baseline_info_24.xml b/app/src/main/res/drawable/ic_baseline_info_24.xml new file mode 100644 index 0000000..17255b7 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_info_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml b/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml new file mode 100644 index 0000000..13c137a --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_account.xml b/app/src/main/res/layout/fragment_account.xml index bf02d59..eb99b63 100644 --- a/app/src/main/res/layout/fragment_account.xml +++ b/app/src/main/res/layout/fragment_account.xml @@ -4,20 +4,144 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="#fafafa" + android:background="#f5f5f5" tools:context=".ui.account.AccountFragment"> - + android:layout_height="match_parent"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 8c2300d..7948aea 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="#fafafa" + android:background="#f5f5f5" tools:context=".ui.home.HomeFragment"> @@ -57,5 +67,13 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/text_title" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index d3c3180..d2ef82e 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="#fafafa" + android:background="#f5f5f5" tools:context=".ui.search.SearchFragment"> Search for movies and series + + Play + + + Account + user@example.com + Tap to edit + Info + Teapod by @Seil0 + Version %1$s (%2$s) + This software is published under the terms and conditions of GPL 3. For further information visit git.mosad.xyz/Seil0 \n\n© 2020 seil0@mosad.xyz + save @android:string/cancel