diff --git a/app/build.gradle b/app/build.gradle index 9ffbc147..cad0a6f1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,8 +43,8 @@ repositories { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.3.2' - implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'androidx.core:core-ktx:1.5.0' + implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'com.google.android.material:material:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5' @@ -68,11 +68,11 @@ dependencies { implementation 'com.github.bumptech.glide:glide:4.12.0' implementation 'jp.wasabeef:glide-transformations:4.0.0' - implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0' + implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' // Exoplayer implementation 'com.google.android.exoplayer:exoplayer:2.14.0' implementation 'com.google.android.exoplayer:extension-cast:2.14.0' implementation "com.google.android.exoplayer:extension-mediasession:2.14.0" - implementation "com.google.android.exoplayer:extension-leanback:2.14.0" + //implementation "com.google.android.exoplayer:extension-leanback:2.14.0" } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0318a76c..c62789a7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,6 +14,9 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> + 0) { @@ -56,6 +62,15 @@ object UIHelper { 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 Activity.fixPaddingStatusbar(v: View) { v.setPadding(v.paddingLeft, v.paddingTop + getStatusBarHeight(), v.paddingRight, v.paddingBottom) } @@ -97,7 +112,7 @@ object UIHelper { var onAudioFocusEvent = Event() fun getAudioListener(): AudioManager.OnAudioFocusChangeListener? { - if(_OnAudioFocusChangeListener != null) return _OnAudioFocusChangeListener + if (_OnAudioFocusChangeListener != null) return _OnAudioFocusChangeListener _OnAudioFocusChangeListener = AudioManager.OnAudioFocusChangeListener { onAudioFocusEvent.invoke( when (it) { @@ -111,6 +126,20 @@ object UIHelper { return _OnAudioFocusChangeListener } + 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 getFocusRequest(): AudioFocusRequest? { if (_AudioFocusRequest != null) return _AudioFocusRequest return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -130,4 +159,89 @@ object UIHelper { null } } + + fun Activity.hideSystemUI() { + // Enables regular immersive mode. + // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE. + // Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY + window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + // Set the content to appear under the system bars so that the + // content doesn't resize when the system bars hide and show. + or View.SYSTEM_UI_FLAG_LAYOUT_STABLE + or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + // Hide the nav bar and status bar + or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_FULLSCREEN + // or View.SYSTEM_UI_FLAG_LOW_PROFILE + ) + // window.addFlags(View.KEEP_SCREEN_ON) + } + + fun FragmentActivity.popCurrentPage(isInPlayer: Boolean, isInExpandedView: Boolean, isInResults: Boolean) { + val currentFragment = supportFragmentManager.fragments.lastOrNull { + it.isVisible + } + ?: //this.onBackPressed() + return + +/* + if (tvActivity == null) { + requestedOrientation = if (settingsManager?.getBoolean("force_landscape", false) == true) { + ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE + } else { + ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + }*/ + + // No fucked animations leaving the player :) + when { + isInPlayer -> { + supportFragmentManager.beginTransaction() + //.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit) + .remove(currentFragment) + .commitAllowingStateLoss() + } + isInExpandedView && !isInResults -> { + supportFragmentManager.beginTransaction() + .setCustomAnimations( + R.anim.enter_anim,//R.anim.enter_from_right, + R.anim.exit_anim,//R.anim.exit_to_right, + R.anim.pop_enter, + R.anim.pop_exit + ) + .remove(currentFragment) + .commitAllowingStateLoss() + } + else -> { + supportFragmentManager.beginTransaction() + .setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit) + .remove(currentFragment) + .commitAllowingStateLoss() + } + } + } + + + fun Activity.changeStatusBarState(hide: Boolean): Int { + return if (hide) { + window?.setFlags( + WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN + ) + 0 + } else { + window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) + this.getStatusBarHeight() + } + } + + // Shows the system bars by removing all the flags + // except for the ones that make the content appear under the system bars. + fun Activity.showSystemUI() { + window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE + or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) + // window.clearFlags(View.KEEP_SCREEN_ON) + } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt index b8a4c662..900b14e0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt @@ -24,12 +24,12 @@ class ShiroProvider : MainAPI() { } } - fun autoLoadToken(): Boolean { + private fun autoLoadToken(): Boolean { if (token != null) return true return loadToken() } - fun loadToken(): Boolean { + private fun loadToken(): Boolean { return try { val response = khttp.get(mainUrl, headers = baseHeader) @@ -188,7 +188,7 @@ class ShiroProvider : MainAPI() { return AnimeLoadResponse( data.english, data.japanese, - data.canonicalTitle ?: data.name.replace("Dubbed", ""), + data.name.replace("Dubbed", ""),//data.canonicalTitle ?: data.name.replace("Dubbed", ""), "$mainUrl/${slug}", this.name, getType(data.type ?: ""), diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/ControllerActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/ControllerActivity.kt new file mode 100644 index 00000000..23f04b0c --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/ControllerActivity.kt @@ -0,0 +1,113 @@ +package com.lagradost.cloudstream3.ui + +import android.os.Bundle +import android.view.Menu +import android.view.View.INVISIBLE +import android.view.View.VISIBLE +import android.widget.ImageView +import androidx.appcompat.app.AlertDialog +import com.google.android.gms.cast.MediaStatus.REPEAT_MODE_REPEAT_SINGLE +import com.google.android.gms.cast.framework.CastButtonFactory +import com.google.android.gms.cast.framework.CastSession +import com.google.android.gms.cast.framework.media.uicontroller.UIController +import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity +import com.lagradost.cloudstream3.R + +import org.json.JSONObject + +class SkipOpController(val view: ImageView) : UIController() { + init { + view.setImageResource(R.drawable.exo_controls_fastforward) + view.setOnClickListener { + remoteMediaClient.seek(remoteMediaClient.approximateStreamPosition + 85000) + } + } +} + +class SelectSourceController(val view: ImageView) : UIController() { + + init { + view.setImageResource(R.drawable.ic_baseline_playlist_play_24) + view.setOnClickListener { + //remoteMediaClient.mediaQueue.itemCount + //println(remoteMediaClient.mediaInfo.customData) + //remoteMediaClient.queueJumpToItem() + lateinit var dialog: AlertDialog + val items = mutableListOf>() + for (i in 0 until remoteMediaClient.mediaQueue.itemCount) { + (remoteMediaClient.mediaQueue.getItemAtIndex(i)?.media?.customData?.get("data") as? String)?.let { name -> + items.add( + remoteMediaClient.mediaQueue.getItemAtIndex(i)!!.itemId to name + ) + } + } + + // TODO FIX + if (items.isNotEmpty()) { + val builder = AlertDialog.Builder(view.context, R.style.AlertDialogCustom) + builder.setTitle("Pick source") + + builder.setSingleChoiceItems( + items.map { it.second }.toTypedArray(), + remoteMediaClient.currentItem.itemId - 1 + ) { _, which -> + println( + remoteMediaClient.queueJumpToItem( + items[which].first, + remoteMediaClient.approximateStreamPosition, + null + ) + ) + dialog.dismiss() + } + dialog = builder.create() + dialog.show() + } + } + } + + override fun onMediaStatusUpdated() { + super.onMediaStatusUpdated() + // If there's 1 item it won't show + val dataString = remoteMediaClient.mediaQueue.getItemAtIndex(1)?.media?.customData?.get("data") as? String + view.visibility = if (dataString != null) VISIBLE else INVISIBLE + } + + override fun onSessionConnected(castSession: CastSession?) { + super.onSessionConnected(castSession) + remoteMediaClient.queueSetRepeatMode(REPEAT_MODE_REPEAT_SINGLE, JSONObject()) + } +} + +class SkipTimeController(val view: ImageView, forwards: Boolean) : UIController() { + init { + //val settingsManager = PreferenceManager.getDefaultSharedPreferences() + //val time = settingsManager?.getInt("chromecast_tap_time", 30) ?: 30 + val time = 30 + view.setImageResource(if (forwards) R.drawable.netflix_skip_forward else R.drawable.netflix_skip_back) + view.setOnClickListener { + remoteMediaClient.seek(remoteMediaClient.approximateStreamPosition + time * 1000 * if (forwards) 1 else -1) + } + } +} + +class ControllerActivity : ExpandedControllerActivity() { + override fun onCreateOptionsMenu(menu: Menu): Boolean { + super.onCreateOptionsMenu(menu) + menuInflater.inflate(R.menu.cast_expanded_controller_menu, menu) + CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item) + return true + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val sourcesButton: ImageView = getButtonImageViewAt(0) + val skipBackButton: ImageView = getButtonImageViewAt(1) + val skipForwardButton: ImageView = getButtonImageViewAt(2) + val skipOpButton: ImageView = getButtonImageViewAt(3) + uiMediaController.bindViewToUIController(sourcesButton, SelectSourceController(sourcesButton)) + uiMediaController.bindViewToUIController(skipBackButton, SkipTimeController(skipBackButton, false)) + uiMediaController.bindViewToUIController(skipForwardButton, SkipTimeController(skipForwardButton, true)) + uiMediaController.bindViewToUIController(skipOpButton, SkipOpController(skipOpButton)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt index 44ab4832..9804abdc 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt @@ -12,6 +12,7 @@ import android.graphics.Color import android.media.AudioManager import android.net.Uri import android.os.* +import android.util.DisplayMetrics import android.view.LayoutInflater import android.view.MotionEvent import android.view.View @@ -20,7 +21,7 @@ import android.view.ViewGroup import android.view.animation.* import android.widget.ProgressBar import android.widget.Toast -import android.widget.Toast.LENGTH_LONG +import android.widget.Toast.LENGTH_SHORT import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment @@ -33,6 +34,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.module.kotlin.KotlinModule import com.google.android.exoplayer2.* +import com.google.android.exoplayer2.C.TIME_UNSET import com.google.android.exoplayer2.source.DefaultMediaSourceFactory import com.google.android.exoplayer2.trackselection.DefaultTrackSelector import com.google.android.exoplayer2.ui.AspectRatioFrameLayout @@ -43,7 +45,12 @@ import com.google.android.exoplayer2.util.MimeTypes import com.lagradost.cloudstream3.* 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.hideSystemUI +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.mvvm.Resource import com.lagradost.cloudstream3.mvvm.observeDirectly @@ -64,6 +71,7 @@ import javax.net.ssl.SSLSession import kotlin.concurrent.thread import kotlin.math.abs import kotlin.math.ceil +import kotlin.properties.Delegates //http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4 @@ -123,11 +131,13 @@ class PlayerFragment : Fragment() { //private var currentPercentage = 0 // private var hasNextEpisode = true - val formatBuilder = StringBuilder() - val formatter = Formatter(formatBuilder, Locale.getDefault()) + // val formatBuilder = StringBuilder() + // val formatter = Formatter(formatBuilder, Locale.getDefault()) private var width = Resources.getSystem().displayMetrics.heightPixels private var height = Resources.getSystem().displayMetrics.widthPixels + private var statusBarHeight by Delegates.notNull() + private var navigationBarHeight by Delegates.notNull() private var isLocked = false @@ -271,27 +281,38 @@ class PlayerFragment : Fragment() { private val swipeVerticalEnabled = true//settingsManager.getBoolean("swipe_vertical_enabled", true) private val playBackSpeedEnabled = true//settingsManager!!.getBoolean("playback_speed_enabled", false) private val playerResizeEnabled = true//settingsManager!!.getBoolean("player_resize_enabled", false) + private val swipeEdgeSize = 10.toPx private var isMovingStartTime = 0L private var currentX = 0F private var currentY = 0F private var cachedVolume = 0f + private var isValidTouch = false fun handleMotionEvent(motionEvent: MotionEvent) { // TIME_UNSET == -9223372036854775807L // No swiping on unloaded // https://exoplayer.dev/doc/reference/constant-values.html - if (isLocked || exoPlayer.duration == -9223372036854775807L || (!swipeEnabled && !swipeVerticalEnabled)) return + if (isLocked || exoPlayer.duration == TIME_UNSET || (!swipeEnabled && !swipeVerticalEnabled)) return + + val audioManager = activity?.getSystemService(AUDIO_SERVICE) as? AudioManager when (motionEvent.action) { MotionEvent.ACTION_DOWN -> { - currentX = motionEvent.rawX - currentY = motionEvent.rawY - //println("DOWN: " + currentX) - isMovingStartTime = exoPlayer.currentPosition + // SO YOU CAN PULL DOWN STATUSBAR OR NAVBAR + if (motionEvent.rawY > statusBarHeight && motionEvent.rawX < width - navigationBarHeight) { + currentX = motionEvent.rawX + currentY = motionEvent.rawY + isValidTouch = true + //println("DOWN: " + currentX) + isMovingStartTime = exoPlayer.currentPosition + } else { + isValidTouch = false + } } MotionEvent.ACTION_MOVE -> { + if (!isValidTouch) return if (swipeVerticalEnabled) { val distanceMultiplierY = 2F val distanceY = (motionEvent.rawY - currentY) * distanceMultiplierY @@ -382,6 +403,7 @@ class PlayerFragment : Fragment() { } } MotionEvent.ACTION_UP -> { + if (!isValidTouch) return val transition: Transition = Fade() transition.duration = 1000 @@ -417,7 +439,9 @@ class PlayerFragment : Fragment() { } fun changeSkip(position: Long? = null) { - if (exoPlayer.currentPosition >= 0) { + val data = localData + + if (this::exoPlayer.isInitialized && exoPlayer.currentPosition >= 0) { val percentage = ((position ?: exoPlayer.currentPosition) * 100 / exoPlayer.contentDuration).toInt() val hasNext = hasNextEpisode() @@ -433,13 +457,17 @@ class PlayerFragment : Fragment() { } val nextEp = percentage >= OPENING_PROCENTAGE - val data = localData - skip_op_text.text = if (nextEp) "Next Episode" else "Skip OP" val isVis = if (nextEp) hasNext //&& !isCurrentlySkippingEp else (data is AnimeLoadResponse && (data.type == TvType.Anime || data.type == TvType.ONA)) skip_op.visibility = if (isVis) View.VISIBLE else View.GONE + } else { + if(data is AnimeLoadResponse) { + val isVis = ((data.type == TvType.Anime || data.type == TvType.ONA)) + skip_op_text.text = "Skip OP" + skip_op.visibility = if (isVis) View.VISIBLE else View.GONE + } } } @@ -557,6 +585,9 @@ class PlayerFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + navigationBarHeight = requireContext().getNavigationBarHeight() + statusBarHeight = requireContext().getStatusBarHeight() + if (savedInstanceState != null) { currentWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW) playbackPosition = savedInstanceState.getLong(STATE_RESUME_POSITION) @@ -711,7 +742,7 @@ class PlayerFragment : Fragment() { override fun onSingleClick() { onClickChange() - // activity?.hideSystemUI() + activity?.hideSystemUI() } override fun onMotionEvent(event: MotionEvent) { @@ -727,6 +758,14 @@ class PlayerFragment : Fragment() { Listener() ) + video_go_back.setOnClickListener { + activity?.popCurrentPage(isInPlayer = true, isInExpandedView = false, isInResults = false) + } + video_go_back_holder.setOnClickListener { + println("video_go_back_pressed") + activity?.popCurrentPage(isInPlayer = true, isInExpandedView = false, isInResults = false) + } + playback_speed_btt.visibility = if (playBackSpeedEnabled) VISIBLE else GONE playback_speed_btt.setOnClickListener { lateinit var dialog: AlertDialog @@ -799,6 +838,8 @@ class PlayerFragment : Fragment() { skipOP() } } + + changeSkip() } private fun getCurrentUrl(): ExtractorLink? { @@ -844,6 +885,24 @@ class PlayerFragment : Fragment() { private var isCurrentlySkippingEp = false + + fun tryNextMirror() { + val urls = getUrls() + val current = getCurrentUrl() + if (urls != null && current != null) { + val id = current.getId() + val sorted = sortUrls(urls) + for ((i, item) in sorted.withIndex()) { + if (item.getId() == id) { + if (sorted.size > i + 1) { + setMirrorId(sorted[i + 1].getId()) + initPlayer() + } + } + } + } + } + private fun skipToNextEpisode() { if (isCurrentlySkippingEp) return isCurrentlySkippingEp = true @@ -868,6 +927,7 @@ class PlayerFragment : Fragment() { override fun onResume() { super.onResume() + activity?.hideSystemUI() activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE thread { initPlayer() @@ -878,6 +938,8 @@ class PlayerFragment : Fragment() { override fun onDestroy() { super.onDestroy() // releasePlayer() + + activity?.showSystemUI() activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER } @@ -1084,11 +1146,12 @@ class PlayerFragment : Fragment() { override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) { // updatePIPModeActions() + if(activity == null) return if (playWhenReady) { when (playbackState) { Player.STATE_READY -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - requireActivity().requestLocalAudioFocus(getFocusRequest()) + activity?.requestLocalAudioFocus(getFocusRequest()) } } Player.STATE_ENDED -> { @@ -1113,20 +1176,21 @@ class PlayerFragment : Fragment() { Toast.makeText( activity, "Source error\n" + error.sourceException.message, - LENGTH_LONG + LENGTH_SHORT ) .show() + tryNextMirror() } } ExoPlaybackException.TYPE_REMOTE -> { - Toast.makeText(activity, "Remote error", LENGTH_LONG) + Toast.makeText(activity, "Remote error", LENGTH_SHORT) .show() } ExoPlaybackException.TYPE_RENDERER -> { Toast.makeText( activity, "Renderer error\n" + error.rendererException.message, - LENGTH_LONG + LENGTH_SHORT ) .show() } @@ -1134,7 +1198,7 @@ class PlayerFragment : Fragment() { Toast.makeText( activity, "Unexpected player error\n" + error.unexpectedException.message, - LENGTH_LONG + LENGTH_SHORT ).show() } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt index 03dd26d1..7f6a1dde 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt @@ -9,8 +9,6 @@ import android.widget.LinearLayout import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.APIHolder.getApiFromName -import com.lagradost.cloudstream3.utils.ExtractorLink import kotlinx.android.synthetic.main.result_episode.view.* const val ACTION_PLAY_EPISODE = 1 @@ -50,20 +48,19 @@ class EpisodeAdapter( class CardViewHolder constructor( itemView: View, - _activity: Activity, + val activity: Activity, resView: RecyclerView, - clickCallback: (EpisodeClickEvent) -> Unit, + private val clickCallback: (EpisodeClickEvent) -> Unit, ) : RecyclerView.ViewHolder(itemView) { - val activity = _activity - val episode_view_procentage: View = itemView.episode_view_procentage - val episode_view_procentage_off: View = itemView.episode_view_procentage_off - val episode_text: TextView = itemView.episode_text - val episode_extra: ImageView = itemView.episode_extra - val episode_play: ImageView = itemView.episode_play - val clickCallback = clickCallback + private val episodeViewPrecentage: View = itemView.episode_view_procentage + private val episodeViewPercentageOff: View = itemView.episode_view_procentage_off + private val episodeText: TextView = itemView.episode_text + val episodeExtra: ImageView = itemView.episode_extra + private val episodePlay: ImageView = itemView.episode_play + private val episodeHolder = itemView.episode_holder fun bind(card: ResultEpisode) { - episode_text.text = card.name ?: "Episode ${card.episode}" + episodeText.text = card.name ?: "Episode ${card.episode}" fun setWidth(v: View, procentage: Float) { val param = LinearLayout.LayoutParams( @@ -73,10 +70,10 @@ class EpisodeAdapter( ) v.layoutParams = param } - setWidth(episode_view_procentage, card.watchProgress) - setWidth(episode_view_procentage_off, 1 - card.watchProgress) + setWidth(episodeViewPrecentage, card.watchProgress) + setWidth(episodeViewPercentageOff, 1 - card.watchProgress) - episode_play.setOnClickListener { + episodeHolder.setOnClickListener { clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE, card)) } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt index cd107b68..b5a5eee2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt @@ -1,35 +1,33 @@ package com.lagradost.cloudstream3.ui.result -import android.Manifest import android.annotation.SuppressLint -import android.app.Activity -import android.content.ComponentName -import android.content.Intent -import android.content.Intent.* -import android.content.pm.PackageManager import android.os.Bundle import android.view.LayoutInflater import android.view.View +import android.view.View.GONE +import android.view.View.VISIBLE import android.view.ViewGroup import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat -import androidx.core.content.FileProvider -import androidx.core.net.toUri import androidx.core.widget.NestedScrollView import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider +import androidx.mediarouter.app.MediaRouteButton import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.request.RequestOptions.bitmapTransform -import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.UIHelper.checkWrite +import com.google.android.gms.cast.framework.CastButtonFactory +import com.google.android.gms.cast.framework.CastContext +import com.google.android.gms.cast.framework.CastState +import com.google.android.material.button.MaterialButton +import com.lagradost.cloudstream3.AnimeLoadResponse +import com.lagradost.cloudstream3.LoadResponse +import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.ShowStatus import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar -import com.lagradost.cloudstream3.UIHelper.loadResult -import com.lagradost.cloudstream3.UIHelper.requestRW +import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.ui.player.PlayerData @@ -37,10 +35,8 @@ import com.lagradost.cloudstream3.ui.player.PlayerFragment import com.lagradost.cloudstream3.utils.ExtractorLink import jp.wasabeef.glide.transformations.BlurTransformation import kotlinx.android.synthetic.main.fragment_result.* -import java.io.File - -const val MAX_SYNO_LENGH = 600 +const val MAX_SYNO_LENGH = 300 data class ResultEpisode( val name: String?, @@ -89,17 +85,34 @@ class ResultFragment : Fragment() { super.onViewCreated(view, savedInstanceState) activity?.fixPaddingStatusbar(result_scroll) activity?.fixPaddingStatusbar(result_barstatus) + + if (activity?.isCastApiAvailable() == true) { + val mMediaRouteButton = view.findViewById(R.id.media_route_button) + + 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) val url = arguments?.getString("url") val slug = arguments?.getString("slug") val apiName = arguments?.getString("apiName") - result_scroll.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, oldScrollY -> + result_scroll.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, _ -> if (result_poster_blur == null) return@OnScrollChangeListener - result_poster_blur.alpha = maxOf(0f, (0.3f - scrollY / 1000f)) - result_barstatus.alpha = scrollY / 200f - result_barstatus.visibility = if (scrollY > 0) View.VISIBLE else View.GONE + result_poster_blur.alpha = maxOf(0f, (0.7f - scrollY / 1000f)) + result_poster_blur_holder.translationY = -scrollY.toFloat() + //result_barstatus.alpha = scrollY / 200f + //result_barstatus.visibility = if (scrollY > 0) View.VISIBLE else View.GONEĀ§ }) result_toolbar.setNavigationIcon(R.drawable.ic_baseline_arrow_back_24) @@ -159,6 +172,7 @@ class ResultFragment : Fragment() { observe(viewModel.episodes) { episodes -> if (result_episodes == null || result_episodes.adapter == null) return@observe + result_episodes_text.text = "${episodes.size} Episode${if (episodes.size == 1) "" else "s"}" (result_episodes.adapter as EpisodeAdapter).cardList = episodes (result_episodes.adapter as EpisodeAdapter).notifyDataSetChanged() } @@ -180,15 +194,15 @@ class ResultFragment : Fragment() { if (d.posterUrl != null) { val glideUrl = GlideUrl(d.posterUrl) - context!!.let { - /* - Glide.with(it) - .load(glideUrl) - .into(result_poster)*/ + requireContext().let { Glide.with(it) .load(glideUrl) - .apply(bitmapTransform(BlurTransformation(10, 3))) + .into(result_poster) + + Glide.with(it) + .load(glideUrl) + .apply(bitmapTransform(BlurTransformation(80, 3))) .into(result_poster_blur) } } @@ -265,14 +279,38 @@ activity?.startActivityForResult(vlcIntent, REQUEST_CODE) result_descript.text = "No Plot found" } + result_tag.removeAllViews() + result_tag_holder.visibility = View.GONE + result_status.visibility = View.GONE + when (d) { is AnimeLoadResponse -> { - val preferEnglish = true - val titleName = (if (preferEnglish) d.engName else d.japName) ?: d.name + result_status.visibility = View.VISIBLE + result_status.text = when (d.showStatus) { + null -> "" + ShowStatus.Ongoing -> "Ongoing" + ShowStatus.Completed -> "Completed" + } + + // val preferEnglish = true + //val titleName = (if (preferEnglish) d.engName else d.japName) ?: d.name + val titleName = d.name result_title.text = titleName result_toolbar.title = titleName - result_tags.text = (d.tags ?: ArrayList()).joinToString(separator = " | ") + if (d.tags == null) { + result_tag_holder.visibility = View.GONE + } else { + result_tag_holder.visibility = View.VISIBLE + + for ((index, tag) in d.tags.withIndex()) { + val viewBtt = layoutInflater.inflate(R.layout.result_tag, null) + val btt = viewBtt.findViewById(R.id.result_tag_card) + btt.text = tag + + result_tag.addView(viewBtt, index) + } + } } else -> result_title.text = d.name } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt index 703ba153..5cd47546 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt @@ -24,21 +24,18 @@ import kotlinx.android.synthetic.main.search_result_grid.view.* import kotlin.math.roundToInt class SearchAdapter( - activity: Activity, - animeList: ArrayList, - resView: AutofitRecyclerView, + private var activity: Activity, + var cardList: ArrayList, + private val resView: AutofitRecyclerView, ) : RecyclerView.Adapter() { - var cardList = animeList - private var activity: Activity = activity - var resView: AutofitRecyclerView? = resView override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val layout = activity.getGridFormatId() return CardViewHolder( LayoutInflater.from(parent.context).inflate(layout, parent, false), activity, - resView!! + resView ) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt index c7ac7062..701c6c28 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt @@ -20,6 +20,7 @@ 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.mvvm.Resource import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.ui.player.PlayerData @@ -41,11 +42,7 @@ class SearchFragment : Fragment() { return inflater.inflate(R.layout.fragment_search, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - activity?.fixPaddingStatusbar(searchRoot) - + private fun fixGrid() { val compactView = activity?.getGridIsCompact() ?: false val spanCountLandscape = if (compactView) 2 else 6 val spanCountPortrait = if (compactView) 1 else 3 @@ -56,6 +53,18 @@ class SearchFragment : Fragment() { } else { cardSpace.spanCount = spanCountPortrait } + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + fixGrid() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + activity?.fixPaddingStatusbar(searchRoot) + fixGrid() val adapter: RecyclerView.Adapter? = activity?.let { SearchAdapter( @@ -129,7 +138,7 @@ class SearchFragment : Fragment() { search_exit_icon.alpha = 1f search_loading_bar.alpha = 0f } - + (activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro") /* (requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction() .setCustomAnimations(R.anim.enter_anim, diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt index d75cbd15..8e9c7a4b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt @@ -11,7 +11,7 @@ import com.lagradost.cloudstream3.mvvm.safeApiCall import kotlinx.coroutines.launch class SearchViewModel : ViewModel() { - val api: MainAPI = apis[0] + val api: MainAPI = apis[0] //TODO MULTI API private val _searchResponse: MutableLiveData>> = MutableLiveData() val searchResponse: LiveData>> get() = _searchResponse diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/CastOptionsProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/CastOptionsProvider.kt new file mode 100644 index 00000000..908a8668 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/CastOptionsProvider.kt @@ -0,0 +1,47 @@ +package com.lagradost.cloudstream3.utils + +import android.content.Context +import com.google.android.gms.cast.framework.CastOptions +import com.google.android.gms.cast.framework.OptionsProvider +import com.google.android.gms.cast.framework.SessionProvider +import com.google.android.gms.cast.framework.media.CastMediaOptions +import com.google.android.gms.cast.framework.media.MediaIntentReceiver +import com.google.android.gms.cast.framework.media.NotificationOptions +import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.ui.ControllerActivity +import java.util.* + +class CastOptionsProvider : OptionsProvider { + override fun getCastOptions(p0: Context?): CastOptions { + val buttonActions = listOf( + MediaIntentReceiver.ACTION_REWIND, + MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK, + MediaIntentReceiver.ACTION_FORWARD, + MediaIntentReceiver.ACTION_STOP_CASTING + ) + val compatButtonAction = intArrayOf(1,3) + val notificationOptions = + NotificationOptions.Builder() + .setTargetActivityClassName(ControllerActivity::class.qualifiedName) + .setActions(buttonActions, compatButtonAction) + .setForward30DrawableResId(R.drawable.go_forward_30) + .setRewind30DrawableResId(R.drawable.go_back_30) + .setSkipStepMs(30000) + .build() + + val mediaOptions = CastMediaOptions.Builder() + .setNotificationOptions(notificationOptions) + .setExpandedControllerActivityClassName(ControllerActivity::class.qualifiedName) + .build() + + return CastOptions.Builder() + .setReceiverApplicationId("A12D4273") + .setStopReceiverApplicationWhenEndingSession(true) + .setCastMediaOptions(mediaOptions) + .build() + } + + override fun getAdditionalSessionProviders(p0: Context?): MutableList { + return Collections.emptyList() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Vidstream.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Vidstream.kt index 1d61c40e..7cc510cc 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Vidstream.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Vidstream.kt @@ -17,17 +17,18 @@ class Vidstream { // https://gogo-stream.com/streaming.php?id=MTE3NDg5 fun getUrl(id: String, isCasting: Boolean = false, callback: (ExtractorLink) -> Unit) : Boolean { try { + normalApis.pmap { api -> + val url = api.getExtractorUrl(id) + val source = api.getUrl(url) + source?.forEach { callback.invoke(it) } + } + val url = getExtractorUrl(id) with(khttp.get(url)) { val document = Jsoup.parse(this.text) val primaryLinks = document.select("ul.list-server-items > li.linkserver") val extractedLinksList: MutableList = mutableListOf() - normalApis.pmap { api -> - val url = api.getExtractorUrl(id) - val source = api.getUrl(url) - source?.forEach { callback.invoke(it) } - } // All vidstream links passed to extractors primaryLinks.forEach { element -> diff --git a/app/src/main/java/com/lagradost/cloudstream3/widget/FlowLayout.kt b/app/src/main/java/com/lagradost/cloudstream3/widget/FlowLayout.kt new file mode 100644 index 00000000..892701f6 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/widget/FlowLayout.kt @@ -0,0 +1,98 @@ +package com.lagradost.cloudstream3.widget + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.ViewGroup +import com.lagradost.cloudstream3.R +import kotlin.math.max + +class FlowLayout : ViewGroup { + constructor(context: Context?) : super(context) {} + + @JvmOverloads + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int = 0) : super(context, attrs, defStyleAttr) { + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val realWidth = MeasureSpec.getSize(widthMeasureSpec) + var currentHeight = 0 + var currentWidth = 0 + var currentChildHookPointx = 0 + var currentChildHookPointy = 0 + val childCount = this.childCount + for (i in 0 until childCount) { + val child = getChildAt(i) + measureChild(child, widthMeasureSpec, heightMeasureSpec) + val childWidth = child.measuredWidth + val childHeight = child.measuredHeight + + //check if child can be placed in the current row, else go to next line + if (currentChildHookPointx + childWidth > realWidth) { + //new line + currentWidth = Math.max(currentWidth, currentChildHookPointx) + + //reset for new line + currentChildHookPointx = 0 + currentChildHookPointy += childHeight + } + val nextChildHookPointx = currentChildHookPointx + childWidth + val nextChildHookPointy = currentChildHookPointy + currentHeight = max(currentHeight, currentChildHookPointy + childHeight) + val lp = child.layoutParams as LayoutParams + lp.x = currentChildHookPointx + lp.y = currentChildHookPointy + currentChildHookPointx = nextChildHookPointx + currentChildHookPointy = nextChildHookPointy + } + currentWidth = Math.max(currentChildHookPointx, currentWidth) + setMeasuredDimension(resolveSize(currentWidth, widthMeasureSpec), + resolveSize(currentHeight, heightMeasureSpec)) + } + + override fun onLayout(b: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + //call layout on children + val childCount = this.childCount + for (i in 0 until childCount) { + val child = getChildAt(i) + val lp = child.layoutParams as LayoutParams + child.layout(lp.x, lp.y, lp.x + child.measuredWidth, lp.y + child.measuredHeight) + } + } + + override fun generateLayoutParams(attrs: AttributeSet): LayoutParams { + return LayoutParams(context, attrs) + } + + override fun generateDefaultLayoutParams(): LayoutParams { + return LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + } + + override fun generateLayoutParams(p: ViewGroup.LayoutParams): LayoutParams { + return LayoutParams(p) + } + + override fun checkLayoutParams(p: ViewGroup.LayoutParams): Boolean { + return p is LayoutParams + } + + class LayoutParams : MarginLayoutParams { + var spacing = -1 + var x = 0 + var y = 0 + + @SuppressLint("CustomViewStyleable") + internal constructor(c: Context, attrs: AttributeSet?) : super(c, attrs) { + val t = c.obtainStyledAttributes(attrs, R.styleable.FlowLayout_Layout) + spacing = 0 //t.getDimensionPixelSize(R.styleable.FlowLayout_Layout_layout_space, 0); + t.recycle() + } + + internal constructor(width: Int, height: Int) : super(width, height) { + spacing = 0 + } + + constructor(source: MarginLayoutParams?) : super(source) {} + internal constructor(source: ViewGroup.LayoutParams?) : super(source) {} + } +} \ No newline at end of file diff --git a/app/src/main/res/anim/.idea/.gitignore b/app/src/main/res/anim/.idea/.gitignore new file mode 100644 index 00000000..26d33521 --- /dev/null +++ b/app/src/main/res/anim/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/app/src/main/res/anim/.idea/misc.xml b/app/src/main/res/anim/.idea/misc.xml new file mode 100644 index 00000000..639900d1 --- /dev/null +++ b/app/src/main/res/anim/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/.idea/modules.xml b/app/src/main/res/anim/.idea/modules.xml new file mode 100644 index 00000000..787e58e6 --- /dev/null +++ b/app/src/main/res/anim/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/.idea/vcs.xml b/app/src/main/res/anim/.idea/vcs.xml new file mode 100644 index 00000000..bc599707 --- /dev/null +++ b/app/src/main/res/anim/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 1ee14938..00000000 --- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/cs3_cloud.xml b/app/src/main/res/drawable/cs3_cloud.xml new file mode 100644 index 00000000..d8fc1dbd --- /dev/null +++ b/app/src/main/res/drawable/cs3_cloud.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/go_back_30.xml b/app/src/main/res/drawable/go_back_30.xml new file mode 100644 index 00000000..8ab536ee --- /dev/null +++ b/app/src/main/res/drawable/go_back_30.xml @@ -0,0 +1,19 @@ + + + + diff --git a/app/src/main/res/drawable/go_forward_30.xml b/app/src/main/res/drawable/go_forward_30.xml new file mode 100644 index 00000000..d3ba0af9 --- /dev/null +++ b/app/src/main/res/drawable/go_forward_30.xml @@ -0,0 +1,19 @@ + + + + diff --git a/app/src/main/res/drawable/ic_baseline_arrow_back_24.xml b/app/src/main/res/drawable/ic_baseline_arrow_back_24.xml index 31e7df2e..a6108143 100644 --- a/app/src/main/res/drawable/ic_baseline_arrow_back_24.xml +++ b/app/src/main/res/drawable/ic_baseline_arrow_back_24.xml @@ -1,5 +1,5 @@ diff --git a/app/src/main/res/drawable/ic_baseline_aspect_ratio_24.xml b/app/src/main/res/drawable/ic_baseline_aspect_ratio_24.xml index c7b8b5f5..d93d1b64 100644 --- a/app/src/main/res/drawable/ic_baseline_aspect_ratio_24.xml +++ b/app/src/main/res/drawable/ic_baseline_aspect_ratio_24.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/drawable/ic_baseline_bookmark_24.xml b/app/src/main/res/drawable/ic_baseline_bookmark_24.xml index 8f0b1b18..542456d8 100644 --- a/app/src/main/res/drawable/ic_baseline_bookmark_24.xml +++ b/app/src/main/res/drawable/ic_baseline_bookmark_24.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/drawable/ic_baseline_brightness_7_24.xml b/app/src/main/res/drawable/ic_baseline_brightness_7_24.xml index dc94884a..191109b7 100644 --- a/app/src/main/res/drawable/ic_baseline_brightness_7_24.xml +++ b/app/src/main/res/drawable/ic_baseline_brightness_7_24.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/drawable/ic_baseline_more_vert_24.xml b/app/src/main/res/drawable/ic_baseline_more_vert_24.xml index 6a7f2748..249fe2a2 100644 --- a/app/src/main/res/drawable/ic_baseline_more_vert_24.xml +++ b/app/src/main/res/drawable/ic_baseline_more_vert_24.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml b/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml index 0870be8f..f880379f 100644 --- a/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml +++ b/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/drawable/ic_baseline_playlist_play_24.xml b/app/src/main/res/drawable/ic_baseline_playlist_play_24.xml index 6ff89010..6295ffae 100644 --- a/app/src/main/res/drawable/ic_baseline_playlist_play_24.xml +++ b/app/src/main/res/drawable/ic_baseline_playlist_play_24.xml @@ -1,5 +1,5 @@ diff --git a/app/src/main/res/drawable/ic_baseline_speed_24.xml b/app/src/main/res/drawable/ic_baseline_speed_24.xml index 1add8a09..046754aa 100644 --- a/app/src/main/res/drawable/ic_baseline_speed_24.xml +++ b/app/src/main/res/drawable/ic_baseline_speed_24.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/drawable/ic_baseline_star_24.xml b/app/src/main/res/drawable/ic_baseline_star_24.xml index 954e7723..ab099425 100644 --- a/app/src/main/res/drawable/ic_baseline_star_24.xml +++ b/app/src/main/res/drawable/ic_baseline_star_24.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/drawable/ic_baseline_subtitles_24.xml b/app/src/main/res/drawable/ic_baseline_subtitles_24.xml index f1863edf..75f674c9 100644 --- a/app/src/main/res/drawable/ic_baseline_subtitles_24.xml +++ b/app/src/main/res/drawable/ic_baseline_subtitles_24.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/drawable/ic_baseline_tune_24.xml b/app/src/main/res/drawable/ic_baseline_tune_24.xml index c7cae9e0..2ce603c5 100644 --- a/app/src/main/res/drawable/ic_baseline_tune_24.xml +++ b/app/src/main/res/drawable/ic_baseline_tune_24.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/drawable/ic_baseline_volume_up_24.xml b/app/src/main/res/drawable/ic_baseline_volume_up_24.xml index 45bf404e..e3ae9806 100644 --- a/app/src/main/res/drawable/ic_baseline_volume_up_24.xml +++ b/app/src/main/res/drawable/ic_baseline_volume_up_24.xml @@ -1,5 +1,5 @@ diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000..da9562ff --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/app/src/main/res/drawable/netflix_download.xml b/app/src/main/res/drawable/netflix_download.xml index a939de44..9d9531d8 100644 --- a/app/src/main/res/drawable/netflix_download.xml +++ b/app/src/main/res/drawable/netflix_download.xml @@ -8,7 +8,7 @@ diff --git a/app/src/main/res/drawable/netflix_play.xml b/app/src/main/res/drawable/netflix_play.xml index 00d17877..816d1069 100644 --- a/app/src/main/res/drawable/netflix_play.xml +++ b/app/src/main/res/drawable/netflix_play.xml @@ -5,5 +5,5 @@ android:viewportHeight="850.4"> + android:fillColor="?attr/white"/> \ No newline at end of file diff --git a/app/src/main/res/drawable/search_icon.xml b/app/src/main/res/drawable/search_icon.xml index 4eb4677d..870d0db6 100644 --- a/app/src/main/res/drawable/search_icon.xml +++ b/app/src/main/res/drawable/search_icon.xml @@ -8,13 +8,13 @@ diff --git a/app/src/main/res/layout/fragment_player.xml b/app/src/main/res/layout/fragment_player.xml index 7bf599d7..3a137bb5 100644 --- a/app/src/main/res/layout/fragment_player.xml +++ b/app/src/main/res/layout/fragment_player.xml @@ -38,7 +38,6 @@ android:backgroundTint="@android:color/black" > - - + + android:layout_width="match_parent" android:layout_height="30dp"> - - + - - + + + + + + + + + + - + + + - - - - + + + + - + android:textSize="17sp" + android:layout_marginTop="10dp" + android:layout_marginBottom="10dp" + android:textStyle="normal" + android:textColor="?attr/textColor" + /> diff --git a/app/src/main/res/layout/player_custom_layout.xml b/app/src/main/res/layout/player_custom_layout.xml index 7279edb3..638d1b2c 100644 --- a/app/src/main/res/layout/player_custom_layout.xml +++ b/app/src/main/res/layout/player_custom_layout.xml @@ -370,7 +370,7 @@ android:textColor="@android:color/white" android:textSize="14sp" android:textStyle="normal"/> - + diff --git a/app/src/main/res/layout/result_episode.xml b/app/src/main/res/layout/result_episode.xml index f3a3c0b9..c26ff182 100644 --- a/app/src/main/res/layout/result_episode.xml +++ b/app/src/main/res/layout/result_episode.xml @@ -6,8 +6,11 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" app:cardCornerRadius="@dimen/roundedImageRadius" - app:cardBackgroundColor="@color/itemBackground" - android:layout_marginBottom="2dp" + app:cardBackgroundColor="@color/transparent" + app:cardElevation="0dp" + android:id="@+id/episode_holder" + android:foreground="?android:attr/selectableItemBackgroundBorderless" + android:layout_marginBottom="5dp" > + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/search_result_compact.xml b/app/src/main/res/layout/search_result_compact.xml index ed73bb01..d756e50c 100644 --- a/app/src/main/res/layout/search_result_compact.xml +++ b/app/src/main/res/layout/search_result_compact.xml @@ -20,7 +20,7 @@ android:elevation="0dp" app:cardCornerRadius="@dimen/roundedImageRadius" - app:cardBackgroundColor="@color/itemBackground" + app:cardBackgroundColor="?attr/boxItemBackground" android:clickable="true" android:focusable="true" > @@ -50,7 +50,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="17sp" - android:textColor="@color/textColor" + android:textColor="?attr/textColor" android:id="@+id/imageText" android:textStyle="bold" android:maxLines="3" @@ -59,7 +59,7 @@ tools:text="@string/no_data" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textColor="@color/lightGrayTextColor" + android:textColor="?attr/grayTextColor" android:id="@+id/imageTextExtra" android:textSize="13sp" android:textStyle="bold" @@ -70,7 +70,7 @@ android:visibility="gone" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textColor="@color/colorPrimary" + android:textColor="?attr/colorPrimary" android:id="@+id/imageTextProvider" android:maxLines="1" /> diff --git a/app/src/main/res/layout/search_result_super_compact.xml b/app/src/main/res/layout/search_result_super_compact.xml index d5ba157a..2e7fb8f0 100644 --- a/app/src/main/res/layout/search_result_super_compact.xml +++ b/app/src/main/res/layout/search_result_super_compact.xml @@ -48,7 +48,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="17sp" - android:textColor="@color/textColor" + android:textColor="?attr/textColor" android:id="@+id/imageText" android:textStyle="normal" android:maxLines="3" @@ -58,7 +58,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone" - android:textColor="@color/lightGrayTextColor" + android:textColor="?attr/grayTextColor" android:id="@+id/imageTextExtra" android:textSize="13sp" android:textStyle="bold" @@ -69,7 +69,7 @@ android:visibility="gone" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textColor="@color/colorPrimary" + android:textColor="?attr/colorPrimary" android:id="@+id/imageTextProvider" android:maxLines="1" /> diff --git a/app/src/main/res/menu/cast_expanded_controller_menu.xml b/app/src/main/res/menu/cast_expanded_controller_menu.xml new file mode 100644 index 00000000..7fbf6ec9 --- /dev/null +++ b/app/src/main/res/menu/cast_expanded_controller_menu.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index bbd3e021..7353dbd1 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index bbd3e021..7353dbd1 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index a571e600..6df27f85 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png index 61da551c..814f61c0 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index c41dd285..0fef429f 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index db5080a7..34d17ffb 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 6dba46da..29cbab7d 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png index da31a871..af368ed2 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 15ac6817..93900a2f 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index b216f2d3..38a51ad2 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index f25a4197..f8c73a40 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index e96783cc..b30fa322 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 00000000..fb66e72c --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 1b96a836..45a2e76d 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -12,11 +12,11 @@ #2B2C30 #1C1C20 #1C1C20 - #131217 + #17171B #e9eaee #9ba0a4 - #9f9fa0 + @color/textColor #1AFFFFFF #00000000 @@ -33,6 +33,9 @@ #66000000 #C0121212 #121212 - #66B5B5B5 - #617EFF + #66B5B5B5 + + @color/colorPrimary + + #9ba0a6 \ No newline at end of file diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 00000000..7bbb50f4 --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #3242D3 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5e4b57b9..bb91e1eb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,4 +15,7 @@ Go back Next episode 10 + Poster + Plot + Genres \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 5ce0aa82..ce927e25 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -27,6 +27,17 @@ @style/AppBottomSheetDialogTheme @style/AppSearchViewStyle @style/Theme.Widget.Tabs + + + @color/textColor + @color/colorItemSeen + @color/grayTextColor + @color/darkBackground + @color/bitDarkerGrayBackground + @color/grayBackground + @color/itemBackground + @color/iconColor + #FFF