Skip to content

Commit

Permalink
Upgrade dependencies and clean up after it
Browse files Browse the repository at this point in the history
This includes upgrading to Coil 3, which breaks current image cache 99.99% of the time.
Please be warned when upgrading to the next release of ViTune.

Other significant changes
- Compose BOM got bumped to 2024.10.00
- Migrated to AGP 8.7(.1) (R8 outputs a new Proguard warning now, which probably doesn't matter)
- Migrated to Ktor 3
  • Loading branch information
25huizengek1 committed Oct 22, 2024
1 parent 4f49a60 commit 1094c70
Show file tree
Hide file tree
Showing 42 changed files with 233 additions and 143 deletions.
12 changes: 9 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
Expand Down Expand Up @@ -100,8 +102,10 @@ ksp {
}

composeCompiler {
enableStrongSkippingMode = true
enableNonSkippingGroupOptimization = true
featureFlags = setOf(
ComposeFeatureFlag.StrongSkipping,
ComposeFeatureFlag.OptimizeNonSkippingGroups
)

if (project.findProperty("enableComposeCompilerReports") == "true") {
val dest = layout.buildDirectory.dir("compose_metrics")
Expand All @@ -126,10 +130,12 @@ dependencies {
implementation(libs.compose.ui)
implementation(libs.compose.ui.util)
implementation(libs.compose.shimmer)
implementation(libs.compose.coil)
implementation(libs.compose.lottie)
implementation(libs.compose.material3)

implementation(libs.coil.compose)
implementation(libs.coil.ktor)

implementation(libs.palette)
implementation(libs.monet)
runtimeOnly(projects.core.materialCompat)
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/app/vitune/android/Database.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ import app.vitune.android.models.SongPlaylistMap
import app.vitune.android.models.SongWithContentLength
import app.vitune.android.models.SortedSongPlaylistMap
import app.vitune.android.service.LOCAL_KEY_PREFIX
import app.vitune.core.ui.utils.songBundle
import app.vitune.core.data.enums.AlbumSortBy
import app.vitune.core.data.enums.ArtistSortBy
import app.vitune.core.data.enums.PlaylistSortBy
import app.vitune.core.data.enums.SongSortBy
import app.vitune.core.data.enums.SortOrder
import app.vitune.core.ui.utils.songBundle
import io.ktor.http.Url
import kotlinx.coroutines.flow.Flow

Expand Down
42 changes: 29 additions & 13 deletions app/src/main/kotlin/app/vitune/android/MainApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,14 @@ import app.vitune.providers.innertube.Innertube
import app.vitune.providers.innertube.models.bodies.BrowseBody
import app.vitune.providers.innertube.requests.playlistPage
import app.vitune.providers.innertube.requests.song
import coil.ImageLoader
import coil.ImageLoaderFactory
import coil.disk.DiskCache
import coil.util.DebugLogger
import coil3.ImageLoader
import coil3.PlatformContext
import coil3.SingletonImageLoader
import coil3.disk.DiskCache
import coil3.disk.directory
import coil3.memory.MemoryCache
import coil3.request.crossfade
import coil3.util.DebugLogger
import com.kieronquinn.monetcompat.core.MonetActivityAccessException
import com.kieronquinn.monetcompat.core.MonetCompat
import com.kieronquinn.monetcompat.interfaces.MonetColorsChangedListener
Expand Down Expand Up @@ -266,7 +270,10 @@ class MainActivity : ComponentActivity(), MonetColorsChangedListener {
}

val pip = isInPip(
onChanged = { if (it && vm.binder?.player?.shouldBePlaying == true) playerBottomSheetState.expandSoft() }
onChange = {
if (!it || vm.binder?.player?.shouldBePlaying != true) return@isInPip
playerBottomSheetState.expandSoft()
}
)

KeyedCrossfade(state = pip) { currentPip ->
Expand Down Expand Up @@ -378,11 +385,15 @@ class MainActivity : ComponentActivity(), MonetColorsChangedListener {
MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE -> extras.artist
MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE -> extras.album
"vnd.android.cursor.item/audio" -> listOfNotNull(
extras.album, extras.artist, extras.genre, extras.title
extras.album,
extras.artist,
extras.genre,
extras.title
).joinToString(separator = " ")

@Suppress("deprecation")
MediaStore.Audio.Playlists.ENTRY_CONTENT_TYPE -> extras.playlist
MediaStore.Audio.Playlists.ENTRY_CONTENT_TYPE
-> extras.playlist

else -> null
}
Expand Down Expand Up @@ -421,6 +432,7 @@ class MainActivity : ComponentActivity(), MonetColorsChangedListener {
}

context(Context)
@Suppress("CyclomaticComplexMethod")
fun handleUrl(
uri: Uri,
binder: PlayerService.Binder?
Expand Down Expand Up @@ -484,7 +496,7 @@ val LocalPlayerAwareWindowInsets =
compositionLocalOf<WindowInsets> { error("No player insets provided") }
val LocalCredentialManager = staticCompositionLocalOf { Dependencies.credentialManager }

class MainApplication : Application(), ImageLoaderFactory, Configuration.Provider {
class MainApplication : Application(), SingletonImageLoader.Factory, Configuration.Provider {
override fun onCreate() {
StrictMode.setVmPolicy(
VmPolicy.Builder()
Expand All @@ -505,15 +517,19 @@ class MainApplication : Application(), ImageLoaderFactory, Configuration.Provide
ServiceNotifications.createAll()
}

override fun newImageLoader() = ImageLoader.Builder(this)
override fun newImageLoader(context: PlatformContext) = ImageLoader.Builder(this)
.crossfade(true)
.respectCacheHeaders(false)
.diskCache(
.memoryCache {
MemoryCache.Builder()
.maxSizePercent(context, 0.1)
.build()
}
.diskCache {
DiskCache.Builder()
.directory(cacheDir.resolve("coil"))
.directory(context.cacheDir.resolve("coil"))
.maxSizeBytes(DataPreferences.coilDiskCacheMaxSize.bytes)
.build()
)
}
.let { if (BuildConfig.DEBUG) it.logger(DebugLogger()) else it }
.build()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import app.vitune.android.GlobalPreferencesHolder
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList

object UIStatePreferences : GlobalPreferencesHolder() {
Expand All @@ -19,17 +20,22 @@ object UIStatePreferences : GlobalPreferencesHolder() {
private var visibleTabs by json(mapOf<String, List<String>>())

@Composable
fun mutableTabStateOf(key: String, default: List<String> = listOf()): MutableState<ImmutableList<String>> =
remember(key, default, visibleTabs) {
mutableStateOf(
value = visibleTabs.getOrDefault(key, default).toImmutableList(),
policy = object : SnapshotMutationPolicy<ImmutableList<String>> {
override fun equivalent(a: ImmutableList<String>, b: ImmutableList<String>): Boolean {
val eq = a == b
if (!eq) visibleTabs += key to b
return eq
}
fun mutableTabStateOf(
key: String,
default: ImmutableList<String> = persistentListOf()
): MutableState<ImmutableList<String>> = remember(key, default, visibleTabs) {
mutableStateOf(
value = visibleTabs.getOrDefault(key, default).toImmutableList(),
policy = object : SnapshotMutationPolicy<ImmutableList<String>> {
override fun equivalent(
a: ImmutableList<String>,
b: ImmutableList<String>
): Boolean {
val eq = a == b
if (!eq) visibleTabs += key to b
return eq
}
)
}
}
)
}
}
11 changes: 6 additions & 5 deletions app/src/main/kotlin/app/vitune/android/service/BitmapProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package app.vitune.android.service
import android.content.Context
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import androidx.core.graphics.applyCanvas
import app.vitune.android.utils.thumbnail
import coil.imageLoader
import coil.request.Disposable
import coil.request.ImageRequest
import coil3.imageLoader
import coil3.request.Disposable
import coil3.request.ImageRequest
import coil3.request.allowHardware
import coil3.toBitmap

context(Context)
class BitmapProvider(
Expand Down Expand Up @@ -84,7 +85,7 @@ class BitmapProvider(
onDone(bitmap)
},
onSuccess = { _, result ->
lastBitmap = (result.drawable as BitmapDrawable).bitmap
lastBitmap = result.image.run { toBitmap(width, height) }
onDone(bitmap)
}
)
Expand Down
36 changes: 23 additions & 13 deletions app/src/main/kotlin/app/vitune/android/service/PlayerService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,9 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
callback: (T) -> Unit
) = launch { prop.stateFlow.collectLatest { handler.post { callback(it) } } }

subscribe(AppearancePreferences.isShowingThumbnailInLockscreenProperty) { maybeShowSongCoverInLockScreen() }
subscribe(AppearancePreferences.isShowingThumbnailInLockscreenProperty) {
maybeShowSongCoverInLockScreen()
}

subscribe(PlayerPreferences.bassBoostLevelProperty) { maybeBassBoost() }
subscribe(PlayerPreferences.bassBoostProperty) { maybeBassBoost() }
Expand All @@ -352,7 +354,9 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
player.setPlaybackPitch(it.coerceAtLeast(0.01f))
}
subscribe(PlayerPreferences.queueLoopEnabledProperty) { updateRepeatMode() }
subscribe(PlayerPreferences.resumePlaybackWhenDeviceConnectedProperty) { maybeResumePlaybackWhenDeviceConnected() }
subscribe(PlayerPreferences.resumePlaybackWhenDeviceConnectedProperty) {
maybeResumePlaybackWhenDeviceConnected()
}
subscribe(PlayerPreferences.skipSilenceProperty) { player.skipSilenceEnabled = it }
subscribe(PlayerPreferences.speedProperty) {
player.setPlaybackSpeed(it.coerceAtLeast(0.01f))
Expand Down Expand Up @@ -633,7 +637,6 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
}
}

@Suppress("ReturnCount")
private fun maybeNormalizeVolume() {
if (!PlayerPreferences.volumeNormalization) {
loudnessEnhancer?.enabled = false
Expand Down Expand Up @@ -684,6 +687,7 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
}
}

@Suppress("CyclomaticComplexMethod") // TODO: evaluate CyclomaticComplexMethod threshold
private fun maybeSponsorBlock() {
poiTimestamp = null

Expand Down Expand Up @@ -726,6 +730,7 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
val lastSegmentEnd =
segments.lastOrNull()?.end?.inWholeMilliseconds ?: return@mapCatching

@Suppress("LoopWithTooManyJumpStatements")
do {
if (lastSegmentEnd < posMillis()) {
yield()
Expand All @@ -741,7 +746,7 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
((nextSegment.start.inWholeMilliseconds - posMillis()) / speed().toDouble()).milliseconds
)

if (posMillis() !in nextSegment.start.inWholeMilliseconds..nextSegment.end.inWholeMilliseconds) {
if (posMillis().milliseconds !in nextSegment.start..nextSegment.end) {
// Player is not in the segment for some reason, maybe the user seeked in the meantime
yield()
continue
Expand Down Expand Up @@ -851,19 +856,23 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene

private fun sendOpenEqualizerIntent() = sendBroadcast(
Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION).apply {
replaceExtras(EqualizerIntentBundleAccessor.bundle {
audioSession = player.audioSessionId
packageName = packageName
contentType = AudioEffect.CONTENT_TYPE_MUSIC
})
replaceExtras(
EqualizerIntentBundleAccessor.bundle {
audioSession = player.audioSessionId
packageName = packageName
contentType = AudioEffect.CONTENT_TYPE_MUSIC
}
)
}
)

private fun sendCloseEqualizerIntent() = sendBroadcast(
Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION).apply {
replaceExtras(EqualizerIntentBundleAccessor.bundle {
audioSession = player.audioSessionId
})
replaceExtras(
EqualizerIntentBundleAccessor.bundle {
audioSession = player.audioSessionId
}
)
}
)

Expand Down Expand Up @@ -1298,6 +1307,7 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
SimpleCache(directory, cacheEvictor, createDatabaseProvider(context))
}

@Suppress("CyclomaticComplexMethod")
fun createYouTubeDataSourceResolverFactory(
context: Context,
cache: Cache,
Expand Down Expand Up @@ -1326,7 +1336,7 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
} ?: this

if (
dataSpec.isLocal || ((chunkLength != null) && cache.isCached(
dataSpec.isLocal || (chunkLength != null && cache.isCached(
/* key = */ mediaId,
/* position = */ dataSpec.position,
/* length = */ chunkLength
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ abstract class NotificationChannels {
}

inline fun <ThisRef, Return> readOnlyProvider(
crossinline provide: (thisRef: ThisRef, property: KProperty<*>) -> (thisRef: ThisRef, property: KProperty<*>) -> Return
crossinline provide: (
thisRef: ThisRef,
property: KProperty<*>
) -> (thisRef: ThisRef, property: KProperty<*>) -> Return
) = PropertyDelegateProvider<ThisRef, ReadOnlyProperty<ThisRef, Return>> { thisRef, property ->
val provider = provide(thisRef, property)
ReadOnlyProperty { innerThisRef, innerProperty -> provider(innerThisRef, innerProperty) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,11 @@ fun BottomSheet(
}
}

@Suppress("TooManyFunctions")
@Stable
class BottomSheetState internal constructor(
class BottomSheetState
@Suppress("LongParameterList")
internal constructor(
density: Density,
initialValue: Dp,
private val coroutineScope: CoroutineScope,
Expand Down Expand Up @@ -267,9 +270,9 @@ class BottomSheetState internal constructor(

@Composable
fun rememberBottomSheetState(
key: Any? = Unit,
dismissedBound: Dp,
expandedBound: Dp,
key: Any? = Unit,
collapsedBound: Dp = dismissedBound,
initialAnchor: BottomSheetState.Anchor = BottomSheetState.Anchor.Dismissed
): BottomSheetState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.times
import app.vitune.android.LocalPlayerAwareWindowInsets
import app.vitune.android.ui.modifiers.pressable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import app.vitune.android.ui.modifiers.pressable
import app.vitune.core.ui.LocalAppearance
import app.vitune.core.ui.utils.roundedShape

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import app.vitune.core.ui.LocalAppearance
import app.vitune.core.ui.shimmer
import app.vitune.core.ui.utils.isLandscape
import app.vitune.core.ui.utils.px
import coil.compose.AsyncImage
import coil3.compose.AsyncImage
import com.valentinilk.shimmer.shimmer

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ import app.vitune.android.utils.isCached
import app.vitune.android.utils.launchYouTubeMusic
import app.vitune.android.utils.medium
import app.vitune.android.utils.semiBold
import app.vitune.core.ui.utils.songBundle
import app.vitune.android.utils.toast
import app.vitune.core.data.enums.PlaylistSortBy
import app.vitune.core.data.enums.SortOrder
Expand All @@ -85,6 +84,7 @@ import app.vitune.core.ui.LocalAppearance
import app.vitune.core.ui.favoritesIcon
import app.vitune.core.ui.utils.px
import app.vitune.core.ui.utils.roundedShape
import app.vitune.core.ui.utils.songBundle
import app.vitune.providers.innertube.models.NavigationEndpoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest
Expand Down
Loading

0 comments on commit 1094c70

Please sign in to comment.