mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 21:15:48 +00:00
Add StickerPackId and StickerPackKey value classes.
This commit is contained in:
committed by
Cody Henthorne
parent
3779dfd290
commit
3fc386d4a3
@@ -252,10 +252,10 @@ class StickerTable(
|
||||
notifyStickerPackListeners()
|
||||
}
|
||||
|
||||
fun markPackAsInstalled(packKey: String, notify: Boolean) {
|
||||
fun markPackAsInstalled(packId: String, notify: Boolean) {
|
||||
updatePackInstalled(
|
||||
db = databaseHelper.signalWritableDatabase,
|
||||
packId = packKey,
|
||||
packId = packId,
|
||||
installed = true,
|
||||
notify = notify
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.thoughtcrime.securesms.database.model
|
||||
import java.util.Optional
|
||||
|
||||
/**
|
||||
* Represents a record for a sticker pack in the [StickerTable].
|
||||
* Represents a record for a sticker pack in the [org.thoughtcrime.securesms.database.StickerTable].
|
||||
*/
|
||||
data class StickerPackRecord(
|
||||
@JvmField val packId: String,
|
||||
@@ -19,3 +19,15 @@ data class StickerPackRecord(
|
||||
@JvmField
|
||||
val authorOptional: Optional<String> = if (author.isBlank()) Optional.empty() else Optional.of(author)
|
||||
}
|
||||
|
||||
/**
|
||||
* A unique identifier for a sticker pack.
|
||||
*/
|
||||
@JvmInline
|
||||
value class StickerPackId(val value: String)
|
||||
|
||||
/**
|
||||
* An encryption key for a sticker pack.
|
||||
*/
|
||||
@JvmInline
|
||||
value class StickerPackKey(val value: String)
|
||||
|
||||
@@ -207,7 +207,7 @@ private fun AvailableStickersContent(
|
||||
item { StickerPackSectionHeader(text = stringResource(R.string.StickerManagement_signal_artist_series_header)) }
|
||||
items(
|
||||
items = blessedPacks,
|
||||
key = { it.record.packId }
|
||||
key = { it.id.value }
|
||||
) {
|
||||
AvailableStickerPackRow(
|
||||
pack = it,
|
||||
@@ -225,7 +225,7 @@ private fun AvailableStickersContent(
|
||||
item { StickerPackSectionHeader(text = stringResource(R.string.StickerManagement_stickers_you_received_header)) }
|
||||
items(
|
||||
items = notBlessedPacks,
|
||||
key = { it.record.packId }
|
||||
key = { it.id.value }
|
||||
) {
|
||||
AvailableStickerPackRow(
|
||||
pack = it,
|
||||
@@ -253,7 +253,7 @@ private fun InstalledStickersContent(
|
||||
item { StickerPackSectionHeader(text = stringResource(R.string.StickerManagement_installed_stickers_header)) }
|
||||
items(
|
||||
items = packs,
|
||||
key = { it.record.packId }
|
||||
key = { it.id.value }
|
||||
) {
|
||||
InstalledStickerPackRow(it)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import org.thoughtcrime.securesms.database.DatabaseObserver
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.StickerTable
|
||||
import org.thoughtcrime.securesms.database.StickerTable.StickerPackRecordReader
|
||||
import org.thoughtcrime.securesms.database.model.StickerPackId
|
||||
import org.thoughtcrime.securesms.database.model.StickerPackKey
|
||||
import org.thoughtcrime.securesms.database.model.StickerPackRecord
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager
|
||||
@@ -39,7 +41,7 @@ object StickerManagementRepository {
|
||||
|
||||
@Discouraged("For Java use only. In Kotlin, use the getStickerPacks() overload that returns a Flow instead.")
|
||||
@WorkerThread
|
||||
fun getStickerPacks(callback: Callback<StickerPackResult>) {
|
||||
fun getStickerPacks(callback: Callback<StickerPacksResult>) {
|
||||
coroutineScope.launch {
|
||||
callback.onComplete(loadStickerPacks())
|
||||
}
|
||||
@@ -48,7 +50,7 @@ object StickerManagementRepository {
|
||||
/**
|
||||
* Emits the sticker packs along with any updates.
|
||||
*/
|
||||
fun getStickerPacks(): Flow<StickerPackResult> = callbackFlow {
|
||||
fun getStickerPacks(): Flow<StickerPacksResult> = callbackFlow {
|
||||
trySend(loadStickerPacks())
|
||||
|
||||
val stickersDbObserver = DatabaseObserver.Observer {
|
||||
@@ -64,12 +66,12 @@ object StickerManagementRepository {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadStickerPacks(): StickerPackResult = withContext(Dispatchers.IO) {
|
||||
private suspend fun loadStickerPacks(): StickerPacksResult = withContext(Dispatchers.IO) {
|
||||
StickerPackRecordReader(stickersDbTable.getAllStickerPacks()).use { reader ->
|
||||
val installedPacks = mutableListOf<StickerPackRecord>()
|
||||
val availablePacks = mutableListOf<StickerPackRecord>()
|
||||
val blessedPacks = mutableListOf<StickerPackRecord>()
|
||||
val sortOrderById = mutableMapOf<String, Int>()
|
||||
val sortOrderById = mutableMapOf<StickerPackId, Int>()
|
||||
|
||||
reader.asSequence().forEachIndexed { index, record ->
|
||||
when {
|
||||
@@ -77,10 +79,10 @@ object StickerManagementRepository {
|
||||
BlessedPacks.contains(record.packId) -> blessedPacks.add(record)
|
||||
else -> availablePacks.add(record)
|
||||
}
|
||||
sortOrderById[record.packId] = index
|
||||
sortOrderById[StickerPackId(record.packId)] = index
|
||||
}
|
||||
|
||||
StickerPackResult(
|
||||
StickerPacksResult(
|
||||
installedPacks = installedPacks,
|
||||
availablePacks = availablePacks,
|
||||
blessedPacks = blessedPacks,
|
||||
@@ -112,34 +114,34 @@ object StickerManagementRepository {
|
||||
|
||||
fun installStickerPackAsync(packId: String, packKey: String, notify: Boolean) {
|
||||
coroutineScope.launch {
|
||||
installStickerPack(packId, packKey, notify)
|
||||
installStickerPack(StickerPackId(packId), StickerPackKey(packKey), notify)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun installStickerPack(packId: String, packKey: String, notify: Boolean) = withContext(Dispatchers.IO) {
|
||||
if (stickersDbTable.isPackAvailableAsReference(packId)) {
|
||||
stickersDbTable.markPackAsInstalled(packId, notify)
|
||||
suspend fun installStickerPack(packId: StickerPackId, packKey: StickerPackKey, notify: Boolean) = withContext(Dispatchers.IO) {
|
||||
if (stickersDbTable.isPackAvailableAsReference(packId.value)) {
|
||||
stickersDbTable.markPackAsInstalled(packId.value, notify)
|
||||
}
|
||||
|
||||
jobManager.add(StickerPackDownloadJob.forInstall(packId, packKey, notify))
|
||||
jobManager.add(StickerPackDownloadJob.forInstall(packId.value, packKey.value, notify))
|
||||
|
||||
if (SignalStore.account.hasLinkedDevices) {
|
||||
jobManager.add(MultiDeviceStickerPackOperationJob(packId, packKey, MultiDeviceStickerPackOperationJob.Type.INSTALL))
|
||||
jobManager.add(MultiDeviceStickerPackOperationJob(packId.value, packKey.value, MultiDeviceStickerPackOperationJob.Type.INSTALL))
|
||||
}
|
||||
}
|
||||
|
||||
@Discouraged("For Java use only. In Kotlin, use uninstallStickerPack() instead.")
|
||||
fun uninstallStickerPackAsync(packId: String, packKey: String) {
|
||||
coroutineScope.launch {
|
||||
uninstallStickerPack(packId, packKey)
|
||||
uninstallStickerPack(StickerPackId(packId), StickerPackKey(packKey))
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun uninstallStickerPack(packId: String, packKey: String) = withContext(Dispatchers.IO) {
|
||||
stickersDbTable.uninstallPack(packId)
|
||||
suspend fun uninstallStickerPack(packId: StickerPackId, packKey: StickerPackKey) = withContext(Dispatchers.IO) {
|
||||
stickersDbTable.uninstallPack(packId.value)
|
||||
|
||||
if (SignalStore.account.hasLinkedDevices) {
|
||||
AppDependencies.jobManager.add(MultiDeviceStickerPackOperationJob(packId, packKey, MultiDeviceStickerPackOperationJob.Type.REMOVE))
|
||||
AppDependencies.jobManager.add(MultiDeviceStickerPackOperationJob(packId.value, packKey.value, MultiDeviceStickerPackOperationJob.Type.REMOVE))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,9 +161,9 @@ object StickerManagementRepository {
|
||||
}
|
||||
}
|
||||
|
||||
data class StickerPackResult(
|
||||
data class StickerPacksResult(
|
||||
val installedPacks: List<StickerPackRecord>,
|
||||
val availablePacks: List<StickerPackRecord>,
|
||||
val blessedPacks: List<StickerPackRecord>,
|
||||
val sortOrderByPackId: Map<String, Int>
|
||||
val sortOrderByPackId: Map<StickerPackId, Int>
|
||||
)
|
||||
|
||||
@@ -17,9 +17,9 @@ import java.util.List;
|
||||
final class StickerManagementViewModel extends ViewModel {
|
||||
|
||||
private final Application application;
|
||||
private final StickerManagementRepository repository;
|
||||
private final MutableLiveData<StickerPackResult> packs;
|
||||
private final DatabaseObserver.Observer observer;
|
||||
private final StickerManagementRepository repository;
|
||||
private final MutableLiveData<StickerPacksResult> packs;
|
||||
private final DatabaseObserver.Observer observer;
|
||||
|
||||
private StickerManagementViewModel(@NonNull Application application, @NonNull StickerManagementRepository repository) {
|
||||
this.application = application;
|
||||
@@ -42,7 +42,7 @@ final class StickerManagementViewModel extends ViewModel {
|
||||
repository.deleteOrphanedStickerPacksAsync();
|
||||
}
|
||||
|
||||
@NonNull LiveData<StickerPackResult> getStickerPacks() {
|
||||
@NonNull LiveData<StickerPacksResult> getStickerPacks() {
|
||||
repository.getStickerPacks(packs::postValue);
|
||||
return packs;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.thoughtcrime.securesms.database.model.StickerPackId
|
||||
import org.thoughtcrime.securesms.database.model.StickerPackKey
|
||||
import org.thoughtcrime.securesms.database.model.StickerPackRecord
|
||||
import org.thoughtcrime.securesms.stickers.AvailableStickerPack.DownloadStatus
|
||||
|
||||
@@ -24,7 +26,7 @@ class StickerManagementViewModelV2 : ViewModel() {
|
||||
private val _uiState = MutableStateFlow(StickerManagementUiState())
|
||||
val uiState: StateFlow<StickerManagementUiState> = _uiState.asStateFlow()
|
||||
|
||||
private val downloadStatusByPackId: MutableStateFlow<Map<String, DownloadStatus>> = MutableStateFlow(emptyMap())
|
||||
private val downloadStatusByPackId: MutableStateFlow<Map<StickerPackId, DownloadStatus>> = MutableStateFlow(emptyMap())
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
@@ -42,25 +44,26 @@ class StickerManagementViewModelV2 : ViewModel() {
|
||||
private suspend fun loadStickerPacks() {
|
||||
combine(stickerManagementRepo.getStickerPacks(), downloadStatusByPackId, ::Pair)
|
||||
.collectLatest { (stickerPacksResult, downloadStatuses) ->
|
||||
val recentlyInstalledPacks = stickerPacksResult.installedPacks.filter { downloadStatuses.contains(it.packId) }
|
||||
val recentlyInstalledPacks = stickerPacksResult.installedPacks.filter { downloadStatuses.contains(StickerPackId(it.packId)) }
|
||||
val allAvailablePacks = (stickerPacksResult.blessedPacks + stickerPacksResult.availablePacks + recentlyInstalledPacks)
|
||||
.map { record ->
|
||||
val packId = StickerPackId(record.packId)
|
||||
AvailableStickerPack(
|
||||
record = record,
|
||||
isBlessed = BlessedPacks.contains(record.packId),
|
||||
downloadStatus = downloadStatuses.getOrElse(record.packId) {
|
||||
downloadStatusByPackId.value.getOrDefault(record.packId, DownloadStatus.NotDownloaded)
|
||||
downloadStatus = downloadStatuses.getOrElse(packId) {
|
||||
downloadStatusByPackId.value.getOrDefault(packId, DownloadStatus.NotDownloaded)
|
||||
}
|
||||
)
|
||||
}
|
||||
.sortedBy { stickerPacksResult.sortOrderByPackId.getValue(it.record.packId) }
|
||||
.sortedBy { stickerPacksResult.sortOrderByPackId.getValue(it.id) }
|
||||
|
||||
val (availableBlessedPacks, availableNotBlessedPacks) = allAvailablePacks.partition { it.isBlessed }
|
||||
val installedPacks = stickerPacksResult.installedPacks.map { record ->
|
||||
InstalledStickerPack(
|
||||
record = record,
|
||||
isBlessed = BlessedPacks.contains(record.packId),
|
||||
sortOrder = stickerPacksResult.sortOrderByPackId.getValue(record.packId)
|
||||
sortOrder = stickerPacksResult.sortOrderByPackId.getValue(StickerPackId(record.packId))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -75,16 +78,16 @@ class StickerManagementViewModelV2 : ViewModel() {
|
||||
}
|
||||
|
||||
fun installStickerPack(pack: AvailableStickerPack) = viewModelScope.launch {
|
||||
updatePackDownloadStatus(pack.record.packId, DownloadStatus.InProgress)
|
||||
updatePackDownloadStatus(pack.id, DownloadStatus.InProgress)
|
||||
|
||||
StickerManagementRepository.installStickerPack(packId = pack.record.packId, packKey = pack.record.packKey, notify = true)
|
||||
updatePackDownloadStatus(pack.record.packId, DownloadStatus.Downloaded)
|
||||
StickerManagementRepository.installStickerPack(packId = pack.id, packKey = pack.key, notify = true)
|
||||
updatePackDownloadStatus(pack.id, DownloadStatus.Downloaded)
|
||||
|
||||
delay(1500) // wait, so we show the downloaded status for a bit before removing this row from the available sticker packs list
|
||||
updatePackDownloadStatus(pack.record.packId, null)
|
||||
updatePackDownloadStatus(pack.id, null)
|
||||
}
|
||||
|
||||
private fun updatePackDownloadStatus(packId: String, newStatus: DownloadStatus?) {
|
||||
private fun updatePackDownloadStatus(packId: StickerPackId, newStatus: DownloadStatus?) {
|
||||
downloadStatusByPackId.value = if (newStatus == null) {
|
||||
downloadStatusByPackId.value.minus(packId)
|
||||
} else {
|
||||
@@ -93,7 +96,7 @@ class StickerManagementViewModelV2 : ViewModel() {
|
||||
}
|
||||
|
||||
fun uninstallStickerPack(pack: AvailableStickerPack) = viewModelScope.launch {
|
||||
StickerManagementRepository.uninstallStickerPack(packId = pack.record.packId, packKey = pack.record.packKey)
|
||||
StickerManagementRepository.uninstallStickerPack(packId = pack.id, packKey = pack.key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +112,9 @@ data class AvailableStickerPack(
|
||||
val isBlessed: Boolean,
|
||||
val downloadStatus: DownloadStatus
|
||||
) {
|
||||
val id = StickerPackId(record.packId)
|
||||
val key = StickerPackKey(record.packKey)
|
||||
|
||||
sealed class DownloadStatus {
|
||||
data object NotDownloaded : DownloadStatus()
|
||||
data object InProgress : DownloadStatus()
|
||||
@@ -121,4 +127,7 @@ data class InstalledStickerPack(
|
||||
val isBlessed: Boolean,
|
||||
val sortOrder: Int,
|
||||
val isSelected: Boolean = false
|
||||
)
|
||||
) {
|
||||
val id = StickerPackId(record.packId)
|
||||
val key = StickerPackKey(record.packKey)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user