mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	added stuff to MainAPI
This commit is contained in:
		
							parent
							
								
									79328502b4
								
							
						
					
					
						commit
						8c0a6dffe9
					
				
					 9 changed files with 152 additions and 102 deletions
				
			
		|  | @ -10,13 +10,10 @@ import com.lagradost.cloudstream3.animeproviders.ShiroProvider | |||
| import com.lagradost.cloudstream3.animeproviders.TenshiProvider | ||||
| import com.lagradost.cloudstream3.animeproviders.WcoProvider | ||||
| import com.lagradost.cloudstream3.movieproviders.HDMProvider | ||||
| import com.lagradost.cloudstream3.movieproviders.LookMovieProvider | ||||
| import com.lagradost.cloudstream3.movieproviders.MeloMovieProvider | ||||
| import com.lagradost.cloudstream3.movieproviders.TrailersToProvider | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import java.util.* | ||||
| import kotlin.collections.ArrayList | ||||
| import kotlin.collections.HashMap | ||||
| 
 | ||||
| const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0" | ||||
| val baseHeader = mapOf("User-Agent" to USER_AGENT) | ||||
|  | @ -38,7 +35,7 @@ object APIHolder { | |||
|         MeloMovieProvider(), | ||||
|         DubbedAnimeProvider(), | ||||
|         HDMProvider(), | ||||
|         LookMovieProvider(), | ||||
|         //LookMovieProvider(), // RECAPTCHA (Please allow up to 5 seconds...) | ||||
|         TrailersToProvider(), | ||||
|     ) | ||||
| 
 | ||||
|  | @ -60,13 +57,23 @@ object APIHolder { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /**Every provider will **not** have try catch built in, so handle exceptions when calling these functions*/ | ||||
| abstract class MainAPI { | ||||
|     open val name = "NONE" | ||||
|     open val mainUrl = "NONE" | ||||
|     open val instantLinkLoading = false // THIS IS IF THE LINK IS STORED IN THE "DATA" | ||||
| 
 | ||||
|     /**If link is stored in the "data" string, so links can be instantly loaded*/ | ||||
|     open val instantLinkLoading = false | ||||
| 
 | ||||
|     open val hasQuickSearch = false | ||||
|     open fun search(query: String): ArrayList<SearchResponse>? { // SearchResponse | ||||
| 
 | ||||
|     /**Set false if links require referer or for some reason cant be played on a chromecast*/ | ||||
|     open val hasChromecastSupport = true | ||||
| 
 | ||||
|     /**If all links are m3u8 then set this to false*/ | ||||
|     open val hasDownloadSupport = true | ||||
| 
 | ||||
|     open fun search(query: String): ArrayList<SearchResponse>? { | ||||
|         return null | ||||
|     } | ||||
| 
 | ||||
|  | @ -78,7 +85,7 @@ abstract class MainAPI { | |||
|         return null | ||||
|     } | ||||
| 
 | ||||
|     // callback is fired once a link is found, will return true if method is executed successfully | ||||
|     /**Callback is fired once a link is found, will return true if method is executed successfully*/ | ||||
|     open fun loadLinks( | ||||
|         data: String, | ||||
|         isCasting: Boolean, | ||||
|  |  | |||
|  | @ -10,6 +10,8 @@ class HDMProvider : MainAPI() { | |||
|         get() = "HD Movies" | ||||
|     override val mainUrl: String | ||||
|         get() = "https://hdm.to" | ||||
|     override val hasDownloadSupport: Boolean | ||||
|         get() = false | ||||
| 
 | ||||
|     override fun search(query: String): ArrayList<SearchResponse> { | ||||
|         val url = "$mainUrl/search/$query" | ||||
|  |  | |||
|  | @ -17,6 +17,8 @@ class MeloMovieProvider : MainAPI() { | |||
|         get() = true | ||||
|     override val hasQuickSearch: Boolean | ||||
|         get() = true | ||||
|     override val hasChromecastSupport: Boolean | ||||
|         get() = false // MKV FILES CANT BE PLAYED ON A CHROMECAST | ||||
| 
 | ||||
|     data class MeloMovieSearchResult( | ||||
|         @JsonProperty("id") val id: Int, | ||||
|  |  | |||
|  | @ -1,28 +1,17 @@ | |||
| package com.lagradost.cloudstream3.ui.result | ||||
| 
 | ||||
| import android.annotation.SuppressLint | ||||
| import android.app.Activity | ||||
| import android.content.Context | ||||
| import android.content.DialogInterface | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.ImageView | ||||
| import android.widget.LinearLayout | ||||
| import android.widget.TextView | ||||
| import androidx.annotation.LayoutRes | ||||
| import androidx.appcompat.app.AlertDialog | ||||
| import androidx.core.widget.ContentLoadingProgressBar | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.bumptech.glide.Glide | ||||
| import com.bumptech.glide.load.model.GlideUrl | ||||
| import com.google.android.gms.cast.framework.CastContext | ||||
| import com.google.android.gms.cast.framework.CastState | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.UIHelper.hideSystemUI | ||||
| import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable | ||||
| import com.lagradost.cloudstream3.UIHelper.isConnectedToChromecast | ||||
| import com.lagradost.cloudstream3.utils.getId | ||||
| import com.lagradost.cloudstream3.R | ||||
| import kotlinx.android.synthetic.main.result_episode.view.episode_holder | ||||
| import kotlinx.android.synthetic.main.result_episode.view.episode_text | ||||
| import kotlinx.android.synthetic.main.result_episode_large.view.* | ||||
|  | @ -42,10 +31,13 @@ const val ACTION_COPY_LINK = 9 | |||
| 
 | ||||
| const val ACTION_SHOW_OPTIONS = 10 | ||||
| 
 | ||||
| const val ACTION_CLICK_DEFAULT = 11 | ||||
| 
 | ||||
| data class EpisodeClickEvent(val action: Int, val data: ResultEpisode) | ||||
| 
 | ||||
| class EpisodeAdapter( | ||||
|     var cardList: List<ResultEpisode>, | ||||
|     val hasDownloadSupport : Boolean, | ||||
|     private val clickCallback: (EpisodeClickEvent) -> Unit, | ||||
| ) : | ||||
|     RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
|  | @ -64,6 +56,7 @@ class EpisodeAdapter( | |||
| 
 | ||||
|         return CardViewHolder( | ||||
|             LayoutInflater.from(parent.context).inflate(layout, parent, false), | ||||
|             hasDownloadSupport, | ||||
|             clickCallback | ||||
|         ) | ||||
|     } | ||||
|  | @ -83,6 +76,7 @@ class EpisodeAdapter( | |||
|     class CardViewHolder | ||||
|     constructor( | ||||
|         itemView: View, | ||||
|         private val hasDownloadSupport : Boolean, | ||||
|         private val clickCallback: (EpisodeClickEvent) -> Unit, | ||||
|     ) : RecyclerView.ViewHolder(itemView) { | ||||
|         private val episodeText: TextView = itemView.episode_text | ||||
|  | @ -131,13 +125,7 @@ class EpisodeAdapter( | |||
|             } | ||||
| 
 | ||||
|             episodeHolder.setOnClickListener { | ||||
|                 episodeHolder.context?.let { ctx -> | ||||
|                     if (ctx.isConnectedToChromecast()) { | ||||
|                         clickCallback.invoke(EpisodeClickEvent(ACTION_CHROME_CAST_EPISODE, card)) | ||||
|                     } else { | ||||
|                         clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card)) | ||||
|                     } | ||||
|                 } | ||||
|                 clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card)) | ||||
|             } | ||||
| 
 | ||||
|             episodeHolder.setOnLongClickListener { | ||||
|  | @ -146,6 +134,8 @@ class EpisodeAdapter( | |||
|                 return@setOnLongClickListener true | ||||
|             } | ||||
| 
 | ||||
|             episodeDownload?.visibility = if(hasDownloadSupport) View.VISIBLE else View.GONE | ||||
| 
 | ||||
|             episodeDownload?.setOnClickListener { | ||||
|                 clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card)) | ||||
|             } | ||||
|  |  | |||
|  | @ -227,25 +227,37 @@ class ResultFragment : Fragment() { | |||
|         ) | ||||
|         result_back.layoutParams = backParameter | ||||
| 
 | ||||
|         if (activity?.isCastApiAvailable() == true) { | ||||
|             CastButtonFactory.setUpMediaRouteButton(activity, media_route_button) | ||||
|             val castContext = CastContext.getSharedInstance(requireActivity().applicationContext) | ||||
| 
 | ||||
|             if (castContext.castState != CastState.NO_DEVICES_AVAILABLE) media_route_button.visibility = VISIBLE | ||||
|             castContext.addCastStateListener { state -> | ||||
|                 if (media_route_button != null) { | ||||
|                     if (state == CastState.NO_DEVICES_AVAILABLE) media_route_button.visibility = GONE else { | ||||
|                         if (media_route_button.visibility == GONE) media_route_button.visibility = VISIBLE | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // activity?.fixPaddingStatusbar(result_toolbar) | ||||
| 
 | ||||
|         url = arguments?.getString("url") | ||||
|         val slug = arguments?.getString("slug") | ||||
|         val apiName = arguments?.getString("apiName") | ||||
|         val apiName = arguments?.getString("apiName") ?: return | ||||
| 
 | ||||
|         val api = getApiFromName(apiName) | ||||
|         if (media_route_button != null) { | ||||
|             val chromecastSupport = api.hasChromecastSupport | ||||
| 
 | ||||
|             media_route_button?.alpha = if (chromecastSupport) 1f else 0.3f | ||||
|             if (!chromecastSupport) { | ||||
|                 media_route_button.setOnClickListener { | ||||
|                     Toast.makeText(it.context, "This provider has no chromecast support", Toast.LENGTH_LONG).show() | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (activity?.isCastApiAvailable() == true) { | ||||
|                 CastButtonFactory.setUpMediaRouteButton(activity, media_route_button) | ||||
|                 val castContext = CastContext.getSharedInstance(requireActivity().applicationContext) | ||||
| 
 | ||||
|                 if (castContext.castState != CastState.NO_DEVICES_AVAILABLE) media_route_button.visibility = VISIBLE | ||||
|                 castContext.addCastStateListener { state -> | ||||
|                     if (media_route_button != null) { | ||||
|                         if (state == CastState.NO_DEVICES_AVAILABLE) media_route_button.visibility = GONE else { | ||||
|                             if (media_route_button.visibility == GONE) media_route_button.visibility = VISIBLE | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         result_scroll.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, _ -> | ||||
|             if (result_poster_blur == null) return@OnScrollChangeListener | ||||
|             result_poster_blur.alpha = maxOf(0f, (0.7f - scrollY / 1000f)) | ||||
|  | @ -397,7 +409,10 @@ class ResultFragment : Fragment() { | |||
| 
 | ||||
|                     val epData = episodeClick.data | ||||
|                     ctx.setKey( | ||||
|                         getFolderName(DOWNLOAD_EPISODE_CACHE, (currentId ?: return@let).toString()), // 3 deep folder for faster acess | ||||
|                         getFolderName( | ||||
|                             DOWNLOAD_EPISODE_CACHE, | ||||
|                             (currentId ?: return@let).toString() | ||||
|                         ), // 3 deep folder for faster acess | ||||
|                         epData.id.toString(), | ||||
|                         VideoDownloadHelper.DownloadEpisodeCached( | ||||
|                             epData.name, | ||||
|  | @ -431,6 +446,16 @@ class ResultFragment : Fragment() { | |||
|             if (!isLoaded) return@main // CANT LOAD | ||||
| 
 | ||||
|             when (episodeClick.action) { | ||||
|                 ACTION_CLICK_DEFAULT -> { | ||||
|                     context?.let { ctx -> | ||||
|                         if (ctx.isConnectedToChromecast()) { | ||||
|                             handleAction(EpisodeClickEvent(ACTION_CHROME_CAST_EPISODE, episodeClick.data)) | ||||
|                         } else { | ||||
|                             handleAction(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, episodeClick.data)) | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 ACTION_SHOW_OPTIONS -> { | ||||
|                     val builder = AlertDialog.Builder(requireContext(), R.style.AlertDialogCustom) | ||||
|                     var dialog: AlertDialog? = null | ||||
|  | @ -442,6 +467,8 @@ class ResultFragment : Fragment() { | |||
|                     val verifiedOptions = ArrayList<String>() | ||||
|                     val verifiedOptionsValues = ArrayList<Int>() | ||||
| 
 | ||||
|                     val hasDownloadSupport = api.hasDownloadSupport | ||||
| 
 | ||||
|                     for (i in options.indices) { | ||||
|                         val opv = optionsValues[i] | ||||
|                         val op = options[i] | ||||
|  | @ -450,6 +477,8 @@ class ResultFragment : Fragment() { | |||
|                         val add = when (opv) { | ||||
|                             ACTION_CHROME_CAST_EPISODE -> isConnected | ||||
|                             ACTION_CHROME_CAST_MIRROR -> isConnected | ||||
|                             ACTION_DOWNLOAD_EPISODE -> hasDownloadSupport | ||||
|                             ACTION_DOWNLOAD_MIRROR -> hasDownloadSupport | ||||
|                             ACTION_PLAY_EPISODE_IN_VLC_PLAYER -> context?.isAppInstalled(VLC_PACKAGE) ?: false | ||||
|                             else -> true | ||||
|                         } | ||||
|  | @ -482,7 +511,7 @@ class ResultFragment : Fragment() { | |||
| 
 | ||||
|                 ACTION_PLAY_EPISODE_IN_BROWSER -> { | ||||
|                     aquireSingeExtractorLink("Play in Browser") { link -> | ||||
|                         val i = Intent(Intent.ACTION_VIEW) | ||||
|                         val i = Intent(ACTION_VIEW) | ||||
|                         i.data = Uri.parse(link.url) | ||||
|                         startActivity(i) | ||||
|                     } | ||||
|  | @ -595,11 +624,11 @@ class ResultFragment : Fragment() { | |||
|         val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = | ||||
|             EpisodeAdapter( | ||||
|                 ArrayList(), | ||||
|                 api.hasDownloadSupport, | ||||
|             ) { episodeClick -> | ||||
|                 handleAction(episodeClick) | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|         result_episodes.adapter = adapter | ||||
|         result_episodes.layoutManager = GridLayoutManager(context, 1) | ||||
| 
 | ||||
|  | @ -678,17 +707,17 @@ class ResultFragment : Fragment() { | |||
|                         currentIsMovie = !d.isEpisodeBased() | ||||
| 
 | ||||
|                         result_openinbrower.setOnClickListener { | ||||
|                             val i = Intent(Intent.ACTION_VIEW) | ||||
|                             val i = Intent(ACTION_VIEW) | ||||
|                             i.data = Uri.parse(d.url) | ||||
|                             startActivity(i) | ||||
|                         } | ||||
| 
 | ||||
|                         result_share.setOnClickListener { | ||||
|                             val i = Intent(Intent.ACTION_SEND) | ||||
|                             val i = Intent(ACTION_SEND) | ||||
|                             i.type = "text/plain" | ||||
|                             i.putExtra(Intent.EXTRA_SUBJECT, d.name) | ||||
|                             i.putExtra(Intent.EXTRA_TEXT, d.url) | ||||
|                             startActivity(Intent.createChooser(i, d.name)) | ||||
|                             i.putExtra(EXTRA_SUBJECT, d.name) | ||||
|                             i.putExtra(EXTRA_TEXT, d.url) | ||||
|                             startActivity(createChooser(i, d.name)) | ||||
|                         } | ||||
| 
 | ||||
|                         val metadataInfoArray = ArrayList<Pair<String, String>>() | ||||
|  | @ -713,6 +742,8 @@ class ResultFragment : Fragment() { | |||
|                         val duration = d.duration | ||||
|                         if (duration != null) metadataInfoArray.add(Pair("Duration", duration)) | ||||
| 
 | ||||
|                         metadataInfoArray.add(Pair("Site", d.apiName)) | ||||
| 
 | ||||
|                         if (metadataInfoArray.size > 0) { | ||||
|                             result_metadata.visibility = VISIBLE | ||||
|                             val text = SpannableStringBuilder() | ||||
|  | @ -777,37 +808,23 @@ class ResultFragment : Fragment() { | |||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|                         when (d.type) { | ||||
|                             TvType.Movie -> { | ||||
|                                 result_play_movie.visibility = VISIBLE | ||||
|                                 result_episodes_text.visibility = GONE | ||||
|                                 result_episodes.visibility = GONE | ||||
|                         if (d.type == TvType.Movie && d is MovieLoadResponse) { | ||||
|                             result_movie_parent.visibility = VISIBLE | ||||
|                             result_episodes_text.visibility = GONE | ||||
|                             result_episodes.visibility = GONE | ||||
| 
 | ||||
|                                 result_play_movie.setOnClickListener { | ||||
|                                     val card = currentEpisodes?.first() ?: return@setOnClickListener | ||||
|                                     if (requireContext().isCastApiAvailable()) { | ||||
|                                         val castContext = CastContext.getSharedInstance(requireContext()) | ||||
| 
 | ||||
|                                         if (castContext.castState == CastState.CONNECTED) { | ||||
|                                             handleAction(EpisodeClickEvent(ACTION_CHROME_CAST_EPISODE, card)) | ||||
|                                         } else { | ||||
|                                             handleAction(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card)) | ||||
|                                         } | ||||
|                                     } else { | ||||
|                                         handleAction( | ||||
|                                             EpisodeClickEvent( | ||||
|                                                 ACTION_PLAY_EPISODE_IN_PLAYER, | ||||
|                                                 card | ||||
|                                             ) | ||||
|                                         ) //TODO REDO TO MAIN | ||||
|                                     } | ||||
|                                 } | ||||
|                             result_play_movie.setOnClickListener { | ||||
|                                 val card = currentEpisodes?.first() ?: return@setOnClickListener | ||||
|                                 handleAction(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card)) | ||||
|                             } | ||||
|                             else -> { | ||||
|                                 result_play_movie.visibility = GONE | ||||
|                                 result_episodes_text.visibility = VISIBLE | ||||
|                                 result_episodes.visibility = VISIBLE | ||||
|                             result_options.setOnClickListener { | ||||
|                                 val card = currentEpisodes?.first() ?: return@setOnClickListener | ||||
|                                 handleAction(EpisodeClickEvent(ACTION_SHOW_OPTIONS, card)) | ||||
|                             } | ||||
|                         } else { | ||||
|                             result_movie_parent.visibility = GONE | ||||
|                             result_episodes_text.visibility = VISIBLE | ||||
|                             result_episodes.visibility = VISIBLE | ||||
|                         } | ||||
| 
 | ||||
|                         when (d) { | ||||
|  | @ -842,7 +859,7 @@ class ResultFragment : Fragment() { | |||
| 
 | ||||
|             if (url != null) { | ||||
|                 result_reload_connection_open_in_browser.setOnClickListener { | ||||
|                     val i = Intent(Intent.ACTION_VIEW) | ||||
|                     val i = Intent(ACTION_VIEW) | ||||
|                     i.data = Uri.parse(url) | ||||
|                     startActivity(i) | ||||
|                 } | ||||
|  |  | |||
|  | @ -165,9 +165,10 @@ class ResultViewModel : ViewModel() { | |||
|                             updateEpisodes( | ||||
|                                 context, mainId, arrayListOf( | ||||
|                                     context.buildResultEpisode( | ||||
|                                         d.name, | ||||
|                                         null, | ||||
|                                         0, | ||||
|                                         null, | ||||
|                                         0, null, | ||||
|                                         d.dataUrl, | ||||
|                                         d.apiName, | ||||
|                                         (mainId + 1), | ||||
|  | @ -211,7 +212,7 @@ class ResultViewModel : ViewModel() { | |||
|     suspend fun loadEpisode( | ||||
|         episode: ResultEpisode, | ||||
|         isCasting: Boolean, | ||||
|     ) : Resource<ResultViewModel.EpisodeData> { | ||||
|     ): Resource<EpisodeData> { | ||||
|         return loadEpisode(episode.id, episode.data, isCasting) | ||||
|     } | ||||
| 
 | ||||
|  | @ -219,7 +220,7 @@ class ResultViewModel : ViewModel() { | |||
|         id: Int, | ||||
|         data: String, | ||||
|         isCasting: Boolean, | ||||
|     ): Resource<ResultViewModel.EpisodeData> { | ||||
|     ): Resource<EpisodeData> { | ||||
|         if (_allEpisodes.value?.contains(id) == true) { | ||||
|             _allEpisodes.value?.remove(id) | ||||
|         } | ||||
|  |  | |||
|  | @ -286,27 +286,56 @@ | |||
|                                                               android:layout_height="wrap_content"> | ||||
| 
 | ||||
|                 </com.lagradost.cloudstream3.widget.FlowLayout> | ||||
|                 <com.google.android.material.button.MaterialButton | ||||
|                         android:visibility="visible" | ||||
|                         android:layout_gravity="center_vertical" | ||||
|                         app:cornerRadius="4dp" | ||||
|                         android:id="@+id/result_play_movie" | ||||
|                         android:text="@string/play_movie_button" | ||||
| 
 | ||||
|                         app:rippleColor="?attr/colorPrimary" | ||||
|                         android:textColor="?attr/textColor" | ||||
|                         app:iconTint="?attr/textColor" | ||||
|                         android:textAllCaps="false" | ||||
|                         android:clickable="true" | ||||
|                         android:focusable="true" | ||||
|                         app:iconGravity="textStart" | ||||
|                         app:strokeColor="?attr/textColor" | ||||
|                         app:icon="@drawable/ic_baseline_play_arrow_24" | ||||
|                         android:backgroundTint="@color/transparent" | ||||
|                         style="@style/Widget.MaterialComponents.Button.OutlinedButton" | ||||
|                 <LinearLayout | ||||
|                         android:orientation="vertical" | ||||
|                         android:id="@+id/result_movie_parent" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="45dp"> | ||||
|                 </com.google.android.material.button.MaterialButton> | ||||
|                         android:layout_height="wrap_content"> | ||||
|                     <com.google.android.material.button.MaterialButton | ||||
|                             android:visibility="visible" | ||||
|                             android:layout_gravity="center_vertical" | ||||
|                             app:cornerRadius="4dp" | ||||
|                             android:id="@+id/result_play_movie" | ||||
|                             android:text="@string/play_movie_button" | ||||
| 
 | ||||
|                             app:rippleColor="?attr/textColor" | ||||
|                             android:textColor="?attr/textColor" | ||||
|                             app:iconTint="?attr/textColor" | ||||
|                             android:textAllCaps="false" | ||||
|                             android:clickable="true" | ||||
|                             android:focusable="true" | ||||
| 
 | ||||
|                             app:iconGravity="textStart" | ||||
|                             app:strokeColor="?attr/textColor" | ||||
|                             app:icon="@drawable/ic_baseline_play_arrow_24" | ||||
|                             android:backgroundTint="@color/transparent" | ||||
|                             style="@style/Widget.MaterialComponents.Button.OutlinedButton" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="45dp"> | ||||
|                     </com.google.android.material.button.MaterialButton> | ||||
|                     <com.google.android.material.button.MaterialButton | ||||
|                             android:visibility="visible" | ||||
|                             android:layout_gravity="center_vertical" | ||||
|                             app:cornerRadius="4dp" | ||||
|                             android:id="@+id/result_options" | ||||
|                             android:text="@string/options" | ||||
| 
 | ||||
|                             app:rippleColor="?attr/textColor" | ||||
|                             android:textColor="?attr/textColor" | ||||
|                             app:iconTint="?attr/textColor" | ||||
|                             android:textAllCaps="false" | ||||
|                             android:clickable="true" | ||||
|                             android:focusable="true" | ||||
|                             app:iconGravity="textStart" | ||||
|                             app:strokeColor="?attr/textColor" | ||||
|                             app:icon="@drawable/ic_baseline_play_arrow_24" | ||||
|                             android:backgroundTint="@color/transparent" | ||||
|                             style="@style/Widget.MaterialComponents.Button.OutlinedButton" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="45dp"> | ||||
|                     </com.google.android.material.button.MaterialButton> | ||||
| 
 | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
|                 <LinearLayout android:orientation="horizontal" android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> | ||||
|                     <com.google.android.material.button.MaterialButton | ||||
|  | @ -314,7 +343,7 @@ | |||
|                             android:layout_gravity="center_vertical" | ||||
|                             app:cornerRadius="4dp" | ||||
|                             android:id="@+id/result_season_button" | ||||
|                             tools:text="Bookmark" | ||||
|                             tools:text="Subbed" | ||||
| 
 | ||||
|                             app:rippleColor="?attr/bitDarkerGrayBackground" | ||||
|                             android:textColor="?attr/textColor" | ||||
|  |  | |||
|  | @ -41,4 +41,5 @@ | |||
|     <string name="download_descript">Download</string> | ||||
|     <string name="error_loading_links">Error Loading Links</string> | ||||
|     <string name="download_storage_text">Internal Storage</string> | ||||
|     <string name="options">Options</string> | ||||
| </resources> | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue