Skip to content

Commit

Permalink
feat/WIP: Started adding mediaplayer
Browse files Browse the repository at this point in the history
fix: Top app bar from Home page now is not scrollable

Signed-off-by: Gabriel Fontán <[email protected]>
  • Loading branch information
BobbyESP committed Apr 17, 2024
1 parent 148b28e commit 5c9d051
Show file tree
Hide file tree
Showing 17 changed files with 207 additions and 39 deletions.
6 changes: 3 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ dependencies {
implementation(libs.bundles.ktor)

// //---------------Media3---------------//
// implementation(libs.bundles.media3)
// implementation(libs.androidx.media3.datasource.okhttp)

implementation(libs.bundles.media3)
implementation(libs.androidx.media3.datasource.okhttp)
implementation(project(":app:mediaplayer"))

//---------------Dependency Injection---------------//
implementation(libs.bundles.hilt)
Expand Down
1 change: 1 addition & 0 deletions app/mediaplayer/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.androidLibrary)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.kotlin.ksp)
alias(libs.plugins.hilt)
}

android {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
class MediaService : MediaSessionService() {
class MediaplayerService : MediaSessionService() {

@Inject
lateinit var mediaSession: MediaSession
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />

<application
android:name=".App"
android:allowBackup="true"
Expand Down Expand Up @@ -43,6 +46,11 @@
android:label="CrashHandlerActivity"
android:launchMode="singleTask"
android:theme="@style/Theme.Metadator" />

<service
android:name="com.bobbyesp.mediaplayer.service.MediaplayerService"
android:foregroundServiceType="mediaPlayback" />

</application>

</manifest>
17 changes: 17 additions & 0 deletions app/src/main/java/com/bobbyesp/metadator/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bobbyesp.metadator

import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
Expand All @@ -9,6 +10,7 @@ import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import com.bobbyesp.mediaplayer.service.MediaplayerService
import com.bobbyesp.metadator.presentation.Navigator
import com.bobbyesp.metadator.presentation.common.AppLocalSettingsProvider
import com.bobbyesp.metadator.presentation.common.LocalDarkTheme
Expand All @@ -18,6 +20,8 @@ import setupFirebase

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private var isMusicPlayerServiceStarted = false

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
Expand All @@ -43,6 +47,19 @@ class MainActivity : ComponentActivity() {
}
}

override fun onDestroy() {
super.onDestroy()
stopService(Intent(this, MediaplayerService::class.java))
isMusicPlayerServiceStarted = false
}

fun startMediaPlayerService() {
if (!isMusicPlayerServiceStarted) {
isMusicPlayerServiceStarted = true
startService(Intent(this, MediaplayerService::class.java))
}
}

companion object {
private lateinit var activity: MainActivity
fun getActivity(): MainActivity {
Expand Down
70 changes: 48 additions & 22 deletions app/src/main/java/com/bobbyesp/metadator/presentation/Navigation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -47,11 +48,13 @@ import com.bobbyesp.metadator.presentation.common.TagEditorParcelableSongParamTy
import com.bobbyesp.metadator.presentation.common.routesToNavigate
import com.bobbyesp.metadator.presentation.pages.MediaStorePageViewModel
import com.bobbyesp.metadator.presentation.pages.home.HomePage
import com.bobbyesp.metadator.presentation.pages.mediaplayer.MediaplayerPage
import com.bobbyesp.metadator.presentation.pages.utilities.tageditor.ID3MetadataEditorPage
import com.bobbyesp.metadator.presentation.pages.utilities.tageditor.ID3MetadataEditorPageViewModel
import com.bobbyesp.ui.motion.animatedComposable
import com.bobbyesp.ui.motion.slideInVerticallyComposable
import com.bobbyesp.utilities.navigation.getParcelable
import kotlinx.coroutines.launch

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Composable
Expand All @@ -73,6 +76,8 @@ fun Navigator() {

val snackbarHostState = LocalSnackbarHostState.current

val scope = rememberCoroutineScope()

val showSnackbarMessage: suspend (String) -> Unit = { message ->
snackbarHostState.showSnackbar(message)
}
Expand Down Expand Up @@ -108,35 +113,47 @@ fun Navigator() {
fontFamily = FontFamily.Monospace
)
routesToNavigate.forEachIndexed { _, route ->
NavigationDrawerItem(label = {
Text(text = route.title?.let { stringResource(id = it) } ?: "")
}, selected = currentRootRoute.value == route.route, onClick = {

}, icon = {
Icon(imageVector = route.icon!!,
contentDescription = route.title?.let { stringResource(id = it) })
}, badge = {
NavigationDrawerItem(
label = {
Text(text = route.title?.let { stringResource(id = it) } ?: "")
}, selected = currentRootRoute.value == route.route, onClick = {
if (currentRootRoute.value == route.route) {
scope.launch {
drawerState.close()
}
return@NavigationDrawerItem
} else {
navController.navigate(route.route) {
popUpTo(navController.graph.startDestinationId)
launchSingleTop = true
}
scope.launch {
drawerState.close()
}
}
}, icon = {
Icon(imageVector = route.icon!!,
contentDescription = route.title?.let { stringResource(id = it) })
}, badge = {

}, modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
}, modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
)
}
}
},
) {
Scaffold(
snackbarHost = {
SnackbarHost(
hostState = snackbarHostState
) { dataReceived ->
Snackbar(
modifier = Modifier,
snackbarData = dataReceived,
containerColor = MaterialTheme.colorScheme.inverseSurface,
contentColor = MaterialTheme.colorScheme.inverseOnSurface,
)
}
Scaffold(snackbarHost = {
SnackbarHost(
hostState = snackbarHostState
) { dataReceived ->
Snackbar(
modifier = Modifier,
snackbarData = dataReceived,
containerColor = MaterialTheme.colorScheme.inverseSurface,
contentColor = MaterialTheme.colorScheme.inverseOnSurface,
)
}
) {
}) {
NavHost(
modifier = Modifier
.fillMaxWidth()
Expand All @@ -154,6 +171,15 @@ fun Navigator() {
}
}

navigation(
startDestination = Route.MediaplayerNavigator.Mediaplayer.route,
route = Route.MediaplayerNavigator.route
) {
animatedComposable(Route.MediaplayerNavigator.Mediaplayer.route) {
MediaplayerPage()
}
}

navigation(
startDestination = Route.UtilitiesNavigator.TagEditor.route,
route = Route.UtilitiesNavigator.route
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Edit
import androidx.compose.material.icons.rounded.Handyman
import androidx.compose.material.icons.rounded.Home
import androidx.compose.material.icons.rounded.PlayArrow
import androidx.compose.ui.graphics.vector.ImageVector
import com.bobbyesp.metadator.App.Companion.json
import com.bobbyesp.metadator.R
Expand Down Expand Up @@ -35,6 +36,20 @@ sealed class Route(
}
}

data object MediaplayerNavigator : Route(
"mediaplayer_navigator",
title = R.string.mediaplayer,
icon = Icons.Rounded.PlayArrow
) {
data object Mediaplayer :
Route(
"mediaplayer",
title = R.string.mediaplayer,
icon = Icons.Rounded.PlayArrow
) {
}
}

data object UtilitiesNavigator :
Route(
"utilities",
Expand All @@ -61,6 +76,7 @@ sealed class Route(

val routesToNavigate = listOf(
Route.MetadatorNavigator,
Route.MediaplayerNavigator
)

fun Route.getTitle(@ApplicationContext context: Context): String? {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.bobbyesp.metadator.presentation.components.cards.songs

import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand All @@ -9,6 +10,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -20,6 +22,7 @@ import com.bobbyesp.metadator.presentation.components.image.ArtworkAsyncImage
import com.bobbyesp.metadator.presentation.theme.MetadatorTheme
import com.bobbyesp.model.Song
import com.bobbyesp.ui.components.text.MarqueeText
import com.bobbyesp.utilities.Time

@Composable
fun HorizontalSongCard(
Expand All @@ -43,7 +46,9 @@ fun HorizontalSongCard(
artworkPath = song.artworkPath
)
Column(
horizontalAlignment = Alignment.Start, modifier = Modifier.padding(8.dp)
horizontalAlignment = Alignment.Start, modifier = Modifier
.padding(vertical = 8.dp, horizontal = 6.dp)
.weight(1f)
) {
MarqueeText(
text = song.title,
Expand All @@ -59,6 +64,19 @@ fun HorizontalSongCard(
fontSize = 12.sp
)
}

Text(
text = Time.formatDuration(song.duration.toLong()),
style = MaterialTheme.typography.bodySmall,
fontSize = 12.sp,
modifier = Modifier
.padding(8.dp)
.background(
MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = 0.1f),
MaterialTheme.shapes.small
)
.padding(6.dp)
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.bobbyesp.metadator.presentation.components.others

import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp

val CollapsedPlayerHeight = 64.dp

val PlayerAnimationSpec = spring<Dp>(stiffness = Spring.StiffnessMediumLow)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.bobbyesp.metadator.presentation.components.others

import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBarDefaults
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.bobbyesp.ui.components.bottomsheet.draggable.DraggableBottomSheet
import com.bobbyesp.ui.components.bottomsheet.draggable.DraggableBottomSheetState

@Composable
fun MediaplayerSheet(modifier: Modifier = Modifier, state: DraggableBottomSheetState) {
DraggableBottomSheet(
state = state,
collapsedContent = {

},
backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(NavigationBarDefaults.Elevation)
) {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class MediaStorePageViewModel @Inject constructor(

val songs = withContext(viewModelScope.coroutineContext + Dispatchers.IO) {
async {
MediaStoreReceiver.getAllSongsFromMediaStore(
MediaStoreReceiver.getSongsBySearchTerm(
applicationContext = context,
)
}.await()
Expand All @@ -70,7 +70,7 @@ class MediaStorePageViewModel @Inject constructor(
) {
val songs = withContext(viewModelScope.coroutineContext + Dispatchers.IO) {
async {
MediaStoreReceiver.getAllSongsFromMediaStore(
MediaStoreReceiver.getSongsBySearchTerm(
applicationContext = context,
)
}.await()
Expand All @@ -95,7 +95,7 @@ class MediaStorePageViewModel @Inject constructor(

val songs = withContext(viewModelScope.coroutineContext + Dispatchers.IO) {
async {
MediaStoreReceiver.getAllSongsFromMediaStore(
MediaStoreReceiver.getSongsBySearchTerm(
applicationContext = context, searchTerm = filter, filterType = filterType
)
}.await()
Expand Down
Loading

0 comments on commit 5c9d051

Please sign in to comment.