add media fragment, add stream parsing
This commit is contained in:
		| @ -38,7 +38,8 @@ dependencies { | |||||||
|     implementation 'androidx.core:core-ktx:1.3.2' |     implementation 'androidx.core:core-ktx:1.3.2' | ||||||
|     implementation 'androidx.appcompat:appcompat:1.2.0' |     implementation 'androidx.appcompat:appcompat:1.2.0' | ||||||
|     implementation 'com.google.android.material:material:1.2.1' |     implementation 'com.google.android.material:material:1.2.1' | ||||||
|     implementation 'androidx.constraintlayout:constraintlayout:2.0.1' |     implementation 'com.google.code.gson:gson:2.8.6' | ||||||
|  |     implementation 'androidx.constraintlayout:constraintlayout:2.0.2' | ||||||
|     implementation 'androidx.navigation:navigation-fragment:2.3.0' |     implementation 'androidx.navigation:navigation-fragment:2.3.0' | ||||||
|     implementation 'androidx.navigation:navigation-ui:2.3.0' |     implementation 'androidx.navigation:navigation-ui:2.3.0' | ||||||
|     implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' |     implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' | ||||||
| @ -49,6 +50,7 @@ dependencies { | |||||||
|     implementation 'com.github.bumptech.glide:glide:4.11.0' |     implementation 'com.github.bumptech.glide:glide:4.11.0' | ||||||
|     implementation 'androidx.legacy:legacy-support-v4:1.0.0' |     implementation 'androidx.legacy:legacy-support-v4:1.0.0' | ||||||
|     implementation 'androidx.recyclerview:recyclerview:1.1.0' |     implementation 'androidx.recyclerview:recyclerview:1.1.0' | ||||||
|  |     implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' | ||||||
|  |  | ||||||
|     testImplementation 'junit:junit:4.12' |     testImplementation 'junit:junit:4.12' | ||||||
|     androidTestImplementation 'androidx.test.ext:junit:1.1.2' |     androidTestImplementation 'androidx.test.ext:junit:1.1.2' | ||||||
|  | |||||||
| @ -1,7 +1,8 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|     package="org.mosad.teapod"> |     package="org.mosad.teapod"> | ||||||
|     <uses-permission android:name="android.permission.INTERNET"/> |  | ||||||
|  |     <uses-permission android:name="android.permission.INTERNET" /> | ||||||
|  |  | ||||||
|     <application |     <application | ||||||
|         android:allowBackup="true" |         android:allowBackup="true" | ||||||
|  | |||||||
| @ -1,35 +1,88 @@ | |||||||
| package org.mosad.teapod | package org.mosad.teapod | ||||||
|  |  | ||||||
| import android.os.Bundle | import android.os.Bundle | ||||||
|  | import android.view.MenuItem | ||||||
| import com.google.android.material.bottomnavigation.BottomNavigationView | import com.google.android.material.bottomnavigation.BottomNavigationView | ||||||
| import androidx.appcompat.app.AppCompatActivity | import androidx.appcompat.app.AppCompatActivity | ||||||
| import androidx.navigation.findNavController | import androidx.fragment.app.Fragment | ||||||
| import androidx.navigation.ui.AppBarConfiguration | import androidx.fragment.app.commit | ||||||
| import androidx.navigation.ui.setupActionBarWithNavController | import kotlinx.android.synthetic.main.activity_main.* | ||||||
| import androidx.navigation.ui.setupWithNavController |  | ||||||
| import kotlinx.coroutines.GlobalScope |  | ||||||
| import kotlinx.coroutines.launch |  | ||||||
| import org.mosad.teapod.parser.AoDParser | import org.mosad.teapod.parser.AoDParser | ||||||
|  | import org.mosad.teapod.ui.MediaFragment | ||||||
|  | import org.mosad.teapod.ui.account.AccountFragment | ||||||
|  | import org.mosad.teapod.ui.home.HomeFragment | ||||||
|  | import org.mosad.teapod.ui.library.LibraryFragment | ||||||
|  | import org.mosad.teapod.ui.search.SearchFragment | ||||||
|  | import org.mosad.teapod.util.GUIMedia | ||||||
|  |  | ||||||
| class MainActivity : AppCompatActivity() { | class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener { | ||||||
|  |  | ||||||
|  |     private var activeFragment: Fragment = HomeFragment() // the currently active fragment, home at the start | ||||||
|  |  | ||||||
|     override fun onCreate(savedInstanceState: Bundle?) { |     override fun onCreate(savedInstanceState: Bundle?) { | ||||||
|         super.onCreate(savedInstanceState) |         super.onCreate(savedInstanceState) | ||||||
|         setContentView(R.layout.activity_main) |         setContentView(R.layout.activity_main) | ||||||
|         val navView: BottomNavigationView = findViewById(R.id.nav_view) |         val navView: BottomNavigationView = findViewById(R.id.nav_view) | ||||||
|  |         navView.setOnNavigationItemSelectedListener(this) | ||||||
|         val navController = findNavController(R.id.nav_host_fragment) |  | ||||||
|         // Passing each menu ID as a set of Ids because each |  | ||||||
|         // menu should be considered as top level destinations. |  | ||||||
|         val appBarConfiguration = AppBarConfiguration(setOf( |  | ||||||
|                 R.id.navigation_home, R.id.navigation_library, R.id.navigation_search)) |  | ||||||
|         setupActionBarWithNavController(navController, appBarConfiguration) |  | ||||||
|         navView.setupWithNavController(navController) |  | ||||||
|  |  | ||||||
|         load() |         load() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     override fun onBackPressed() { | ||||||
|  |         if (supportFragmentManager.backStackEntryCount > 0) { | ||||||
|  |             supportFragmentManager.popBackStack() | ||||||
|  |         } else { | ||||||
|  |             if (activeFragment !is HomeFragment) { | ||||||
|  |                 nav_view.selectedItemId = R.id.navigation_home | ||||||
|  |             } else { | ||||||
|  |                 super.onBackPressed() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun onNavigationItemSelected(item: MenuItem): Boolean { | ||||||
|  |         val ret = when (item.itemId) { | ||||||
|  |             R.id.navigation_home -> { | ||||||
|  |                 activeFragment = HomeFragment() | ||||||
|  |                 true | ||||||
|  |             } | ||||||
|  |             R.id.navigation_library -> { | ||||||
|  |                 activeFragment = LibraryFragment() | ||||||
|  |                 true | ||||||
|  |             } | ||||||
|  |             R.id.navigation_search -> { | ||||||
|  |                 activeFragment = SearchFragment() | ||||||
|  |                 true | ||||||
|  |             } | ||||||
|  |             R.id.navigation_account -> { | ||||||
|  |                 activeFragment = AccountFragment() | ||||||
|  |                 true | ||||||
|  |             } | ||||||
|  |             else -> false | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         supportFragmentManager.commit { | ||||||
|  |             replace(R.id.nav_host_fragment, activeFragment) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return ret | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private fun load() { |     private fun load() { | ||||||
|         // TODO |         // TODO | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fun showDetailFragment(media: GUIMedia) { | ||||||
|  |         val streams = AoDParser().loadStreams(media.link) // load the streams for the selected media | ||||||
|  |  | ||||||
|  |         val mediaFragment = MediaFragment(media, streams) | ||||||
|  |         supportFragmentManager.commit { | ||||||
|  |             add(R.id.nav_host_fragment, mediaFragment, "MediaFragment") | ||||||
|  |             addToBackStack(null) | ||||||
|  |             show(mediaFragment) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         println("visible !!!: " + mediaFragment.isVisible) | ||||||
|  |         println(supportFragmentManager.backStackEntryCount) | ||||||
|  |     } | ||||||
| } | } | ||||||
| @ -1,7 +1,7 @@ | |||||||
| package org.mosad.teapod.parser | package org.mosad.teapod.parser | ||||||
|  |  | ||||||
|  | import com.google.gson.JsonParser | ||||||
| import kotlinx.coroutines.* | import kotlinx.coroutines.* | ||||||
| import org.json.JSONObject |  | ||||||
| import org.jsoup.Connection | import org.jsoup.Connection | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| import org.mosad.teapod.util.GUIMedia | import org.mosad.teapod.util.GUIMedia | ||||||
| @ -15,8 +15,12 @@ class AoDParser { | |||||||
|     private val login = "" |     private val login = "" | ||||||
|     private val pwd = "" |     private val pwd = "" | ||||||
|  |  | ||||||
|     private var sessionCookies = mutableMapOf<String, String>() |     companion object { | ||||||
|     private var loginSuccess = false |         private var sessionCookies = mutableMapOf<String, String>() | ||||||
|  |         private var loginSuccess = false | ||||||
|  |  | ||||||
|  |         val mediaList = arrayListOf<GUIMedia>() | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private fun login() = runBlocking { |     private fun login() = runBlocking { | ||||||
|  |  | ||||||
| @ -63,14 +67,14 @@ class AoDParser { | |||||||
|         if (sessionCookies.isEmpty()) login() |         if (sessionCookies.isEmpty()) login() | ||||||
|  |  | ||||||
|         withContext(Dispatchers.Default) { |         withContext(Dispatchers.Default) { | ||||||
|             val res = Jsoup.connect("$baseURL/animes") |             val resAnimes = Jsoup.connect("$baseURL/animes") | ||||||
|                 .cookies(sessionCookies) |                 .cookies(sessionCookies) | ||||||
|                 .get() |                 .get() | ||||||
|  |  | ||||||
|             //println(res) |             //println(resAnimes) | ||||||
|  |  | ||||||
|             val animes = arrayListOf<GUIMedia>() |             mediaList.clear() | ||||||
|             res.select("div.animebox").forEach { |             resAnimes.select("div.animebox").forEach { | ||||||
|                 val media = GUIMedia( |                 val media = GUIMedia( | ||||||
|                     it.select("h3.animebox-title").text(), |                     it.select("h3.animebox-title").text(), | ||||||
|                     it.select("p.animebox-image").select("img").attr("src"), |                     it.select("p.animebox-image").select("img").attr("src"), | ||||||
| @ -78,25 +82,27 @@ class AoDParser { | |||||||
|                     it.select("p.animebox-link").select("a").attr("href") |                     it.select("p.animebox-link").select("a").attr("href") | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|                 animes.add(media) |                 mediaList.add(media) | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             println("got ${animes.size} anime") |             println("got ${mediaList.size} anime") | ||||||
|  |  | ||||||
|             return@withContext animes |             return@withContext mediaList | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fun loadDetails(mediaPath: String) = runBlocking { |     /** | ||||||
|  |      * load streams for the media path | ||||||
|  |      */ | ||||||
|  |     fun loadStreams(mediaPath: String): List<String> = runBlocking { | ||||||
|         if (sessionCookies.isEmpty()) login() |         if (sessionCookies.isEmpty()) login() | ||||||
|  |  | ||||||
|         if (!loginSuccess) { |         if (!loginSuccess) { | ||||||
|             println("please log in") |             println("please log in") // TODO | ||||||
|             return@runBlocking |             return@runBlocking listOf() | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         withContext(Dispatchers.Default) { |         withContext(Dispatchers.Default) { | ||||||
|             println(baseURL + mediaPath) |  | ||||||
|  |  | ||||||
|             val res = Jsoup.connect(baseURL + mediaPath) |             val res = Jsoup.connect(baseURL + mediaPath) | ||||||
|                 .cookies(sessionCookies) |                 .cookies(sessionCookies) | ||||||
| @ -105,19 +111,20 @@ class AoDParser { | |||||||
|             //println(res) |             //println(res) | ||||||
|  |  | ||||||
|             val playlists = res.select("input.streamstarter_html5").eachAttr("data-playlist") |             val playlists = res.select("input.streamstarter_html5").eachAttr("data-playlist") | ||||||
|             println(playlists.first()) |  | ||||||
|  |  | ||||||
|             val csrfToken = res.select("meta[name=csrf-token]").attr("content") |             val csrfToken = res.select("meta[name=csrf-token]").attr("content") | ||||||
|             println("csrf token is: $csrfToken") |  | ||||||
|  |  | ||||||
|             loadStreamInfo(playlists.first(), csrfToken) |             //println("first entry: ${playlists.first()}") | ||||||
|  |             //println("csrf token is: $csrfToken") | ||||||
|  |  | ||||||
|  |             return@withContext loadStreamInfo(playlists.first(), csrfToken) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private fun loadStreamInfo(playlistPath: String, csrfToken: String) = runBlocking { |     /** | ||||||
|  |      * load the playlist path and parse it, read the stream info from json | ||||||
|  |      */ | ||||||
|  |     private fun loadStreamInfo(playlistPath: String, csrfToken: String): List<String> = runBlocking { | ||||||
|         withContext(Dispatchers.Default) { |         withContext(Dispatchers.Default) { | ||||||
|             println(baseURL + playlistPath) |  | ||||||
|  |  | ||||||
|             val headers = mutableMapOf( |             val headers = mutableMapOf( | ||||||
|                 Pair("Accept", "application/json, text/javascript, */*; q=0.01"), |                 Pair("Accept", "application/json, text/javascript, */*; q=0.01"), | ||||||
|                 Pair("Accept-Language", "de,en-US;q=0.7,en;q=0.3"), |                 Pair("Accept-Language", "de,en-US;q=0.7,en;q=0.3"), | ||||||
| @ -126,7 +133,6 @@ class AoDParser { | |||||||
|                 Pair("X-Requested-With", "XMLHttpRequest"), |                 Pair("X-Requested-With", "XMLHttpRequest"), | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|  |  | ||||||
|             val res = Jsoup.connect(baseURL + playlistPath) |             val res = Jsoup.connect(baseURL + playlistPath) | ||||||
|                 .ignoreContentType(true) |                 .ignoreContentType(true) | ||||||
|                 .cookies(sessionCookies) |                 .cookies(sessionCookies) | ||||||
| @ -135,16 +141,15 @@ class AoDParser { | |||||||
|  |  | ||||||
|             //println(res.body()) |             //println(res.body()) | ||||||
|  |  | ||||||
|             // TODO replace with gson |             // TODO if it's a series there sources for each episode | ||||||
|             val jsonObject = JSONObject(res.body()) |             val sources = JsonParser.parseString(res.body()).asJsonObject | ||||||
|             val sourcesObject = jsonObject.getJSONArray("playlist").get(0).toString() |                 .get("playlist").asJsonArray.first().asJsonObject | ||||||
|  |                 .get("sources").asJsonArray | ||||||
|  |  | ||||||
|             val sourcesArray = JSONObject(sourcesObject).getJSONArray("sources") |             return@withContext sources.toList().map { | ||||||
|  |                 it.asJsonObject.get("file").toString() | ||||||
|             for (i in 0 until sourcesArray.length()) { |  | ||||||
|                 println(sourcesArray[i].toString()) |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										42
									
								
								app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | |||||||
|  | package org.mosad.teapod.ui | ||||||
|  |  | ||||||
|  | import android.os.Bundle | ||||||
|  | import androidx.fragment.app.Fragment | ||||||
|  | import android.view.LayoutInflater | ||||||
|  | import android.view.View | ||||||
|  | import android.view.ViewGroup | ||||||
|  | import com.bumptech.glide.Glide | ||||||
|  | import kotlinx.android.synthetic.main.fragment_media.* | ||||||
|  | import org.mosad.teapod.R | ||||||
|  | import org.mosad.teapod.util.GUIMedia | ||||||
|  |  | ||||||
|  | class MediaFragment(val media: GUIMedia, val streams: List<String>) : Fragment() { | ||||||
|  |  | ||||||
|  |     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||||
|  |         return inflater.inflate(R.layout.fragment_media, container, false) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     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 | ||||||
|  |  | ||||||
|  |         println("media streams: $streams") | ||||||
|  |  | ||||||
|  |         initActions() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun initActions() { | ||||||
|  |         button_play.setOnClickListener { onClickButtonPlay() } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun onClickButtonPlay() { | ||||||
|  |         println("play ${streams.first()}") | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -27,6 +27,6 @@ class HomeFragment : Fragment() { | |||||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||||
|         super.onViewCreated(view, savedInstanceState) |         super.onViewCreated(view, savedInstanceState) | ||||||
|  |  | ||||||
|         println("created!!!!") |         println("HomeFragment created") | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -5,10 +5,13 @@ 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.fragment.app.Fragment | ||||||
|  | import androidx.fragment.app.commit | ||||||
| import kotlinx.android.synthetic.main.fragment_library.* | import kotlinx.android.synthetic.main.fragment_library.* | ||||||
| import kotlinx.coroutines.* | import kotlinx.coroutines.* | ||||||
|  | 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.ui.MediaFragment | ||||||
| import org.mosad.teapod.util.CustomAdapter | import org.mosad.teapod.util.CustomAdapter | ||||||
| import org.mosad.teapod.util.GUIMedia | import org.mosad.teapod.util.GUIMedia | ||||||
|  |  | ||||||
| @ -19,6 +22,7 @@ class LibraryFragment : Fragment() { | |||||||
|     private var mediaList = arrayListOf<GUIMedia>() |     private var mediaList = arrayListOf<GUIMedia>() | ||||||
|     private lateinit var adapter : CustomAdapter |     private lateinit var adapter : CustomAdapter | ||||||
|  |  | ||||||
|  |  | ||||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { |     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||||
|         return inflater.inflate(R.layout.fragment_library, container, false) |         return inflater.inflate(R.layout.fragment_library, container, false) | ||||||
|     } |     } | ||||||
| @ -27,7 +31,11 @@ class LibraryFragment : Fragment() { | |||||||
|         super.onViewCreated(view, savedInstanceState) |         super.onViewCreated(view, savedInstanceState) | ||||||
|  |  | ||||||
|         GlobalScope.launch { |         GlobalScope.launch { | ||||||
|             mediaList = parser.listAnimes() |             if (AoDParser.mediaList.isEmpty()) { | ||||||
|  |                 AoDParser().listAnimes() | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             mediaList = AoDParser.mediaList | ||||||
|  |  | ||||||
|             // create and set the adapter, needs context |             // create and set the adapter, needs context | ||||||
|             withContext(Dispatchers.Main) { |             withContext(Dispatchers.Main) { | ||||||
| @ -43,14 +51,33 @@ class LibraryFragment : Fragment() { | |||||||
|     private fun initActions() { |     private fun initActions() { | ||||||
|         list_library.setOnItemClickListener { parent, view, position, id -> |         list_library.setOnItemClickListener { parent, view, position, id -> | ||||||
|             println("selected item is: ${mediaList[position]}") |             println("selected item is: ${mediaList[position]}") | ||||||
|             showDetailFragment(mediaList[position]) |             //showDetailFragment(mediaList[position]) | ||||||
|  |  | ||||||
|  |             val mainActivity = activity as MainActivity | ||||||
|  |             mainActivity.showDetailFragment(mediaList[position]) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private fun showDetailFragment(media: GUIMedia) { |     private fun showDetailFragment(media: GUIMedia) { | ||||||
|         parser.loadDetails(media.link) |         val streams = parser.loadStreams(media.link) // load the streams for the selected media | ||||||
|  |         println("done: $streams") | ||||||
|  |  | ||||||
|         println("done") |         // TODO create detail fragment | ||||||
|  |         val mediaFragment = MediaFragment(media, streams) | ||||||
|  |  | ||||||
|  |         activity?.supportFragmentManager?.commit { | ||||||
|  |             add(mediaFragment, "MediaFragment") | ||||||
|  |             addToBackStack(null) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  | //        activity?.supportFragmentManager?.beginTransaction()?.let { | ||||||
|  | //            it.replace(mContainer.id, mediaFragment, "MediaFragment") | ||||||
|  | //            it.addToBackStack("MediaFragment") | ||||||
|  | //            it.commit() | ||||||
|  | //        } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         println("done!!!") | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -1,22 +1,23 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
| xmlns:app="http://schemas.android.com/apk/res-auto" |     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||||
| xmlns:tools="http://schemas.android.com/tools" |     xmlns:tools="http://schemas.android.com/tools" | ||||||
| android:layout_width="match_parent" |  | ||||||
| android:layout_height="match_parent" |  | ||||||
| tools:context=".ui.account.AccountFragment"> |  | ||||||
|  |  | ||||||
| <TextView |  | ||||||
|     android:id="@+id/text_account" |  | ||||||
|     android:layout_width="match_parent" |     android:layout_width="match_parent" | ||||||
|     android:layout_height="wrap_content" |     android:layout_height="match_parent" | ||||||
|     android:layout_marginStart="8dp" |     android:background="#fafafa" | ||||||
|     android:layout_marginTop="8dp" |     tools:context=".ui.account.AccountFragment"> | ||||||
|     android:layout_marginEnd="8dp" |  | ||||||
|     android:textAlignment="center" |     <TextView | ||||||
|     android:textSize="20sp" |         android:id="@+id/text_account" | ||||||
|     app:layout_constraintBottom_toBottomOf="parent" |         android:layout_width="match_parent" | ||||||
|     app:layout_constraintEnd_toEndOf="parent" |         android:layout_height="wrap_content" | ||||||
|     app:layout_constraintStart_toStartOf="parent" |         android:layout_marginStart="8dp" | ||||||
|     app:layout_constraintTop_toTopOf="parent" /> |         android:layout_marginTop="8dp" | ||||||
|  |         android:layout_marginEnd="8dp" | ||||||
|  |         android:textAlignment="center" | ||||||
|  |         android:textSize="20sp" | ||||||
|  |         app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |         app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |         app:layout_constraintStart_toStartOf="parent" | ||||||
|  |         app:layout_constraintTop_toTopOf="parent" /> | ||||||
| </androidx.constraintlayout.widget.ConstraintLayout> | </androidx.constraintlayout.widget.ConstraintLayout> | ||||||
| @ -4,6 +4,7 @@ | |||||||
|     xmlns:tools="http://schemas.android.com/tools" |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|     android:layout_width="match_parent" |     android:layout_width="match_parent" | ||||||
|     android:layout_height="match_parent" |     android:layout_height="match_parent" | ||||||
|  |     android:background="#fafafa" | ||||||
|     tools:context=".ui.home.HomeFragment"> |     tools:context=".ui.home.HomeFragment"> | ||||||
|  |  | ||||||
|     <TextView |     <TextView | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ | |||||||
|     xmlns:tools="http://schemas.android.com/tools" |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|     android:layout_width="match_parent" |     android:layout_width="match_parent" | ||||||
|     android:layout_height="match_parent" |     android:layout_height="match_parent" | ||||||
|  |     android:background="#fafafa" | ||||||
|     tools:context=".ui.library.LibraryFragment"> |     tools:context=".ui.library.LibraryFragment"> | ||||||
|  |  | ||||||
|     <ListView |     <ListView | ||||||
|  | |||||||
							
								
								
									
										61
									
								
								app/src/main/res/layout/fragment_media.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								app/src/main/res/layout/fragment_media.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||||
|  |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|  |     android:layout_width="match_parent" | ||||||
|  |     android:layout_height="match_parent" | ||||||
|  |     android:background="#fafafa" | ||||||
|  |     tools:context=".ui.MediaFragment"> | ||||||
|  |  | ||||||
|  |     <androidx.constraintlayout.widget.ConstraintLayout | ||||||
|  |         android:layout_width="match_parent" | ||||||
|  |         android:layout_height="match_parent"> | ||||||
|  |  | ||||||
|  |         <ImageView | ||||||
|  |             android:id="@+id/image_poster" | ||||||
|  |             android:layout_width="wrap_content" | ||||||
|  |             android:layout_height="108dp" | ||||||
|  |             android:layout_marginTop="40dp" | ||||||
|  |             android:src="@drawable/ic_launcher_background" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintStart_toStartOf="parent" | ||||||
|  |             app:layout_constraintTop_toTopOf="parent" /> | ||||||
|  |  | ||||||
|  |         <Button | ||||||
|  |             android:id="@+id/button_play" | ||||||
|  |             android:layout_width="0dp" | ||||||
|  |             android:layout_height="48dp" | ||||||
|  |             android:layout_marginStart="7dp" | ||||||
|  |             android:layout_marginTop="25dp" | ||||||
|  |             android:layout_marginEnd="7dp" | ||||||
|  |             android:text="Play" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintStart_toStartOf="parent" | ||||||
|  |             app:layout_constraintTop_toBottomOf="@+id/image_poster" /> | ||||||
|  |  | ||||||
|  |         <TextView | ||||||
|  |             android:id="@+id/text_title" | ||||||
|  |             android:layout_width="wrap_content" | ||||||
|  |             android:layout_height="19dp" | ||||||
|  |             android:layout_marginStart="7dp" | ||||||
|  |             android:layout_marginTop="12dp" | ||||||
|  |             android:layout_marginEnd="7dp" | ||||||
|  |             android:text="TextView" | ||||||
|  |             android:textStyle="bold" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintStart_toStartOf="parent" | ||||||
|  |             app:layout_constraintTop_toBottomOf="@+id/button_play" /> | ||||||
|  |  | ||||||
|  |         <TextView | ||||||
|  |             android:id="@+id/text_desc" | ||||||
|  |             android:layout_width="0dp" | ||||||
|  |             android:layout_height="wrap_content" | ||||||
|  |             android:layout_marginStart="17dp" | ||||||
|  |             android:layout_marginTop="10dp" | ||||||
|  |             android:layout_marginEnd="17dp" | ||||||
|  |             android:text="TextView" | ||||||
|  |             app:layout_constraintEnd_toEndOf="parent" | ||||||
|  |             app:layout_constraintStart_toStartOf="parent" | ||||||
|  |             app:layout_constraintTop_toBottomOf="@+id/text_title" /> | ||||||
|  |     </androidx.constraintlayout.widget.ConstraintLayout> | ||||||
|  | </FrameLayout> | ||||||
| @ -4,6 +4,7 @@ | |||||||
|     xmlns:tools="http://schemas.android.com/tools" |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|     android:layout_width="match_parent" |     android:layout_width="match_parent" | ||||||
|     android:layout_height="match_parent" |     android:layout_height="match_parent" | ||||||
|  |     android:background="#fafafa" | ||||||
|     tools:context=".ui.search.SearchFragment"> |     tools:context=".ui.search.SearchFragment"> | ||||||
|  |  | ||||||
|     <TextView |     <TextView | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user