Skip to content

Commit

Permalink
feat(Explore)!: continue watching feed
Browse files Browse the repository at this point in the history
1. Move database related classes to the core module
2. Divide database [acting_team] field on two fields
3. Use ReleaseStatus enum values instead of cyrillic words
  • Loading branch information
urFate committed Jun 30, 2024
1 parent 55633ae commit d00c5a6
Show file tree
Hide file tree
Showing 36 changed files with 892 additions and 350 deletions.
20 changes: 6 additions & 14 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ android {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
ksp {
arg("room.schemaLocation", "$projectDir/schemas")
}
}

dependencies {
Expand All @@ -78,7 +75,8 @@ dependencies {
implementation (platform("androidx.compose:compose-bom:2024.05.00"))
implementation (platform("org.jetbrains.kotlin:kotlin-bom:1.9.23"))
implementation ("androidx.lifecycle:lifecycle-runtime-compose:2.7.0")
implementation("androidx.core:core-splashscreen:1.0.1")
implementation ("androidx.core:core-splashscreen:1.0.1")
implementation ("androidx.graphics:graphics-core:1.0.0-rc01")

testImplementation ("junit:junit:4.13.2")
androidTestImplementation ("androidx.test.ext:junit:1.1.5")
Expand Down Expand Up @@ -119,25 +117,19 @@ dependencies {
implementation ("androidx.media3:media3-ui:$media3Version")
implementation ("androidx.media3:media3-exoplayer-hls:$media3Version")

// Room
val roomVersion = "2.6.1"

implementation ("androidx.room:room-common:$roomVersion")
implementation ("androidx.room:room-runtime:$roomVersion")
ksp ("androidx.room:room-compiler:$roomVersion")
implementation ("androidx.room:room-ktx:$roomVersion")

// Firebase
implementation (platform("com.google.firebase:firebase-bom:33.0.0"))
implementation ("com.google.firebase:firebase-crashlytics-ktx")
implementation ("com.google.firebase:firebase-analytics-ktx")
implementation ("com.google.firebase:firebase-messaging-ktx")

// Network
// Image processing
implementation ("io.coil-kt:coil-compose:2.5.0")
implementation("com.github.kittinunf.fuel:fuel:3.0.0-alpha1")
implementation("io.coil-kt:coil-svg:2.6.0")

// Network
implementation("com.github.kittinunf.fuel:fuel:3.0.0-alpha1")

// Datastore
implementation ("androidx.datastore:datastore-preferences:1.1.1")

Expand Down
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

<application
android:name="live.shirabox.shirabox.App"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import live.shirabox.core.db.AppDatabase
import live.shirabox.core.entity.NotificationEntity
import live.shirabox.core.model.ContentType
import live.shirabox.core.util.Util
import live.shirabox.shirabox.db.AppDatabase
import live.shirabox.shirabox.ui.activity.resource.ResourceActivity
import java.net.URL

Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
package live.shirabox.shirabox.ui.activity.player

import android.app.Activity
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.annotation.OptIn
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DefaultHttpDataSource
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.serialization.json.Json
import dagger.hilt.android.AndroidEntryPoint
import live.shirabox.core.util.Util
import live.shirabox.core.util.Values
import live.shirabox.shirabox.ui.theme.ShiraBoxTheme

@AndroidEntryPoint
class PlayerActivity : ComponentActivity() {

private var player: ExoPlayer? = null

@OptIn(UnstableApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

Expand All @@ -37,7 +43,6 @@ class PlayerActivity : ComponentActivity() {
) {
val arguments = intent.extras
val context = LocalContext.current
val activity = context as? Activity

rememberSystemUiController().apply {
setStatusBarColor(
Expand All @@ -47,36 +52,32 @@ class PlayerActivity : ComponentActivity() {
Util.hideSystemUi(this)
}

val httpDataSourceFactory = DefaultHttpDataSource.Factory()
.setAllowCrossProtocolRedirects(true).setUserAgent(Values.USER_AGENT)

val dataSourceFactory = DataSource.Factory { httpDataSourceFactory.createDataSource() }

val exoPlayer = remember {
ExoPlayer.Builder(context).build().apply { prepare() }
ExoPlayer.Builder(context).setMediaSourceFactory(
DefaultMediaSourceFactory(context).setDataSourceFactory(
dataSourceFactory
)
).build().apply { prepare() }
}
player = exoPlayer

lateinit var model: PlayerViewModel

try {
model = PlayerViewModel(
context = context,
val model = hiltViewModel<PlayerViewModel, PlayerViewModel.PlayerViewModelFactory> {
it.create(
contentUid = arguments!!.getLong("content_uid"),
contentName = arguments.getString("name").toString(),
contentEnName = arguments.getString("en_name").toString(),
actingTeam = Json.decodeFromString(arguments.getString("acting_team") ?: ""),
episode = arguments.getInt("episode"),
startIndex = arguments.getInt("start_index"),
playlist = Json.decodeFromString(
arguments.getString("playlist") ?: ""
)
team = arguments.getString("acting_team").toString(),
repository = arguments.getString("repository").toString(),
initialEpisode = arguments.getInt("episode"),
)
} catch (ex: Exception) {
ex.printStackTrace()
activity?.finish()
Toast.makeText(context, ex.localizedMessage, Toast.LENGTH_LONG).show()
}

ShiraPlayer(
exoPlayer = exoPlayer,
model = viewModel(factory = Util.viewModelFactory { model })
)
ShiraPlayer(exoPlayer = exoPlayer, model = model)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@ import androidx.media3.exoplayer.ExoPlayer
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import live.shirabox.core.entity.EpisodeEntity
import live.shirabox.core.model.Quality
import live.shirabox.core.util.Util
import live.shirabox.shirabox.R

@Composable
fun SettingsBottomSheet(exoPlayer: ExoPlayer, model: PlayerViewModel) {
fun SettingsBottomSheet(exoPlayer: ExoPlayer, playlist: List<EpisodeEntity>, model: PlayerViewModel) {
val currentSheetScreen = remember {
mutableStateOf(SettingsSheetScreen.OVERVIEW)
}
Expand All @@ -48,14 +49,15 @@ fun SettingsBottomSheet(exoPlayer: ExoPlayer, model: PlayerViewModel) {
when (currentSheetScreen.value) {
SettingsSheetScreen.OVERVIEW -> SettingsOptions(currentSheetScreen, model)
SettingsSheetScreen.VIDEO_QUALITY -> QualityBottomSheet(
currentSheetScreen,
exoPlayer,
model
currentSheetScreen = currentSheetScreen,
exoPlayer = exoPlayer,
playlist = playlist,
model = model
)

SettingsSheetScreen.PLAYBACK_SPEED -> PlaybackSpeedBottomSheet(
currentSheetScreen,
model
currentSheetScreen = currentSheetScreen,
model = model
)

SettingsSheetScreen.CLOSED_CAPTIONS -> ClosedCationsBottomSheet(currentSheetScreen)
Expand Down Expand Up @@ -98,8 +100,8 @@ private fun SettingsOptions(
modifier = Modifier.padding(0.dp, 0.dp, 0.dp, 16.dp)
) {
/*
* Video Quality
*/
* Video Quality
*/

ListItem(
modifier = Modifier.clickable {
Expand Down Expand Up @@ -186,6 +188,7 @@ private fun SettingsOptions(
fun QualityBottomSheet(
currentSheetScreen: MutableState<SettingsSheetScreen>,
exoPlayer: ExoPlayer,
playlist: List<EpisodeEntity>,
model: PlayerViewModel
) {
val state = rememberModalBottomSheetState(
Expand All @@ -202,7 +205,7 @@ fun QualityBottomSheet(
Column(
modifier = Modifier.padding(0.dp, 0.dp, 0.dp, 16.dp)
) {
model.playlist[exoPlayer.currentMediaItemIndex].streamUrls.keys.reversed().forEach {
playlist[exoPlayer.currentMediaItemIndex].videos.keys.reversed().forEach {
ListItem(
modifier = Modifier.clickable {
model.currentQuality = it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ import androidx.media3.exoplayer.ExoPlayer
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import live.shirabox.core.datastore.DataStoreScheme
import live.shirabox.core.entity.EpisodeEntity
import live.shirabox.core.util.Util
import live.shirabox.core.util.Values
import live.shirabox.shirabox.R

@Composable
fun ControlsScaffold(exoPlayer: ExoPlayer, model: PlayerViewModel) {
fun ControlsScaffold(exoPlayer: ExoPlayer, playlist: List<EpisodeEntity>, model: PlayerViewModel) {

val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
Expand All @@ -91,16 +92,16 @@ fun ControlsScaffold(exoPlayer: ExoPlayer, model: PlayerViewModel) {
var currentPosition by remember { mutableLongStateOf(exoPlayer.currentPosition) }
var totalDuration by remember { mutableLongStateOf(exoPlayer.duration) }
var playbackState by remember { mutableIntStateOf(exoPlayer.playbackState) }
var hasNextMediaItem by remember { mutableStateOf(model.playlist.lastIndex != exoPlayer.currentMediaItemIndex) }
var hasNextMediaItem by remember { mutableStateOf(exoPlayer.hasNextMediaItem()) }
var hasPreviousMediaItem by remember { mutableStateOf(exoPlayer.hasPreviousMediaItem()) }
var currentMediaItemIndex by remember { mutableIntStateOf(exoPlayer.currentMediaItemIndex) }

val currentEpisode = remember(currentMediaItemIndex) {
model.playlist[exoPlayer.currentMediaItemIndex].episode
playlist.getOrNull(exoPlayer.currentMediaItemIndex)?.episode ?: 1
}

val providedIntroMarkers = remember(currentMediaItemIndex) {
model.playlist[exoPlayer.currentMediaItemIndex].openingMarkers
playlist[exoPlayer.currentMediaItemIndex].videoMarkers
}
val animeSkipIntroMarkers = remember(currentMediaItemIndex) {
model.animeSkipTimestamps[currentEpisode]
Expand Down Expand Up @@ -149,7 +150,7 @@ fun ControlsScaffold(exoPlayer: ExoPlayer, model: PlayerViewModel) {
totalDuration = exoPlayer.duration
currentPosition = exoPlayer.contentPosition
playbackState = exoPlayer.playbackState
hasNextMediaItem = model.playlist.lastIndex != exoPlayer.currentMediaItemIndex
hasNextMediaItem = exoPlayer.hasNextMediaItem()
hasPreviousMediaItem = exoPlayer.hasPreviousMediaItem()
currentMediaItemIndex = exoPlayer.currentMediaItemIndex.inc()

Expand Down Expand Up @@ -179,7 +180,11 @@ fun ControlsScaffold(exoPlayer: ExoPlayer, model: PlayerViewModel) {
) {
Scaffold(
topBar = {
PlayerTopBar(model.contentName, currentEpisode) {
PlayerTopBar(
title = model.contentName,
episode = currentEpisode,
onBackClick = { activity.finish() },
) {
model.bottomSheetVisibilityState = true
}
},
Expand All @@ -196,22 +201,24 @@ fun ControlsScaffold(exoPlayer: ExoPlayer, model: PlayerViewModel) {
}
},
content = {
val isLoaded = (playbackState == Player.STATE_READY) || (playbackState == Player.STATE_ENDED)

PlaybackControls(
modifier = Modifier.padding(it),
isPlaying = isPlaying,
isLoaded = playbackState == Player.STATE_READY,
isLoaded = isLoaded,
hasNextMediaItem = hasNextMediaItem,
hasPreviousMediaItem = hasPreviousMediaItem,
onSkipPrevious = {
model.saveEpisodePosition(currentEpisode, exoPlayer.currentPosition)
model.saveEpisodePosition(currentEpisode, exoPlayer.currentPosition, exoPlayer.duration)
exoPlayer.seekToPrevious()
},
onPlayToggle = {
exoPlayer.playWhenReady = !exoPlayer.isPlaying
coroutineScope.launch { hideControls(exoPlayer, model) }
},
onSkipNext = {
model.saveEpisodePosition(currentEpisode, exoPlayer.currentPosition)
model.saveEpisodePosition(currentEpisode, exoPlayer.currentPosition, exoPlayer.duration)
exoPlayer.seekToNext()
}
)
Expand Down Expand Up @@ -248,9 +255,7 @@ fun ControlsScaffold(exoPlayer: ExoPlayer, model: PlayerViewModel) {

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PlayerTopBar(title: String, episode: Int, onSettingsClick: () -> Unit) {
val activity = LocalContext.current as Activity

fun PlayerTopBar(title: String, episode: Int, onBackClick: () -> Unit, onSettingsClick: () -> Unit) {
TopAppBar(
modifier = Modifier.fillMaxWidth(),
title = {
Expand All @@ -277,7 +282,7 @@ fun PlayerTopBar(title: String, episode: Int, onSettingsClick: () -> Unit) {
}
},
navigationIcon = {
IconButton(onClick = { activity.finish() }) {
IconButton(onClick = onBackClick) {
Icon(
imageVector = Icons.AutoMirrored.Rounded.ArrowBack,
contentDescription = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import live.shirabox.core.util.Values

class PlayerLoadingStateListener(

class PlayerStateListener(
private val coroutineScope: CoroutineScope,
private val model: PlayerViewModel
) : Player.Listener {
Expand Down
Loading

0 comments on commit d00c5a6

Please sign in to comment.