From e912bfed1cfffa023fe212fac785bded96457cb6 Mon Sep 17 00:00:00 2001 From: vfsfitvnm Date: Sat, 23 Jul 2022 16:57:38 +0200 Subject: [PATCH] Tweak code --- .../kotlin/it/vfsfitvnm/vimusic/Database.kt | 131 +++++++++++++----- .../it/vfsfitvnm/vimusic/MainActivity.kt | 36 ++++- .../it/vfsfitvnm/vimusic/MainApplication.kt | 8 +- .../vimusic/enums/BuiltInPlaylist.kt | 1 - .../vimusic/enums/CoilDiskCacheSize.kt | 1 - .../vimusic/enums/ColorPaletteMode.kt | 1 - .../enums/ExoPlayerDiskCacheMaxSize.kt | 1 - .../it/vfsfitvnm/vimusic/models/Artist.kt | 2 +- .../vfsfitvnm/vimusic/models/DetailedSong.kt | 1 - .../models/DetailedSongWithContentLength.kt | 1 - .../it/vfsfitvnm/vimusic/models/Format.kt | 5 +- .../vimusic/models/PlaylistWithSongs.kt | 5 +- .../vimusic/models/QueuedMediaItem.kt | 3 +- .../vfsfitvnm/vimusic/models/SearchQuery.kt | 1 - .../it/vfsfitvnm/vimusic/models/Song.kt | 6 +- .../vfsfitvnm/vimusic/models/SongAlbumMap.kt | 1 - .../vfsfitvnm/vimusic/models/SongArtistMap.kt | 3 +- .../vimusic/models/SongPlaylistMap.kt | 3 - .../vimusic/service/BitmapProvider.kt | 13 +- .../vimusic/service/PlayerService.kt | 61 ++++++-- .../vimusic/ui/components/BottomSheet.kt | 33 ++++- .../vimusic/ui/components/ChunkyButton.kt | 15 +- .../vimusic/ui/components/ChunkyChipGroup.kt | 6 +- .../vfsfitvnm/vimusic/ui/components/Menu.kt | 16 ++- .../vimusic/ui/components/MusicBars.kt | 102 ++++++++++++-- .../vfsfitvnm/vimusic/ui/components/Pager.kt | 24 +++- .../vimusic/ui/components/SeekBar.kt | 12 +- .../vimusic/ui/components/TopAppBar.kt | 2 +- .../vimusic/ui/components/themed/Dialog.kt | 32 ++++- .../ui/components/themed/DropDownSection.kt | 13 +- .../ui/components/themed/DropdownMenu.kt | 22 ++- .../ui/components/themed/LoadingOrError.kt | 2 +- .../ui/components/themed/MediaItemMenu.kt | 36 ++++- .../vimusic/ui/components/themed/Menu.kt | 16 ++- .../vimusic/ui/components/themed/Switch.kt | 3 +- .../vimusic/ui/components/themed/TextCard.kt | 3 +- .../ui/components/themed/TextPlaceholder.kt | 2 +- .../vimusic/ui/screens/AlbumScreen.kt | 98 +++++++++---- .../vimusic/ui/screens/ArtistScreen.kt | 25 +++- .../ui/screens/BuiltInPlaylistScreen.kt | 22 ++- .../vimusic/ui/screens/HomeScreen.kt | 76 ++++++++-- .../vimusic/ui/screens/IntentUriScreen.kt | 37 +++-- .../vimusic/ui/screens/LocalPlaylistScreen.kt | 61 ++++++-- .../vimusic/ui/screens/PlaylistScreen.kt | 120 ++++++++++------ .../ui/screens/{routes.kt => Routes.kt} | 8 -- .../vimusic/ui/screens/SearchResultScreen.kt | 37 +++-- .../vimusic/ui/screens/SearchScreen.kt | 31 ++++- .../vimusic/ui/screens/SettingsScreen.kt | 4 +- .../ui/screens/settings/AboutScreen.kt | 17 ++- .../settings/AppearanceSettingsScreen.kt | 30 +++- .../settings/BackupAndRestoreScreen.kt | 33 ++++- .../screens/settings/CacheSettingsScreen.kt | 42 +++++- .../screens/settings/OtherSettingsScreen.kt | 30 +++- .../screens/settings/PlayerSettingsScreen.kt | 50 +++++-- .../screens/settings/{routes.kt => Routes.kt} | 0 .../vimusic/ui/styling/Appearance.kt | 2 +- .../vimusic/ui/styling/ColorPalette.kt | 2 +- .../vimusic/ui/styling/Dimensions.kt | 5 +- .../vimusic/ui/styling/Typography.kt | 12 -- .../vfsfitvnm/vimusic/ui/views/PlayerView.kt | 84 +++++++++-- .../vimusic/ui/views/PlaylistPreviewItem.kt | 10 +- .../it/vfsfitvnm/vimusic/ui/views/SongItem.kt | 14 +- .../it/vfsfitvnm/vimusic/utils/Context.kt | 12 +- .../it/vfsfitvnm/vimusic/utils/DrawScope.kt | 9 +- .../{verticalFadingEdge.kt => FadingEdge.kt} | 0 .../vimusic/utils/InvincibleService.kt | 1 - .../it/vfsfitvnm/vimusic/utils/Player.kt | 11 +- .../it/vfsfitvnm/vimusic/utils/PlayerState.kt | 19 ++- .../it/vfsfitvnm/vimusic/utils/Preferences.kt | 21 ++- .../vimusic/utils/RelaunchableEffect.kt | 8 +- .../it/vfsfitvnm/vimusic/utils/TimerJob.kt | 3 - .../vimusic/utils/{utils.kt => Utils.kt} | 0 .../vfsfitvnm/vimusic/utils/YoutubeRadio.kt | 1 - .../vimusic/utils/rememberHapticFeedback.kt | 2 +- 74 files changed, 1162 insertions(+), 398 deletions(-) rename app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/{routes.kt => Routes.kt} (95%) rename app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/{routes.kt => Routes.kt} (100%) rename app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/{verticalFadingEdge.kt => FadingEdge.kt} (100%) rename app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/{utils.kt => Utils.kt} (100%) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/Database.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/Database.kt index 58082ed..7fef553 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/Database.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/Database.kt @@ -7,7 +7,22 @@ import android.database.sqlite.SQLiteDatabase.CONFLICT_IGNORE import android.os.Parcel import androidx.core.database.getFloatOrNull import androidx.media3.common.MediaItem -import androidx.room.* +import androidx.room.AutoMigration +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.DeleteTable +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.RenameColumn +import androidx.room.RenameTable +import androidx.room.RewriteQueriesToDropUnusedColumns +import androidx.room.Room +import androidx.room.RoomDatabase +import androidx.room.Transaction +import androidx.room.TypeConverter +import androidx.room.TypeConverters +import androidx.room.Update import androidx.room.migration.AutoMigrationSpec import androidx.room.migration.Migration import androidx.sqlite.db.SimpleSQLiteQuery @@ -15,11 +30,24 @@ import androidx.sqlite.db.SupportSQLiteDatabase import it.vfsfitvnm.vimusic.enums.PlaylistSortBy import it.vfsfitvnm.vimusic.enums.SongSortBy import it.vfsfitvnm.vimusic.enums.SortOrder -import it.vfsfitvnm.vimusic.models.* +import it.vfsfitvnm.vimusic.models.Album +import it.vfsfitvnm.vimusic.models.Artist +import it.vfsfitvnm.vimusic.models.DetailedSong +import it.vfsfitvnm.vimusic.models.DetailedSongWithContentLength +import it.vfsfitvnm.vimusic.models.Format +import it.vfsfitvnm.vimusic.models.Playlist +import it.vfsfitvnm.vimusic.models.PlaylistPreview +import it.vfsfitvnm.vimusic.models.PlaylistWithSongs +import it.vfsfitvnm.vimusic.models.QueuedMediaItem +import it.vfsfitvnm.vimusic.models.SearchQuery +import it.vfsfitvnm.vimusic.models.Song +import it.vfsfitvnm.vimusic.models.SongAlbumMap +import it.vfsfitvnm.vimusic.models.SongArtistMap +import it.vfsfitvnm.vimusic.models.SongPlaylistMap +import it.vfsfitvnm.vimusic.models.SortedSongPlaylistMap import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map - @Dao interface Database { companion object : Database by DatabaseInitializer.Instance.database @@ -118,7 +146,10 @@ interface Database { @Query("SELECT id, name, (SELECT COUNT(*) FROM SongPlaylistMap WHERE playlistId = id) as songCount FROM Playlist ORDER BY songCount ASC") fun playlistPreviewsByDateSongCount(): Flow> - fun playlistPreviews(sortBy: PlaylistSortBy, sortOrder: SortOrder): Flow> { + fun playlistPreviews( + sortBy: PlaylistSortBy, + sortOrder: SortOrder + ): Flow> { return when (sortBy) { PlaylistSortBy.Name -> playlistPreviewsByName() PlaylistSortBy.DateAdded -> playlistPreviewsByDateAdded() @@ -337,11 +368,15 @@ abstract class DatabaseInitializer protected constructor() : RoomDatabase() { lateinit var Instance: DatabaseInitializer context(Context) - operator fun invoke() { + operator fun invoke() { if (!::Instance.isInitialized) { Instance = Room .databaseBuilder(this@Context, DatabaseInitializer::class.java, "data.db") - .addMigrations(From8To9Migration(), From10To11Migration(), From14To15Migration()) + .addMigrations( + From8To9Migration(), + From10To11Migration(), + From14To15Migration() + ) .build() } } @@ -355,35 +390,56 @@ abstract class DatabaseInitializer protected constructor() : RoomDatabase() { class From8To9Migration : Migration(8, 9) { override fun migrate(it: SupportSQLiteDatabase) { - it.query(SimpleSQLiteQuery("SELECT DISTINCT browseId, text, Info.id FROM Info JOIN Song ON Info.id = Song.albumId;")).use { cursor -> - val albumValues = ContentValues(2) - while (cursor.moveToNext()) { - albumValues.put("id", cursor.getString(0)) - albumValues.put("title", cursor.getString(1)) - it.insert("Album", CONFLICT_IGNORE, albumValues) + it.query(SimpleSQLiteQuery("SELECT DISTINCT browseId, text, Info.id FROM Info JOIN Song ON Info.id = Song.albumId;")) + .use { cursor -> + val albumValues = ContentValues(2) + while (cursor.moveToNext()) { + albumValues.put("id", cursor.getString(0)) + albumValues.put("title", cursor.getString(1)) + it.insert("Album", CONFLICT_IGNORE, albumValues) - it.execSQL("UPDATE Song SET albumId = '${cursor.getString(0)}' WHERE albumId = ${cursor.getLong(2)}") + it.execSQL( + "UPDATE Song SET albumId = '${cursor.getString(0)}' WHERE albumId = ${ + cursor.getLong( + 2 + ) + }" + ) + } } - } - it.query(SimpleSQLiteQuery("SELECT GROUP_CONCAT(text, ''), SongWithAuthors.songId FROM Info JOIN SongWithAuthors ON Info.id = SongWithAuthors.authorInfoId GROUP BY songId;")).use { cursor -> - val songValues = ContentValues(1) - while (cursor.moveToNext()) { - songValues.put("artistsText", cursor.getString(0)) - it.update("Song", CONFLICT_IGNORE, songValues, "id = ?", arrayOf(cursor.getString(1))) + it.query(SimpleSQLiteQuery("SELECT GROUP_CONCAT(text, ''), SongWithAuthors.songId FROM Info JOIN SongWithAuthors ON Info.id = SongWithAuthors.authorInfoId GROUP BY songId;")) + .use { cursor -> + val songValues = ContentValues(1) + while (cursor.moveToNext()) { + songValues.put("artistsText", cursor.getString(0)) + it.update( + "Song", + CONFLICT_IGNORE, + songValues, + "id = ?", + arrayOf(cursor.getString(1)) + ) + } } - } - it.query(SimpleSQLiteQuery("SELECT browseId, text, Info.id FROM Info JOIN SongWithAuthors ON Info.id = SongWithAuthors.authorInfoId WHERE browseId NOT NULL;")).use { cursor -> - val artistValues = ContentValues(2) - while (cursor.moveToNext()) { - artistValues.put("id", cursor.getString(0)) - artistValues.put("name", cursor.getString(1)) - it.insert("Artist", CONFLICT_IGNORE, artistValues) + it.query(SimpleSQLiteQuery("SELECT browseId, text, Info.id FROM Info JOIN SongWithAuthors ON Info.id = SongWithAuthors.authorInfoId WHERE browseId NOT NULL;")) + .use { cursor -> + val artistValues = ContentValues(2) + while (cursor.moveToNext()) { + artistValues.put("id", cursor.getString(0)) + artistValues.put("name", cursor.getString(1)) + it.insert("Artist", CONFLICT_IGNORE, artistValues) - it.execSQL("UPDATE SongWithAuthors SET authorInfoId = '${cursor.getString(0)}' WHERE authorInfoId = ${cursor.getLong(2)}") + it.execSQL( + "UPDATE SongWithAuthors SET authorInfoId = '${cursor.getString(0)}' WHERE authorInfoId = ${ + cursor.getLong( + 2 + ) + }" + ) + } } - } it.execSQL("INSERT INTO SongArtistMap(songId, artistId) SELECT songId, authorInfoId FROM SongWithAuthors") @@ -417,15 +473,16 @@ abstract class DatabaseInitializer protected constructor() : RoomDatabase() { class From14To15Migration : Migration(14, 15) { override fun migrate(it: SupportSQLiteDatabase) { - it.query(SimpleSQLiteQuery("SELECT id, loudnessDb, contentLength FROM Song;")).use { cursor -> - val formatValues = ContentValues(3) - while (cursor.moveToNext()) { - formatValues.put("songId", cursor.getString(0)) - formatValues.put("loudnessDb", cursor.getFloatOrNull(1)) - formatValues.put("contentLength", cursor.getFloatOrNull(2)) - it.insert("Format", CONFLICT_IGNORE, formatValues) + it.query(SimpleSQLiteQuery("SELECT id, loudnessDb, contentLength FROM Song;")) + .use { cursor -> + val formatValues = ContentValues(3) + while (cursor.moveToNext()) { + formatValues.put("songId", cursor.getString(0)) + formatValues.put("loudnessDb", cursor.getFloatOrNull(1)) + formatValues.put("contentLength", cursor.getFloatOrNull(2)) + it.insert("Format", CONFLICT_IGNORE, formatValues) + } } - } it.execSQL("CREATE TABLE IF NOT EXISTS `Song_new` (`id` TEXT NOT NULL, `title` TEXT NOT NULL, `artistsText` TEXT, `durationText` TEXT NOT NULL, `thumbnailUrl` TEXT, `lyrics` TEXT, `likedAt` INTEGER, `totalPlayTimeMs` INTEGER NOT NULL, PRIMARY KEY(`id`))") @@ -445,7 +502,6 @@ object Converters { val parcel = Parcel.obtain() parcel.unmarshall(byteArray, 0, byteArray.size) parcel.setDataPosition(0) - val bundle = parcel.readBundle(MediaItem::class.java.classLoader) parcel.recycle() @@ -459,7 +515,6 @@ object Converters { return mediaItem?.toBundle()?.let { persistableBundle -> val parcel = Parcel.obtain() parcel.writeBundle(persistableBundle) - val bytes = parcel.marshall() parcel.recycle() diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainActivity.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainActivity.kt index 7827f5c..1e46af9 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainActivity.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainActivity.kt @@ -1,6 +1,10 @@ package it.vfsfitvnm.vimusic -import android.content.* +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.content.SharedPreferences import android.net.Uri import android.os.Bundle import android.os.IBinder @@ -11,14 +15,27 @@ import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.RepeatMode import androidx.compose.animation.core.infiniteRepeatable import androidx.compose.animation.core.tween -import androidx.compose.foundation.* +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.LocalIndication +import androidx.compose.foundation.LocalOverscrollConfiguration +import androidx.compose.foundation.background +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.ripple.LocalRippleTheme import androidx.compose.material.ripple.RippleAlpha import androidx.compose.material.ripple.RippleTheme import androidx.compose.material.ripple.rememberRipple -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.SideEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.neverEqualPolicy +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -41,7 +58,13 @@ import it.vfsfitvnm.vimusic.ui.styling.Appearance import it.vfsfitvnm.vimusic.ui.styling.Dimensions import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.views.PlayerView -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.colorPaletteModeKey +import it.vfsfitvnm.vimusic.utils.getEnum +import it.vfsfitvnm.vimusic.utils.intent +import it.vfsfitvnm.vimusic.utils.listener +import it.vfsfitvnm.vimusic.utils.preferences +import it.vfsfitvnm.vimusic.utils.rememberHapticFeedback +import it.vfsfitvnm.vimusic.utils.thumbnailRoundnessKey class MainActivity : ComponentActivity() { private val serviceConnection = object : ServiceConnection { @@ -73,7 +96,8 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val expandPlayerBottomSheet = intent?.extras?.getBoolean("expandPlayerBottomSheet", false) ?: false + val expandPlayerBottomSheet = + intent?.extras?.getBoolean("expandPlayerBottomSheet", false) ?: false uri = intent?.data @@ -245,4 +269,4 @@ fun ExpandPlayerOnPlaylistChange(player: Player, expand: () -> Unit) { } }) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainApplication.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainApplication.kt index a7c82ca..bb6e259 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainApplication.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/MainApplication.kt @@ -9,7 +9,6 @@ import it.vfsfitvnm.vimusic.utils.coilDiskCacheMaxSizeKey import it.vfsfitvnm.vimusic.utils.getEnum import it.vfsfitvnm.vimusic.utils.preferences - class MainApplication : Application(), ImageLoaderFactory { override fun onCreate() { super.onCreate() @@ -22,7 +21,12 @@ class MainApplication : Application(), ImageLoaderFactory { .diskCache( DiskCache.Builder() .directory(filesDir.resolve("coil")) - .maxSizeBytes(preferences.getEnum(coilDiskCacheMaxSizeKey, CoilDiskCacheMaxSize.`128MB`).bytes) + .maxSizeBytes( + preferences.getEnum( + coilDiskCacheMaxSizeKey, + CoilDiskCacheMaxSize.`128MB` + ).bytes + ) .build() ) .build() diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/BuiltInPlaylist.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/BuiltInPlaylist.kt index d920a49..03b8f1e 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/BuiltInPlaylist.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/BuiltInPlaylist.kt @@ -1,6 +1,5 @@ package it.vfsfitvnm.vimusic.enums - enum class BuiltInPlaylist { Favorites, Cached diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/CoilDiskCacheSize.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/CoilDiskCacheSize.kt index 66c67f3..fa13e0c 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/CoilDiskCacheSize.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/CoilDiskCacheSize.kt @@ -1,6 +1,5 @@ package it.vfsfitvnm.vimusic.enums - enum class CoilDiskCacheMaxSize { `128MB`, `256MB`, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ColorPaletteMode.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ColorPaletteMode.kt index cd2e193..1dc1af3 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ColorPaletteMode.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ColorPaletteMode.kt @@ -15,7 +15,6 @@ import it.vfsfitvnm.vimusic.ui.styling.DarkColorPalette import it.vfsfitvnm.vimusic.ui.styling.LightColorPalette import it.vfsfitvnm.vimusic.ui.styling.Typography - enum class ColorPaletteMode { Light, Dark, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ExoPlayerDiskCacheMaxSize.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ExoPlayerDiskCacheMaxSize.kt index 2803f58..a613f05 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ExoPlayerDiskCacheMaxSize.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/enums/ExoPlayerDiskCacheMaxSize.kt @@ -1,6 +1,5 @@ package it.vfsfitvnm.vimusic.enums - enum class ExoPlayerDiskCacheMaxSize { `512MB`, `1GB`, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Artist.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Artist.kt index f011958..84cd35d 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Artist.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Artist.kt @@ -14,4 +14,4 @@ data class Artist( val radioVideoId: String? = null, val radioPlaylistId: String? = null, val timestamp: Long? -) \ No newline at end of file +) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/DetailedSong.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/DetailedSong.kt index 23f76b0..501c82a 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/DetailedSong.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/DetailedSong.kt @@ -4,7 +4,6 @@ import androidx.room.Embedded import androidx.room.Junction import androidx.room.Relation - open class DetailedSong( @Embedded val song: Song, @Relation( diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/DetailedSongWithContentLength.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/DetailedSongWithContentLength.kt index b88be4f..32a2636 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/DetailedSongWithContentLength.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/DetailedSongWithContentLength.kt @@ -2,7 +2,6 @@ package it.vfsfitvnm.vimusic.models import androidx.room.Relation - class DetailedSongWithContentLength( song: Song, albumId: String?, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Format.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Format.kt index 74f3b9a..88fef51 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Format.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Format.kt @@ -1,8 +1,9 @@ package it.vfsfitvnm.vimusic.models import androidx.compose.runtime.Immutable -import androidx.room.* - +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.PrimaryKey @Immutable @Entity( diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/PlaylistWithSongs.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/PlaylistWithSongs.kt index a98f0fa..2b8ad5c 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/PlaylistWithSongs.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/PlaylistWithSongs.kt @@ -1,7 +1,8 @@ package it.vfsfitvnm.vimusic.models -import androidx.room.* - +import androidx.room.Embedded +import androidx.room.Junction +import androidx.room.Relation data class PlaylistWithSongs( @Embedded val playlist: Playlist, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/QueuedMediaItem.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/QueuedMediaItem.kt index d76d259..bfb95df 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/QueuedMediaItem.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/QueuedMediaItem.kt @@ -1,6 +1,5 @@ package it.vfsfitvnm.vimusic.models - import androidx.media3.common.MediaItem import androidx.room.ColumnInfo import androidx.room.Entity @@ -11,4 +10,4 @@ class QueuedMediaItem( @PrimaryKey(autoGenerate = true) val id: Long = 0, @ColumnInfo(typeAffinity = ColumnInfo.BLOB) val mediaItem: MediaItem, var position: Long? -) \ No newline at end of file +) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SearchQuery.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SearchQuery.kt index de7417e..a3479f1 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SearchQuery.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SearchQuery.kt @@ -5,7 +5,6 @@ import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey - @Immutable @Entity( indices = [ diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Song.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Song.kt index 799bf52..0c36c20 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Song.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/Song.kt @@ -1,7 +1,7 @@ package it.vfsfitvnm.vimusic.models -import androidx.room.* - +import androidx.room.Entity +import androidx.room.PrimaryKey @Entity data class Song( @@ -20,7 +20,7 @@ data class Song( val hours = seconds / 3600 - return when { + return when { hours == 0L -> "${seconds / 60}m" hours < 24L -> "${hours}h" else -> "${hours / 24}d" diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongAlbumMap.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongAlbumMap.kt index 3716392..4fc61a3 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongAlbumMap.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongAlbumMap.kt @@ -5,7 +5,6 @@ import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.ForeignKey - @Immutable @Entity( primaryKeys = ["songId", "albumId"], diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongArtistMap.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongArtistMap.kt index b2cbedb..e8d3d8f 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongArtistMap.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongArtistMap.kt @@ -4,7 +4,6 @@ import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.ForeignKey - @Entity( primaryKeys = ["songId", "artistId"], foreignKeys = [ @@ -25,4 +24,4 @@ import androidx.room.ForeignKey data class SongArtistMap( @ColumnInfo(index = true) val songId: String, @ColumnInfo(index = true) val artistId: String -) \ No newline at end of file +) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongPlaylistMap.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongPlaylistMap.kt index 9d91e05..cb1f804 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongPlaylistMap.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/models/SongPlaylistMap.kt @@ -1,12 +1,9 @@ package it.vfsfitvnm.vimusic.models -import androidx.compose.runtime.Immutable import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.ForeignKey - -@Immutable @Entity( primaryKeys = ["songId", "playlistId"], foreignKeys = [ diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/BitmapProvider.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/BitmapProvider.kt index 27255d6..1eb7b13 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/BitmapProvider.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/BitmapProvider.kt @@ -6,7 +6,7 @@ import android.graphics.Bitmap import android.graphics.drawable.BitmapDrawable import android.net.Uri import androidx.core.graphics.applyCanvas -import coil.Coil +import coil.imageLoader import coil.request.Disposable import coil.request.ImageRequest import it.vfsfitvnm.vimusic.utils.thumbnail @@ -39,9 +39,10 @@ class BitmapProvider( lastIsSystemInDarkMode = isSystemInDarkMode - defaultBitmap = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888).applyCanvas { - drawColor(colorProvider(isSystemInDarkMode)) - } + defaultBitmap = + Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888).applyCanvas { + drawColor(colorProvider(isSystemInDarkMode)) + } return lastBitmap == null } @@ -52,7 +53,7 @@ class BitmapProvider( lastEnqueued?.dispose() lastUri = uri - lastEnqueued = Coil.imageLoader(applicationContext).enqueue( + lastEnqueued = applicationContext.imageLoader.enqueue( ImageRequest.Builder(applicationContext) .data(uri.thumbnail(bitmapSize)) .listener( @@ -68,4 +69,4 @@ class BitmapProvider( .build() ) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/PlayerService.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/PlayerService.kt index eacc81c..0fc4596 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/PlayerService.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/service/PlayerService.kt @@ -1,10 +1,15 @@ package it.vfsfitvnm.vimusic.service +import android.os.Binder as AndroidBinder import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent -import android.content.* +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.content.SharedPreferences import android.content.res.Configuration import android.graphics.Color import android.media.MediaMetadata @@ -21,19 +26,32 @@ import androidx.core.content.ContextCompat.startForegroundService import androidx.core.content.edit import androidx.core.content.getSystemService import androidx.core.net.toUri -import androidx.media3.common.* +import androidx.media3.common.AudioAttributes +import androidx.media3.common.C +import androidx.media3.common.MediaItem +import androidx.media3.common.PlaybackException +import androidx.media3.common.Player +import androidx.media3.common.Timeline import androidx.media3.database.StandaloneDatabaseProvider import androidx.media3.datasource.DataSource import androidx.media3.datasource.DefaultHttpDataSource import androidx.media3.datasource.ResolvingDataSource -import androidx.media3.datasource.cache.* +import androidx.media3.datasource.cache.Cache +import androidx.media3.datasource.cache.CacheDataSource +import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor +import androidx.media3.datasource.cache.NoOpCacheEvictor +import androidx.media3.datasource.cache.SimpleCache import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.RenderersFactory import androidx.media3.exoplayer.analytics.AnalyticsListener import androidx.media3.exoplayer.analytics.PlaybackStats import androidx.media3.exoplayer.analytics.PlaybackStatsListener -import androidx.media3.exoplayer.audio.* +import androidx.media3.exoplayer.audio.AudioRendererEventListener +import androidx.media3.exoplayer.audio.DefaultAudioSink import androidx.media3.exoplayer.audio.DefaultAudioSink.DefaultAudioProcessorChain +import androidx.media3.exoplayer.audio.MediaCodecAudioRenderer +import androidx.media3.exoplayer.audio.SilenceSkippingAudioProcessor +import androidx.media3.exoplayer.audio.SonicAudioProcessor import androidx.media3.exoplayer.mediacodec.MediaCodecSelector import androidx.media3.exoplayer.source.DefaultMediaSourceFactory import androidx.media3.exoplayer.source.MediaSource @@ -46,17 +64,40 @@ import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.enums.ExoPlayerDiskCacheMaxSize import it.vfsfitvnm.vimusic.models.QueuedMediaItem import it.vfsfitvnm.vimusic.query -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.InvincibleService +import it.vfsfitvnm.vimusic.utils.RingBuffer +import it.vfsfitvnm.vimusic.utils.TimerJob +import it.vfsfitvnm.vimusic.utils.YouTubeRadio +import it.vfsfitvnm.vimusic.utils.activityPendingIntent +import it.vfsfitvnm.vimusic.utils.broadCastPendingIntent +import it.vfsfitvnm.vimusic.utils.exoPlayerDiskCacheMaxSizeKey +import it.vfsfitvnm.vimusic.utils.findNextMediaItemById +import it.vfsfitvnm.vimusic.utils.forcePlayFromBeginning +import it.vfsfitvnm.vimusic.utils.getEnum +import it.vfsfitvnm.vimusic.utils.intent +import it.vfsfitvnm.vimusic.utils.isInvincibilityEnabledKey +import it.vfsfitvnm.vimusic.utils.mediaItems +import it.vfsfitvnm.vimusic.utils.persistentQueueKey +import it.vfsfitvnm.vimusic.utils.preferences +import it.vfsfitvnm.vimusic.utils.repeatModeKey +import it.vfsfitvnm.vimusic.utils.shouldBePlaying +import it.vfsfitvnm.vimusic.utils.skipSilenceKey +import it.vfsfitvnm.vimusic.utils.timer +import it.vfsfitvnm.vimusic.utils.volumeNormalizationKey import it.vfsfitvnm.youtubemusic.YouTube import it.vfsfitvnm.youtubemusic.models.NavigationEndpoint -import kotlinx.coroutines.* +import kotlin.math.roundToInt +import kotlin.system.exitProcess +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.cancellable import kotlinx.coroutines.flow.distinctUntilChanged -import kotlin.math.roundToInt -import kotlin.system.exitProcess -import android.os.Binder as AndroidBinder - +import kotlinx.coroutines.launch +import kotlinx.coroutines.plus +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext @Suppress("DEPRECATION") class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListener.Callback, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/BottomSheet.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/BottomSheet.kt index 27e56cd..7007cc9 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/BottomSheet.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/BottomSheet.kt @@ -1,15 +1,32 @@ package it.vfsfitvnm.vimusic.ui.components import androidx.activity.compose.BackHandler -import androidx.compose.animation.core.* +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.AnimationSpec +import androidx.compose.animation.core.AnimationVector1D +import androidx.compose.animation.core.SpringSpec +import androidx.compose.animation.core.VectorConverter +import androidx.compose.animation.core.tween import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.DraggableState import androidx.compose.foundation.gestures.detectVerticalDragGestures import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset import androidx.compose.material.ripple.rememberRipple -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.derivedStateOf +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.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Offset @@ -24,10 +41,10 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.dp +import kotlin.math.absoluteValue import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch -import kotlin.math.absoluteValue @Composable fun BottomSheet( @@ -109,7 +126,7 @@ fun BottomSheet( class BottomSheetState( draggableState: DraggableState, private val coroutineScope: CoroutineScope, - private val animatable: Animatable, + private val animatable: Animatable, private val onWasExpandedChanged: (Boolean) -> Unit, ) : DraggableState by draggableState { val lowerBound: Dp @@ -220,7 +237,11 @@ class BottomSheetState( } @Composable -fun rememberBottomSheetState(lowerBound: Dp, upperBound: Dp, isExpanded: Boolean = false): BottomSheetState { +fun rememberBottomSheetState( + lowerBound: Dp, + upperBound: Dp, + isExpanded: Boolean = false +): BottomSheetState { val density = LocalDensity.current val coroutineScope = rememberCoroutineScope() diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/ChunkyButton.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/ChunkyButton.kt index 3e32c11..c50a436 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/ChunkyButton.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/ChunkyButton.kt @@ -5,7 +5,14 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicText import androidx.compose.material.ripple.rememberRipple @@ -20,7 +27,7 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp - +import it.vfsfitvnm.vimusic.R @Composable fun ChunkyButton( @@ -69,7 +76,7 @@ fun ChunkyButton( style = textStyle ) - secondaryText?.let { secondaryText -> + secondaryText?.let { secondaryText -> BasicText( text = secondaryText, style = secondaryTextStyle @@ -88,7 +95,7 @@ fun ChunkyButton( Image( // TODO: this is themed... - painter = painterResource(it.vfsfitvnm.vimusic.R.drawable.ellipsis_vertical), + painter = painterResource(R.drawable.ellipsis_vertical), contentDescription = null, colorFilter = ColorFilter.tint(rippleColor.copy(alpha = 0.6f)), modifier = Modifier diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/ChunkyChipGroup.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/ChunkyChipGroup.kt index 63206a8..9eafc96 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/ChunkyChipGroup.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/ChunkyChipGroup.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp @Composable -fun ChipGroup( +fun ChipGroup( items: List>, value: T, selectedBackgroundColor: Color, @@ -27,7 +27,7 @@ fun ChipGroup( Row( horizontalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier - .horizontalScroll(rememberScrollState().also { }) + .horizontalScroll(rememberScrollState()) .then(modifier) ) { items.forEach { chipItem -> @@ -47,4 +47,4 @@ fun ChipGroup( data class ChipItem( val text: String, val value: T -) \ No newline at end of file +) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/Menu.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/Menu.kt index db41735..6ccd848 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/Menu.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/Menu.kt @@ -1,12 +1,22 @@ package it.vfsfitvnm.vimusic.ui.components import androidx.activity.compose.BackHandler -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.compositionLocalOf +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.graphics.Color import androidx.compose.ui.input.pointer.pointerInput @@ -74,4 +84,4 @@ fun BottomSheetMenu( ) { state.content() } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/MusicBars.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/MusicBars.kt index 8d7b6b5..47e40d7 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/MusicBars.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/MusicBars.kt @@ -2,23 +2,18 @@ package it.vfsfitvnm.vimusic.ui.components import androidx.compose.animation.core.Animatable import androidx.compose.foundation.Canvas -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.CornerRadius import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.graphics.StrokeCap -import androidx.compose.ui.graphics.StrokeJoin -import androidx.compose.ui.graphics.drawscope.DrawStyle -import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch @@ -32,9 +27,90 @@ fun MusicBars( ) { val animatablesWithSteps = remember { listOf( - Animatable(0f) to listOf(0.2f, 0.8f, 0.1f, 0.1f, 0.3f, 0.1f, 0.2f, 0.8f, 0.7f, 0.2f, 0.4f, 0.9f, 0.7f, 0.6f, 0.1f, 0.3f, 0.1f, 0.4f, 0.1f, 0.8f, 0.7f, 0.9f, 0.5f, 0.6f, 0.3f, 0.1f), - Animatable(0f) to listOf(0.2f, 0.5f, 1.0f, 0.5f, 0.3f, 0.1f, 0.2f, 0.3f, 0.5f, 0.1f, 0.6f, 0.5f, 0.3f, 0.7f, 0.8f, 0.9f, 0.3f, 0.1f, 0.5f, 0.3f, 0.6f, 1.0f, 0.6f, 0.7f, 0.4f, 0.1f), - Animatable(0f) to listOf(0.6f, 0.5f, 1.0f, 0.6f, 0.5f, 1.0f, 0.6f, 0.5f, 1.0f, 0.5f, 0.6f, 0.7f, 0.2f, 0.3f, 0.1f, 0.5f, 0.4f, 0.6f, 0.7f, 0.1f, 0.4f, 0.3f, 0.1f, 0.4f, 0.3f, 0.7f) + Animatable(0f) to listOf( + 0.2f, + 0.8f, + 0.1f, + 0.1f, + 0.3f, + 0.1f, + 0.2f, + 0.8f, + 0.7f, + 0.2f, + 0.4f, + 0.9f, + 0.7f, + 0.6f, + 0.1f, + 0.3f, + 0.1f, + 0.4f, + 0.1f, + 0.8f, + 0.7f, + 0.9f, + 0.5f, + 0.6f, + 0.3f, + 0.1f + ), + Animatable(0f) to listOf( + 0.2f, + 0.5f, + 1.0f, + 0.5f, + 0.3f, + 0.1f, + 0.2f, + 0.3f, + 0.5f, + 0.1f, + 0.6f, + 0.5f, + 0.3f, + 0.7f, + 0.8f, + 0.9f, + 0.3f, + 0.1f, + 0.5f, + 0.3f, + 0.6f, + 1.0f, + 0.6f, + 0.7f, + 0.4f, + 0.1f + ), + Animatable(0f) to listOf( + 0.6f, + 0.5f, + 1.0f, + 0.6f, + 0.5f, + 1.0f, + 0.6f, + 0.5f, + 1.0f, + 0.5f, + 0.6f, + 0.7f, + 0.2f, + 0.3f, + 0.1f, + 0.5f, + 0.4f, + 0.6f, + 0.7f, + 0.1f, + 0.4f, + 0.3f, + 0.1f, + 0.4f, + 0.3f, + 0.7f + ) ) } @@ -70,4 +146,4 @@ fun MusicBars( } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/Pager.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/Pager.kt index 282f534..6577e20 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/Pager.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/Pager.kt @@ -4,9 +4,16 @@ import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.calculateTargetValue import androidx.compose.animation.splineBasedDecay import androidx.compose.foundation.gestures.Orientation -import androidx.compose.foundation.gestures.detectVerticalDragGestures import androidx.compose.foundation.gestures.detectHorizontalDragGestures -import androidx.compose.runtime.* +import androidx.compose.foundation.gestures.detectVerticalDragGestures +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds @@ -18,9 +25,8 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.center import androidx.compose.ui.util.lerp -import kotlinx.coroutines.launch import kotlin.math.absoluteValue - +import kotlinx.coroutines.launch @Composable fun Pager( @@ -59,7 +65,10 @@ fun Pager( {}, { val velocity = -velocityTracker.calculateVelocity().x - val initialTargetValue = splineBasedDecay(this).calculateTargetValue(state.value, velocity) + val initialTargetValue = splineBasedDecay(this).calculateTargetValue( + state.value, + velocity + ) velocityTracker.resetTracking() @@ -129,7 +138,10 @@ fun Pager( } } - state.updateBounds(lowerBound = steps.first().toFloat(), upperBound = steps.last().toFloat()) + state.updateBounds( + lowerBound = steps.first().toFloat(), + upperBound = steps.last().toFloat() + ) val layoutDimension = IntSize( width = if (constraints.minWidth > 0 || placeables.isEmpty()) { diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/SeekBar.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/SeekBar.kt index c78fd72..03046f4 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/SeekBar.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/SeekBar.kt @@ -3,7 +3,11 @@ package it.vfsfitvnm.vimusic.ui.components import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectHorizontalDragGestures import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -16,7 +20,6 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import kotlin.math.roundToLong - @Composable fun SeekBar( value: Long, @@ -89,8 +92,9 @@ fun SeekBar( ) if (drawSteps) { - for (i in value + 1 .. maximumValue) { - val stepPosition = (i.toFloat() - minimumValue) / (maximumValue - minimumValue) * size.width + for (i in value + 1..maximumValue) { + val stepPosition = + (i.toFloat() - minimumValue) / (maximumValue - minimumValue) * size.width drawCircle( color = scrubberColor, radius = scrubberRadius.toPx() / 2, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/TopAppBar.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/TopAppBar.kt index 6b9c50e..238d304 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/TopAppBar.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/TopAppBar.kt @@ -20,4 +20,4 @@ inline fun TopAppBar( .fillMaxWidth(), content = content ) -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Dialog.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Dialog.kt index abae40c..46c9ee5 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Dialog.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Dialog.kt @@ -3,18 +3,36 @@ package it.vfsfitvnm.vimusic.ui.components.themed import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.foundation.* +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicText import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll import androidx.compose.material.ripple.rememberRipple -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier @@ -35,7 +53,12 @@ import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import it.vfsfitvnm.vimusic.ui.components.ChunkyButton import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.center +import it.vfsfitvnm.vimusic.utils.color +import it.vfsfitvnm.vimusic.utils.drawCircle +import it.vfsfitvnm.vimusic.utils.medium +import it.vfsfitvnm.vimusic.utils.secondary +import it.vfsfitvnm.vimusic.utils.semiBold import kotlinx.coroutines.delay @Composable @@ -228,7 +251,6 @@ inline fun DefaultDialog( } } - @Composable inline fun ValueSelectorDialog( noinline onDismiss: () -> Unit, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/DropDownSection.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/DropDownSection.kt index 510e6e1..fcaa883 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/DropDownSection.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/DropDownSection.kt @@ -3,7 +3,15 @@ package it.vfsfitvnm.vimusic.ui.components.themed import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicText import androidx.compose.material.ripple.rememberRipple @@ -18,7 +26,6 @@ import androidx.compose.ui.unit.sp import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.medium - @Composable fun DropDownSection(content: @Composable ColumnScope.() -> Unit) { val (colorPalette) = LocalAppearance.current @@ -96,4 +103,4 @@ fun DropDownTextItem( vertical = 8.dp ) ) -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/DropdownMenu.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/DropdownMenu.kt index 794e095..bd86c6d 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/DropdownMenu.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/DropdownMenu.kt @@ -1,21 +1,35 @@ package it.vfsfitvnm.vimusic.ui.components.themed -import androidx.compose.animation.core.* +import androidx.compose.animation.core.LinearOutSlowInEasing +import androidx.compose.animation.core.MutableTransitionState +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.tween +import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +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.graphics.TransformOrigin import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.unit.* +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.DpOffset +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntRect +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import androidx.compose.ui.window.PopupPositionProvider import androidx.compose.ui.window.PopupProperties import kotlin.math.max import kotlin.math.min - @Composable fun DropdownMenu( isDisplayed: Boolean, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/LoadingOrError.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/LoadingOrError.kt index 03885c4..d81efa8 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/LoadingOrError.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/LoadingOrError.kt @@ -38,4 +38,4 @@ fun LoadingOrError( } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt index 60f8d81..81a67a4 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt @@ -6,11 +6,21 @@ import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.with import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicText -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -20,13 +30,16 @@ import androidx.compose.ui.unit.dp import androidx.media3.common.MediaItem import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.route.empty -import it.vfsfitvnm.vimusic.* +import it.vfsfitvnm.vimusic.Database +import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.enums.PlaylistSortBy import it.vfsfitvnm.vimusic.enums.SortOrder import it.vfsfitvnm.vimusic.models.DetailedSong import it.vfsfitvnm.vimusic.models.Playlist import it.vfsfitvnm.vimusic.models.SongPlaylistMap +import it.vfsfitvnm.vimusic.query +import it.vfsfitvnm.vimusic.transaction import it.vfsfitvnm.vimusic.ui.components.ChunkyButton import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.Pager @@ -34,12 +47,17 @@ import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute import it.vfsfitvnm.vimusic.ui.screens.rememberCreatePlaylistRoute import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.addNext +import it.vfsfitvnm.vimusic.utils.asMediaItem +import it.vfsfitvnm.vimusic.utils.color +import it.vfsfitvnm.vimusic.utils.enqueue +import it.vfsfitvnm.vimusic.utils.forcePlay +import it.vfsfitvnm.vimusic.utils.semiBold +import it.vfsfitvnm.vimusic.utils.shareAsYouTubeSong import it.vfsfitvnm.youtubemusic.models.NavigationEndpoint import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.flowOf - @ExperimentalAnimationApi @Composable fun InFavoritesMediaItemMenu( @@ -533,7 +551,13 @@ fun MediaItemMenu( MenuEntry( icon = R.drawable.alarm, text = "Sleep timer", - secondaryText = sleepTimerMillisLeft?.let { "${DateUtils.formatElapsedTime(it / 1000)} left" }, + secondaryText = sleepTimerMillisLeft?.let { + "${ + DateUtils.formatElapsedTime( + it / 1000 + ) + } left" + }, onClick = { isShowingSleepTimerDialog = true } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Menu.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Menu.kt index ba82a3e..2f7f8ca 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Menu.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Menu.kt @@ -1,11 +1,22 @@ package it.vfsfitvnm.vimusic.ui.components.themed import androidx.annotation.DrawableRes -import androidx.compose.foundation.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicText +import androidx.compose.foundation.verticalScroll import androidx.compose.material.ripple.rememberRipple import androidx.compose.runtime.Composable import androidx.compose.runtime.remember @@ -20,7 +31,6 @@ import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.medium import it.vfsfitvnm.vimusic.utils.secondary - @Composable inline fun Menu( modifier: Modifier = Modifier, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Switch.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Switch.kt index 3185962..2e5effb 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Switch.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/Switch.kt @@ -19,7 +19,6 @@ import androidx.compose.ui.unit.dp import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.drawCircle - @Composable fun Switch( isChecked: Boolean, @@ -49,4 +48,4 @@ fun Switch( ) } ) -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextCard.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextCard.kt index e538811..ee24e61 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextCard.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextCard.kt @@ -22,7 +22,6 @@ import it.vfsfitvnm.vimusic.utils.align import it.vfsfitvnm.vimusic.utils.secondary import it.vfsfitvnm.vimusic.utils.semiBold - @Composable fun TextCard( modifier: Modifier = Modifier, @@ -110,4 +109,4 @@ private object IconTextCardScopeImpl : TextCardScope { .padding(horizontal = 16.dp) ) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextPlaceholder.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextPlaceholder.kt index 0f99173..9cb21e0 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextPlaceholder.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/TextPlaceholder.kt @@ -25,4 +25,4 @@ fun TextPlaceholder( .fillMaxWidth(remember { 0.25f + Random.nextFloat() * 0.5f }) .height(16.dp) ) -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/AlbumScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/AlbumScreen.kt index 1ad00da..6858d8d 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/AlbumScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/AlbumScreen.kt @@ -5,7 +5,19 @@ import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState @@ -32,24 +44,40 @@ import it.vfsfitvnm.vimusic.Database import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness -import it.vfsfitvnm.vimusic.models.* +import it.vfsfitvnm.vimusic.models.Album +import it.vfsfitvnm.vimusic.models.DetailedSong +import it.vfsfitvnm.vimusic.models.Playlist +import it.vfsfitvnm.vimusic.models.SongAlbumMap +import it.vfsfitvnm.vimusic.models.SongPlaylistMap import it.vfsfitvnm.vimusic.query import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.TopAppBar -import it.vfsfitvnm.vimusic.ui.components.themed.* +import it.vfsfitvnm.vimusic.ui.components.themed.LoadingOrError +import it.vfsfitvnm.vimusic.ui.components.themed.Menu +import it.vfsfitvnm.vimusic.ui.components.themed.MenuEntry +import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu +import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder import it.vfsfitvnm.vimusic.ui.styling.Dimensions import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.SongItem -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.asMediaItem +import it.vfsfitvnm.vimusic.utils.bold +import it.vfsfitvnm.vimusic.utils.center +import it.vfsfitvnm.vimusic.utils.enqueue +import it.vfsfitvnm.vimusic.utils.forcePlayAtIndex +import it.vfsfitvnm.vimusic.utils.forcePlayFromBeginning +import it.vfsfitvnm.vimusic.utils.secondary +import it.vfsfitvnm.vimusic.utils.semiBold +import it.vfsfitvnm.vimusic.utils.thumbnail +import it.vfsfitvnm.vimusic.utils.toMediaItem import it.vfsfitvnm.youtubemusic.YouTube +import java.text.DateFormat +import java.util.Date import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.runBlocking -import java.text.DateFormat -import java.util.* - @ExperimentalAnimationApi @Composable @@ -143,27 +171,29 @@ fun AlbumScreen( onClick = { menuState.hide() - albumResult?.getOrNull()?.let { album -> - query { - val playlistId = - Database.insert( - Playlist( - name = album.title - ?: "Unknown" + albumResult + ?.getOrNull() + ?.let { album -> + query { + val playlistId = + Database.insert( + Playlist( + name = album.title + ?: "Unknown" + ) ) - ) - songs.forEachIndexed { index, song -> - Database.insert( - SongPlaylistMap( - songId = song.song.id, - playlistId = playlistId, - position = index + songs.forEachIndexed { index, song -> + Database.insert( + SongPlaylistMap( + songId = song.song.id, + playlistId = playlistId, + position = index + ) ) - ) + } } } - } } ) @@ -194,14 +224,20 @@ fun AlbumScreen( icon = R.drawable.download, text = "Refetch", secondaryText = albumResult?.getOrNull()?.timestamp?.let { timestamp -> - "Last updated on ${DateFormat.getDateTimeInstance().format(Date(timestamp))}" + "Last updated on ${ + DateFormat + .getDateTimeInstance() + .format(Date(timestamp)) + }" }, isEnabled = albumResult?.getOrNull() != null, onClick = { menuState.hide() query { - albumResult?.getOrNull()?.let(Database::delete) + albumResult + ?.getOrNull() + ?.let(Database::delete) runBlocking(Dispatchers.IO) { fetchAlbum(browseId) } @@ -275,7 +311,9 @@ fun AlbumScreen( .clickable { binder?.stopRadio() binder?.player?.forcePlayFromBeginning( - songs.shuffled().map(DetailedSong::asMediaItem) + songs + .shuffled() + .map(DetailedSong::asMediaItem) ) } .shadow(elevation = 2.dp, shape = CircleShape) @@ -325,7 +363,10 @@ fun AlbumScreen( durationText = song.song.durationText, onClick = { binder?.stopRadio() - binder?.player?.forcePlayAtIndex(songs.map(DetailedSong::asMediaItem), index) + binder?.player?.forcePlayAtIndex( + songs.map(DetailedSong::asMediaItem), + index + ) }, startContent = { BasicText( @@ -350,7 +391,6 @@ fun AlbumScreen( } } - @Composable private fun LoadingOrError( errorMessage: String? = null, @@ -419,4 +459,4 @@ private suspend fun fetchAlbum(browseId: String): Result? { } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/ArtistScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/ArtistScreen.kt index 1f3072e..9058f89 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/ArtistScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/ArtistScreen.kt @@ -1,11 +1,18 @@ package it.vfsfitvnm.vimusic.ui.screens import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState @@ -37,9 +44,15 @@ import it.vfsfitvnm.vimusic.ui.components.themed.InHistoryMediaItemMenu import it.vfsfitvnm.vimusic.ui.components.themed.LoadingOrError import it.vfsfitvnm.vimusic.ui.components.themed.TextCard import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder -import it.vfsfitvnm.vimusic.ui.styling.* +import it.vfsfitvnm.vimusic.ui.styling.Dimensions +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance +import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.SongItem -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.asMediaItem +import it.vfsfitvnm.vimusic.utils.forcePlayAtIndex +import it.vfsfitvnm.vimusic.utils.forcePlayFromBeginning +import it.vfsfitvnm.vimusic.utils.semiBold +import it.vfsfitvnm.vimusic.utils.thumbnail import it.vfsfitvnm.youtubemusic.YouTube import it.vfsfitvnm.youtubemusic.models.NavigationEndpoint import kotlinx.coroutines.Dispatchers @@ -48,8 +61,6 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.runBlocking - -@OptIn(ExperimentalFoundationApi::class) @ExperimentalAnimationApi @Composable fun ArtistScreen( @@ -337,4 +348,4 @@ private suspend fun fetchArtist(browseId: String): Result? { timestamp = System.currentTimeMillis() ).also(Database::upsert) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/BuiltInPlaylistScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/BuiltInPlaylistScreen.kt index 27c07b5..d974371 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/BuiltInPlaylistScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/BuiltInPlaylistScreen.kt @@ -4,7 +4,14 @@ import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState @@ -36,11 +43,15 @@ import it.vfsfitvnm.vimusic.ui.styling.Dimensions import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.SongItem -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.asMediaItem +import it.vfsfitvnm.vimusic.utils.enqueue +import it.vfsfitvnm.vimusic.utils.forcePlayAtIndex +import it.vfsfitvnm.vimusic.utils.forcePlayFromBeginning +import it.vfsfitvnm.vimusic.utils.secondary +import it.vfsfitvnm.vimusic.utils.semiBold import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.map - @ExperimentalAnimationApi @Composable fun BuiltInPlaylistScreen( @@ -221,7 +232,10 @@ fun BuiltInPlaylistScreen( thumbnailSize = thumbnailSize, onClick = { binder?.stopRadio() - binder?.player?.forcePlayAtIndex(songs.map(DetailedSong::asMediaItem), index) + binder?.player?.forcePlayAtIndex( + songs.map(DetailedSong::asMediaItem), + index + ) }, menuContent = { when (builtInPlaylist) { diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/HomeScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/HomeScreen.kt index 438684e..80b4b9b 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/HomeScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/HomeScreen.kt @@ -1,13 +1,24 @@ package it.vfsfitvnm.vimusic.ui.screens import android.net.Uri -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.animateContentSize +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid @@ -17,16 +28,29 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.text.BasicText import androidx.compose.material.ripple.rememberRipple -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.drawWithCache import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.center -import androidx.compose.ui.graphics.* +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.ClipOp +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.Paint +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.Shadow +import androidx.compose.ui.graphics.asAndroidPath import androidx.compose.ui.graphics.drawscope.clipPath +import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextOverflow @@ -37,23 +61,44 @@ import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.vimusic.Database import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder import it.vfsfitvnm.vimusic.R -import it.vfsfitvnm.vimusic.enums.* +import it.vfsfitvnm.vimusic.enums.BuiltInPlaylist +import it.vfsfitvnm.vimusic.enums.PlaylistSortBy +import it.vfsfitvnm.vimusic.enums.SongSortBy +import it.vfsfitvnm.vimusic.enums.SortOrder +import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness import it.vfsfitvnm.vimusic.models.DetailedSong import it.vfsfitvnm.vimusic.models.Playlist import it.vfsfitvnm.vimusic.models.SearchQuery import it.vfsfitvnm.vimusic.query import it.vfsfitvnm.vimusic.ui.components.TopAppBar -import it.vfsfitvnm.vimusic.ui.components.themed.* +import it.vfsfitvnm.vimusic.ui.components.themed.DropDownSection +import it.vfsfitvnm.vimusic.ui.components.themed.DropDownSectionSpacer +import it.vfsfitvnm.vimusic.ui.components.themed.DropDownTextItem +import it.vfsfitvnm.vimusic.ui.components.themed.DropdownMenu +import it.vfsfitvnm.vimusic.ui.components.themed.InHistoryMediaItemMenu +import it.vfsfitvnm.vimusic.ui.components.themed.TextFieldDialog import it.vfsfitvnm.vimusic.ui.styling.Dimensions import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.BuiltInPlaylistItem import it.vfsfitvnm.vimusic.ui.views.PlaylistPreviewItem import it.vfsfitvnm.vimusic.ui.views.SongItem -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.asMediaItem +import it.vfsfitvnm.vimusic.utils.center +import it.vfsfitvnm.vimusic.utils.color +import it.vfsfitvnm.vimusic.utils.drawCircle +import it.vfsfitvnm.vimusic.utils.forcePlayAtIndex +import it.vfsfitvnm.vimusic.utils.forcePlayFromBeginning +import it.vfsfitvnm.vimusic.utils.isFirstLaunchKey +import it.vfsfitvnm.vimusic.utils.playlistGridExpandedKey +import it.vfsfitvnm.vimusic.utils.playlistSortByKey +import it.vfsfitvnm.vimusic.utils.playlistSortOrderKey +import it.vfsfitvnm.vimusic.utils.rememberPreference +import it.vfsfitvnm.vimusic.utils.semiBold +import it.vfsfitvnm.vimusic.utils.songSortByKey +import it.vfsfitvnm.vimusic.utils.songSortOrderKey import kotlinx.coroutines.Dispatchers - @ExperimentalFoundationApi @ExperimentalAnimationApi @Composable @@ -243,7 +288,10 @@ fun HomeScreen() { if (colorPalette.isDark) { return@drawWithCache onDrawBehind { - drawPath(path = decorationPath, color = colorPalette.primaryContainer) + drawPath( + path = decorationPath, + color = colorPalette.primaryContainer + ) } } @@ -253,7 +301,10 @@ fun HomeScreen() { isAntiAlias = true textSize = typography.l.fontSize.toPx() color = colorPalette.text.toArgb() - typeface = ResourcesCompat.getFont(context, R.font.poppins_w500) + typeface = ResourcesCompat.getFont( + context, + R.font.poppins_w500 + ) textAlign = android.graphics.Paint.Align.CENTER } @@ -273,7 +324,10 @@ fun HomeScreen() { onDrawWithContent { clipPath(textPath, ClipOp.Difference) { - drawPath(path = decorationPath, color = colorPalette.primaryContainer) + drawPath( + path = decorationPath, + color = colorPalette.primaryContainer + ) } clipPath(decorationPath, ClipOp.Difference) { diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/IntentUriScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/IntentUriScreen.kt index e498afb..bcb4bbf 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/IntentUriScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/IntentUriScreen.kt @@ -5,12 +5,21 @@ import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -26,7 +35,11 @@ import it.vfsfitvnm.vimusic.models.SongPlaylistMap import it.vfsfitvnm.vimusic.transaction import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.TopAppBar -import it.vfsfitvnm.vimusic.ui.components.themed.* +import it.vfsfitvnm.vimusic.ui.components.themed.LoadingOrError +import it.vfsfitvnm.vimusic.ui.components.themed.Menu +import it.vfsfitvnm.vimusic.ui.components.themed.MenuEntry +import it.vfsfitvnm.vimusic.ui.components.themed.TextCard +import it.vfsfitvnm.vimusic.ui.components.themed.TextFieldDialog import it.vfsfitvnm.vimusic.ui.styling.Dimensions import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px @@ -38,7 +51,6 @@ import it.vfsfitvnm.youtubemusic.YouTube import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext - @ExperimentalAnimationApi @Composable fun IntentUriScreen(uri: Uri) { @@ -224,18 +236,21 @@ fun IntentUriScreen(uri: Uri) { thumbnailSizePx = thumbnailSizePx, onClick = { binder?.stopRadio() - binder?.player?.forcePlayAtIndex(items.map(YouTube.Item.Song::asMediaItem), index) + binder?.player?.forcePlayAtIndex( + items.map(YouTube.Item.Song::asMediaItem), + index + ) } ) } } } ?: itemsResult?.exceptionOrNull()?.let { throwable -> - item { - LoadingOrError( - errorMessage = throwable.javaClass.canonicalName, - onRetry = onLoad - ) - } + item { + LoadingOrError( + errorMessage = throwable.javaClass.canonicalName, + onRetry = onLoad + ) + } } ?: item { LoadingOrError() } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/LocalPlaylistScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/LocalPlaylistScreen.kt index 309c2f3..abd6d1c 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/LocalPlaylistScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/LocalPlaylistScreen.kt @@ -4,14 +4,26 @@ import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.BasicText -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow @@ -23,23 +35,34 @@ import androidx.compose.ui.unit.dp import it.vfsfitvnm.reordering.rememberReorderingState import it.vfsfitvnm.reordering.verticalDragAfterLongPressToReorder import it.vfsfitvnm.route.RouteHandler -import it.vfsfitvnm.vimusic.* +import it.vfsfitvnm.vimusic.Database +import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.models.DetailedSong import it.vfsfitvnm.vimusic.models.PlaylistWithSongs import it.vfsfitvnm.vimusic.models.SongPlaylistMap +import it.vfsfitvnm.vimusic.query +import it.vfsfitvnm.vimusic.transaction import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.TopAppBar -import it.vfsfitvnm.vimusic.ui.components.themed.* +import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog +import it.vfsfitvnm.vimusic.ui.components.themed.InPlaylistMediaItemMenu +import it.vfsfitvnm.vimusic.ui.components.themed.Menu +import it.vfsfitvnm.vimusic.ui.components.themed.MenuEntry +import it.vfsfitvnm.vimusic.ui.components.themed.TextFieldDialog import it.vfsfitvnm.vimusic.ui.styling.Dimensions import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.SongItem -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.asMediaItem +import it.vfsfitvnm.vimusic.utils.enqueue +import it.vfsfitvnm.vimusic.utils.forcePlayAtIndex +import it.vfsfitvnm.vimusic.utils.forcePlayFromBeginning +import it.vfsfitvnm.vimusic.utils.secondary +import it.vfsfitvnm.vimusic.utils.semiBold import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.map - @ExperimentalAnimationApi @Composable fun LocalPlaylistScreen( @@ -152,7 +175,11 @@ fun LocalPlaylistScreen( isEnabled = playlistWithSongs.songs.isNotEmpty(), onClick = { menuState.hide() - binder?.player?.enqueue(playlistWithSongs.songs.map(DetailedSong::asMediaItem)) + binder?.player?.enqueue( + playlistWithSongs.songs.map( + DetailedSong::asMediaItem + ) + ) } ) @@ -217,7 +244,13 @@ fun LocalPlaylistScreen( modifier = Modifier .clickable { binder?.stopRadio() - binder?.player?.forcePlayFromBeginning(playlistWithSongs.songs.map(DetailedSong::asMediaItem).shuffled()) + binder?.player?.forcePlayFromBeginning( + playlistWithSongs.songs + .map( + DetailedSong::asMediaItem + ) + .shuffled() + ) } .shadow(elevation = 2.dp, shape = CircleShape) .background( @@ -235,7 +268,11 @@ fun LocalPlaylistScreen( modifier = Modifier .clickable { binder?.stopRadio() - binder?.player?.forcePlayFromBeginning(playlistWithSongs.songs.map(DetailedSong::asMediaItem)) + binder?.player?.forcePlayFromBeginning( + playlistWithSongs.songs.map( + DetailedSong::asMediaItem + ) + ) } .shadow(elevation = 2.dp, shape = CircleShape) .background( @@ -259,7 +296,11 @@ fun LocalPlaylistScreen( thumbnailSize = thumbnailSize, onClick = { binder?.stopRadio() - binder?.player?.forcePlayAtIndex(playlistWithSongs.songs.map(DetailedSong::asMediaItem), index) + binder?.player?.forcePlayAtIndex( + playlistWithSongs.songs.map( + DetailedSong::asMediaItem + ), index + ) }, menuContent = { InPlaylistMediaItemMenu( diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/PlaylistScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/PlaylistScreen.kt index 7ebdf14..4d063ee 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/PlaylistScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/PlaylistScreen.kt @@ -5,13 +5,30 @@ import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.BasicText -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -34,17 +51,28 @@ import it.vfsfitvnm.vimusic.models.SongPlaylistMap import it.vfsfitvnm.vimusic.transaction import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.TopAppBar -import it.vfsfitvnm.vimusic.ui.components.themed.* +import it.vfsfitvnm.vimusic.ui.components.themed.LoadingOrError +import it.vfsfitvnm.vimusic.ui.components.themed.Menu +import it.vfsfitvnm.vimusic.ui.components.themed.MenuEntry +import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu +import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder import it.vfsfitvnm.vimusic.ui.styling.Dimensions import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.SongItem -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.bold +import it.vfsfitvnm.vimusic.utils.center +import it.vfsfitvnm.vimusic.utils.enqueue +import it.vfsfitvnm.vimusic.utils.forcePlayAtIndex +import it.vfsfitvnm.vimusic.utils.forcePlayFromBeginning +import it.vfsfitvnm.vimusic.utils.relaunchableEffect +import it.vfsfitvnm.vimusic.utils.secondary +import it.vfsfitvnm.vimusic.utils.semiBold +import it.vfsfitvnm.vimusic.utils.toMediaItem import it.vfsfitvnm.youtubemusic.YouTube import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext - @ExperimentalAnimationApi @Composable fun PlaylistScreen( @@ -126,17 +154,22 @@ fun PlaylistScreen( text = "Enqueue", onClick = { menuState.hide() - playlist?.getOrNull()?.let { album -> - album.items - ?.mapNotNull { song -> - song.toMediaItem(browseId, album) - } - ?.let { mediaItems -> - binder?.player?.enqueue( - mediaItems - ) - } - } + playlist + ?.getOrNull() + ?.let { album -> + album.items + ?.mapNotNull { song -> + song.toMediaItem( + browseId, + album + ) + } + ?.let { mediaItems -> + binder?.player?.enqueue( + mediaItems + ) + } + } } ) @@ -146,33 +179,40 @@ fun PlaylistScreen( onClick = { menuState.hide() - playlist?.getOrNull()?.let { album -> - transaction { - val playlistId = - Database.insert( - Playlist( - name = album.title - ?: "Unknown" - ) - ) - - album.items?.forEachIndexed { index, song -> - song - .toMediaItem(browseId, album) - ?.let { mediaItem -> - Database.insert(mediaItem) - - Database.insert( - SongPlaylistMap( - songId = mediaItem.mediaId, - playlistId = playlistId, - position = index - ) + playlist + ?.getOrNull() + ?.let { album -> + transaction { + val playlistId = + Database.insert( + Playlist( + name = album.title + ?: "Unknown" ) - } + ) + + album.items?.forEachIndexed { index, song -> + song + .toMediaItem( + browseId, + album + ) + ?.let { mediaItem -> + Database.insert( + mediaItem + ) + + Database.insert( + SongPlaylistMap( + songId = mediaItem.mediaId, + playlistId = playlistId, + position = index + ) + ) + } + } } } - } } ) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/routes.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/Routes.kt similarity index 95% rename from app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/routes.kt rename to app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/Routes.kt index 1b1152a..7c8c0f0 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/routes.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/Routes.kt @@ -9,7 +9,6 @@ import it.vfsfitvnm.route.Route0 import it.vfsfitvnm.route.Route1 import it.vfsfitvnm.vimusic.enums.BuiltInPlaylist - @Composable fun rememberIntentUriRoute(): Route1 { val uri = rememberSaveable { @@ -97,13 +96,6 @@ fun rememberSearchResultRoute(): Route1 { } } -@Composable -fun rememberLyricsRoute(): Route0 { - return remember { - Route0("LyricsRoute") - } -} - @Composable fun rememberSettingsRoute(): Route0 { return remember { diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchResultScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchResultScreen.kt index aab2bcb..2d18b9d 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchResultScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchResultScreen.kt @@ -5,7 +5,16 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState @@ -13,7 +22,13 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicText import androidx.compose.material.ripple.rememberRipple -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -40,12 +55,20 @@ import it.vfsfitvnm.vimusic.ui.styling.Dimensions import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.ui.styling.px import it.vfsfitvnm.vimusic.ui.views.SongItem -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.asMediaItem +import it.vfsfitvnm.vimusic.utils.center +import it.vfsfitvnm.vimusic.utils.color +import it.vfsfitvnm.vimusic.utils.forcePlay +import it.vfsfitvnm.vimusic.utils.medium +import it.vfsfitvnm.vimusic.utils.relaunchableEffect +import it.vfsfitvnm.vimusic.utils.rememberPreference +import it.vfsfitvnm.vimusic.utils.searchFilterKey +import it.vfsfitvnm.vimusic.utils.secondary +import it.vfsfitvnm.vimusic.utils.semiBold import it.vfsfitvnm.youtubemusic.YouTube import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext - @ExperimentalAnimationApi @Composable fun SearchResultScreen( @@ -88,9 +111,7 @@ fun SearchResultScreen( val playlistRoute = rememberPlaylistRoute() val artistRoute = rememberArtistRoute() - RouteHandler( - listenToGlobalEmitter = true - ) { + RouteHandler(listenToGlobalEmitter = true) { albumRoute { browseId -> AlbumScreen( browseId = browseId ?: "browseId cannot be null" @@ -583,4 +604,4 @@ private fun LoadingOrError( } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchScreen.kt index 9f080e2..ec507e0 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SearchScreen.kt @@ -5,17 +5,36 @@ import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.foundation.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.BasicText import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll import androidx.compose.material.ripple.rememberRipple -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.produceState +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate @@ -46,7 +65,6 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.withContext - @ExperimentalAnimationApi @Composable fun SearchScreen( @@ -189,7 +207,10 @@ fun SearchScreen( textFieldValue = TextFieldValue() } .padding(horizontal = 14.dp, vertical = 6.dp) - .background(color = colorPalette.lightBackground, shape = CircleShape) + .background( + color = colorPalette.lightBackground, + shape = CircleShape + ) .size(28.dp) ) { Image( diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SettingsScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SettingsScreen.kt index 3eb3559..df2eb28 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SettingsScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/SettingsScreen.kt @@ -26,7 +26,6 @@ import it.vfsfitvnm.vimusic.ui.screens.settings.* import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.* - @ExperimentalAnimationApi @Composable fun SettingsScreen() { @@ -271,7 +270,7 @@ inline fun > EnumValueSelectorSettingsEntry( title = title, selectedValue = selectedValue, values = enumValues().toList(), - onValueSelected =onValueSelected, + onValueSelected = onValueSelected, modifier = modifier, valueText = valueText ) @@ -313,7 +312,6 @@ inline fun ValueSelectorSettingsEntry( ) } - @Composable fun SwitchSettingEntry( title: String, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AboutScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AboutScreen.kt index a44e2a9..04c05a4 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AboutScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AboutScreen.kt @@ -1,10 +1,21 @@ package it.vfsfitvnm.vimusic.ui.screens.settings import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.* -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.BasicText +import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -133,4 +144,4 @@ fun AboutScreen() { } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AppearanceSettingsScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AppearanceSettingsScreen.kt index 95e7a57..f60728e 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AppearanceSettingsScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/AppearanceSettingsScreen.kt @@ -1,9 +1,18 @@ package it.vfsfitvnm.vimusic.ui.screens.settings import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.* -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.BasicText +import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue @@ -16,9 +25,17 @@ import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.enums.ColorPaletteMode import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness import it.vfsfitvnm.vimusic.ui.components.TopAppBar -import it.vfsfitvnm.vimusic.ui.screens.* +import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen +import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen +import it.vfsfitvnm.vimusic.ui.screens.EnumValueSelectorSettingsEntry +import it.vfsfitvnm.vimusic.ui.screens.SettingsEntryGroupText +import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute +import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.utils.colorPaletteModeKey +import it.vfsfitvnm.vimusic.utils.rememberPreference +import it.vfsfitvnm.vimusic.utils.semiBold +import it.vfsfitvnm.vimusic.utils.thumbnailRoundnessKey @ExperimentalAnimationApi @Composable @@ -45,7 +62,10 @@ fun AppearanceSettingsScreen() { val (colorPalette, typography) = LocalAppearance.current var colorPaletteMode by rememberPreference(colorPaletteModeKey, ColorPaletteMode.System) - var thumbnailRoundness by rememberPreference(thumbnailRoundnessKey, ThumbnailRoundness.Light) + var thumbnailRoundness by rememberPreference( + thumbnailRoundnessKey, + ThumbnailRoundness.Light + ) Column( modifier = Modifier diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/BackupAndRestoreScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/BackupAndRestoreScreen.kt index 89f2a3a..fe244e8 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/BackupAndRestoreScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/BackupAndRestoreScreen.kt @@ -4,10 +4,22 @@ import android.annotation.SuppressLint import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.* -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.BasicText +import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -21,8 +33,12 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import it.vfsfitvnm.route.RouteHandler -import it.vfsfitvnm.vimusic.* +import it.vfsfitvnm.vimusic.Database import it.vfsfitvnm.vimusic.R +import it.vfsfitvnm.vimusic.checkpoint +import it.vfsfitvnm.vimusic.internal +import it.vfsfitvnm.vimusic.path +import it.vfsfitvnm.vimusic.query import it.vfsfitvnm.vimusic.service.PlayerService import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog @@ -37,10 +53,9 @@ import it.vfsfitvnm.vimusic.utils.semiBold import java.io.FileInputStream import java.io.FileOutputStream import java.text.SimpleDateFormat -import java.util.* +import java.util.Date import kotlin.system.exitProcess - @ExperimentalAnimationApi @Composable fun BackupAndRestoreScreen() { @@ -113,7 +128,11 @@ fun BackupAndRestoreScreen() { }, onConfirm = { restoreLauncher.launch( - arrayOf("application/x-sqlite3", "application/vnd.sqlite3", "application/octet-stream") + arrayOf( + "application/x-sqlite3", + "application/vnd.sqlite3", + "application/octet-stream" + ) ) }, confirmText = "Ok" @@ -249,4 +268,4 @@ fun BackupAndRestoreScreen() { } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/CacheSettingsScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/CacheSettingsScreen.kt index 6013e49..42f284f 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/CacheSettingsScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/CacheSettingsScreen.kt @@ -2,10 +2,25 @@ package it.vfsfitvnm.vimusic.ui.screens.settings import android.text.format.Formatter import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.* -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.BasicText -import androidx.compose.runtime.* +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalContext @@ -20,7 +35,14 @@ import it.vfsfitvnm.vimusic.enums.CoilDiskCacheMaxSize import it.vfsfitvnm.vimusic.enums.ExoPlayerDiskCacheMaxSize import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.TextCard -import it.vfsfitvnm.vimusic.ui.screens.* +import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen +import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen +import it.vfsfitvnm.vimusic.ui.screens.DisabledSettingsEntry +import it.vfsfitvnm.vimusic.ui.screens.EnumValueSelectorSettingsEntry +import it.vfsfitvnm.vimusic.ui.screens.SettingsEntry +import it.vfsfitvnm.vimusic.ui.screens.SettingsEntryGroupText +import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute +import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.coilDiskCacheMaxSizeKey import it.vfsfitvnm.vimusic.utils.exoPlayerDiskCacheMaxSizeKey @@ -56,8 +78,14 @@ fun CacheSettingsScreen() { val (colorPalette, typography) = LocalAppearance.current val binder = LocalPlayerServiceBinder.current - var coilDiskCacheMaxSize by rememberPreference(coilDiskCacheMaxSizeKey, CoilDiskCacheMaxSize.`128MB`) - var exoPlayerDiskCacheMaxSize by rememberPreference(exoPlayerDiskCacheMaxSizeKey, ExoPlayerDiskCacheMaxSize.`2GB`) + var coilDiskCacheMaxSize by rememberPreference( + coilDiskCacheMaxSizeKey, + CoilDiskCacheMaxSize.`128MB` + ) + var exoPlayerDiskCacheMaxSize by rememberPreference( + exoPlayerDiskCacheMaxSizeKey, + ExoPlayerDiskCacheMaxSize.`2GB` + ) val coroutineScope = rememberCoroutineScope() @@ -170,4 +198,4 @@ fun CacheSettingsScreen() { } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/OtherSettingsScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/OtherSettingsScreen.kt index 1d10a01..439eea0 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/OtherSettingsScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/OtherSettingsScreen.kt @@ -9,10 +9,23 @@ import android.widget.Toast import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.* -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.BasicText -import androidx.compose.runtime.* +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +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.graphics.ColorFilter import androidx.compose.ui.platform.LocalContext @@ -22,14 +35,19 @@ import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.themed.TextCard -import it.vfsfitvnm.vimusic.ui.screens.* +import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen +import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen +import it.vfsfitvnm.vimusic.ui.screens.SettingsEntry +import it.vfsfitvnm.vimusic.ui.screens.SettingsEntryGroupText +import it.vfsfitvnm.vimusic.ui.screens.SwitchSettingEntry +import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute +import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance import it.vfsfitvnm.vimusic.utils.isIgnoringBatteryOptimizations import it.vfsfitvnm.vimusic.utils.isInvincibilityEnabledKey import it.vfsfitvnm.vimusic.utils.rememberPreference import it.vfsfitvnm.vimusic.utils.semiBold - @ExperimentalAnimationApi @Composable fun OtherSettingsScreen() { @@ -164,5 +182,3 @@ fun OtherSettingsScreen() { } } } - - diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/PlayerSettingsScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/PlayerSettingsScreen.kt index bbfbc17..96e76ee 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/PlayerSettingsScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/PlayerSettingsScreen.kt @@ -6,9 +6,18 @@ import android.widget.Toast import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.* -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.BasicText +import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue @@ -21,10 +30,19 @@ import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.ui.components.TopAppBar -import it.vfsfitvnm.vimusic.ui.screens.* +import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen +import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen +import it.vfsfitvnm.vimusic.ui.screens.SettingsEntry +import it.vfsfitvnm.vimusic.ui.screens.SettingsEntryGroupText +import it.vfsfitvnm.vimusic.ui.screens.SwitchSettingEntry +import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute +import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance -import it.vfsfitvnm.vimusic.utils.* - +import it.vfsfitvnm.vimusic.utils.persistentQueueKey +import it.vfsfitvnm.vimusic.utils.rememberPreference +import it.vfsfitvnm.vimusic.utils.semiBold +import it.vfsfitvnm.vimusic.utils.skipSilenceKey +import it.vfsfitvnm.vimusic.utils.volumeNormalizationKey @ExperimentalAnimationApi @Composable @@ -128,20 +146,28 @@ fun PlayerSettingsScreen() { title = "Equalizer", text = "Interact with the system equalizer", onClick = { - val intent = Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL).apply { - putExtra(AudioEffect.EXTRA_AUDIO_SESSION, binder?.player?.audioSessionId) - putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.packageName) - putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC) - } + val intent = + Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL).apply { + putExtra( + AudioEffect.EXTRA_AUDIO_SESSION, + binder?.player?.audioSessionId + ) + putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.packageName) + putExtra( + AudioEffect.EXTRA_CONTENT_TYPE, + AudioEffect.CONTENT_TYPE_MUSIC + ) + } if (intent.resolveActivity(context.packageManager) != null) { activityResultLauncher.launch(intent) } else { - Toast.makeText(context, "No equalizer app found!", Toast.LENGTH_SHORT).show() + Toast.makeText(context, "No equalizer app found!", Toast.LENGTH_SHORT) + .show() } } ) } } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/routes.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/Routes.kt similarity index 100% rename from app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/routes.kt rename to app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/settings/Routes.kt diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Appearance.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Appearance.kt index 06acdf6..051ae54 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Appearance.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Appearance.kt @@ -9,4 +9,4 @@ data class Appearance( val thumbnailShape: Shape ) -val LocalAppearance = staticCompositionLocalOf { TODO() } \ No newline at end of file +val LocalAppearance = staticCompositionLocalOf { TODO() } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/ColorPalette.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/ColorPalette.kt index ce1b2c7..63d386e 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/ColorPalette.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/ColorPalette.kt @@ -1,6 +1,6 @@ package it.vfsfitvnm.vimusic.ui.styling -import androidx.compose.runtime.* +import androidx.compose.runtime.Immutable import androidx.compose.ui.graphics.Color @Immutable diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Dimensions.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Dimensions.kt index d8a3618..ebd56f8 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Dimensions.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Dimensions.kt @@ -6,7 +6,6 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp - @Suppress("ClassName") object Dimensions { object thumbnails { @@ -19,7 +18,7 @@ object Dimensions { val songPreview = collapsedPlayer val song: Dp @Composable - get() = with (LocalConfiguration.current) { + get() = with(LocalConfiguration.current) { minOf(screenHeightDp, screenWidthDp) }.dp } @@ -30,4 +29,4 @@ object Dimensions { inline val Dp.px: Int @Composable - inline get() = with (LocalDensity.current) { roundToPx() } + inline get() = with(LocalDensity.current) { roundToPx() } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Typography.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Typography.kt index 0db5811..6c15340 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Typography.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/styling/Typography.kt @@ -1,19 +1,7 @@ package it.vfsfitvnm.vimusic.ui.styling -import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable -import androidx.compose.runtime.remember -import androidx.compose.runtime.staticCompositionLocalOf -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.ExperimentalTextApi -import androidx.compose.ui.text.PlatformTextStyle import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp -import it.vfsfitvnm.vimusic.R @Immutable data class Typography( diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerView.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerView.kt index b2f0fb1..f0afb95 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerView.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerView.kt @@ -9,24 +9,56 @@ import android.text.format.Formatter import android.widget.Toast import androidx.activity.compose.LocalActivityResultRegistryOwner import androidx.activity.result.contract.ActivityResultContracts -import androidx.compose.animation.* -import androidx.compose.foundation.* +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.SizeTransform +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically +import androidx.compose.animation.with +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicText +import androidx.compose.foundation.verticalScroll import androidx.compose.material.ripple.rememberRipple -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.* +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.pointer.pointerInput @@ -51,19 +83,44 @@ import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness import it.vfsfitvnm.vimusic.models.Song import it.vfsfitvnm.vimusic.query -import it.vfsfitvnm.vimusic.ui.components.* -import it.vfsfitvnm.vimusic.ui.components.themed.* -import it.vfsfitvnm.vimusic.ui.styling.* -import it.vfsfitvnm.vimusic.utils.* +import it.vfsfitvnm.vimusic.ui.components.BottomSheet +import it.vfsfitvnm.vimusic.ui.components.BottomSheetState +import it.vfsfitvnm.vimusic.ui.components.LocalMenuState +import it.vfsfitvnm.vimusic.ui.components.SeekBar +import it.vfsfitvnm.vimusic.ui.components.rememberBottomSheetState +import it.vfsfitvnm.vimusic.ui.components.themed.BaseMediaItemMenu +import it.vfsfitvnm.vimusic.ui.components.themed.LoadingOrError +import it.vfsfitvnm.vimusic.ui.components.themed.TextFieldDialog +import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder +import it.vfsfitvnm.vimusic.ui.styling.BlackColorPalette +import it.vfsfitvnm.vimusic.ui.styling.DarkColorPalette +import it.vfsfitvnm.vimusic.ui.styling.Dimensions +import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance +import it.vfsfitvnm.vimusic.ui.styling.px +import it.vfsfitvnm.vimusic.utils.bold +import it.vfsfitvnm.vimusic.utils.center +import it.vfsfitvnm.vimusic.utils.color +import it.vfsfitvnm.vimusic.utils.medium +import it.vfsfitvnm.vimusic.utils.rememberError +import it.vfsfitvnm.vimusic.utils.rememberMediaItem +import it.vfsfitvnm.vimusic.utils.rememberMediaItemIndex +import it.vfsfitvnm.vimusic.utils.rememberPositionAndDuration +import it.vfsfitvnm.vimusic.utils.rememberRepeatMode +import it.vfsfitvnm.vimusic.utils.rememberShouldBePlaying +import it.vfsfitvnm.vimusic.utils.rememberVolume +import it.vfsfitvnm.vimusic.utils.seamlessPlay +import it.vfsfitvnm.vimusic.utils.secondary +import it.vfsfitvnm.vimusic.utils.semiBold +import it.vfsfitvnm.vimusic.utils.thumbnail +import it.vfsfitvnm.vimusic.utils.verticalFadingEdge import it.vfsfitvnm.youtubemusic.YouTube import it.vfsfitvnm.youtubemusic.models.NavigationEndpoint +import kotlin.math.absoluteValue +import kotlin.math.roundToInt import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.runBlocking -import kotlin.math.absoluteValue -import kotlin.math.roundToInt - @ExperimentalAnimationApi @Composable @@ -98,7 +155,8 @@ fun PlayerView( .background(colorPalette.elevatedBackground) .fillMaxSize() .drawBehind { - val progress = positionAndDuration.first.toFloat() / positionAndDuration.second.absoluteValue + val progress = + positionAndDuration.first.toFloat() / positionAndDuration.second.absoluteValue val offset = Dimensions.thumbnails.player.songPreview.toPx() drawLine( diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlaylistPreviewItem.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlaylistPreviewItem.kt index a0a4e7f..e586cc8 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlaylistPreviewItem.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlaylistPreviewItem.kt @@ -4,7 +4,12 @@ import androidx.annotation.DrawableRes import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.text.BasicText import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -33,7 +38,6 @@ import it.vfsfitvnm.vimusic.utils.thumbnail import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.distinctUntilChanged - @Composable fun PlaylistPreviewItem( playlistPreview: PlaylistPreview, @@ -168,4 +172,4 @@ fun PlaylistItem( .padding(horizontal = 8.dp, vertical = 4.dp) ) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/SongItem.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/SongItem.kt index 4d881f5..9837e68 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/SongItem.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/SongItem.kt @@ -5,7 +5,15 @@ import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.text.BasicText import androidx.compose.material.ripple.rememberRipple import androidx.compose.runtime.Composable @@ -31,7 +39,6 @@ import it.vfsfitvnm.vimusic.utils.secondary import it.vfsfitvnm.vimusic.utils.semiBold import it.vfsfitvnm.vimusic.utils.thumbnail - @ExperimentalAnimationApi @Composable @NonRestartableComposable @@ -89,7 +96,6 @@ fun SongItem( ) } - @ExperimentalAnimationApi @Composable @NonRestartableComposable @@ -199,4 +205,4 @@ fun SongItem( trailingContent?.invoke() } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Context.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Context.kt index dc08dbc..96958b3 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Context.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Context.kt @@ -9,22 +9,26 @@ import android.os.Build import android.os.PowerManager import androidx.core.content.getSystemService - inline fun Context.intent(): Intent = Intent(this@Context, T::class.java) -inline fun Context.broadCastPendingIntent( +inline fun Context.broadCastPendingIntent( requestCode: Int = 0, flags: Int = if (Build.VERSION.SDK_INT >= 23) PendingIntent.FLAG_IMMUTABLE else 0, ): PendingIntent = PendingIntent.getBroadcast(this, requestCode, intent(), flags) -inline fun Context.activityPendingIntent( +inline fun Context.activityPendingIntent( requestCode: Int = 0, flags: Int = 0, block: Intent.() -> Unit = {}, ): PendingIntent = - PendingIntent.getActivity(this, requestCode, intent().apply(block), (if (Build.VERSION.SDK_INT >= 23) PendingIntent.FLAG_IMMUTABLE else 0) or flags) + PendingIntent.getActivity( + this, + requestCode, + intent().apply(block), + (if (Build.VERSION.SDK_INT >= 23) PendingIntent.FLAG_IMMUTABLE else 0) or flags + ) val Context.isIgnoringBatteryOptimizations: Boolean get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/DrawScope.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/DrawScope.kt index 1d7e9fb..0e62796 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/DrawScope.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/DrawScope.kt @@ -24,6 +24,11 @@ fun DrawScope.drawCircle( it.colorFilter = colorFilter it.style = style }.asFrameworkPaint().also { - it.setShadowLayer(shadow.blurRadius, shadow.offset.x, shadow.offset.y, shadow.color.toArgb()) + it.setShadowLayer( + shadow.blurRadius, + shadow.offset.x, + shadow.offset.y, + shadow.color.toArgb() + ) } -) \ No newline at end of file +) diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/verticalFadingEdge.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/FadingEdge.kt similarity index 100% rename from app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/verticalFadingEdge.kt rename to app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/FadingEdge.kt diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/InvincibleService.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/InvincibleService.kt index 917cd4e..b9092e9 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/InvincibleService.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/InvincibleService.kt @@ -11,7 +11,6 @@ import android.os.Build import android.os.Handler import android.os.Looper - // https://stackoverflow.com/q/53502244/16885569 // I found four ways to make the system not kill the stopped foreground service: e.g. when // the player is paused: diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Player.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Player.kt index efe118c..79174a9 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Player.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Player.kt @@ -4,15 +4,14 @@ import androidx.media3.common.MediaItem import androidx.media3.common.Player import androidx.media3.common.Timeline - val Timeline.mediaItems: List - get() = (0 until windowCount).map { index -> - getWindow(index, Timeline.Window()).mediaItem + get() = List(windowCount) { + getWindow(it, Timeline.Window()).mediaItem } -val Timeline.windows: List - get() = (0 until windowCount).map { index -> - getWindow(index, Timeline.Window()) +inline val Timeline.windows: List + get() = List(windowCount) { + getWindow(it, Timeline.Window()) } val Player.shouldBePlaying: Boolean diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/PlayerState.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/PlayerState.kt index e09b9a5..d1b7c08 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/PlayerState.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/PlayerState.kt @@ -1,6 +1,13 @@ package it.vfsfitvnm.vimusic.utils -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.DisposableEffectResult +import androidx.compose.runtime.DisposableEffectScope +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.produceState +import androidx.compose.runtime.remember import androidx.media3.common.MediaItem import androidx.media3.common.PlaybackException import androidx.media3.common.Player @@ -9,7 +16,6 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch - context(DisposableEffectScope) fun Player.listener(listener: Player.Listener): DisposableEffectResult { addListener(listener) @@ -27,11 +33,13 @@ fun rememberMediaItemIndex(player: Player): State { DisposableEffect(player) { player.listener(object : Player.Listener { override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) { - mediaItemIndexState.value = if (player.mediaItemCount == 0) -1 else player.currentMediaItemIndex + mediaItemIndexState.value = + if (player.mediaItemCount == 0) -1 else player.currentMediaItemIndex } override fun onTimelineChanged(timeline: Timeline, reason: Int) { - mediaItemIndexState.value = if (player.mediaItemCount == 0) -1 else player.currentMediaItemIndex + mediaItemIndexState.value = + if (player.mediaItemCount == 0) -1 else player.currentMediaItemIndex } }) } @@ -187,6 +195,7 @@ fun rememberError(player: Player): State { override fun onPlaybackStateChanged(playbackState: Int) { errorState.value = player.playerError } + override fun onPlayerError(playbackException: PlaybackException) { errorState.value = playbackException } @@ -194,4 +203,4 @@ fun rememberError(player: Player): State { } return errorState -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Preferences.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Preferences.kt index e57b80e..f46cd42 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Preferences.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Preferences.kt @@ -2,11 +2,14 @@ package it.vfsfitvnm.vimusic.utils import android.content.Context import android.content.SharedPreferences -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.SnapshotMutationPolicy +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.core.content.edit - const val colorPaletteModeKey = "colorPaletteMode" const val thumbnailRoundnessKey = "thumbnailRoundness" const val coilDiskCacheMaxSizeKey = "coilDiskCacheMaxSize" @@ -36,14 +39,15 @@ inline fun > SharedPreferences.getEnum( } } ?: defaultValue -inline fun > SharedPreferences.Editor.putEnum(key: String, value: T) = +inline fun > SharedPreferences.Editor.putEnum( + key: String, + value: T +): SharedPreferences.Editor = putString(key, value.name) - val Context.preferences: SharedPreferences get() = getSharedPreferences("preferences", Context.MODE_PRIVATE) - @Composable fun rememberPreference(key: String, defaultValue: Boolean): MutableState { val context = LocalContext.current @@ -65,7 +69,7 @@ fun rememberPreference(key: String, defaultValue: String): MutableState } @Composable -inline fun > rememberPreference(key: String, defaultValue: T): MutableState { +inline fun > rememberPreference(key: String, defaultValue: T): MutableState { val context = LocalContext.current return remember { mutableStatePreferenceOf(context.preferences.getEnum(key, defaultValue)) { @@ -74,7 +78,10 @@ inline fun > rememberPreference(key: String, defaultValue: T) } } -inline fun mutableStatePreferenceOf(value: T, crossinline onStructuralInequality: (newValue: T) -> Unit) = +inline fun mutableStatePreferenceOf( + value: T, + crossinline onStructuralInequality: (newValue: T) -> Unit +) = mutableStateOf( value = value, policy = object : SnapshotMutationPolicy { diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/RelaunchableEffect.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/RelaunchableEffect.kt index 74987a0..abb7056 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/RelaunchableEffect.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/RelaunchableEffect.kt @@ -1,10 +1,14 @@ - @file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @file:OptIn(InternalComposeApi::class) package it.vfsfitvnm.vimusic.utils -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.InternalComposeApi +import androidx.compose.runtime.LaunchedEffectImpl +import androidx.compose.runtime.NonRestartableComposable +import androidx.compose.runtime.currentComposer +import androidx.compose.runtime.remember import kotlinx.coroutines.CoroutineScope @Composable diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/TimerJob.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/TimerJob.kt index 1dd5110..381743a 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/TimerJob.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/TimerJob.kt @@ -8,7 +8,6 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.isActive import kotlinx.coroutines.launch - interface TimerJob { val millisLeft: StateFlow fun cancel() @@ -16,14 +15,12 @@ interface TimerJob { fun CoroutineScope.timer(delayMillis: Long, onCompletion: () -> Unit): TimerJob { val millisLeft = MutableStateFlow(delayMillis) - val job = launch { while (isActive && millisLeft.value != null) { delay(1000) millisLeft.emit(millisLeft.value?.minus(1000)?.takeIf { it > 0 }) } } - val disposableHandle = job.invokeOnCompletion { if (it == null) { onCompletion() diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/utils.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Utils.kt similarity index 100% rename from app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/utils.kt rename to app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/Utils.kt diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/YoutubeRadio.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/YoutubeRadio.kt index 6e0cec7..bd8f8e0 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/YoutubeRadio.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/YoutubeRadio.kt @@ -5,7 +5,6 @@ import it.vfsfitvnm.youtubemusic.YouTube import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext - data class YouTubeRadio( private val videoId: String? = null, private val playlistId: String? = null, diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/rememberHapticFeedback.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/rememberHapticFeedback.kt index ef0fa42..0965b67 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/rememberHapticFeedback.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/utils/rememberHapticFeedback.kt @@ -21,4 +21,4 @@ fun rememberHapticFeedback(): HapticFeedback { } } } -} \ No newline at end of file +}