feat: [DEEPLINK] add history (#248)

Co-authored-by: Florent Champigny <florent@bere.al>
This commit is contained in:
Florent CHAMPIGNY 2025-09-16 20:49:58 +02:00 committed by GitHub
parent 05045ef0b4
commit e52f5c1687
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 332 additions and 24 deletions

View file

@ -1,11 +1,13 @@
package io.github.openflocon.data.local.deeplink.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import io.github.openflocon.data.local.deeplink.models.DeeplinkEntity
import io.github.openflocon.domain.device.models.AppPackageName
import io.github.openflocon.domain.device.models.DeviceId
import kotlinx.coroutines.flow.Flow
@ -20,6 +22,7 @@ interface FloconDeeplinkDao {
DELETE FROM DeeplinkEntity
WHERE deviceId = :deviceId
AND packageName = :packageName
AND isHistory = false
""",
)
suspend fun deleteAll(deviceId: String, packageName: String)
@ -40,8 +43,45 @@ interface FloconDeeplinkDao {
FROM DeeplinkEntity
WHERE deviceId = :deviceId
AND packageName = :packageName
AND isHistory = false
ORDER BY id ASC
""",
)
fun observeAll(deviceId: String, packageName: String): Flow<List<DeeplinkEntity>>
@Query(
"""
SELECT *
FROM DeeplinkEntity
WHERE deviceId = :deviceId
AND packageName = :packageName
AND isHistory = true
ORDER BY id DESC
""",
)
fun observeHistory(deviceId: String, packageName: String): Flow<List<DeeplinkEntity>>
@Query(
"""
DELETE
FROM DeeplinkEntity
WHERE deviceId = :deviceId
AND id = :deeplinkId
AND packageName = :packageName
AND isHistory = :isHistory
""",
)
suspend fun delete(deviceId: String, packageName: String, deeplinkId: Long, isHistory: Boolean)
@Query(
"""
SELECT *
FROM DeeplinkEntity
WHERE deviceId = :deviceId
AND packageName = :packageName
AND id = :deeplinkId
LIMIT 1
""",
)
suspend fun getById(deviceId: String, packageName: String, deeplinkId: Long) : DeeplinkEntity?
}

View file

@ -2,8 +2,10 @@ package io.github.openflocon.data.local.deeplink.datasource
import io.github.openflocon.data.core.deeplink.datasource.DeeplinkLocalDataSource
import io.github.openflocon.data.local.deeplink.dao.FloconDeeplinkDao
import io.github.openflocon.data.local.deeplink.mapper.toDomainModel
import io.github.openflocon.data.local.deeplink.mapper.toDomainModels
import io.github.openflocon.data.local.deeplink.mapper.toEntities
import io.github.openflocon.data.local.deeplink.mapper.toEntity
import io.github.openflocon.domain.deeplink.models.DeeplinkDomainModel
import io.github.openflocon.domain.device.models.DeviceIdAndPackageNameDomainModel
import kotlinx.coroutines.flow.Flow
@ -13,6 +15,7 @@ import kotlinx.coroutines.flow.map
internal class LocalDeeplinkDataSourceRoom(
private val deeplinkDao: FloconDeeplinkDao,
) : DeeplinkLocalDataSource {
override suspend fun update(deviceIdAndPackageNameDomainModel: DeviceIdAndPackageNameDomainModel, deeplinks: List<DeeplinkDomainModel>) {
deeplinkDao.updateAll(
deviceId = deviceIdAndPackageNameDomainModel.deviceId,
@ -31,4 +34,45 @@ internal class LocalDeeplinkDataSourceRoom(
)
.map { toDomainModels(it) }
.distinctUntilChanged()
override fun observeHistory(deviceIdAndPackageNameDomainModel: DeviceIdAndPackageNameDomainModel): Flow<List<DeeplinkDomainModel>> =
deeplinkDao.observeHistory(
deviceId = deviceIdAndPackageNameDomainModel.deviceId,
packageName = deviceIdAndPackageNameDomainModel.packageName,
)
.map { toDomainModels(it) }
.distinctUntilChanged()
override suspend fun addToHistory(
deviceIdAndPackageName: DeviceIdAndPackageNameDomainModel,
item: DeeplinkDomainModel
) {
deeplinkDao.insert(deeplink = item.toEntity(
deviceIdAndPackageName = deviceIdAndPackageName,
isHistory = true,
))
}
override suspend fun removeFromHistory(
deviceIdAndPackageName: DeviceIdAndPackageNameDomainModel,
deeplinkId: Long,
) {
deeplinkDao.delete(
deviceId = deviceIdAndPackageName.deviceId,
packageName = deviceIdAndPackageName.packageName,
deeplinkId = deeplinkId,
isHistory = true,
)
}
override suspend fun getDeeplinkById(
deeplinkId: Long,
deviceIdAndPackageName: DeviceIdAndPackageNameDomainModel
): DeeplinkDomainModel? {
return deeplinkDao.getById(
deviceId = deviceIdAndPackageName.deviceId,
packageName = deviceIdAndPackageName.packageName,
deeplinkId = deeplinkId,
)?.toDomainModel()
}
}

View file

@ -8,10 +8,12 @@ fun DeeplinkEntity.toDomainModel(): DeeplinkDomainModel = DeeplinkDomainModel(
label = this.label,
link = this.link,
description = this.description,
id = this.id,
)
fun DeeplinkDomainModel.toEntity(
deviceIdAndPackageName: DeviceIdAndPackageNameDomainModel,
isHistory: Boolean,
): DeeplinkEntity {
// Note: L'ID sera généré automatiquement par Room lors de l'insertion,
// donc nous n'avons pas besoin de le spécifier ici si nous faisons une nouvelle insertion.
@ -22,6 +24,7 @@ fun DeeplinkDomainModel.toEntity(
label = label,
packageName = deviceIdAndPackageName.packageName,
description = description,
isHistory = isHistory,
)
}
@ -30,5 +33,5 @@ fun toDomainModels(entities: List<DeeplinkEntity>): List<DeeplinkDomainModel> =
fun toEntities(deviceIdAndPackageName: DeviceIdAndPackageNameDomainModel, deeplinks: List<DeeplinkDomainModel>): List<DeeplinkEntity> =
deeplinks.map {
it.toEntity(deviceIdAndPackageName = deviceIdAndPackageName)
it.toEntity(deviceIdAndPackageName = deviceIdAndPackageName, isHistory = false)
}

View file

@ -28,4 +28,5 @@ data class DeeplinkEntity(
val link: String,
val label: String?,
val description: String?,
val isHistory: Boolean,
)