Skip to content

Commit

Permalink
Gallery: Add blacklist feature
Browse files Browse the repository at this point in the history
Fixes #252

Signed-off-by: IacobIonut01 <[email protected]>
  • Loading branch information
IacobIonut01 committed Nov 28, 2023
1 parent 344ec1a commit 1fbace7
Show file tree
Hide file tree
Showing 18 changed files with 566 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "57402321aff199c16e2f25a4a21623ba",
"entities": [
{
"tableName": "pinned_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "blacklist",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `label` TEXT NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "label",
"columnName": "label",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '57402321aff199c16e2f25a4a21623ba')"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import com.dot.gallery.core.Settings.Misc.rememberTimelineGroupByMonth
import com.dot.gallery.core.presentation.components.util.permissionGranted
import com.dot.gallery.feature_node.presentation.albums.AlbumsScreen
import com.dot.gallery.feature_node.presentation.albums.AlbumsViewModel
import com.dot.gallery.feature_node.presentation.blacklist.BlacklistScreen
import com.dot.gallery.feature_node.presentation.blacklist.BlacklistViewModel
import com.dot.gallery.feature_node.presentation.common.ChanneledViewModel
import com.dot.gallery.feature_node.presentation.common.MediaViewModel
import com.dot.gallery.feature_node.presentation.favorites.FavoriteScreen
Expand Down Expand Up @@ -336,5 +338,18 @@ fun NavigationComp(
navigateUp = navPipe::navigateUp
)
}
composable(
route = Screen.BlacklistScreen(),
enterTransition = { navigateInAnimation },
exitTransition = { navigateUpAnimation },
popEnterTransition = { navigateInAnimation },
popExitTransition = { navigateUpAnimation },
) {
val blacklistViewModel = hiltViewModel<BlacklistViewModel>()
BlacklistScreen(
vm = blacklistViewModel,
navigateUp = navPipe::navigateUp
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.dot.gallery.feature_node.data.data_source

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Query
import androidx.room.Upsert
import com.dot.gallery.feature_node.domain.model.BlacklistedAlbum
import kotlinx.coroutines.flow.Flow

@Dao
interface BlacklistDao {

@Query("SELECT * FROM blacklist")
fun getBlacklistedAlbums(): Flow<List<BlacklistedAlbum>>

@Upsert
suspend fun addBlacklistedAlbum(blacklistedAlbum: BlacklistedAlbum)

@Delete
suspend fun removeBlacklistedAlbum(blacklistedAlbum: BlacklistedAlbum)

@Query("SELECT EXISTS(SELECT * FROM blacklist WHERE id = :albumId)")
fun albumIsBlacklisted(albumId: Long): Boolean

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,26 @@

package com.dot.gallery.feature_node.data.data_source

import androidx.room.AutoMigration
import androidx.room.Database
import androidx.room.RoomDatabase
import com.dot.gallery.feature_node.domain.model.BlacklistedAlbum
import com.dot.gallery.feature_node.domain.model.PinnedAlbum

@Database(
entities = [PinnedAlbum::class],
version = 1,
exportSchema = true
entities = [PinnedAlbum::class, BlacklistedAlbum::class],
version = 2,
exportSchema = true,
autoMigrations = [
AutoMigration(from = 1, to = 2)
]
)
abstract class InternalDatabase: RoomDatabase() {

abstract fun getPinnedDao(): PinnedDao

abstract fun getBlacklistDao(): BlacklistDao

companion object {
const val NAME = "internal_db"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import com.dot.gallery.feature_node.data.data_types.getMediaTrashed
import com.dot.gallery.feature_node.data.data_types.updateMedia
import com.dot.gallery.feature_node.data.data_types.updateMediaExif
import com.dot.gallery.feature_node.domain.model.Album
import com.dot.gallery.feature_node.domain.model.BlacklistedAlbum
import com.dot.gallery.feature_node.domain.model.ExifAttributes
import com.dot.gallery.feature_node.domain.model.Media
import com.dot.gallery.feature_node.domain.model.PinnedAlbum
Expand All @@ -53,7 +54,9 @@ class MediaRepositoryImpl(
* TODO: Add media reordering
*/
override fun getMedia(): Flow<Resource<List<Media>>> =
context.retrieveMedia { it.getMedia(mediaOrder = DEFAULT_ORDER) }
context.retrieveMedia {
it.getMedia(mediaOrder = DEFAULT_ORDER).removeBlacklisted()
}

override fun getMediaByType(allowedMedia: AllowedMedia): Flow<Resource<List<Media>>> =
context.retrieveMedia {
Expand All @@ -62,21 +65,30 @@ class MediaRepositoryImpl(
VIDEOS -> Query.VideoQuery()
BOTH -> Query.MediaQuery()
}
it.getMedia(mediaQuery = query, mediaOrder = DEFAULT_ORDER)
it.getMedia(mediaQuery = query, mediaOrder = DEFAULT_ORDER).removeBlacklisted()
}

override fun getFavorites(mediaOrder: MediaOrder): Flow<Resource<List<Media>>> =
context.retrieveMedia { it.getMediaFavorite(mediaOrder = mediaOrder) }
context.retrieveMedia {
it.getMediaFavorite(mediaOrder = mediaOrder).removeBlacklisted()
}

override fun getTrashed(): Flow<Resource<List<Media>>> =
context.retrieveMedia { it.getMediaTrashed() }
context.retrieveMedia {
it.getMediaTrashed().removeBlacklisted()
}

override fun getAlbums(mediaOrder: MediaOrder): Flow<Resource<List<Album>>> =
override fun getAlbums(mediaOrder: MediaOrder, ignoreBlacklisted: Boolean): Flow<Resource<List<Album>>> =
context.retrieveAlbums {
it.getAlbums(mediaOrder = mediaOrder).toMutableList().apply {
replaceAll { album ->
album.copy(isPinned = database.getPinnedDao().albumIsPinned(album.id))
}
if (!ignoreBlacklisted) {
removeAll { album ->
database.getBlacklistDao().albumIsBlacklisted(album.id)
}
}
}
}

Expand All @@ -86,6 +98,15 @@ class MediaRepositoryImpl(
override suspend fun removePinnedAlbum(pinnedAlbum: PinnedAlbum) =
database.getPinnedDao().removePinnedAlbum(pinnedAlbum)

override suspend fun addBlacklistedAlbum(blacklistedAlbum: BlacklistedAlbum) =
database.getBlacklistDao().addBlacklistedAlbum(blacklistedAlbum)

override suspend fun removeBlacklistedAlbum(blacklistedAlbum: BlacklistedAlbum) =
database.getBlacklistDao().removeBlacklistedAlbum(blacklistedAlbum)

override fun getBlacklistedAlbums(): Flow<List<BlacklistedAlbum>> =
database.getBlacklistDao().getBlacklistedAlbums()

override suspend fun getMediaById(mediaId: Long): Media? {
val query = Query.MediaQuery().copy(
bundle = Bundle().apply {
Expand Down Expand Up @@ -196,7 +217,10 @@ class MediaRepositoryImpl(
}
}

override fun getMediaListByUris(listOfUris: List<Uri>, reviewMode: Boolean): Flow<Resource<List<Media>>> =
override fun getMediaListByUris(
listOfUris: List<Uri>,
reviewMode: Boolean
): Flow<Resource<List<Media>>> =
context.retrieveMediaAsResource {
var mediaList = it.getMediaListByUris(listOfUris)
if (reviewMode) {
Expand Down Expand Up @@ -258,7 +282,9 @@ class MediaRepositoryImpl(
mediaList: List<Media>
) {
val intentSender =
MediaStore.createDeleteRequest(context.contentResolver, mediaList.map { it.uri }).intentSender
MediaStore.createDeleteRequest(
context.contentResolver,
mediaList.map { it.uri }).intentSender
val senderRequest: IntentSenderRequest = IntentSenderRequest.Builder(intentSender)
.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 0)
.build()
Expand Down Expand Up @@ -297,6 +323,11 @@ class MediaRepositoryImpl(
exifAttributes = exifAttributes
)

private fun List<Media>.removeBlacklisted(): List<Media> = toMutableList().apply {
removeAll { media ->
database.getBlacklistDao().albumIsBlacklisted(media.albumID)
}
}

companion object {
private val DEFAULT_ORDER = MediaOrder.Date(OrderType.Descending)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.dot.gallery.feature_node.domain.model

import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.parcelize.Parcelize

@Entity(tableName = "blacklist")
@Parcelize
data class BlacklistedAlbum(
@PrimaryKey(autoGenerate = false)
val id: Long,
val label: String
): Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.IntentSenderRequest
import com.dot.gallery.core.Resource
import com.dot.gallery.feature_node.domain.model.Album
import com.dot.gallery.feature_node.domain.model.BlacklistedAlbum
import com.dot.gallery.feature_node.domain.model.ExifAttributes
import com.dot.gallery.feature_node.domain.model.Media
import com.dot.gallery.feature_node.domain.model.PinnedAlbum
Expand All @@ -27,12 +28,21 @@ interface MediaRepository {

fun getTrashed(): Flow<Resource<List<Media>>>

fun getAlbums(mediaOrder: MediaOrder): Flow<Resource<List<Album>>>
fun getAlbums(
mediaOrder: MediaOrder,
ignoreBlacklisted: Boolean = false
): Flow<Resource<List<Album>>>

suspend fun insertPinnedAlbum(pinnedAlbum: PinnedAlbum)

suspend fun removePinnedAlbum(pinnedAlbum: PinnedAlbum)

suspend fun addBlacklistedAlbum(blacklistedAlbum: BlacklistedAlbum)

suspend fun removeBlacklistedAlbum(blacklistedAlbum: BlacklistedAlbum)

fun getBlacklistedAlbums(): Flow<List<BlacklistedAlbum>>

suspend fun getMediaById(mediaId: Long): Media?

fun getMediaByAlbumId(albumId: Long): Flow<Resource<List<Media>>>
Expand Down Expand Up @@ -81,6 +91,4 @@ interface MediaRepository {
media: Media,
exifAttributes: ExifAttributes
): Boolean


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.dot.gallery.feature_node.domain.use_case

import com.dot.gallery.feature_node.domain.model.BlacklistedAlbum
import com.dot.gallery.feature_node.domain.repository.MediaRepository

class BlacklistUseCase(
private val repository: MediaRepository
) {

suspend fun addToBlacklist(blacklistedAlbum: BlacklistedAlbum) =
repository.addBlacklistedAlbum(blacklistedAlbum)

suspend fun removeFromBlacklist(blacklistedAlbum: BlacklistedAlbum) =
repository.removeBlacklistedAlbum(blacklistedAlbum)

val blacklistedAlbums by lazy { repository.getBlacklistedAlbums() }

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class GetAlbumsUseCase(
) {

operator fun invoke(
mediaOrder: MediaOrder = MediaOrder.Date(OrderType.Descending)
): Flow<Resource<List<Album>>> = repository.getAlbums(mediaOrder)
mediaOrder: MediaOrder = MediaOrder.Date(OrderType.Descending),
ignoreBlacklisted: Boolean = false
): Flow<Resource<List<Album>>> = repository.getAlbums(mediaOrder, ignoreBlacklisted)
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ data class MediaUseCases(
val mediaHandleUseCase = MediaHandleUseCase(repository, context)
val insertPinnedAlbumUseCase = InsertPinnedAlbumUseCase(repository)
val deletePinnedAlbumUseCase = DeletePinnedAlbumUseCase(repository)
val blacklistUseCase = BlacklistUseCase(repository)
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class AlbumsViewModel @Inject constructor(
}
}

private fun getAlbums(mediaOrder: MediaOrder = MediaOrder.Date(OrderType.Descending)) {
fun getAlbums(mediaOrder: MediaOrder = MediaOrder.Date(OrderType.Descending)) {
viewModelScope.launch(Dispatchers.IO) {
mediaUseCases.getAlbumsUseCase(mediaOrder).flowOn(Dispatchers.IO).collectLatest { result ->
// Result data list
Expand Down
Loading

0 comments on commit 1fbace7

Please sign in to comment.