Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
fast4x committed Sep 2, 2024
1 parent 4cd7424 commit 7c22a11
Show file tree
Hide file tree
Showing 58 changed files with 587 additions and 4 deletions.
9 changes: 9 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@
android:name="android.appwidget.provider"
android:resource="@xml/player_vertical_widget_info" />
</receiver>
<receiver android:name=".ui.widgets.PlayerHorizontalWidgetReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/player_horizontal_widget_info" />
</receiver>

<service
android:name=".service.PlayerService"
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/kotlin/it/fast4x/rimusic/service/PlayerService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ import it.fast4x.rimusic.models.asMediaItem
import it.fast4x.rimusic.query
import it.fast4x.rimusic.transaction
import it.fast4x.rimusic.ui.components.themed.SmartMessage
import it.fast4x.rimusic.ui.widgets.PlayerHorizontalWidget
import it.fast4x.rimusic.ui.widgets.PlayerVerticalWidget
import it.fast4x.rimusic.utils.InvincibleService
import it.fast4x.rimusic.utils.RingBuffer
Expand Down Expand Up @@ -352,6 +353,7 @@ class PlayerService : InvincibleService(),
private lateinit var notificationActionReceiver: NotificationActionReceiver
//private lateinit var audioQualityFormat: AudioQualityFormat
private val playerVerticalWidget = PlayerVerticalWidget()
private val playerHorizontalWidget = PlayerHorizontalWidget()

/*
private val media = MutableStateFlow<MediaItem?>(null)
Expand Down Expand Up @@ -2020,6 +2022,14 @@ class PlayerService : InvincibleService(),
bitmap = bitmapProvider.bitmap,
player = player
)
playerHorizontalWidget.updateInfo(
context = applicationContext,
songTitle = songTitle,
songArtist = songArtist,
isPlaying = isPlaying,
bitmap = bitmapProvider.bitmap,
player = player
)
}
}

Expand Down
215 changes: 215 additions & 0 deletions app/src/main/kotlin/it/fast4x/rimusic/ui/widgets/Contents.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
package it.fast4x.rimusic.ui.widgets

import android.content.Context
import androidx.annotation.OptIn
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.datastore.preferences.core.Preferences
import androidx.glance.GlanceModifier
import androidx.glance.GlanceTheme
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.action.actionStartActivity
import androidx.glance.action.clickable
import androidx.glance.background
import androidx.glance.currentState
import androidx.glance.layout.Alignment
import androidx.glance.layout.Column
import androidx.glance.layout.Row
import androidx.glance.layout.fillMaxWidth
import androidx.glance.layout.height
import androidx.glance.layout.padding
import androidx.glance.layout.width
import androidx.glance.text.Text
import androidx.media3.common.util.UnstableApi
import it.fast4x.rimusic.MainActivity
import it.fast4x.rimusic.R
import it.fast4x.rimusic.ui.widgets.PlayerHorizontalWidget.Companion.isPlayingKey
import it.fast4x.rimusic.ui.widgets.PlayerHorizontalWidget.Companion.songArtistKey
import it.fast4x.rimusic.ui.widgets.PlayerHorizontalWidget.Companion.songTitleKey
import it.fast4x.rimusic.ui.widgets.PlayerHorizontalWidget.Companion.widgetBitmap
import it.fast4x.rimusic.ui.widgets.PlayerHorizontalWidget.Companion.widgetPlayer


@OptIn(UnstableApi::class)
@Composable
fun WidgetActiveVerticalContent(context: Context) {
val preferences = currentState<Preferences>()
Column(
modifier = GlanceModifier.fillMaxWidth()
.background(GlanceTheme.colors.widgetBackground)
.padding(4.dp),
verticalAlignment = Alignment.Top,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = preferences[PlayerVerticalWidget.songTitleKey] ?: "", modifier = GlanceModifier)
Text(text = preferences[PlayerVerticalWidget.songArtistKey] ?: "", modifier = GlanceModifier)
//Text(text = "isPlaying: ${preferences[isPlayingKey]}", modifier = GlanceModifier)

Row(
modifier = GlanceModifier.fillMaxWidth()
.background(GlanceTheme.colors.widgetBackground)
.padding(vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalAlignment = Alignment.CenterHorizontally
) {

Image(
provider = ImageProvider(R.drawable.play_skip_back),
contentDescription = "back",
modifier = GlanceModifier
.clickable {
PlayerVerticalWidget.widgetPlayer.seekToPrevious()
}
)

Image(
provider = ImageProvider(
if (preferences[PlayerVerticalWidget.isPlayingKey] == true) {
R.drawable.pause
} else {
R.drawable.play
}
),
contentDescription = "play/pause",
modifier = GlanceModifier.padding(horizontal = 20.dp)
.clickable {
if (preferences[PlayerVerticalWidget.isPlayingKey] == true) {
PlayerVerticalWidget.widgetPlayer.pause()
} else {
PlayerVerticalWidget.widgetPlayer.play()
}
}
)

Image(
provider = ImageProvider(R.drawable.play_skip_forward),
contentDescription = "next",
modifier = GlanceModifier
.clickable {
PlayerVerticalWidget.widgetPlayer.seekToNext()
}
)

}


Image(
provider = ImageProvider(PlayerVerticalWidget.widgetBitmap),
contentDescription = "cover",
modifier = GlanceModifier.padding(horizontal = 5.dp)
.clickable (
onClick = actionStartActivity<MainActivity>()
/*
onClick = actionStartActivity(
Intent( context, MainActivity::class.java)
.putExtra("expandPlayerBottomSheet", true)
)
*/
)

)


}

}

@OptIn(UnstableApi::class)
@Composable
fun WidgetActiveHorizontalContent(context: Context) {
val preferences = currentState<Preferences>()
Row(
modifier = GlanceModifier.fillMaxWidth()
.background(GlanceTheme.colors.widgetBackground)
.padding(4.dp),
verticalAlignment = Alignment.Top,
horizontalAlignment = Alignment.Start
) {

Image(
provider = ImageProvider(widgetBitmap),
contentDescription = "cover",
modifier = GlanceModifier.padding(start = 5.dp, end = 20.dp)
.width(120.dp).height(120.dp)
.clickable (
onClick = actionStartActivity<MainActivity>()
/*
onClick = actionStartActivity(
Intent( context, MainActivity::class.java)
.putExtra("expandPlayerBottomSheet", true)
)
*/
)

)

Column(
modifier = GlanceModifier.fillMaxWidth()
//.background(GlanceTheme.colors.widgetBackground)
.padding(vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = preferences[songTitleKey] ?: "", modifier = GlanceModifier)
Text(text = preferences[songArtistKey] ?: "", modifier = GlanceModifier)
//Text(text = "isPlaying: ${preferences[isPlayingKey]}", modifier = GlanceModifier)


Row(
modifier = GlanceModifier
//.background(GlanceTheme.colors.widgetBackground)
.padding(vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalAlignment = Alignment.CenterHorizontally
) {

Image(
provider = ImageProvider(R.drawable.play_skip_back),
contentDescription = "back",
modifier = GlanceModifier
.clickable {
widgetPlayer.seekToPrevious()
}
)

Image(
provider = ImageProvider(
if (preferences[isPlayingKey] == true) {
R.drawable.pause
} else {
R.drawable.play
}
),
contentDescription = "play/pause",
modifier = GlanceModifier.padding(horizontal = 20.dp)
.clickable {
if (preferences[isPlayingKey] == true) {
widgetPlayer.pause()
} else {
widgetPlayer.play()
}
}
)

Image(
provider = ImageProvider(R.drawable.play_skip_forward),
contentDescription = "next",
modifier = GlanceModifier
.clickable {
widgetPlayer.seekToNext()
}
)

}
}




}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package it.fast4x.rimusic.ui.widgets

import android.content.Context
import android.graphics.Bitmap
import androidx.annotation.OptIn
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.glance.GlanceId
import androidx.glance.GlanceModifier
import androidx.glance.GlanceTheme
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.action.actionStartActivity
import androidx.glance.action.clickable
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetManager
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import androidx.glance.appwidget.provideContent
import androidx.glance.appwidget.state.updateAppWidgetState
import androidx.glance.background
import androidx.glance.currentState
import androidx.glance.layout.Alignment
import androidx.glance.layout.Column
import androidx.glance.layout.Row
import androidx.glance.layout.fillMaxWidth
import androidx.glance.layout.padding
import androidx.glance.state.GlanceStateDefinition
import androidx.glance.state.PreferencesGlanceStateDefinition
import androidx.glance.text.Text
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import it.fast4x.rimusic.MainActivity
import it.fast4x.rimusic.R
import it.fast4x.rimusic.ui.widgets.PlayerVerticalWidget.Companion.isPlayingKey
import it.fast4x.rimusic.ui.widgets.PlayerVerticalWidget.Companion.songArtistKey
import it.fast4x.rimusic.ui.widgets.PlayerVerticalWidget.Companion.songTitleKey
import it.fast4x.rimusic.ui.widgets.PlayerVerticalWidget.Companion.widgetBitmap
import it.fast4x.rimusic.ui.widgets.PlayerVerticalWidget.Companion.widgetPlayer
import it.fast4x.rimusic.utils.cleanPrefix

class PlayerHorizontalWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = PlayerHorizontalWidget()
}

class PlayerHorizontalWidget: GlanceAppWidget() {
companion object {
val songTitleKey = stringPreferencesKey("songTitleKey")
val songArtistKey = stringPreferencesKey("songArtistKey")
val isPlayingKey = booleanPreferencesKey("isPlayingKey")
var widgetBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
lateinit var widgetPlayer: ExoPlayer
}

override val stateDefinition: GlanceStateDefinition<*> = PreferencesGlanceStateDefinition

override suspend fun provideGlance(context: Context, id: GlanceId) {

provideContent {
GlanceTheme {
WidgetActiveHorizontalContent(context)
}
}
}

@OptIn(UnstableApi::class)
suspend fun updateInfo(
context: Context,
songTitle: String,
songArtist: String,
isPlaying: Boolean,
bitmap: Bitmap,
player: ExoPlayer
) {

val glanceId =
GlanceAppWidgetManager(context).getGlanceIds(PlayerHorizontalWidget::class.java).firstOrNull()
?: return

updateAppWidgetState(context, PreferencesGlanceStateDefinition, glanceId) { preferences ->
preferences.toMutablePreferences().apply {
this[songTitleKey] = cleanPrefix(songTitle)
this[songArtistKey] = songArtist
this[isPlayingKey] = isPlaying
}
}

widgetBitmap = bitmap
widgetPlayer = player
PlayerHorizontalWidget().update(context, glanceId)
}

}



Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class PlayerVerticalWidget: GlanceAppWidget() {

provideContent {
GlanceTheme {
WidgetActiveContent(context)
WidgetActiveVerticalContent(context)
}
}
}
Expand Down Expand Up @@ -119,10 +119,11 @@ fun WidgetContent() {


}
/*
@OptIn(UnstableApi::class)
@Composable
fun WidgetActiveContent(context: Context) {
fun WidgetActiveVerticalContent(context: Context) {
val preferences = currentState<Preferences>()
Column(
modifier = GlanceModifier.fillMaxWidth()
Expand Down Expand Up @@ -204,4 +205,4 @@ fun WidgetActiveContent(context: Context) {
}
}

*/
Loading

0 comments on commit 7c22a11

Please sign in to comment.