Skip to content

Commit

Permalink
v1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
sosauce committed Apr 30, 2024
1 parent 6775ef2 commit 9ab6193
Show file tree
Hide file tree
Showing 43 changed files with 1,381 additions and 1,281 deletions.
Binary file modified .DS_Store
Binary file not shown.
Binary file modified app/.DS_Store
Binary file not shown.
24 changes: 13 additions & 11 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ plugins {

}


android {
namespace = "com.sosauce.cutemusic"
compileSdk = 34

defaultConfig {
applicationId = "com.sosauce.cutemusic"
minSdk = 24
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "Beta 1 (Build_1)"
versionCode = 2
versionName = "1.0.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand Down Expand Up @@ -53,18 +54,19 @@ android {
}

dependencies {
implementation(platform("androidx.compose:compose-bom:2024.03.00"))
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.activity:activity-compose:1.8.2")
implementation(platform("androidx.compose:compose-bom:2024.04.01"))
implementation("androidx.core:core-ktx:1.13.0")
implementation("androidx.activity:activity-compose:1.9.0")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.ui:ui:1.6.4")
implementation("androidx.compose.ui:ui:1.6.6")
implementation("androidx.compose.material:material-icons-extended")
implementation("androidx.lifecycle:lifecycle-runtime-compose")
implementation("androidx.navigation:navigation-compose:2.7.7")
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("androidx.datastore:datastore-preferences:1.0.0")
implementation("androidx.datastore:datastore-preferences:1.1.0")
implementation("io.coil-kt:coil-compose:2.6.0")
implementation ("androidx.media3:media3-common:1.3.0")
implementation ("androidx.media3:media3-exoplayer:1.3.0")
implementation("androidx.media3:media3-session:1.3.0")
implementation ("androidx.media3:media3-common:1.3.1")
implementation ("androidx.media3:media3-exoplayer:1.3.1")
implementation("androidx.media3:media3-session:1.3.1")
implementation("me.saket.squigglyslider:squigglyslider:1.0.0")
}
Binary file modified app/release/.DS_Store
Binary file not shown.
Binary file modified app/release/baselineProfiles/0/app-release.dm
Binary file not shown.
Binary file modified app/release/baselineProfiles/1/app-release.dm
Binary file not shown.
6 changes: 3 additions & 3 deletions app/release/output-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "Beta 1 (Build_1)",
"versionCode": 2,
"versionName": "1.0.0",
"outputFile": "app-release.apk"
}
],
Expand All @@ -33,5 +33,5 @@
]
}
],
"minSdkVersionForDexing": 24
"minSdkVersionForDexing": 26
}
Binary file modified app/src/main/java/com/sosauce/cutemusic/.DS_Store
Binary file not shown.
96 changes: 57 additions & 39 deletions app/src/main/java/com/sosauce/cutemusic/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,9 @@ import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
Expand All @@ -37,94 +34,112 @@ import androidx.media3.session.MediaController
import androidx.media3.session.SessionToken
import com.google.common.util.concurrent.MoreExecutors
import com.sosauce.cutemusic.activities.MusicViewModel
import com.sosauce.cutemusic.audio.Album
import com.sosauce.cutemusic.audio.Music
import com.sosauce.cutemusic.audio.getAlbums
import com.sosauce.cutemusic.audio.getMusics
import com.sosauce.cutemusic.audio.service.PlayerService
import com.sosauce.cutemusic.logic.Nav
import com.sosauce.cutemusic.logic.PreferencesKeys
import com.sosauce.cutemusic.logic.dataStore
import com.sosauce.cutemusic.ui.theme.CuteMusicTheme
import com.sosauce.cutemusic.ui.theme.DarkAmoledColorPalette
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {


private lateinit var player: Player

private val _mediaItems = mutableStateOf<List<Music>>(emptyList())
private val mediaItems: List<Music>
get() = _mediaItems.value

private val _albums = mutableStateOf<List<Album>>(emptyList())
private val albums: List<Album>
get() = _albums.value

private val requestPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
preparePlaylist()
}
}


@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "SuspiciousIndentation")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val showSplash = mutableStateOf(true)

installSplashScreen()
installSplashScreen().setKeepOnScreenCondition{ showSplash.value }

enableEdgeToEdge()
enableEdgeToEdge(
statusBarStyle = SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT),
navigationBarStyle = SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT)
)

requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT // delete this when landscape and state bugs are fixed

val sessionToken = SessionToken(applicationContext, ComponentName(this, PlayerService::class.java))
val mediaControllerFuture = MediaController.Builder(this, sessionToken).buildAsync()

mediaControllerFuture.addListener({
player = mediaControllerFuture.get()
}, MoreExecutors.directExecutor())


showSplash.value = false
setContent {
CuteMusicTheme {
requestPermission()
val context = LocalContext.current
val themeDataStore = context.dataStore
val themeFlow: Flow<String?> = themeDataStore.data
.map { preferences ->
preferences[PreferencesKeys.THEME]
val isSysDark = isSystemInDarkTheme()
val dataStore = context.dataStore
val _useDarkMode = dataStore.data.map { preferences ->
preferences[PreferencesKeys.USE_DARK_MODE] ?: isSysDark
}

val useDarkMode by _useDarkMode.collectAsState(initial = false)
val _useAmoledMode = dataStore.data.map { preferences ->
preferences[PreferencesKeys.USE_AMOLED_MODE]
}

val useAmoledMode by _useAmoledMode.collectAsState(initial = false)

val colors = when {
useAmoledMode == true-> DarkAmoledColorPalette
useDarkMode == true -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
dynamicDarkColorScheme(context)
} else {
darkColorScheme()
}
}
val theme by themeFlow.collectAsState(initial = null)

val colors = when (theme) {
"Dark" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) dynamicDarkColorScheme(context) else darkColorScheme()
"Light" -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) dynamicLightColorScheme(context) else lightColorScheme()
"Amoled" -> DarkAmoledColorPalette
else -> if (isSystemInDarkTheme()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) dynamicDarkColorScheme(context) else darkColorScheme()
} else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) dynamicLightColorScheme(context) else lightColorScheme()
else -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
dynamicLightColorScheme(context)
} else {
lightColorScheme()
}
}
}



Scaffold(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.background),
contentColor = MaterialTheme.colorScheme.background
) {
var delay by remember { mutableStateOf(false) } // Delay because else app crashes
LaunchedEffect(Unit) {
delay(50)
delay = true
}
if (delay) {
MaterialTheme(
colorScheme = colors,
content = {
Nav(player, mediaItems, viewModel = MusicViewModel(player))
}
)
}
MaterialTheme(
colorScheme = colors,
content = {
Nav(player, mediaItems, MusicViewModel(player), albums)
}
)
}
}
}
}, MoreExecutors.directExecutor())

}

override fun onDestroy() {
Expand All @@ -149,10 +164,13 @@ class MainActivity : ComponentActivity() {
val mediaItem = convertMusicToMedia(music)
player.addMediaItem(mediaItem)
}
_albums.value = getAlbums(contentResolver)
}
player.prepare()
}
}
}



fun convertMusicToMedia(music: Music): MediaItem {
return MediaItem.Builder()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.sosauce.cutemusic.activities

import android.media.MediaMetadataRetriever
import android.net.Uri
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
Expand All @@ -14,21 +12,22 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.media3.common.MediaMetadata
import androidx.media3.common.Player
import com.sosauce.cutemusic.audio.PlayerState
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.Calendar

class MusicViewModel(
private val player: Player
) : ViewModel() {


var currentValue by mutableLongStateOf(0L)
var showMainScreen by mutableStateOf(false)
var isSheetOpen by mutableStateOf(false)
var playerState: MutableState<PlayerState> = mutableStateOf(PlayerState())
var title by mutableStateOf(player.mediaMetadata.title.toString())
var artist by mutableStateOf(player.mediaMetadata.artist.toString())
var previousTitle by mutableStateOf("")
var previousArtist by mutableStateOf("")
var art by mutableStateOf(player.mediaMetadata.artworkData)
var previousArt: ByteArray? by mutableStateOf(byteArrayOf())
var isPlayerPlaying by mutableStateOf(player.isPlaying)
var isPlayerLooping by mutableStateOf(isLooping())
var isShuffleEnabled by mutableStateOf(player.shuffleModeEnabled)
Expand Down Expand Up @@ -59,8 +58,12 @@ class MusicViewModel(

override fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) {
super.onMediaMetadataChanged(mediaMetadata)
previousTitle = title
previousArtist = artist
previousArt = art
title = player.mediaMetadata.title.toString().ifEmpty { "<unknown>" }
artist = player.mediaMetadata.artist.toString().ifEmpty { "<unknown>" }
art = player.mediaMetadata.artworkData
}
})
}
Expand Down Expand Up @@ -135,6 +138,18 @@ class MusicViewModel(
}
}

fun greetings(): String {
val calendar = Calendar.getInstance()
val hour = calendar.get(Calendar.HOUR_OF_DAY)

return when {
hour < 12 -> "Hi !"
hour < 17 -> "Good afternoon!"
else -> "Good evening!"
}
}





Expand Down
41 changes: 41 additions & 0 deletions app/src/main/java/com/sosauce/cutemusic/audio/GetDeviceMusics.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,44 @@ suspend fun getMusics(contentResolver: ContentResolver): List<Music> = withConte
return@withContext musics
}

suspend fun getAlbums(contentResolver: ContentResolver): List<Album> = withContext(Dispatchers.IO) {
val albums = mutableListOf<Album>()

val projection = arrayOf(
MediaStore.Audio.Albums._ID,
MediaStore.Audio.Albums.ALBUM,
MediaStore.Audio.Albums.ARTIST,
MediaStore.Audio.Albums.NUMBER_OF_SONGS
)

contentResolver.query(
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
projection,
null,
null,
"${MediaStore.Audio.Albums.ALBUM} ASC"
)?.use { cursor ->
val idColumn = cursor.getColumnIndex(MediaStore.Audio.Albums._ID)
val albumColumn = cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM)
val artistColumn = cursor.getColumnIndex(MediaStore.Audio.Albums.ARTIST)
val numberOfSongsColumn = cursor.getColumnIndex(MediaStore.Audio.Albums.NUMBER_OF_SONGS)

while (cursor.moveToNext()) {
val id = cursor.getLong(idColumn)
val album = cursor.getString(albumColumn)
val artist = cursor.getString(artistColumn)
val numberOfSongs = cursor.getInt(numberOfSongsColumn)
val uri = ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
id
)

val albumInfo = Album(id, album, artist, numberOfSongs, uri)
albums.add(albumInfo)
}
}

return@withContext albums
}


12 changes: 9 additions & 3 deletions app/src/main/java/com/sosauce/cutemusic/audio/Music.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package com.sosauce.cutemusic.audio

import android.net.Uri
import androidx.compose.runtime.Immutable

@Immutable
data class Music(
val id: Long,
val title: String,
val artist: String,
val album: String,
val uri: Uri
)
)

data class Album(
val id: Long,
val name: String,
val artist: String,
val numberOfSongs: Int,
val uri: Uri
)
7 changes: 0 additions & 7 deletions app/src/main/java/com/sosauce/cutemusic/audio/PlayerState.kt

This file was deleted.

Loading

0 comments on commit 9ab6193

Please sign in to comment.