Skip to content

Commit

Permalink
[optimize] Optimize player title and cover display
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyD666 committed Jan 12, 2025
1 parent bf66bf1 commit b33da4f
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 40 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ android {
minSdk = 24
targetSdk = 35
versionCode = 25
versionName = "2.1-rc07"
versionName = "2.1-rc08"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down
24 changes: 24 additions & 0 deletions app/src/main/java/com/skyd/anivu/ext/ImageLoaderExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.skyd.anivu.ext

import android.content.Context
import coil3.ImageLoader
import coil3.request.CachePolicy
import coil3.request.ErrorResult
import coil3.request.ImageRequest
import coil3.request.SuccessResult
import java.io.File

suspend fun ImageLoader.getImage(context: Context, url: String): File? {
val request = ImageRequest.Builder(context)
.data(url)
.diskCachePolicy(CachePolicy.ENABLED)
.build()
when (execute(request)) {
is ErrorResult -> return null
is SuccessResult -> {
diskCache!!.openSnapshot(url).use { snapshot ->
return snapshot!!.data.toFile()
}
}
}
}
33 changes: 11 additions & 22 deletions app/src/main/java/com/skyd/anivu/model/repository/ReadRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.skyd.anivu.base.BaseRepository
import com.skyd.anivu.config.Const.TEMP_PICTURES_DIR
import com.skyd.anivu.ext.copyToClipboard
import com.skyd.anivu.ext.deleteDirs
import com.skyd.anivu.ext.getImage
import com.skyd.anivu.ext.imageLoaderBuilder
import com.skyd.anivu.ext.savePictureToMediaStore
import com.skyd.anivu.ext.share
Expand Down Expand Up @@ -40,28 +41,16 @@ class ReadRepository @Inject constructor(

fun downloadImage(url: String, title: String?): Flow<Unit> {
return flow {
val request = ImageRequest.Builder(appContext)
.data(url)
.diskCachePolicy(CachePolicy.ENABLED)
.build()
val imageLoader = appContext.imageLoaderBuilder().build()
when (val result = imageLoader.execute(request)) {
is ErrorResult -> throw result.throwable
is SuccessResult -> {
imageLoader.diskCache!!.openSnapshot(url).use { snapshot ->
val imageFile = snapshot!!.data.toFile()
val format = imageFile.inputStream().use { ImageFormatChecker.check(it) }
imageFile.savePictureToMediaStore(
context = appContext,
mimetype = format.toMimeType(),
fileName = (title.orEmpty().ifEmpty {
url.substringAfterLast('/')
} + "_" + Random.nextInt()).validateFileName() + format.toString(),
autoDelete = false,
)
}
}
}
val imageFile = appContext.imageLoaderBuilder().build().getImage(appContext, url)!!
val format = imageFile.inputStream().use { ImageFormatChecker.check(it) }
imageFile.savePictureToMediaStore(
context = appContext,
mimetype = format.toMimeType(),
fileName = (title.orEmpty().ifEmpty {
url.substringAfterLast('/')
} + "_" + Random.nextInt()).validateFileName() + format.toString(),
autoDelete = false,
)
emit(Unit)
}.flowOn(Dispatchers.IO)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,19 @@ class PlayActivity : BaseComposeActivity() {
companion object {
const val VIDEO_URI_KEY = "videoUri"
const val VIDEO_TITLE_KEY = "videoTitle"

fun play(activity: Activity, uri: Uri, title: String? = null) {
const val VIDEO_THUMBNAIL_KEY = "videoThumbnail"

fun play(
activity: Activity,
uri: Uri,
title: String? = null,
thumbnail: String? = null,
) {
activity.startActivity(
Intent(activity, PlayActivity::class.java).apply {
putExtra(VIDEO_URI_KEY, uri)
putExtra(VIDEO_TITLE_KEY, title)
putExtra(VIDEO_THUMBNAIL_KEY, thumbnail)
}
)
}
Expand Down Expand Up @@ -119,11 +126,13 @@ class PlayActivity : BaseComposeActivity() {
}
val uri by viewModel.uri.collectAsStateWithLifecycle()
val title by viewModel.title.collectAsStateWithLifecycle()
val thumbnail by viewModel.thumbnail.collectAsStateWithLifecycle()
if (uri != Uri.EMPTY) {
PlayerViewRoute(
service = if (serviceBound) service else null,
uri = uri,
title = title,
thumbnail = thumbnail,
onBack = { finish() },
onSaveScreenshot = {
picture = it
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
package com.skyd.anivu.ui.activity.player

import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import androidx.core.content.IntentCompat
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.skyd.anivu.appContext
import com.skyd.anivu.ext.getImage
import com.skyd.anivu.ext.imageLoaderBuilder
import com.skyd.anivu.ui.activity.player.PlayActivity.Companion.VIDEO_THUMBNAIL_KEY
import com.skyd.anivu.ui.activity.player.PlayActivity.Companion.VIDEO_TITLE_KEY
import com.skyd.anivu.ui.activity.player.PlayActivity.Companion.VIDEO_URI_KEY
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class PlayerViewModel @Inject constructor() : ViewModel() {
val uri: MutableStateFlow<Uri> = MutableStateFlow(Uri.EMPTY)
val title: MutableStateFlow<String?> = MutableStateFlow(null)
val thumbnail: MutableStateFlow<Bitmap?> = MutableStateFlow(null)

fun handleIntent(intent: Intent?) {
intent ?: return
Expand All @@ -23,5 +32,14 @@ class PlayerViewModel @Inject constructor() : ViewModel() {
) ?: intent.data ?: return
this.uri.tryEmit(uri)
this.title.tryEmit(intent.getStringExtra(VIDEO_TITLE_KEY))
viewModelScope.launch {
val bitmapUrl = intent.getStringExtra(VIDEO_THUMBNAIL_KEY)
if (bitmapUrl != null) {
appContext.imageLoaderBuilder().build()
.getImage(appContext, bitmapUrl)
?.inputStream()
?.use { thumbnail.tryEmit(BitmapFactory.decodeStream(it)) }
}
}
}
}
5 changes: 4 additions & 1 deletion app/src/main/java/com/skyd/anivu/ui/mpv/PlayerCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import android.view.Surface
import android.view.SurfaceHolder
import androidx.compose.ui.geometry.Offset
import com.skyd.anivu.ui.mpv.MPVPlayer.Track
import com.skyd.anivu.ui.mpv.service.PlayerState
import java.io.File

sealed interface PlayerCommand {
data class Attach(val surfaceHolder: SurfaceHolder) : PlayerCommand
data class Detach(val surface: Surface) : PlayerCommand
data class SetUri(val uri: Uri) : PlayerCommand
data class SetTitle(val title: String) : PlayerCommand
data class SetThumbnail(val thumbnail: Bitmap) : PlayerCommand
data object Destroy : PlayerCommand
data class Paused(val paused: Boolean, val uri: Uri?) : PlayerCommand
data object PlayOrPause : PlayerCommand
Expand All @@ -34,6 +35,7 @@ sealed interface PlayerEvent {
data class Idling(val value: Boolean) : PlayerEvent
data class Position(val value: Long) : PlayerEvent
data class Duration(val value: Long) : PlayerEvent
data class MediaTitle(val value: String) : PlayerEvent
data class Title(val value: String) : PlayerEvent
data class Paused(val value: Boolean) : PlayerEvent
data class PausedForCache(val value: Boolean) : PlayerEvent
Expand All @@ -57,5 +59,6 @@ sealed interface PlayerEvent {
data class PlaylistCount(val value: Int) : PlayerEvent
data class Artist(val value: String) : PlayerEvent
data class Album(val value: String) : PlayerEvent
data class MediaThumbnail(val value: Bitmap?) : PlayerEvent
data class Thumbnail(val value: Bitmap?) : PlayerEvent
}
23 changes: 16 additions & 7 deletions app/src/main/java/com/skyd/anivu/ui/mpv/PlayerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LocalLifecycleOwner
import coil3.Bitmap
import com.skyd.anivu.ext.activity
import com.skyd.anivu.ext.collectIn
import com.skyd.anivu.ui.component.OnLifecycleEvent
Expand Down Expand Up @@ -54,11 +55,12 @@ fun PlayerViewRoute(
service: PlayerService?,
uri: Uri,
title: String? = null,
thumbnail: Bitmap? = null,
onBack: () -> Unit,
onSaveScreenshot: (File) -> Unit,
) {
if (service != null) {
PlayerView(service, uri, title, onBack, onSaveScreenshot)
PlayerView(service, uri, title, thumbnail, onBack, onSaveScreenshot)
}
}

Expand All @@ -67,6 +69,7 @@ fun PlayerView(
service: PlayerService,
uri: Uri,
title: String? = null,
thumbnail: Bitmap? = null,
onBack: () -> Unit,
onSaveScreenshot: (File) -> Unit,
) {
Expand All @@ -89,11 +92,6 @@ fun PlayerView(
var subtitleTrackDialogState by remember { mutableStateOf(SubtitleTrackDialogState.initial) }
var audioTrackDialogState by remember { mutableStateOf(AudioTrackDialogState.initial) }
var speedDialogState by remember { mutableStateOf(SpeedDialogState.initial) }
LaunchedEffect(title) {
if (title != null) {
playState = playState.copyIfNecessary(title = title)
}
}
LaunchedEffect(playState.speed) {
speedDialogState = speedDialogState.copy(currentSpeed = playState.speed)
}
Expand Down Expand Up @@ -184,7 +182,8 @@ fun PlayerView(
duration = state.duration.toInt(),
currentPosition = state.position.toInt(),
speed = state.speed,
mediaTitle = state.title.orEmpty()
mediaTitle = state.mediaTitle.orEmpty(),
title = state.title.orEmpty(),
)
transformState = transformState.copyIfNecessary(
videoRotate = state.rotate,
Expand Down Expand Up @@ -227,6 +226,16 @@ fun PlayerView(
service.addObserver(playerObserver)
service.onCommand(PlayerCommand.SetUri(uri))
}
LaunchedEffect(title) {
if (title != null) {
service.onCommand(PlayerCommand.SetTitle(title))
}
}
LaunchedEffect(thumbnail) {
if (thumbnail != null) {
service.onCommand(PlayerCommand.SetThumbnail(thumbnail))
}
}

val inPipMode = rememberIsInPipMode()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ class MediaSessionManager(
return with(mediaMetadataBuilder) {
putText(MediaMetadataCompat.METADATA_KEY_ALBUM, album)
// put even if it's null to reset any previous art
putBitmap(MediaMetadataCompat.METADATA_KEY_ART, thumbnail)
putBitmap(MediaMetadataCompat.METADATA_KEY_ART, thumbnail ?: mediaThumbnail)
putText(MediaMetadataCompat.METADATA_KEY_ARTIST, artist)
putLong(
MediaMetadataCompat.METADATA_KEY_DURATION,
(duration * 1000).takeIf { it > 0 } ?: -1)
putText(MediaMetadataCompat.METADATA_KEY_TITLE, title)
putText(MediaMetadataCompat.METADATA_KEY_TITLE, title.orEmpty().ifBlank { mediaTitle })
build()
}
}
Expand Down Expand Up @@ -120,7 +120,9 @@ class MediaSessionManager(
is PlayerEvent.Shuffle -> old.copy(shuffle = value)
is PlayerEvent.Speed -> old.copy(speed = value)
is PlayerEvent.SubtitleTrackChanged -> old.copy(subtitleTrackId = trackId)
is PlayerEvent.MediaThumbnail -> old.copy(mediaThumbnail = value)
is PlayerEvent.Thumbnail -> old.copy(thumbnail = value)
is PlayerEvent.MediaTitle -> old.copy(mediaTitle = value)
is PlayerEvent.Title -> old.copy(title = value)
is PlayerEvent.VideoOffsetX -> old.copy(offsetX = value)
is PlayerEvent.VideoOffsetY -> old.copy(offsetY = value)
Expand Down Expand Up @@ -162,9 +164,11 @@ class MediaSessionManager(
}

is PlayerEvent.Idling,
is PlayerEvent.MediaTitle,
is PlayerEvent.Title,
is PlayerEvent.Artist,
is PlayerEvent.Album,
is PlayerEvent.MediaThumbnail,
is PlayerEvent.Thumbnail -> {
mediaSession.setMetadata(newState.buildMediaMetadata())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class PlayerNotificationManager(
}

private fun NotificationCompat.Builder.setContentTitle() = apply {
setContentTitle(playerState.value.title)
setContentTitle(playerState.value.run { title.orEmpty().ifBlank { mediaTitle } })
}

private fun NotificationCompat.Builder.setContentText() = apply {
Expand All @@ -140,7 +140,7 @@ class PlayerNotificationManager(
}

private fun NotificationCompat.Builder.setThumbnail() = apply {
playerState.value.thumbnail?.also {
playerState.value.run { thumbnail ?: mediaThumbnail }?.also {
setLargeIcon(it)
setColorized(true)
// scale thumbnail to a single color in two steps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class PlayerService : Service() {

override fun eventProperty(property: String, value: String) {
when (property) {
"media-title" -> sendEvent(PlayerEvent.Title(value))
"media-title" -> sendEvent(PlayerEvent.MediaTitle(value))
}
}

Expand All @@ -127,7 +127,7 @@ class PlayerService : Service() {
sendEvent(PlayerEvent.FileLoaded)
sendEvent(PlayerEvent.Paused(player.paused))
loadLastPosition().invokeOnCompletion {
sendEvent(PlayerEvent.Thumbnail(player.thumbnail))
sendEvent(PlayerEvent.MediaThumbnail(player.thumbnail))
}
}

Expand Down Expand Up @@ -220,9 +220,13 @@ class PlayerService : Service() {
savePosition() // Save last media position
uri = command.uri
command.uri.resolveUri(this@PlayerService)?.let { loadFile(it) }
sendEvent(PlayerEvent.Title(""))
sendEvent(PlayerEvent.Thumbnail(null))
}
}

is PlayerCommand.SetTitle -> sendEvent(PlayerEvent.Title(command.title))
is PlayerCommand.SetThumbnail -> sendEvent(PlayerEvent.Thumbnail(command.thumbnail))
PlayerCommand.Destroy -> stopSelf()
is PlayerCommand.Paused -> {
if (!command.paused) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ data class PlayerState(
val pausedForCache: Boolean = false,
val shuffle: Boolean = false,
val idling: Boolean = true,
val mediaTitle: String? = null,
val title: String? = null,
val mediaThumbnail: Bitmap? = null,
val thumbnail: Bitmap? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,12 @@ private fun Content(
}
}
MediaRow(articleWithFeed = articleState.article, onPlay = { url ->
PlayActivity.play(context.activity, uri = Uri.parse(url), title = article.article.title)
PlayActivity.play(
activity = context.activity,
uri = Uri.parse(url),
title = article.article.title,
thumbnail = article.media?.image ?: articleState.article.feed.icon,
)
})
HtmlText(
modifier = Modifier.padding(horizontal = 16.dp),
Expand Down

0 comments on commit b33da4f

Please sign in to comment.