mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	refactor + fixed back crash issue + fixed downloads to redirect to downloads + fixed toast arca + downloads wrap around text
This commit is contained in:
		
							parent
							
								
									db4cdb0ae2
								
							
						
					
					
						commit
						70b7e5c60b
					
				
					 32 changed files with 325 additions and 251 deletions
				
			
		|  | @ -2,7 +2,10 @@ package com.lagradost.cloudstream3 | |||
| 
 | ||||
| import android.app.Application | ||||
| import android.content.Context | ||||
| import android.widget.Toast | ||||
| import com.google.auto.service.AutoService | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread | ||||
| import org.acra.ReportField | ||||
| import org.acra.config.CoreConfiguration | ||||
| import org.acra.config.toast | ||||
|  | @ -16,19 +19,24 @@ import kotlin.concurrent.thread | |||
| class CustomReportSender : ReportSender { | ||||
|     // Sends all your crashes to google forms | ||||
|     override fun send(context: Context, errorContent: CrashReportData) { | ||||
|         try { | ||||
|             println("Report sent") | ||||
|             val url = | ||||
|                 "https://docs.google.com/forms/u/0/d/e/1FAIpQLSeFmyBChi6HF3IkhTVWPiDXJtxt8W0Hf4Agljm_0-0_QuEYFg/formResponse" | ||||
|             val data = mapOf( | ||||
|                 "entry.134906550" to errorContent.toJSON() | ||||
|             ) | ||||
|             thread { | ||||
|         println("Sending report") | ||||
|         val url = | ||||
|             "https://docs.google.com/forms/u/0/d/e/1FAIpQLSeFmyBChi6HF3IkhTVWPiDXJtxt8W0Hf4Agljm_0-0_QuEYFg/formResponse" | ||||
|         val data = mapOf( | ||||
|             "entry.134906550" to errorContent.toJSON() | ||||
|         ) | ||||
| 
 | ||||
|         thread { // to not run it on main thread | ||||
|             normalSafeApiCall { | ||||
|                 val post = khttp.post(url, data = data) | ||||
|                 println("Report response: $post") | ||||
|             } | ||||
|         } catch (e: Exception) { | ||||
|             println("ERROR SENDING BUG") | ||||
|         } | ||||
| 
 | ||||
|         runOnMainThread { // to run it on main looper | ||||
|             normalSafeApiCall { | ||||
|                 Toast.makeText(context, R.string.acra_report_toast, Toast.LENGTH_SHORT).show() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -59,12 +67,12 @@ class AcraApplication : Application() { | |||
|                 ReportField.STACK_TRACE | ||||
|             ) | ||||
| 
 | ||||
|             // removed this due to bug when starting the app, moved it to when it actually crashes | ||||
|             //each plugin you chose above can be configured in a block like this: | ||||
|             toast { | ||||
|             /*toast { | ||||
|                 text = getString(R.string.acra_report_toast) | ||||
|                 //opening this block automatically enables the plugin. | ||||
|             } | ||||
| 
 | ||||
|             }*/ | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -14,16 +14,24 @@ import androidx.navigation.findNavController | |||
| import androidx.navigation.fragment.NavHostFragment | ||||
| import com.google.android.gms.cast.framework.CastButtonFactory | ||||
| import com.google.android.material.bottomnavigation.BottomNavigationView | ||||
| import com.lagradost.cloudstream3.UIHelper.checkWrite | ||||
| import com.lagradost.cloudstream3.UIHelper.getResourceColor | ||||
| import com.lagradost.cloudstream3.UIHelper.hasPIPPermission | ||||
| import com.lagradost.cloudstream3.UIHelper.requestRW | ||||
| import com.lagradost.cloudstream3.UIHelper.shouldShowPIPMode | ||||
| import com.lagradost.cloudstream3.APIHolder.apis | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.checkWrite | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.getResourceColor | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.hasPIPPermission | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.requestRW | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode | ||||
| import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver | ||||
| import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadChildFragment | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadFragment | ||||
| import com.lagradost.cloudstream3.ui.home.HomeFragment | ||||
| import com.lagradost.cloudstream3.ui.search.SearchFragment | ||||
| import com.lagradost.cloudstream3.ui.settings.SettingsFragment | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.loadResult | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getKey | ||||
| import com.lagradost.cloudstream3.utils.DataStore.removeKey | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos | ||||
| import kotlinx.android.synthetic.main.activity_main.* | ||||
| import kotlinx.android.synthetic.main.fragment_result.* | ||||
| 
 | ||||
| const val VLC_PACKAGE = "org.videolan.vlc" | ||||
|  | @ -90,6 +98,10 @@ class MainActivity : AppCompatActivity() { | |||
|                 navController.navigate(R.id.navigation_downloads, Bundle(), navOptions) | ||||
|                 return true | ||||
|             } | ||||
|             if(child is SearchFragment || child is HomeFragment || child is DownloadFragment || child is SettingsFragment) { | ||||
|                 this.finish() | ||||
|                 return true | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (currentFragment != null && supportFragmentManager.fragments.size > 2) { | ||||
|  | @ -134,12 +146,35 @@ class MainActivity : AppCompatActivity() { | |||
|         super.onDestroy() | ||||
|     } | ||||
| 
 | ||||
|     override fun onNewIntent(intent: Intent?) { | ||||
|         handleAppIntent(intent) | ||||
|         super.onNewIntent(intent) | ||||
|     } | ||||
| 
 | ||||
|     private fun handleAppIntent(intent: Intent?) { | ||||
|         if (intent == null) return | ||||
|         val str = intent.dataString | ||||
|         if (str != null) { | ||||
|             if (str.startsWith(DOWNLOAD_NAVIGATE_TO)) { | ||||
|                 findNavController(R.id.nav_host_fragment).navigate(R.id.navigation_downloads, null, navOptions) | ||||
|             } else { | ||||
|                 for (api in apis) { | ||||
|                     if (str.startsWith(api.mainUrl)) { | ||||
|                         loadResult(str, str, api.name) | ||||
|                         break | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
| 
 | ||||
|         window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) | ||||
| 
 | ||||
|         setContentView(R.layout.activity_main) | ||||
|         val navView: BottomNavigationView = findViewById(R.id.nav_view) | ||||
|         //  val navView: BottomNavigationView = findViewById(R.id.nav_view) | ||||
| 
 | ||||
|         //https://stackoverflow.com/questions/52594181/how-to-know-if-user-has-disabled-picture-in-picture-feature-permission | ||||
|         //https://developer.android.com/guide/topics/ui/picture-in-picture | ||||
|  | @ -159,7 +194,7 @@ class MainActivity : AppCompatActivity() { | |||
|             .setPopUpTo(navController.graph.startDestination, false) | ||||
|             .build() | ||||
| 
 | ||||
|         navView.setOnNavigationItemSelectedListener { item -> | ||||
|         nav_view.setOnNavigationItemSelectedListener { item -> | ||||
|             when (item.itemId) { | ||||
|                 R.id.navigation_home -> { | ||||
|                     navController.navigate(R.id.navigation_home, null, navOptions) | ||||
|  | @ -177,7 +212,7 @@ class MainActivity : AppCompatActivity() { | |||
|             true | ||||
|         } | ||||
| 
 | ||||
|         navView.itemRippleColor = ColorStateList.valueOf(getResourceColor(R.attr.colorPrimary, 0.1f)) | ||||
|         nav_view.itemRippleColor = ColorStateList.valueOf(getResourceColor(R.attr.colorPrimary, 0.1f)) | ||||
| 
 | ||||
|         if (!checkWrite()) { | ||||
|             requestRW() | ||||
|  | @ -244,5 +279,7 @@ class MainActivity : AppCompatActivity() { | |||
|                 } | ||||
|             } | ||||
|         }*/ | ||||
| 
 | ||||
|         handleAppIntent(intent) | ||||
|     } | ||||
| } | ||||
|  | @ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty | |||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.extractors.Vidstream | ||||
| import com.lagradost.cloudstream3.extractors.Vidstream | ||||
| import java.net.URLEncoder | ||||
| import java.util.* | ||||
| import kotlin.collections.ArrayList | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ package com.lagradost.cloudstream3.animeproviders | |||
| 
 | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.extractors.WcoStream | ||||
| import com.lagradost.cloudstream3.extractors.WcoStream | ||||
| import org.jsoup.Jsoup | ||||
| import org.jsoup.nodes.Document | ||||
| import java.util.* | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3.utils.extractors | ||||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| //{"auto":"/manifests/movies/15559/1624728920/qDwu5BOsfAwfTmnnjmkmXA/master.m3u8","1080p":"https://vdoc3.sallenes.space/qDwu5BOsfAwfTmnnjmkmXA/1624728920/storage6/movies/the-man-with-the-iron-heart-2017/1080p/index.m3u8","720p":"https://vdoc3.sallenes.space/qDwu5BOsfAwfTmnnjmkmXA/1624728920/storage6/movies/the-man-with-the-iron-heart-2017/720p/index.m3u8","360p":"https://vdoc3.sallenes.space/qDwu5BOsfAwfTmnnjmkmXA/1624728920/storage6/movies/the-man-with-the-iron-heart-2017/360p/index.m3u8","480p":"https://vdoc3.sallenes.space/qDwu5BOsfAwfTmnnjmkmXA/1624728920/storage6/movies/the-man-with-the-iron-heart-2017/480p/index.m3u8"} | ||||
| object M3u8Manifest { | ||||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3.utils.extractors | ||||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
| 
 | ||||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3.utils.extractors | ||||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
| 
 | ||||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3.utils.extractors | ||||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3.utils.extractors | ||||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3.utils.extractors | ||||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3.utils.extractors | ||||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3.utils.extractors | ||||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.pmap | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3.utils.extractors | ||||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3.utils.extractors | ||||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
|  | @ -5,7 +5,7 @@ import com.fasterxml.jackson.module.kotlin.readValue | |||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.APIHolder.unixTime | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.extractors.M3u8Manifest | ||||
| import com.lagradost.cloudstream3.extractors.M3u8Manifest | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import org.jsoup.Jsoup | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,12 +7,11 @@ import android.view.View | |||
| import android.widget.LinearLayout | ||||
| import android.widget.ProgressBar | ||||
| import android.widget.RelativeLayout | ||||
| import androidx.core.content.ContextCompat | ||||
| import com.google.android.gms.cast.framework.media.widget.MiniControllerFragment | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.adjustAlpha | ||||
| import com.lagradost.cloudstream3.UIHelper.colorFromAttribute | ||||
| import com.lagradost.cloudstream3.UIHelper.toPx | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.adjustAlpha | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.toPx | ||||
| 
 | ||||
| 
 | ||||
| class MyMiniControllerFragment : MiniControllerFragment() { | ||||
|  |  | |||
|  | @ -117,6 +117,8 @@ class DownloadChildAdapter( | |||
|             } | ||||
| 
 | ||||
|             title.text = d.name ?: "Episode ${d.episode}" //TODO FIX | ||||
|             title.isSelected = true // is needed for text repeating | ||||
| 
 | ||||
|             downloadButton.setUpButton( | ||||
|                 card.currentBytes, | ||||
|                 card.totalBytes, | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ import androidx.fragment.app.Fragment | |||
| import androidx.recyclerview.widget.GridLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.main | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getKey | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ import androidx.navigation.findNavController | |||
| import androidx.recyclerview.widget.GridLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.isMovieType | ||||
| import com.lagradost.cloudstream3.mvvm.observe | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick | ||||
|  | @ -21,6 +21,8 @@ import com.lagradost.cloudstream3.utils.DataStore.getFolderName | |||
| import com.lagradost.cloudstream3.utils.VideoDownloadManager | ||||
| import kotlinx.android.synthetic.main.fragment_downloads.* | ||||
| 
 | ||||
| const val DOWNLOAD_NAVIGATE_TO = "downloadpage" | ||||
| 
 | ||||
| class DownloadFragment : Fragment() { | ||||
|     private lateinit var downloadsViewModel: DownloadViewModel | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ import android.widget.TextView | |||
| import androidx.core.widget.ContentLoadingProgressBar | ||||
| import com.google.android.material.button.MaterialButton | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons | ||||
| import com.lagradost.cloudstream3.utils.Coroutines | ||||
| import com.lagradost.cloudstream3.utils.IDisposable | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadHelper | ||||
|  |  | |||
|  | @ -22,15 +22,15 @@ import com.lagradost.cloudstream3.AnimeSearchResponse | |||
| import com.lagradost.cloudstream3.HomePageResponse | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.SearchResponse | ||||
| import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.UIHelper.getGridIsCompact | ||||
| import com.lagradost.cloudstream3.UIHelper.loadSearchResult | ||||
| import com.lagradost.cloudstream3.UIHelper.popupMenuNoIconsAndNoStringRes | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes | ||||
| import com.lagradost.cloudstream3.mvvm.Resource | ||||
| import com.lagradost.cloudstream3.mvvm.observe | ||||
| import com.lagradost.cloudstream3.ui.AutofitRecyclerView | ||||
| import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST | ||||
| import com.lagradost.cloudstream3.ui.search.SearchAdapter | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getKey | ||||
| import com.lagradost.cloudstream3.utils.DataStore.setKey | ||||
| import com.lagradost.cloudstream3.utils.Event | ||||
|  |  | |||
|  | @ -57,27 +57,29 @@ import com.lagradost.cloudstream3.* | |||
| import com.lagradost.cloudstream3.MainActivity.Companion.isInPIPMode | ||||
| import com.lagradost.cloudstream3.MainActivity.Companion.isInPlayer | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.getFocusRequest | ||||
| import com.lagradost.cloudstream3.UIHelper.getNavigationBarHeight | ||||
| import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight | ||||
| import com.lagradost.cloudstream3.UIHelper.hideKeyboard | ||||
| import com.lagradost.cloudstream3.UIHelper.hideSystemUI | ||||
| import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable | ||||
| import com.lagradost.cloudstream3.UIHelper.popCurrentPage | ||||
| import com.lagradost.cloudstream3.UIHelper.requestLocalAudioFocus | ||||
| import com.lagradost.cloudstream3.UIHelper.showSystemUI | ||||
| import com.lagradost.cloudstream3.UIHelper.toPx | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.getNavigationBarHeight | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.getStatusBarHeight | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.hideSystemUI | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.showSystemUI | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.toPx | ||||
| import com.lagradost.cloudstream3.mvvm.Resource | ||||
| import com.lagradost.cloudstream3.mvvm.observe | ||||
| import com.lagradost.cloudstream3.mvvm.observeDirectly | ||||
| import com.lagradost.cloudstream3.ui.result.ResultEpisode | ||||
| import com.lagradost.cloudstream3.ui.result.ResultViewModel | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.getFocusRequest | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.getVideoContentUri | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.onAudioFocusEvent | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.requestLocalAudioFocus | ||||
| import com.lagradost.cloudstream3.utils.CastHelper.startCast | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getKey | ||||
| import com.lagradost.cloudstream3.utils.DataStore.setKey | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.UIHelper | ||||
| import com.lagradost.cloudstream3.utils.VIDEO_PLAYER_BRIGHTNESS | ||||
| import com.lagradost.cloudstream3.utils.getId | ||||
| import kotlinx.android.synthetic.main.fragment_player.* | ||||
|  | @ -1283,7 +1285,7 @@ class PlayerFragment : Fragment() { | |||
| 
 | ||||
|     override fun onResume() { | ||||
|         super.onResume() | ||||
|         UIHelper.onAudioFocusEvent += ::handlePauseEvent | ||||
|         onAudioFocusEvent += ::handlePauseEvent | ||||
| 
 | ||||
|         activity?.hideSystemUI() | ||||
|         activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE | ||||
|  | @ -1310,7 +1312,7 @@ class PlayerFragment : Fragment() { | |||
|         savePositionInPlayer() | ||||
|         safeReleasePlayer() | ||||
| 
 | ||||
|         UIHelper.onAudioFocusEvent -= ::handlePauseEvent | ||||
|         onAudioFocusEvent -= ::handlePauseEvent | ||||
| 
 | ||||
|         activity?.showSystemUI() | ||||
|         activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER | ||||
|  |  | |||
|  | @ -34,28 +34,28 @@ import com.google.android.material.button.MaterialButton | |||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.APIHolder.getApiFromName | ||||
| import com.lagradost.cloudstream3.APIHolder.getId | ||||
| import com.lagradost.cloudstream3.UIHelper.checkWrite | ||||
| import com.lagradost.cloudstream3.UIHelper.colorFromAttribute | ||||
| import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight | ||||
| import com.lagradost.cloudstream3.UIHelper.hideKeyboard | ||||
| import com.lagradost.cloudstream3.UIHelper.isAppInstalled | ||||
| import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable | ||||
| import com.lagradost.cloudstream3.UIHelper.isConnectedToChromecast | ||||
| import com.lagradost.cloudstream3.UIHelper.popCurrentPage | ||||
| import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons | ||||
| import com.lagradost.cloudstream3.UIHelper.popupMenuNoIconsAndNoStringRes | ||||
| import com.lagradost.cloudstream3.UIHelper.requestRW | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.checkWrite | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.getStatusBarHeight | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.requestRW | ||||
| import com.lagradost.cloudstream3.mvvm.Resource | ||||
| import com.lagradost.cloudstream3.mvvm.observe | ||||
| import com.lagradost.cloudstream3.ui.WatchType | ||||
| import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD | ||||
| import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO | ||||
| import com.lagradost.cloudstream3.ui.download.EasyDownloadButton | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick | ||||
| import com.lagradost.cloudstream3.ui.player.PlayerData | ||||
| import com.lagradost.cloudstream3.ui.player.PlayerFragment | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.isAppInstalled | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.isConnectedToChromecast | ||||
| import com.lagradost.cloudstream3.utils.CastHelper.startCast | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.main | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getFolderName | ||||
|  | @ -422,12 +422,16 @@ class ResultFragment : Fragment() { | |||
|                 } | ||||
| 
 | ||||
|                 context?.let { ctx -> | ||||
|                     val parentId = currentId ?: return@let | ||||
|                     val src = "$DOWNLOAD_NAVIGATE_TO/$parentId" // url ?: return@let | ||||
| 
 | ||||
|                     // SET VISUAL KEYS | ||||
|                     ctx.setKey( | ||||
|                         DOWNLOAD_HEADER_CACHE, (currentId ?: return@let).toString(), | ||||
|                         DOWNLOAD_HEADER_CACHE, parentId.toString(), | ||||
|                         VideoDownloadHelper.DownloadHeaderCached( | ||||
|                             apiName, | ||||
|                             url ?: return@let, | ||||
|                             slug ?: return@let, | ||||
|                             currentType ?: return@let, | ||||
|                             currentHeaderName ?: return@let, | ||||
|                             currentPoster ?: return@let, | ||||
|  | @ -439,7 +443,7 @@ class ResultFragment : Fragment() { | |||
|                     ctx.setKey( | ||||
|                         getFolderName( | ||||
|                             DOWNLOAD_EPISODE_CACHE, | ||||
|                             (currentId ?: return@let).toString() | ||||
|                             parentId.toString() | ||||
|                         ), // 3 deep folder for faster acess | ||||
|                         epData.id.toString(), | ||||
|                         VideoDownloadHelper.DownloadEpisodeCached( | ||||
|  | @ -448,7 +452,7 @@ class ResultFragment : Fragment() { | |||
|                             epData.episode, | ||||
|                             epData.season, | ||||
|                             epData.id, | ||||
|                             currentId ?: return@let, | ||||
|                             parentId, | ||||
|                             epData.rating, | ||||
|                             epData.descript | ||||
|                         ) | ||||
|  | @ -457,7 +461,7 @@ class ResultFragment : Fragment() { | |||
|                     // DOWNLOAD VIDEO | ||||
|                     VideoDownloadManager.downloadEpisode( | ||||
|                         ctx, | ||||
|                         url ?: return, | ||||
|                         src,//url ?: return, | ||||
|                         folder, | ||||
|                         meta, | ||||
|                         links | ||||
|  |  | |||
|  | @ -14,9 +14,9 @@ import com.lagradost.cloudstream3.AnimeSearchResponse | |||
| import com.lagradost.cloudstream3.DubStatus | ||||
| import com.lagradost.cloudstream3.SearchResponse | ||||
| import com.lagradost.cloudstream3.TvType | ||||
| import com.lagradost.cloudstream3.UIHelper.getGridFormatId | ||||
| import com.lagradost.cloudstream3.UIHelper.getGridIsCompact | ||||
| import com.lagradost.cloudstream3.UIHelper.toPx | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.getGridFormatId | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.toPx | ||||
| import com.lagradost.cloudstream3.ui.AutofitRecyclerView | ||||
| import kotlinx.android.synthetic.main.search_result_compact.view.backgroundCard | ||||
| import kotlinx.android.synthetic.main.search_result_compact.view.imageText | ||||
|  |  | |||
|  | @ -11,7 +11,6 @@ import android.view.inputmethod.InputMethodManager | |||
| import android.widget.ImageView | ||||
| import android.widget.Toast | ||||
| import androidx.appcompat.app.AlertDialog | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.appcompat.widget.SearchView | ||||
| import androidx.fragment.app.Fragment | ||||
| import androidx.lifecycle.ViewModelProvider | ||||
|  | @ -21,12 +20,11 @@ import com.lagradost.cloudstream3.APIHolder.allApi | |||
| import com.lagradost.cloudstream3.APIHolder.apis | ||||
| import com.lagradost.cloudstream3.APIHolder.getApiSettings | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.UIHelper.getGridIsCompact | ||||
| import com.lagradost.cloudstream3.UIHelper.loadResult | ||||
| import com.lagradost.cloudstream3.UIHelper.loadSearchResult | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact | ||||
| import com.lagradost.cloudstream3.mvvm.Resource | ||||
| import com.lagradost.cloudstream3.mvvm.observe | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult | ||||
| import kotlinx.android.synthetic.main.fragment_search.* | ||||
| 
 | ||||
| class SearchFragment : Fragment() { | ||||
|  | @ -167,6 +165,7 @@ class SearchFragment : Fragment() { | |||
|             } | ||||
|         } | ||||
|         main_search.onActionViewExpanded() | ||||
|         val q = 0 / 0 | ||||
|         //searchViewModel.search("iron man") | ||||
|         //(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro") | ||||
| /* | ||||
|  |  | |||
|  | @ -1,9 +1,28 @@ | |||
| package com.lagradost.cloudstream3.utils | ||||
| 
 | ||||
| import android.app.Activity | ||||
| import android.content.ContentValues | ||||
| import android.content.Context | ||||
| import android.content.pm.PackageManager | ||||
| import android.media.AudioAttributes | ||||
| import android.media.AudioFocusRequest | ||||
| import android.media.AudioManager | ||||
| import android.net.ConnectivityManager | ||||
| import android.net.NetworkCapabilities | ||||
| import android.net.Uri | ||||
| import android.os.Build | ||||
| import android.provider.MediaStore | ||||
| import android.view.View | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.preference.PreferenceManager | ||||
| import com.google.android.gms.cast.framework.CastContext | ||||
| import com.google.android.gms.cast.framework.CastState | ||||
| import com.google.android.gms.common.ConnectionResult | ||||
| import com.google.android.gms.common.GoogleApiAvailability | ||||
| import com.google.android.gms.common.wrappers.Wrappers | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.SearchResponse | ||||
| import com.lagradost.cloudstream3.ui.result.ResultFragment | ||||
| 
 | ||||
| object AppUtils { | ||||
|     fun getVideoContentUri(context: Context, videoFilePath: String): Uri? { | ||||
|  | @ -23,4 +42,117 @@ object AppUtils { | |||
|             ) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String, startAction: Int = 0) { | ||||
|         this.runOnUiThread { | ||||
|             viewModelStore.clear() | ||||
|             this.supportFragmentManager.beginTransaction() | ||||
|                 .setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit) | ||||
|                 .add(R.id.homeRoot, ResultFragment.newInstance(url, slug, apiName, startAction)) | ||||
|                 .commit() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun Activity?.loadSearchResult(card: SearchResponse, startAction: Int = 0) { | ||||
|         (this as AppCompatActivity?)?.loadResult(card.url, card.slug, card.apiName, startAction) | ||||
|     } | ||||
| 
 | ||||
|     fun Activity.requestLocalAudioFocus(focusRequest: AudioFocusRequest?) { | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && focusRequest != null) { | ||||
|             val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager | ||||
|             audioManager.requestAudioFocus(focusRequest) | ||||
|         } else { | ||||
|             val audioManager: AudioManager = | ||||
|                 getSystemService(Context.AUDIO_SERVICE) as AudioManager | ||||
|             audioManager.requestAudioFocus( | ||||
|                 null, | ||||
|                 AudioManager.STREAM_MUSIC, | ||||
|                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private var currentAudioFocusRequest: AudioFocusRequest? = null | ||||
|     private var currentAudioFocusChangeListener: AudioManager.OnAudioFocusChangeListener? = null | ||||
|     var onAudioFocusEvent = Event<Boolean>() | ||||
| 
 | ||||
|     private fun getAudioListener(): AudioManager.OnAudioFocusChangeListener? { | ||||
|         if (currentAudioFocusChangeListener != null) return currentAudioFocusChangeListener | ||||
|         currentAudioFocusChangeListener = AudioManager.OnAudioFocusChangeListener { | ||||
|             onAudioFocusEvent.invoke( | ||||
|                 when (it) { | ||||
|                     AudioManager.AUDIOFOCUS_GAIN -> false | ||||
|                     AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE -> false | ||||
|                     AudioManager.AUDIOFOCUS_GAIN_TRANSIENT -> false | ||||
|                     else -> true | ||||
|                 } | ||||
|             ) | ||||
|         } | ||||
|         return currentAudioFocusChangeListener | ||||
|     } | ||||
| 
 | ||||
|     fun Context.isCastApiAvailable(): Boolean { | ||||
|         val isCastApiAvailable = | ||||
|             GoogleApiAvailability.getInstance() | ||||
|                 .isGooglePlayServicesAvailable(applicationContext) == ConnectionResult.SUCCESS | ||||
|         try { | ||||
|             applicationContext?.let { CastContext.getSharedInstance(it) } | ||||
|         } catch (e: Exception) { | ||||
|             println(e) | ||||
|             // track non-fatal | ||||
|             return false | ||||
|         } | ||||
|         return isCastApiAvailable | ||||
|     } | ||||
| 
 | ||||
|     fun Context.isConnectedToChromecast(): Boolean { | ||||
|         if (isCastApiAvailable()) { | ||||
|             val castContext = CastContext.getSharedInstance(this) | ||||
|             if (castContext.castState == CastState.CONNECTED) { | ||||
|                 return true | ||||
|             } | ||||
|         } | ||||
|         return false | ||||
|     } | ||||
| 
 | ||||
|     fun Context.isUsingMobileData(): Boolean { | ||||
|         val conManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager | ||||
|         val networkInfo = conManager.allNetworks | ||||
|         return networkInfo.any { | ||||
|             conManager.getNetworkCapabilities(it)?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun Context.isAppInstalled(uri: String): Boolean { | ||||
|         val pm = Wrappers.packageManager(this) | ||||
|         var appInstalled = false | ||||
|         appInstalled = try { | ||||
|             pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES) | ||||
|             true | ||||
|         } catch (e: PackageManager.NameNotFoundException) { | ||||
|             false | ||||
|         } | ||||
|         return appInstalled | ||||
|     } | ||||
| 
 | ||||
|     fun getFocusRequest(): AudioFocusRequest? { | ||||
|         if (currentAudioFocusRequest != null) return currentAudioFocusRequest | ||||
|         currentAudioFocusRequest = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||
|             AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run { | ||||
|                 setAudioAttributes(AudioAttributes.Builder().run { | ||||
|                     setUsage(AudioAttributes.USAGE_MEDIA) | ||||
|                     setContentType(AudioAttributes.CONTENT_TYPE_MOVIE) | ||||
|                     build() | ||||
|                 }) | ||||
|                 setAcceptsDelayedFocusGain(true) | ||||
|                 getAudioListener()?.let { | ||||
|                     setOnAudioFocusChangeListener(it) | ||||
|                 } | ||||
|                 build() | ||||
|             } | ||||
|         } else { | ||||
|             null | ||||
|         } | ||||
|         return currentAudioFocusRequest | ||||
|     } | ||||
| } | ||||
|  | @ -1,5 +1,6 @@ | |||
| package com.lagradost.cloudstream3.utils | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.extractors.* | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.utils.extractors.* | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| package com.lagradost.cloudstream3 | ||||
| package com.lagradost.cloudstream3.utils | ||||
| 
 | ||||
| import android.Manifest | ||||
| import android.annotation.SuppressLint | ||||
|  | @ -11,8 +11,6 @@ import android.graphics.Color | |||
| import android.media.AudioAttributes | ||||
| import android.media.AudioFocusRequest | ||||
| import android.media.AudioManager | ||||
| import android.net.ConnectivityManager | ||||
| import android.net.NetworkCapabilities | ||||
| import android.os.Build | ||||
| import android.view.Gravity | ||||
| import android.view.MenuItem | ||||
|  | @ -21,7 +19,6 @@ import android.view.WindowManager | |||
| import android.view.inputmethod.InputMethodManager | ||||
| import androidx.annotation.AttrRes | ||||
| import androidx.annotation.ColorInt | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.appcompat.view.ContextThemeWrapper | ||||
| import androidx.appcompat.view.menu.MenuBuilder | ||||
| import androidx.appcompat.widget.PopupMenu | ||||
|  | @ -34,13 +31,7 @@ import androidx.core.graphics.red | |||
| import androidx.fragment.app.Fragment | ||||
| import androidx.fragment.app.FragmentActivity | ||||
| import androidx.preference.PreferenceManager | ||||
| import com.google.android.gms.cast.framework.CastContext | ||||
| import com.google.android.gms.cast.framework.CastState | ||||
| import com.google.android.gms.common.ConnectionResult | ||||
| import com.google.android.gms.common.GoogleApiAvailability | ||||
| import com.google.android.gms.common.wrappers.Wrappers.packageManager | ||||
| import com.lagradost.cloudstream3.ui.result.ResultFragment | ||||
| import com.lagradost.cloudstream3.utils.Event | ||||
| import com.lagradost.cloudstream3.R | ||||
| import kotlin.math.roundToInt | ||||
| 
 | ||||
| 
 | ||||
|  | @ -91,137 +82,6 @@ object UIHelper { | |||
|         return color | ||||
|     } | ||||
| 
 | ||||
|     fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String, startAction: Int = 0) { | ||||
|         this.runOnUiThread { | ||||
|             viewModelStore.clear() | ||||
|             this.supportFragmentManager.beginTransaction() | ||||
|                 .setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit) | ||||
|                 .add(R.id.homeRoot, ResultFragment.newInstance(url, slug, apiName, startAction)) | ||||
|                 .commit() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun Activity?.loadSearchResult(card: SearchResponse, startAction: Int = 0) { | ||||
|         (this as AppCompatActivity?)?.loadResult(card.url, card.slug, card.apiName, startAction) | ||||
|     } | ||||
| 
 | ||||
|     fun Context.getStatusBarHeight(): Int { | ||||
|         var result = 0 | ||||
|         val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android") | ||||
|         if (resourceId > 0) { | ||||
|             result = resources.getDimensionPixelSize(resourceId) | ||||
|         } | ||||
|         return result | ||||
|     } | ||||
| 
 | ||||
|     fun Context.getNavigationBarHeight(): Int { | ||||
|         var result = 0 | ||||
|         val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android") | ||||
|         if (resourceId > 0) { | ||||
|             result = resources.getDimensionPixelSize(resourceId) | ||||
|         } | ||||
|         return result | ||||
|     } | ||||
| 
 | ||||
|     fun Context.fixPaddingStatusbar(v: View) { | ||||
|         v.setPadding(v.paddingLeft, v.paddingTop + getStatusBarHeight(), v.paddingRight, v.paddingBottom) | ||||
|     } | ||||
| 
 | ||||
|     private fun Context.getGridFormat(): String { | ||||
|         val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) | ||||
|         return settingsManager.getString(getString(R.string.grid_format_key), "grid")!! | ||||
|     } | ||||
| 
 | ||||
|     fun Context.getGridFormatId(): Int { | ||||
|         return when (getGridFormat()) { | ||||
|             "list" -> R.layout.search_result_compact | ||||
|             "compact_list" -> R.layout.search_result_super_compact | ||||
|             else -> R.layout.search_result_grid | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun Context.getGridIsCompact(): Boolean { | ||||
|         return getGridFormat() != "grid" | ||||
|     } | ||||
| 
 | ||||
|     fun Activity.requestLocalAudioFocus(focusRequest: AudioFocusRequest?) { | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && focusRequest != null) { | ||||
|             val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager | ||||
|             audioManager.requestAudioFocus(focusRequest) | ||||
|         } else { | ||||
|             val audioManager: AudioManager = | ||||
|                 getSystemService(Context.AUDIO_SERVICE) as AudioManager | ||||
|             audioManager.requestAudioFocus( | ||||
|                 null, | ||||
|                 AudioManager.STREAM_MUSIC, | ||||
|                 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private var currentAudioFocusRequest: AudioFocusRequest? = null | ||||
|     private var currentAudioFocusChangeListener: AudioManager.OnAudioFocusChangeListener? = null | ||||
|     var onAudioFocusEvent = Event<Boolean>() | ||||
| 
 | ||||
|     private fun getAudioListener(): AudioManager.OnAudioFocusChangeListener? { | ||||
|         if (currentAudioFocusChangeListener != null) return currentAudioFocusChangeListener | ||||
|         currentAudioFocusChangeListener = AudioManager.OnAudioFocusChangeListener { | ||||
|             onAudioFocusEvent.invoke( | ||||
|                 when (it) { | ||||
|                     AudioManager.AUDIOFOCUS_GAIN -> false | ||||
|                     AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE -> false | ||||
|                     AudioManager.AUDIOFOCUS_GAIN_TRANSIENT -> false | ||||
|                     else -> true | ||||
|                 } | ||||
|             ) | ||||
|         } | ||||
|         return currentAudioFocusChangeListener | ||||
|     } | ||||
| 
 | ||||
|     fun Context.isCastApiAvailable(): Boolean { | ||||
|         val isCastApiAvailable = | ||||
|             GoogleApiAvailability.getInstance() | ||||
|                 .isGooglePlayServicesAvailable(applicationContext) == ConnectionResult.SUCCESS | ||||
|         try { | ||||
|             applicationContext?.let { CastContext.getSharedInstance(it) } | ||||
|         } catch (e: Exception) { | ||||
|             println(e) | ||||
|             // track non-fatal | ||||
|             return false | ||||
|         } | ||||
|         return isCastApiAvailable | ||||
|     } | ||||
| 
 | ||||
|     fun Context.isConnectedToChromecast(): Boolean { | ||||
|         if (isCastApiAvailable()) { | ||||
|             val castContext = CastContext.getSharedInstance(this) | ||||
|             if (castContext.castState == CastState.CONNECTED) { | ||||
|                 return true | ||||
|             } | ||||
|         } | ||||
|         return false | ||||
|     } | ||||
| 
 | ||||
|     fun Context.isUsingMobileData(): Boolean { | ||||
|         val conManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager | ||||
|         val networkInfo = conManager.allNetworks | ||||
|         return networkInfo.any { | ||||
|             conManager.getNetworkCapabilities(it)?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun Context.isAppInstalled(uri: String): Boolean { | ||||
|         val pm = packageManager(this) | ||||
|         var appInstalled = false | ||||
|         appInstalled = try { | ||||
|             pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES) | ||||
|             true | ||||
|         } catch (e: PackageManager.NameNotFoundException) { | ||||
|             false | ||||
|         } | ||||
|         return appInstalled | ||||
|     } | ||||
| 
 | ||||
|     fun adjustAlpha(@ColorInt color: Int, factor: Float): Int { | ||||
|         val alpha = (Color.alpha(color) * factor).roundToInt() | ||||
|         val red = Color.red(color) | ||||
|  | @ -237,27 +97,6 @@ object UIHelper { | |||
|         return color | ||||
|     } | ||||
| 
 | ||||
|     fun getFocusRequest(): AudioFocusRequest? { | ||||
|         if (currentAudioFocusRequest != null) return currentAudioFocusRequest | ||||
|         currentAudioFocusRequest = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||
|             AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run { | ||||
|                 setAudioAttributes(AudioAttributes.Builder().run { | ||||
|                     setUsage(AudioAttributes.USAGE_MEDIA) | ||||
|                     setContentType(AudioAttributes.CONTENT_TYPE_MOVIE) | ||||
|                     build() | ||||
|                 }) | ||||
|                 setAcceptsDelayedFocusGain(true) | ||||
|                 getAudioListener()?.let { | ||||
|                     setOnAudioFocusChangeListener(it) | ||||
|                 } | ||||
|                 build() | ||||
|             } | ||||
|         } else { | ||||
|             null | ||||
|         } | ||||
|         return currentAudioFocusRequest | ||||
|     } | ||||
| 
 | ||||
|     fun Activity.hideSystemUI() { | ||||
|         // Enables regular immersive mode. | ||||
|         // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE. | ||||
|  | @ -337,6 +176,43 @@ object UIHelper { | |||
|         } | ||||
|     }*/ | ||||
| 
 | ||||
|     fun Context.getStatusBarHeight(): Int { | ||||
|         var result = 0 | ||||
|         val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android") | ||||
|         if (resourceId > 0) { | ||||
|             result = resources.getDimensionPixelSize(resourceId) | ||||
|         } | ||||
|         return result | ||||
|     } | ||||
| 
 | ||||
|     fun Context.fixPaddingStatusbar(v: View) { | ||||
|         v.setPadding(v.paddingLeft, v.paddingTop + getStatusBarHeight(), v.paddingRight, v.paddingBottom) | ||||
|     } | ||||
|     fun Context.getNavigationBarHeight(): Int { | ||||
|         var result = 0 | ||||
|         val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android") | ||||
|         if (resourceId > 0) { | ||||
|             result = resources.getDimensionPixelSize(resourceId) | ||||
|         } | ||||
|         return result | ||||
|     } | ||||
| 
 | ||||
|     private fun Context.getGridFormat(): String { | ||||
|         val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) | ||||
|         return settingsManager.getString(getString(R.string.grid_format_key), "grid")!! | ||||
|     } | ||||
| 
 | ||||
|     fun Context.getGridFormatId(): Int { | ||||
|         return when (getGridFormat()) { | ||||
|             "list" -> R.layout.search_result_compact | ||||
|             "compact_list" -> R.layout.search_result_super_compact | ||||
|             else -> R.layout.search_result_grid | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun Context.getGridIsCompact(): Boolean { | ||||
|         return getGridFormat() != "grid" | ||||
|     } | ||||
| 
 | ||||
|     fun Activity.changeStatusBarState(hide: Boolean): Int { | ||||
|         return if (hide) { | ||||
|  | @ -16,7 +16,8 @@ object VideoDownloadHelper { | |||
| 
 | ||||
|     data class DownloadHeaderCached( | ||||
|         val apiName: String, | ||||
|         val source: String, | ||||
|         val url: String, | ||||
|         val slug : String, | ||||
|         val type : TvType, | ||||
|         val name: String, | ||||
|         val poster: String?, | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ import androidx.core.net.toUri | |||
| import com.bumptech.glide.Glide | ||||
| import com.lagradost.cloudstream3.MainActivity | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.colorFromAttribute | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute | ||||
| import com.lagradost.cloudstream3.mvvm.logError | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.services.VideoDownloadService | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ | |||
|                 android:layout_height="wrap_content" | ||||
|                 android:background="@color/darkBackground" | ||||
|                 app:itemRippleColor="@color/colorRipple" | ||||
|                 app:labelVisibilityMode="labeled" | ||||
| 
 | ||||
|                 app:layout_constraintLeft_toLeftOf="parent" | ||||
|                 app:layout_constraintRight_toRightOf="parent" | ||||
|  |  | |||
|  | @ -36,14 +36,24 @@ | |||
|                 android:layout_gravity="center_vertical" | ||||
|                 android:orientation="vertical" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_marginEnd="50dp" | ||||
|                 android:layout_width="match_parent" | ||||
|             > | ||||
|             <TextView | ||||
|                     android:id="@+id/download_child_episode_text" | ||||
|                     android:layout_marginStart="10dp" | ||||
|                     android:layout_marginEnd="10dp" | ||||
|                     android:layout_gravity="center_vertical" android:gravity="center_vertical" tools:text="Episode 1" | ||||
|                     android:textColor="@color/textColor" android:layout_width="wrap_content" | ||||
|                     android:layout_gravity="center_vertical" | ||||
|                     android:gravity="center_vertical" | ||||
|                     tools:text="Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1" | ||||
| 
 | ||||
|                     android:scrollHorizontally="true" | ||||
|                     android:ellipsize="marquee" | ||||
|                     android:marqueeRepeatLimit="marquee_forever" | ||||
|                     android:singleLine="true" | ||||
| 
 | ||||
|                     android:textColor="@color/textColor" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="match_parent"> | ||||
|             </TextView> | ||||
|             <TextView | ||||
|  | @ -57,9 +67,9 @@ | |||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="match_parent"> | ||||
|             </TextView> | ||||
| 
 | ||||
|         </LinearLayout> | ||||
|         <FrameLayout | ||||
|                 android:layout_marginStart="-50dp" | ||||
|                 android:layout_gravity="end" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="match_parent"> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue