show loading screen while loading media fragment
* use material components for shaped images and progress indicator
This commit is contained in:
		| @ -32,6 +32,7 @@ import androidx.fragment.app.Fragment | ||||
| import androidx.fragment.app.commit | ||||
| import kotlinx.android.synthetic.main.activity_main.* | ||||
| import kotlinx.coroutines.GlobalScope | ||||
| import kotlinx.coroutines.async | ||||
| import kotlinx.coroutines.launch | ||||
| import org.mosad.teapod.parser.AoDParser | ||||
| import org.mosad.teapod.preferences.EncryptedPreferences | ||||
| @ -41,8 +42,7 @@ import org.mosad.teapod.ui.components.LoginDialog | ||||
| 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.Media | ||||
| import org.mosad.teapod.util.TMDBApiController | ||||
| import org.mosad.teapod.util.* | ||||
|  | ||||
| class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener { | ||||
|  | ||||
| @ -70,6 +70,10 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS | ||||
|     } | ||||
|  | ||||
|     override fun onNavigationItemSelected(item: MenuItem): Boolean { | ||||
|         if (supportFragmentManager.backStackEntryCount > 0) { | ||||
|             supportFragmentManager.popBackStack() | ||||
|         } | ||||
|  | ||||
|         val ret = when (item.itemId) { | ||||
|             R.id.navigation_home -> { | ||||
|                 activeFragment = HomeFragment() | ||||
| @ -109,11 +113,18 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * TODO show loading fragment | ||||
|      * show the media fragment for the selected media | ||||
|      * while loading show the loading fragment | ||||
|      */ | ||||
|     fun showDetailFragment(media: Media) = GlobalScope.launch { | ||||
|         media.episodes = AoDParser().loadStreams(media) // load the streams for the selected media | ||||
|     fun showMediaFragment(media: Media) = GlobalScope.launch { | ||||
|         val loadingFragment = LoadingFragment() | ||||
|         supportFragmentManager.commit { | ||||
|             add(R.id.nav_host_fragment, loadingFragment, "MediaFragment") | ||||
|             show(loadingFragment) | ||||
|         } | ||||
|  | ||||
|         // load the streams for the selected media | ||||
|         media.episodes = AoDParser().loadStreams(media) | ||||
|         val tmdb = TMDBApiController().search(media.title, media.type) | ||||
|  | ||||
|         val mediaFragment = MediaFragment(media, tmdb) | ||||
| @ -122,6 +133,10 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS | ||||
|             addToBackStack(null) | ||||
|             show(mediaFragment) | ||||
|         } | ||||
|  | ||||
|         supportFragmentManager.commit { | ||||
|             remove(loadingFragment) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun startPlayer(streamUrl: String) { | ||||
|  | ||||
| @ -19,13 +19,13 @@ import org.mosad.teapod.MainActivity | ||||
| import org.mosad.teapod.R | ||||
| import org.mosad.teapod.parser.AoDParser | ||||
| import org.mosad.teapod.util.DataTypes.MediaType | ||||
| import org.mosad.teapod.util.EpisodesAdapter | ||||
| import org.mosad.teapod.util.adapter.EpisodeItemAdapter | ||||
| import org.mosad.teapod.util.Media | ||||
| import org.mosad.teapod.util.TMDBResponse | ||||
|  | ||||
| class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) : Fragment() { | ||||
|  | ||||
|     private lateinit var adapterRecEpisodes: EpisodesAdapter | ||||
|     private lateinit var adapterRecEpisodes: EpisodeItemAdapter | ||||
|     private lateinit var viewManager: RecyclerView.LayoutManager | ||||
|  | ||||
|  | ||||
| @ -55,17 +55,16 @@ class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) : | ||||
|             .into(image_backdrop) | ||||
|  | ||||
|         Glide.with(requireContext()).load(posterUrl) | ||||
|             .apply(RequestOptions.bitmapTransform(RoundedCornersTransformation(posterCornerRadius, 0))) | ||||
|             .into(image_poster) | ||||
|  | ||||
|         text_title.text = media.title | ||||
|         text_year.text = media.info.year.toString() | ||||
|         text_age.text = media.info.age.toString() | ||||
|         text_overview.text = media.info.shortDesc //if (tmdb.overview.isNotEmpty()) tmdb.overview else media.shortDesc | ||||
|         text_overview.text = media.info.shortDesc | ||||
|  | ||||
|         // specific gui | ||||
|         if (media.type == MediaType.TVSHOW) { | ||||
|             adapterRecEpisodes = EpisodesAdapter(media.episodes, requireContext()) | ||||
|             adapterRecEpisodes = EpisodeItemAdapter(media.episodes, requireContext()) | ||||
|             viewManager = LinearLayoutManager(context) | ||||
|             recycler_episodes.layoutManager = viewManager | ||||
|             recycler_episodes.adapter = adapterRecEpisodes | ||||
|  | ||||
| @ -6,17 +6,16 @@ import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import androidx.fragment.app.Fragment | ||||
| import kotlinx.android.synthetic.main.fragment_library.* | ||||
| import kotlinx.android.synthetic.main.item_media.view.* | ||||
| import kotlinx.coroutines.* | ||||
| import org.mosad.teapod.MainActivity | ||||
| import org.mosad.teapod.R | ||||
| import org.mosad.teapod.parser.AoDParser | ||||
| import org.mosad.teapod.util.CustomAdapter | ||||
| import org.mosad.teapod.util.adapter.MediaItemAdapter | ||||
| import org.mosad.teapod.util.Media | ||||
|  | ||||
| class LibraryFragment : Fragment() { | ||||
|  | ||||
|     private lateinit var adapter : CustomAdapter | ||||
|     private lateinit var adapter : MediaItemAdapter | ||||
|  | ||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||
|         return inflater.inflate(R.layout.fragment_library, container, false) | ||||
| @ -33,7 +32,7 @@ class LibraryFragment : Fragment() { | ||||
|             // create and set the adapter, needs context | ||||
|             withContext(Dispatchers.Main) { | ||||
|                 context?.let { | ||||
|                     adapter = CustomAdapter(it, AoDParser.mediaList) | ||||
|                     adapter = MediaItemAdapter(it, AoDParser.mediaList) | ||||
|                     grid_media_library.adapter = adapter | ||||
|                 } | ||||
|             } | ||||
| @ -47,7 +46,7 @@ class LibraryFragment : Fragment() { | ||||
|             val media = adapter.getItem(position) as Media | ||||
|             println("selected item is: ${media.title}") | ||||
|  | ||||
|             (activity as MainActivity).showDetailFragment(media) | ||||
|             (activity as MainActivity).showMediaFragment(media) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -11,12 +11,12 @@ import kotlinx.coroutines.* | ||||
| import org.mosad.teapod.MainActivity | ||||
| import org.mosad.teapod.R | ||||
| import org.mosad.teapod.parser.AoDParser | ||||
| import org.mosad.teapod.util.CustomAdapter | ||||
| import org.mosad.teapod.util.adapter.MediaItemAdapter | ||||
| import org.mosad.teapod.util.Media | ||||
|  | ||||
| class SearchFragment : Fragment() { | ||||
|  | ||||
|     private var adapter : CustomAdapter? = null | ||||
|     private var adapter : MediaItemAdapter? = null | ||||
|  | ||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||
|         return inflater.inflate(R.layout.fragment_search, container, false) | ||||
| @ -33,7 +33,7 @@ class SearchFragment : Fragment() { | ||||
|             // create and set the adapter, needs context | ||||
|             withContext(Dispatchers.Main) { | ||||
|                 context?.let { | ||||
|                     adapter = CustomAdapter(it, AoDParser.mediaList) | ||||
|                     adapter = MediaItemAdapter(it, AoDParser.mediaList) | ||||
|                     grid_media_search.adapter = adapter | ||||
|                 } | ||||
|             } | ||||
| @ -60,12 +60,10 @@ class SearchFragment : Fragment() { | ||||
|         grid_media_search.setOnItemClickListener { _, _, position, _ -> | ||||
|             search_text.clearFocus() // remove focus from the SearchView | ||||
|  | ||||
|             runBlocking { | ||||
|                 val media = adapter?.getItem(position) as Media | ||||
|                 println("selected item is: ${media.title}") | ||||
|             val media = adapter?.getItem(position) as Media | ||||
|             println("selected item is: ${media.title}") | ||||
|  | ||||
|                 (activity as MainActivity).showDetailFragment(media).join() | ||||
|             } | ||||
|             (activity as MainActivity).showMediaFragment(media) | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										16
									
								
								app/src/main/java/org/mosad/teapod/util/LoadingFragment.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/src/main/java/org/mosad/teapod/util/LoadingFragment.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| package org.mosad.teapod.util | ||||
|  | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import androidx.fragment.app.Fragment | ||||
| import org.mosad.teapod.R | ||||
|  | ||||
| class LoadingFragment : Fragment() { | ||||
|  | ||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||
|         return inflater.inflate(R.layout.fragment_loading, container, false) | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| package org.mosad.teapod.util | ||||
| package org.mosad.teapod.util.adapter | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.view.LayoutInflater | ||||
| @ -10,8 +10,9 @@ import com.bumptech.glide.request.RequestOptions | ||||
| import jp.wasabeef.glide.transformations.RoundedCornersTransformation | ||||
| import kotlinx.android.synthetic.main.item_episode.view.* | ||||
| import org.mosad.teapod.R | ||||
| import org.mosad.teapod.util.Episode | ||||
| 
 | ||||
| class EpisodesAdapter(private val episodes: List<Episode>, private val context: Context) : RecyclerView.Adapter<EpisodesAdapter.MyViewHolder>() { | ||||
| class EpisodeItemAdapter(private val episodes: List<Episode>, private val context: Context) : RecyclerView.Adapter<EpisodeItemAdapter.MyViewHolder>() { | ||||
| 
 | ||||
|     var onItemClick: ((String, Int) -> Unit)? = null | ||||
| 
 | ||||
| @ -1,4 +1,4 @@ | ||||
| package org.mosad.teapod.util | ||||
| package org.mosad.teapod.util.adapter | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.view.LayoutInflater | ||||
| @ -7,9 +7,10 @@ import android.view.ViewGroup | ||||
| import android.widget.* | ||||
| import com.bumptech.glide.Glide | ||||
| import org.mosad.teapod.R | ||||
| import org.mosad.teapod.util.Media | ||||
| import java.util.* | ||||
| 
 | ||||
| class CustomAdapter(val context: Context, private val originalMedia: ArrayList<Media>) : BaseAdapter(), Filterable { | ||||
| class MediaItemAdapter(val context: Context, private val originalMedia: ArrayList<Media>) : BaseAdapter(), Filterable { | ||||
| 
 | ||||
|     private var filteredMedia = originalMedia.map { it.copy() } | ||||
|     private val customFilter = CustomFilter() | ||||
| @ -1,6 +1,5 @@ | ||||
| <?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" | ||||
| @ -15,10 +14,12 @@ | ||||
|         android:layout_gravity="center" /> | ||||
|     <!--    app:controller_layout_id="@layout/player_custom_control"/>--> | ||||
|  | ||||
|     <ProgressBar | ||||
|     <com.google.android.material.progressindicator.ProgressIndicator | ||||
|         android:id="@+id/loading" | ||||
|         style="@style/Widget.MaterialComponents.ProgressIndicator.Circular.Indeterminate" | ||||
|         android:layout_width="70dp" | ||||
|         android:layout_height="70dp" | ||||
|         android:layout_gravity="center" /> | ||||
|         android:layout_gravity="center" | ||||
|         tools:visibility="visible" /> | ||||
|  | ||||
| </FrameLayout> | ||||
							
								
								
									
										17
									
								
								app/src/main/res/layout/fragment_loading.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/src/main/res/layout/fragment_loading.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="#f5f5f5" | ||||
|     android:clickable="true" | ||||
|     android:focusable="true"> | ||||
|  | ||||
|     <com.google.android.material.progressindicator.ProgressIndicator | ||||
|         android:id="@+id/progressBar2" | ||||
|         style="@style/Widget.MaterialComponents.ProgressIndicator.Circular.Indeterminate" | ||||
|         android:layout_width="70dp" | ||||
|         android:layout_height="70dp" | ||||
|         android:layout_gravity="center" | ||||
|         tools:visibility="visible" /> | ||||
| </FrameLayout> | ||||
| @ -30,12 +30,13 @@ | ||||
|                     android:minHeight="220dp" | ||||
|                     android:scaleType="centerCrop" /> | ||||
|  | ||||
|                 <ImageView | ||||
|                 <com.google.android.material.imageview.ShapeableImageView | ||||
|                     android:id="@+id/image_poster" | ||||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="200dp" | ||||
|                     android:layout_gravity="center" | ||||
|                     android:src="@drawable/ic_launcher_background" /> | ||||
|                     app:shapeAppearance="@style/ShapeAppearance.Teapod.RoundedPoster" | ||||
|                     app:srcCompat="@drawable/ic_launcher_background" /> | ||||
|  | ||||
|             </FrameLayout> | ||||
|  | ||||
|  | ||||
| @ -14,12 +14,13 @@ | ||||
|         android:layout_height="wrap_content" | ||||
|         android:orientation="horizontal"> | ||||
|  | ||||
|         <ImageView | ||||
|         <com.google.android.material.imageview.ShapeableImageView | ||||
|             android:id="@+id/image_episode" | ||||
|             android:layout_width="128dp" | ||||
|             android:layout_height="72dp" | ||||
|             android:contentDescription="@string/component_poster_desc" | ||||
|             app:srcCompat="@color/md_disabled_text_dark_theme" /> | ||||
|             app:srcCompat="@color/md_disabled_text_dark_theme" | ||||
|             app:shapeAppearance="@style/ShapeAppearance.Teapod.RoundedPoster"/> | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/text_episode_title" | ||||
|  | ||||
| @ -14,5 +14,10 @@ | ||||
|         <item name="android:windowContentOverlay">@null</item> | ||||
|     </style> | ||||
|  | ||||
|     <!-- shapes --> | ||||
|     <style name="ShapeAppearance.Teapod.RoundedPoster" parent="ShapeAppearance.MaterialComponents.LargeComponent"> | ||||
|         <item name="cornerFamily">rounded</item> | ||||
|         <item name="cornerSize">5dp</item> | ||||
|     </style> | ||||
|  | ||||
| </resources> | ||||
		Reference in New Issue
	
	Block a user