Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implemented "dislike" by long-tap & related fixes #5180

Draft
wants to merge 22 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9cb85e4
added method for dislike in database
twistios Jan 8, 2025
c192f6a
added method `setDislike`
twistios Jan 8, 2025
e7ae37a
implemented "dislike" by long-tap on like-icon in controls
twistios Jan 8, 2025
80f162d
renamed to "setDisliked"
twistios Jan 8, 2025
3eef752
refactor: moved argument in parameter list
twistios Jan 8, 2025
282dc4f
Merge branch 'master' into feature_dislike_long_tap
twistios Jan 9, 2025
75364bc
improved code formatting
twistios Jan 9, 2025
18a0cf6
added `setDislikeState`
twistios Jan 9, 2025
2c104bb
renamed `setDisLiked` to `toggleDislike`, use `setDislikeState`
twistios Jan 9, 2025
4ed3a9a
implemented toggling between disliked and "unliked"
twistios Jan 9, 2025
3a922a3
Merge branch 'master' into feature_dislike_long_tap
twistios Jan 10, 2025
57da819
fixed `mediaItemToggleLike`
twistios Jan 10, 2025
59d6b2a
added method `mediaItemSetLiked`
twistios Jan 10, 2025
eb236ed
improved mass-liking for playlists and albums
twistios Jan 10, 2025
a96d010
implemented dislike in `MediaItemGridMenu`
twistios Jan 10, 2025
748b01f
implemented dislike via long-tap in `MediaItemMenu`
twistios Jan 10, 2025
d12d719
improved single-tap consistency and autodownload fix
twistios Jan 10, 2025
85d5d06
fixed `songLiked`
twistios Jan 10, 2025
2cc267d
fixed `songsFavorites*` methods
twistios Jan 10, 2025
b0c898b
Merge branch 'master' into feature_dislike_long_tap
twistios Jan 10, 2025
142878e
Merge branch 'refs/heads/master' into feature_dislike_long_tap
twistios Jan 13, 2025
4dd16de
Merge branch 'master' into feature_dislike_long_tap
twistios Jan 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions composeApp/src/androidMain/kotlin/it/fast4x/rimusic/Database.kt
Original file line number Diff line number Diff line change
Expand Up @@ -194,19 +194,19 @@ interface Database {

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY artistsText")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY artistsText")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByArtistAsc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY artistsText DESC")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY artistsText DESC")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByArtistDesc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY totalPlayTimeMs")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY totalPlayTimeMs")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByPlayTimeAsc(): Flow<List<SongEntity>>

Expand All @@ -222,7 +222,7 @@ interface Database {

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY totalPlayTimeMs DESC")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY totalPlayTimeMs DESC")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByPlayTimeDesc(): Flow<List<SongEntity>>

Expand All @@ -238,63 +238,63 @@ interface Database {

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY title COLLATE NOCASE ASC")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY title COLLATE NOCASE ASC")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByTitleAsc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY title COLLATE NOCASE DESC")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY title COLLATE NOCASE DESC")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByTitleDesc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY ROWID")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY ROWID")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByRowIdAsc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY ROWID DESC")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY ROWID DESC")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByRowIdDesc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY likedAt")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY likedAt")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByLikedAtAsc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY likedAt DESC")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY likedAt DESC")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByLikedAtDesc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT DISTINCT S.* FROM Song S LEFT JOIN Event E ON E.songId=S.id " +
"WHERE likedAt IS NOT NULL " +
"WHERE likedAt IS NOT NULL AND likedAt > 0 " +
"ORDER BY E.timestamp DESC")
fun songsFavoritesByDatePlayedDesc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT DISTINCT S.* FROM Song S LEFT JOIN Event E ON E.songId=S.id " +
"WHERE likedAt IS NOT NULL " +
"WHERE likedAt IS NOT NULL AND likedAt > 0 " +
"ORDER BY E.timestamp")
fun songsFavoritesByDatePlayedAsc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY durationText")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY durationText")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByDurationAsc(): Flow<List<SongEntity>>

@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@Transaction
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL ORDER BY durationText DESC")
@Query("SELECT * FROM Song WHERE likedAt IS NOT NULL AND likedAt > 0 ORDER BY durationText DESC")
@RewriteQueriesToDropUnusedColumns
fun songsFavoritesByDurationDesc(): Flow<List<SongEntity>>

Expand Down Expand Up @@ -1329,7 +1329,7 @@ interface Database {
@Query("UPDATE Playlist SET name = REPLACE(name,'${PINNED_PREFIX}','') WHERE id = :playlistId")
fun unPinPlaylist(playlistId: Long): Int

@Query("SELECT count(id) FROM Song WHERE id = :songId and likedAt IS NOT NULL")
@Query("SELECT count(id) FROM Song WHERE id = :songId and likedAt IS NOT NULL and likedAt > 0")
fun songliked(songId: String): Int

@Query("SELECT * FROM Song WHERE id = :id")
Expand All @@ -1341,6 +1341,9 @@ interface Database {
@Query("SELECT likedAt FROM Song WHERE id = :songId")
fun likedAt(songId: String): Flow<Long?>

@Query("SELECT likedAt FROM Song WHERE id = :songId")
fun getLikedAt(songId: String): Long?

@Query("UPDATE Album SET bookmarkedAt = :bookmarkedAt WHERE id = :id")
fun bookmarkAlbum(id: String, bookmarkedAt: Long?): Int

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.room.Entity
import androidx.room.PrimaryKey
import it.fast4x.rimusic.cleanPrefix
import it.fast4x.rimusic.utils.durationTextToMillis
import it.fast4x.rimusic.utils.setDisLikeState
import it.fast4x.rimusic.utils.setLikeState
import kotlinx.serialization.Serializable

Expand Down Expand Up @@ -40,6 +41,12 @@ data class Song(
)
}

fun toggleDislike(): Song {
return copy(
likedAt = setDisLikeState(likedAt)
)
}

fun cleanTitle() = cleanPrefix( this.title )

fun relativePlayTime(): Double {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package it.fast4x.rimusic.ui.components.themed

import androidx.annotation.DrawableRes
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.Indication
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
Expand Down Expand Up @@ -39,9 +41,11 @@ fun HeaderIconButton(
)
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun IconButton(
onClick: () -> Unit,
onLongClick: (() -> Unit)? = null,
@DrawableRes icon: Int,
color: Color,
modifier: Modifier = Modifier,
Expand All @@ -53,11 +57,12 @@ fun IconButton(
contentDescription = null,
colorFilter = ColorFilter.tint(color),
modifier = Modifier
.clickable(
.combinedClickable(
indication = indication ?: ripple(bounded = false),
interactionSource = remember { MutableInteractionSource() },
enabled = enabled,
onClick = onClick
onClick = onClick,
onLongClick = onLongClick
)
.then(modifier)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,13 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import it.fast4x.rimusic.colorPalette
import it.fast4x.rimusic.context
import it.fast4x.rimusic.models.Song
import it.fast4x.rimusic.service.MyDownloadHelper
import it.fast4x.rimusic.typography
import it.fast4x.rimusic.ui.screens.settings.isYouTubeSyncEnabled
import it.fast4x.rimusic.utils.getLikeState
import it.fast4x.rimusic.utils.setDisLikeState

@OptIn(UnstableApi::class)
@Composable
Expand Down Expand Up @@ -304,14 +309,13 @@ fun MediaItemGridMenu (

val isLocal by remember { derivedStateOf { mediaItem.isLocal } }

var updateData by remember {
mutableStateOf(false)
}
var likedAt by remember {
mutableStateOf<Long?>(null)
}
LaunchedEffect(Unit, mediaItem.mediaId, updateData) {
Database.likedAt(mediaItem.mediaId).collect { likedAt = it }
LaunchedEffect(Unit, mediaItem.mediaId) {
Database.likedAt(mediaItem.mediaId).collect {
likedAt = it
}
}

var downloadState by remember {
Expand Down Expand Up @@ -434,11 +438,22 @@ fun MediaItemGridMenu (

Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
IconButton(
icon = if (likedAt == null) R.drawable.heart_outline else R.drawable.heart,
icon = getLikeState(mediaItem.mediaId),
color = colorPalette().favoritesIcon,
onClick = {
mediaItemToggleLike(mediaItem)
updateData = !updateData
Database.asyncQuery {
if(songliked(mediaItem.mediaId) != 0){
MyDownloadHelper.autoDownloadWhenLiked(context(), mediaItem)
}
}
},
onLongClick = {
Database.asyncTransaction {
if (like(mediaItem.mediaId, setDisLikeState(likedAt)) == 0) {
insert(mediaItem, Song::toggleDislike)
}
}
},
modifier = Modifier
.padding(all = 4.dp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ import it.fast4x.rimusic.context
import it.fast4x.rimusic.service.MyDownloadHelper
import it.fast4x.rimusic.typography
import it.fast4x.rimusic.ui.screens.settings.isYouTubeSyncEnabled
import it.fast4x.rimusic.utils.mediaItemToggleLike
import it.fast4x.rimusic.utils.setDisLikeState
import timber.log.Timber
import java.time.LocalTime.now
import java.time.format.DateTimeFormatter
Expand Down Expand Up @@ -1130,12 +1132,19 @@ fun MediaItemMenu(
color = colorPalette().favoritesIcon,
//color = if (likedAt == null) colorPalette().textDisabled else colorPalette().text,
onClick = {
mediaItemToggleLike(mediaItem)
Database.asyncQuery {
if(songliked(mediaItem.mediaId) != 0){
MyDownloadHelper.autoDownloadWhenLiked(context(), mediaItem)
}
}
},
onLongClick = {
Database.asyncTransaction {
if ( like( mediaItem.mediaId, setLikeState(likedAt) ) == 0 ) {
insert(mediaItem, Song::toggleLike)
if (like(mediaItem.mediaId, setDisLikeState(likedAt)) == 0) {
insert(mediaItem, Song::toggleDislike)
}
}
MyDownloadHelper.autoDownloadWhenLiked(context(),mediaItem)
},
modifier = Modifier
.padding(all = 4.dp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ import it.fast4x.rimusic.models.SongAlbumMap
import it.fast4x.rimusic.service.MyDownloadHelper
import it.fast4x.rimusic.typography
import it.fast4x.rimusic.ui.screens.settings.isYouTubeSyncEnabled
import it.fast4x.rimusic.utils.mediaItemSetLiked
import it.fast4x.rimusic.utils.mediaItemToggleLike
import kotlinx.coroutines.flow.first
import timber.log.Timber
Expand Down Expand Up @@ -989,12 +990,9 @@ fun AlbumDetails(
},
onAddToFavourites = {
songs.forEach { song ->

val likedAt: Long? = song.likedAt
if(likedAt == null) {
mediaItemToggleLike(song.asMediaItem)
}
}
mediaItemSetLiked(song.asMediaItem)
}
SmartMessage(context.resources.getString(R.string.done), context = context)
},
disableScrollingText = disableScrollingText
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ import it.fast4x.rimusic.utils.isNowPlaying
import it.fast4x.rimusic.utils.saveImageToInternalStorage
import kotlinx.coroutines.CoroutineScope
import it.fast4x.rimusic.models.SongEntity
import it.fast4x.rimusic.utils.mediaItemSetLiked
import it.fast4x.rimusic.utils.mediaItemToggleLike
import kotlinx.coroutines.flow.map

Expand Down Expand Up @@ -1287,10 +1288,9 @@ fun LocalPlaylistSongsModern(
},
onAddToPreferites = {
playlistSongs.forEachIndexed { _, song ->
if(song.song.likedAt == null) {
mediaItemToggleLike(song.asMediaItem)
}
mediaItemSetLiked(song.asMediaItem)
}
SmartMessage(context.resources.getString(R.string.done), context = context)
},
onRenumberPositions = {
if (playlistNotMonthlyType)
Expand Down
Loading