Moves notifications to unified DB
Adds separation between layers for push notifications feature MAILAND-2742
This commit is contained in:
parent
9e515a71e1
commit
c20ef4ee34
|
@ -54,7 +54,6 @@ import ch.protonmail.android.data.local.CounterDao
|
|||
import ch.protonmail.android.data.local.CounterDatabase
|
||||
import ch.protonmail.android.data.local.MessageDao
|
||||
import ch.protonmail.android.data.local.MessageDatabase
|
||||
import ch.protonmail.android.data.local.NotificationDao
|
||||
import ch.protonmail.android.data.local.PendingActionDao
|
||||
import ch.protonmail.android.data.local.PendingActionDatabase
|
||||
import ch.protonmail.android.domain.entity.user.Address
|
||||
|
@ -64,7 +63,6 @@ import ch.protonmail.android.jobs.FetchByLocationJob
|
|||
import ch.protonmail.android.labels.presentation.ui.EXTRA_MANAGE_FOLDERS
|
||||
import ch.protonmail.android.labels.presentation.ui.LabelsManagerActivity
|
||||
import ch.protonmail.android.mailbox.data.local.ConversationDao
|
||||
import ch.protonmail.android.notifications.domain.NotificationDatabase
|
||||
import ch.protonmail.android.notifications.presentation.utils.CHANNEL_ID_EMAIL
|
||||
import ch.protonmail.android.settings.pin.PinSettingsActivity
|
||||
import ch.protonmail.android.settings.presentation.AccountSettingsActivity
|
||||
|
@ -141,7 +139,6 @@ abstract class BaseSettingsActivity : BaseConnectivityActivity() {
|
|||
var messageDao: MessageDao? = null
|
||||
var conversationDao: ConversationDao? = null
|
||||
private var searchDatabase: MessageDao? = null
|
||||
private var notificationDao: NotificationDao? = null
|
||||
var counterDao: CounterDao? = null
|
||||
var pendingActionDao: PendingActionDao? = null
|
||||
var preferences: SharedPreferences? = null
|
||||
|
@ -185,7 +182,6 @@ abstract class BaseSettingsActivity : BaseConnectivityActivity() {
|
|||
contactDao = ContactDatabase.getInstance(applicationContext, userId).getDao()
|
||||
messageDao = MessageDatabase.getInstance(applicationContext, userId).getDao()
|
||||
conversationDao = MessageDatabase.getInstance(applicationContext, userId).getConversationDao()
|
||||
notificationDao = NotificationDatabase.getInstance(applicationContext, userId).getDao()
|
||||
counterDao = CounterDatabase.getInstance(applicationContext, userId).getDao()
|
||||
pendingActionDao = PendingActionDatabase.getInstance(applicationContext, userId).getDao()
|
||||
preferences = userManager.preferencesFor(userId)
|
||||
|
@ -444,7 +440,6 @@ abstract class BaseSettingsActivity : BaseConnectivityActivity() {
|
|||
messageDao,
|
||||
searchDatabase,
|
||||
conversationDao,
|
||||
notificationDao,
|
||||
attachmentMetadataDao,
|
||||
pendingActionDao,
|
||||
true
|
||||
|
|
|
@ -27,11 +27,9 @@ import ch.protonmail.android.data.local.CounterDatabase
|
|||
import ch.protonmail.android.data.local.MessageDao
|
||||
import ch.protonmail.android.data.local.MessageDatabase
|
||||
import ch.protonmail.android.data.local.MessagePreferenceDao
|
||||
import ch.protonmail.android.data.local.NotificationDao
|
||||
import ch.protonmail.android.data.local.PendingActionDao
|
||||
import ch.protonmail.android.data.local.PendingActionDatabase
|
||||
import ch.protonmail.android.mailbox.data.local.ConversationDao
|
||||
import ch.protonmail.android.notifications.domain.NotificationDatabase
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
@ -72,10 +70,6 @@ class DatabaseProvider @Inject constructor(
|
|||
fun provideConversationDao(userId: UserId): ConversationDao =
|
||||
MessageDatabase.getInstance(context, userId).getConversationDao()
|
||||
|
||||
// Notification
|
||||
fun provideNotificationDao(userId: UserId): NotificationDao =
|
||||
NotificationDatabase.getInstance(context, userId).getDao()
|
||||
|
||||
// Pending action
|
||||
fun providePendingActionDao(userId: UserId): PendingActionDao =
|
||||
PendingActionDatabase.getInstance(context, userId).getDao()
|
||||
|
|
|
@ -28,6 +28,8 @@ import androidx.room.migration.Migration
|
|||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import ch.protonmail.android.labels.data.local.LabelDao
|
||||
import ch.protonmail.android.labels.data.local.model.LabelEntity
|
||||
import ch.protonmail.android.notifications.data.local.NotificationDao
|
||||
import ch.protonmail.android.notifications.data.local.model.NotificationEntity
|
||||
import me.proton.core.account.data.db.AccountConverters
|
||||
import me.proton.core.account.data.db.AccountDatabase
|
||||
import me.proton.core.account.data.entity.AccountEntity
|
||||
|
@ -96,6 +98,7 @@ import timber.log.Timber
|
|||
FeatureFlagEntity::class,
|
||||
// Mail
|
||||
LabelEntity::class,
|
||||
NotificationEntity::class
|
||||
],
|
||||
version = AppDatabase.version,
|
||||
exportSchema = true
|
||||
|
@ -127,6 +130,7 @@ internal abstract class AppDatabase :
|
|||
FeatureFlagDatabase {
|
||||
|
||||
abstract fun labelDao(): LabelDao
|
||||
abstract fun notificationDao(): NotificationDao
|
||||
|
||||
companion object {
|
||||
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
package ch.protonmail.android.data.local
|
||||
|
||||
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 ch.protonmail.android.data.local.model.COLUMN_NOTIFICATION_MESSAGE_ID
|
||||
import ch.protonmail.android.data.local.model.Notification
|
||||
import ch.protonmail.android.data.local.model.TABLE_NOTIFICATION
|
||||
|
||||
@Dao
|
||||
interface NotificationDao {
|
||||
|
||||
@Query("SELECT * FROM Notification WHERE message_id=:messageId")
|
||||
fun findByMessageId(messageId: String): Notification?
|
||||
|
||||
@Query("DELETE FROM Notification WHERE message_id=:messageId")
|
||||
fun deleteByMessageId(messageId: String)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertNotification(notification: Notification)
|
||||
|
||||
@Query("DELETE FROM Notification")
|
||||
fun clearNotificationCache()
|
||||
|
||||
@Query("SELECT * FROM Notification")
|
||||
fun findAllNotifications(): List<Notification>
|
||||
|
||||
@Delete
|
||||
fun deleteNotifications(notifications: List<Notification>)
|
||||
|
||||
@Query("SELECT COUNT($COLUMN_NOTIFICATION_MESSAGE_ID) FROM $TABLE_NOTIFICATION")
|
||||
fun count(): Int
|
||||
|
||||
@Transaction
|
||||
fun insertNewNotificationAndReturnAll(notification: Notification): List<Notification> {
|
||||
insertNotification(notification)
|
||||
return findAllNotifications()
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
package ch.protonmail.android.data.local.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
const val TABLE_NOTIFICATION = "Notification"
|
||||
const val COLUMN_NOTIFICATION_MESSAGE_ID = "message_id"
|
||||
const val COLUMN_NOTIFICATION_TITLE = "notification_title"
|
||||
const val COLUMN_NOTIFICATION_BODY = "notification_body"
|
||||
|
||||
@Entity(
|
||||
tableName = TABLE_NOTIFICATION,
|
||||
indices = [Index(COLUMN_NOTIFICATION_MESSAGE_ID, unique = true)]
|
||||
)
|
||||
data class Notification constructor(
|
||||
|
||||
@ColumnInfo(name = COLUMN_NOTIFICATION_MESSAGE_ID)
|
||||
var messageId: String,
|
||||
|
||||
@ColumnInfo(name = COLUMN_NOTIFICATION_TITLE)
|
||||
val notificationTitle: String,
|
||||
|
||||
@ColumnInfo(name = COLUMN_NOTIFICATION_BODY)
|
||||
val notificationBody: String
|
||||
) {
|
||||
@PrimaryKey
|
||||
var dbId: Long? = null
|
||||
}
|
|
@ -29,6 +29,8 @@ import ch.protonmail.android.labels.data.LabelRepositoryImpl
|
|||
import ch.protonmail.android.labels.domain.LabelRepository
|
||||
import ch.protonmail.android.mailbox.data.ConversationsRepositoryImpl
|
||||
import ch.protonmail.android.mailbox.domain.ConversationsRepository
|
||||
import ch.protonmail.android.notifications.data.NotificationRepositoryImpl
|
||||
import ch.protonmail.android.notifications.domain.NotificationRepository
|
||||
import ch.protonmail.android.settings.data.SharedPreferencesDeviceSettingsRepository
|
||||
import ch.protonmail.android.settings.domain.DeviceSettingsRepository
|
||||
import dagger.Binds
|
||||
|
@ -58,4 +60,7 @@ internal interface ApplicationBindsModule {
|
|||
@Binds
|
||||
fun provideCounterRepository(repo: CounterRepositoryImpl): CounterRepository
|
||||
|
||||
@Binds
|
||||
fun provideNotificationRepository(repo: NotificationRepositoryImpl): NotificationRepository
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import ch.protonmail.android.data.local.PendingActionDatabase
|
|||
import ch.protonmail.android.labels.data.local.LabelDao
|
||||
import ch.protonmail.android.mailbox.data.local.ConversationDao
|
||||
import ch.protonmail.android.mailbox.data.local.UnreadCounterDao
|
||||
import ch.protonmail.android.notifications.data.local.NotificationDao
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
@ -58,6 +59,11 @@ internal object DatabaseModule {
|
|||
appDatabase: AppDatabase
|
||||
): LabelDao = appDatabase.labelDao()
|
||||
|
||||
@Provides
|
||||
fun provideNotificationDao(
|
||||
appDatabase: AppDatabase
|
||||
): NotificationDao = appDatabase.notificationDao()
|
||||
|
||||
@Provides
|
||||
fun provideAttachmentMetadataDao(
|
||||
context: Context,
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.notifications.data
|
||||
|
||||
import ch.protonmail.android.notifications.data.local.NotificationDao
|
||||
import ch.protonmail.android.notifications.data.local.model.NotificationEntity
|
||||
import ch.protonmail.android.notifications.data.mapper.NotificationApiEntityMapper
|
||||
import ch.protonmail.android.notifications.data.mapper.NotificationEntityDomainMapper
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotification
|
||||
import ch.protonmail.android.notifications.domain.NotificationRepository
|
||||
import ch.protonmail.android.notifications.domain.model.Notification
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class NotificationRepositoryImpl @Inject constructor(
|
||||
private val notificationDao: NotificationDao,
|
||||
private val notificationApiEntityMapper: NotificationApiEntityMapper,
|
||||
private val notificationEntityDomainMapper: NotificationEntityDomainMapper
|
||||
) : NotificationRepository {
|
||||
|
||||
override suspend fun saveNotification(notification: PushNotification, userId: UserId): List<NotificationEntity> {
|
||||
notificationDao.insertOrUpdate(notificationApiEntityMapper.toEntity(notification, userId))
|
||||
return notificationDao.findAllNotifications()
|
||||
}
|
||||
|
||||
override suspend fun deleteNotification(userId: UserId, notificationId: String) {
|
||||
notificationDao.deleteByMessageId(notificationId)
|
||||
}
|
||||
|
||||
override suspend fun clearNotificationsByUserId(userId: UserId) {
|
||||
notificationDao.clearNotificationsByUserId(userId = userId.id)
|
||||
}
|
||||
|
||||
override fun clearNotifications() {
|
||||
notificationDao.clearNotifications()
|
||||
}
|
||||
|
||||
override fun findNotificationById(messageId: String): Notification? =
|
||||
notificationDao.findByMessageId(messageId)?.let {
|
||||
notificationEntityDomainMapper.toNotification(it)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
package ch.protonmail.android.notifications.data.local
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import ch.protonmail.android.notifications.data.local.model.COLUMN_NOTIFICATION_MESSAGE_ID
|
||||
import ch.protonmail.android.notifications.data.local.model.NotificationEntity
|
||||
import ch.protonmail.android.notifications.data.local.model.TABLE_NOTIFICATION
|
||||
import me.proton.core.data.room.db.BaseDao
|
||||
|
||||
@Dao
|
||||
internal abstract class NotificationDao : BaseDao<NotificationEntity>() {
|
||||
|
||||
@Query("SELECT * FROM NotificationEntity WHERE message_id=:messageId")
|
||||
abstract fun findByMessageId(messageId: String): NotificationEntity?
|
||||
|
||||
@Query("DELETE FROM NotificationEntity WHERE message_id=:messageId")
|
||||
abstract suspend fun deleteByMessageId(messageId: String)
|
||||
|
||||
@Query("DELETE FROM NotificationEntity WHERE userId=:userId")
|
||||
abstract suspend fun clearNotificationsByUserId(userId: String)
|
||||
|
||||
@Query("DELETE FROM NotificationEntity")
|
||||
abstract fun clearNotifications()
|
||||
|
||||
@Query("SELECT COUNT($COLUMN_NOTIFICATION_MESSAGE_ID) FROM $TABLE_NOTIFICATION")
|
||||
abstract fun count(): Int
|
||||
|
||||
@Query("SELECT * FROM NotificationEntity")
|
||||
abstract fun findAllNotifications(): List<NotificationEntity>
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
package ch.protonmail.android.notifications.data.local.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Index
|
||||
import ch.protonmail.android.notifications.domain.model.NotificationType
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import me.proton.core.user.data.entity.UserEntity
|
||||
|
||||
const val TABLE_NOTIFICATION = "NotificationEntity"
|
||||
internal const val COLUMN_NOTIFICATION_MESSAGE_ID = "message_id"
|
||||
internal const val COLUMN_NOTIFICATION_USER_ID = "userId"
|
||||
internal const val COLUMN_NOTIFICATION_TITLE = "notification_title"
|
||||
internal const val COLUMN_NOTIFICATION_BODY = "notification_body"
|
||||
internal const val COLUMN_NOTIFICATION_URL = "url"
|
||||
internal const val COLUMN_NOTIFICATION_TYPE = "type"
|
||||
|
||||
@Entity(
|
||||
tableName = TABLE_NOTIFICATION,
|
||||
primaryKeys = [COLUMN_NOTIFICATION_MESSAGE_ID],
|
||||
indices = [
|
||||
Index(COLUMN_NOTIFICATION_MESSAGE_ID),
|
||||
Index(COLUMN_NOTIFICATION_USER_ID)
|
||||
],
|
||||
foreignKeys = [
|
||||
ForeignKey(
|
||||
entity = UserEntity::class,
|
||||
parentColumns = [COLUMN_NOTIFICATION_USER_ID],
|
||||
childColumns = [COLUMN_NOTIFICATION_USER_ID],
|
||||
onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
]
|
||||
)
|
||||
data class NotificationEntity(
|
||||
|
||||
@ColumnInfo(name = COLUMN_NOTIFICATION_USER_ID)
|
||||
val userId: UserId,
|
||||
|
||||
@ColumnInfo(name = COLUMN_NOTIFICATION_MESSAGE_ID)
|
||||
val messageId: String,
|
||||
|
||||
@ColumnInfo(name = COLUMN_NOTIFICATION_TITLE)
|
||||
val notificationTitle: String,
|
||||
|
||||
@ColumnInfo(name = COLUMN_NOTIFICATION_BODY)
|
||||
val notificationBody: String,
|
||||
|
||||
@ColumnInfo(name = COLUMN_NOTIFICATION_URL)
|
||||
val url: String?,
|
||||
|
||||
@ColumnInfo(name = COLUMN_NOTIFICATION_TYPE)
|
||||
val type: NotificationType
|
||||
)
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.notifications.data.mapper
|
||||
|
||||
import ch.protonmail.android.notifications.data.local.model.NotificationEntity
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotification
|
||||
import ch.protonmail.android.notifications.domain.model.NotificationType
|
||||
import me.proton.core.domain.arch.Mapper
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import me.proton.core.util.kotlin.EMPTY_STRING
|
||||
import javax.inject.Inject
|
||||
|
||||
class NotificationApiEntityMapper @Inject constructor() : Mapper<PushNotification, NotificationEntity> {
|
||||
|
||||
fun toEntity(model: PushNotification, userId: UserId): NotificationEntity {
|
||||
val data = checkNotNull(model.data)
|
||||
return NotificationEntity(
|
||||
userId = userId,
|
||||
messageId = data.messageId,
|
||||
notificationTitle = data.sender?.let {
|
||||
it.senderName.ifEmpty { it.senderAddress }
|
||||
} ?: EMPTY_STRING,
|
||||
notificationBody = data.body,
|
||||
url = data.url,
|
||||
type = requireNotNull(NotificationType.fromStringOrNull(model.type)) { "Notification type is null" }
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.notifications.data.mapper
|
||||
|
||||
import ch.protonmail.android.notifications.data.local.model.NotificationEntity
|
||||
import ch.protonmail.android.notifications.domain.model.Notification
|
||||
import ch.protonmail.android.notifications.domain.model.NotificationId
|
||||
import me.proton.core.domain.arch.Mapper
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import me.proton.core.util.kotlin.EMPTY_STRING
|
||||
import javax.inject.Inject
|
||||
|
||||
class NotificationEntityDomainMapper @Inject constructor() : Mapper<NotificationEntity, Notification> {
|
||||
|
||||
fun toNotification(model: NotificationEntity) = Notification(
|
||||
id = NotificationId(model.messageId),
|
||||
notificationTitle = model.notificationTitle,
|
||||
notificationBody = model.notificationBody,
|
||||
url = model.url ?: EMPTY_STRING,
|
||||
type = model.type
|
||||
)
|
||||
|
||||
fun toEntity(model: Notification, userId: UserId) = NotificationEntity(
|
||||
messageId = model.id.value,
|
||||
userId = userId,
|
||||
notificationTitle = model.notificationTitle,
|
||||
notificationBody = model.notificationBody,
|
||||
url = model.url,
|
||||
type = model.type
|
||||
)
|
||||
}
|
|
@ -26,5 +26,6 @@ import kotlinx.serialization.Serializable
|
|||
data class PushNotification(
|
||||
@SerialName("type") val type: String,
|
||||
@SerialName("version") val version: Int,
|
||||
@SerialName("data") val data: PushNotificationData?
|
||||
@SerialName("data") val data: PushNotificationData?,
|
||||
@SerialName("action") val action: String = "message_created"
|
||||
)
|
||||
|
|
|
@ -34,5 +34,6 @@ data class PushNotificationData(
|
|||
@SerialName("badge") val badge: Int,
|
||||
@SerialName("messageId") val messageId: String,
|
||||
@SerialName("customId") val customId: String,
|
||||
@SerialName("sender") val sender: PushNotificationSender?
|
||||
@SerialName("sender") val sender: PushNotificationSender?,
|
||||
@SerialName("url") val url: String = ""
|
||||
)
|
||||
|
|
|
@ -19,19 +19,20 @@
|
|||
|
||||
package ch.protonmail.android.notifications.domain
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import ch.protonmail.android.data.local.DatabaseFactory
|
||||
import ch.protonmail.android.data.local.NotificationDao
|
||||
import ch.protonmail.android.data.local.model.Notification
|
||||
import ch.protonmail.android.notifications.data.local.model.NotificationEntity
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotification
|
||||
import ch.protonmail.android.notifications.domain.model.Notification
|
||||
import me.proton.core.domain.entity.UserId
|
||||
|
||||
@Database(entities = [Notification::class], version = 1)
|
||||
abstract class NotificationDatabase : RoomDatabase() {
|
||||
interface NotificationRepository {
|
||||
|
||||
abstract fun getDao(): NotificationDao
|
||||
suspend fun saveNotification(notification: PushNotification, userId: UserId): List<NotificationEntity>
|
||||
|
||||
companion object : DatabaseFactory<NotificationDatabase>(
|
||||
NotificationDatabase::class,
|
||||
"NotificationsDatabase.db"
|
||||
)
|
||||
suspend fun deleteNotification(userId: UserId, notificationId: String)
|
||||
|
||||
suspend fun clearNotificationsByUserId(userId: UserId)
|
||||
|
||||
fun clearNotifications()
|
||||
|
||||
fun findNotificationById(messageId: String): Notification?
|
||||
}
|
||||
|
|
|
@ -30,13 +30,11 @@ import androidx.work.OneTimeWorkRequestBuilder
|
|||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import ch.protonmail.android.api.models.DatabaseProvider
|
||||
import ch.protonmail.android.api.models.User
|
||||
import ch.protonmail.android.api.segments.event.AlarmReceiver
|
||||
import ch.protonmail.android.core.QueueNetworkUtil
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.crypto.UserCrypto
|
||||
import ch.protonmail.android.data.local.model.Notification
|
||||
import ch.protonmail.android.mailbox.presentation.ConversationModeEnabled
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotification
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotificationData
|
||||
|
@ -69,7 +67,7 @@ internal class ProcessPushNotificationDataWorker @AssistedInject constructor(
|
|||
private val alarmReceiver: AlarmReceiver,
|
||||
private val queueNetworkUtil: QueueNetworkUtil,
|
||||
private val userManager: UserManager,
|
||||
private val databaseProvider: DatabaseProvider,
|
||||
private val notificationRepository: NotificationRepository,
|
||||
private val messageRepository: MessageRepository,
|
||||
private val sessionManager: SessionManager,
|
||||
private val conversationModeEnabled: ConversationModeEnabled
|
||||
|
@ -149,7 +147,7 @@ internal class ProcessPushNotificationDataWorker @AssistedInject constructor(
|
|||
val isScheduledSnoozeEnabled = userManager.isSnoozeScheduledEnabled()
|
||||
|
||||
if (!isQuickSnoozeEnabled && (!isScheduledSnoozeEnabled || !shouldSuppressNotification())) {
|
||||
sendNotification(userId, user, messageId, notificationBody, sender, isPrimaryUser)
|
||||
sendNotification(userId, user, messageId, notificationBody, sender, pushNotification, isPrimaryUser)
|
||||
}
|
||||
|
||||
return Result.success()
|
||||
|
@ -161,13 +159,13 @@ internal class ProcessPushNotificationDataWorker @AssistedInject constructor(
|
|||
messageId: String,
|
||||
notificationBody: String,
|
||||
sender: String,
|
||||
pushNotification: PushNotification,
|
||||
isPrimaryUser: Boolean
|
||||
) {
|
||||
|
||||
// Insert current Notification in Database
|
||||
val notificationsDatabase = databaseProvider.provideNotificationDao(userId)
|
||||
val notification = Notification(messageId, sender, notificationBody)
|
||||
val notifications = notificationsDatabase.insertNewNotificationAndReturnAll(notification)
|
||||
val notifications = checkNotNull(notificationRepository.saveNotification(pushNotification, userId))
|
||||
|
||||
val message = messageRepository.getMessage(userId, messageId)
|
||||
|
||||
if (notifications.size > 1) {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.notifications.domain.model
|
||||
|
||||
data class Notification(
|
||||
val id: NotificationId,
|
||||
val notificationTitle: String,
|
||||
val notificationBody: String,
|
||||
val url: String,
|
||||
val type: NotificationType
|
||||
)
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.notifications.domain.model
|
||||
|
||||
/**
|
||||
* Entity representing a NotificationId.
|
||||
*/
|
||||
@JvmInline
|
||||
value class NotificationId(val value: String)
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.notifications.domain.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
const val NOTIFICATION_TYPE_EMAIL = "email"
|
||||
const val NOTIFICATION_TYPE_OPEN_URL = "open_url"
|
||||
|
||||
@Serializable
|
||||
enum class NotificationType(val type: String) {
|
||||
|
||||
@SerialName(NOTIFICATION_TYPE_EMAIL)
|
||||
EMAIL("email"),
|
||||
|
||||
@SerialName(NOTIFICATION_TYPE_OPEN_URL)
|
||||
OPEN_URL("open_url");
|
||||
|
||||
companion object {
|
||||
|
||||
fun fromStringOrNull(type: String): NotificationType? {
|
||||
return values().find {
|
||||
it.type == type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ import ch.protonmail.android.details.presentation.MessageDetailsActivity
|
|||
import ch.protonmail.android.domain.entity.Name
|
||||
import ch.protonmail.android.domain.entity.user.User
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxActivity
|
||||
import ch.protonmail.android.notifications.data.local.model.NotificationEntity
|
||||
import ch.protonmail.android.receivers.EXTRA_NOTIFICATION_DELETE_MESSAGE
|
||||
import ch.protonmail.android.utils.MessageUtils
|
||||
import ch.protonmail.android.utils.buildArchiveIntent
|
||||
|
@ -57,7 +58,6 @@ import me.proton.core.domain.entity.UserId
|
|||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import ch.protonmail.android.api.models.User as LegacyUser
|
||||
import ch.protonmail.android.data.local.model.Notification as RoomNotification
|
||||
|
||||
const val CHANNEL_ID_EMAIL = "emails"
|
||||
const val EXTRA_MAILBOX_LOCATION = "mailbox_location"
|
||||
|
@ -487,7 +487,7 @@ class NotificationServer @Inject constructor(
|
|||
notificationSettings: Int,
|
||||
ringtoneUri: Uri?,
|
||||
isNotificationVisibleInLockScreen: Boolean,
|
||||
unreadNotifications: List<RoomNotification>
|
||||
unreadNotifications: List<NotificationEntity>
|
||||
) {
|
||||
val contentPendingIntent = getMailboxActivityIntent(loggedInUser.id)
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ import ch.protonmail.android.data.local.MessageDatabase;
|
|||
import ch.protonmail.android.data.local.PendingActionDatabase;
|
||||
import ch.protonmail.android.data.local.model.AttachmentMetadata;
|
||||
import ch.protonmail.android.data.local.model.Message;
|
||||
import ch.protonmail.android.notifications.domain.NotificationDatabase;
|
||||
import dagger.hilt.android.AndroidEntryPoint;
|
||||
import me.proton.core.domain.entity.UserId;
|
||||
import timber.log.Timber;
|
||||
|
@ -142,7 +141,6 @@ public class AttachmentClearingService extends ProtonJobIntentService {
|
|||
Context context = this;
|
||||
ContactDatabase.Companion.deleteDatabase(context, userId);
|
||||
MessageDatabase.Factory.deleteDatabase(context, userId);
|
||||
NotificationDatabase.Companion.deleteDatabase(context, userId);
|
||||
CounterDatabase.Companion.deleteDatabase(context, userId);
|
||||
AttachmentMetadataDatabase.Companion.deleteDatabase(context, userId);
|
||||
PendingActionDatabase.Companion.deleteDatabase(context, userId);
|
||||
|
|
|
@ -22,7 +22,6 @@ package ch.protonmail.android.usecase.delete
|
|||
import android.content.Context
|
||||
import ch.protonmail.android.api.models.DatabaseProvider
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.labels.domain.LabelRepository
|
||||
import ch.protonmail.android.storage.AttachmentClearingService
|
||||
import ch.protonmail.android.storage.MessageBodyClearingService
|
||||
import ch.protonmail.android.utils.AppUtil
|
||||
|
@ -46,8 +45,7 @@ import javax.inject.Inject
|
|||
class ClearUserData @Inject constructor(
|
||||
private val context: Context,
|
||||
private val databaseProvider: DatabaseProvider,
|
||||
private val dispatchers: DispatcherProvider,
|
||||
private val labelRepository: LabelRepository
|
||||
private val dispatchers: DispatcherProvider
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(userId: UserId, alsoClearContacts: Boolean = true) {
|
||||
|
@ -61,7 +59,6 @@ class ClearUserData @Inject constructor(
|
|||
val conversationDao = runCatching { databaseProvider.provideConversationDao(userId) }.getOrNull()
|
||||
val counterDao = runCatching { databaseProvider.provideUnreadCounterDao(userId) }.getOrNull()
|
||||
|
||||
val notificationDao = runCatching { databaseProvider.provideNotificationDao(userId) }.getOrNull()
|
||||
val pendingActionDao = runCatching { databaseProvider.providePendingActionDao(userId) }.getOrNull()
|
||||
|
||||
// Ensure that all the queries run on Io thread, as some are still blocking calls
|
||||
|
@ -81,7 +78,6 @@ class ClearUserData @Inject constructor(
|
|||
clearAttachmentsCache()
|
||||
}
|
||||
conversationDao?.clear()
|
||||
notificationDao?.clearNotificationCache()
|
||||
pendingActionDao?.run {
|
||||
clearPendingSendCache()
|
||||
clearPendingUploadCache()
|
||||
|
|
|
@ -63,13 +63,11 @@ import ch.protonmail.android.data.local.ContactDao;
|
|||
import ch.protonmail.android.data.local.ContactDatabase;
|
||||
import ch.protonmail.android.data.local.MessageDao;
|
||||
import ch.protonmail.android.data.local.MessageDatabase;
|
||||
import ch.protonmail.android.data.local.NotificationDao;
|
||||
import ch.protonmail.android.data.local.PendingActionDao;
|
||||
import ch.protonmail.android.data.local.PendingActionDatabase;
|
||||
import ch.protonmail.android.events.ApiOfflineEvent;
|
||||
import ch.protonmail.android.events.ForceUpgradeEvent;
|
||||
import ch.protonmail.android.mailbox.data.local.ConversationDao;
|
||||
import ch.protonmail.android.notifications.domain.NotificationDatabase;
|
||||
import ch.protonmail.android.storage.AttachmentClearingService;
|
||||
import ch.protonmail.android.storage.MessageBodyClearingService;
|
||||
import me.proton.core.domain.entity.UserId;
|
||||
|
@ -175,7 +173,6 @@ public class AppUtil {
|
|||
ContactDatabase.Companion.getInstance(context, userId).getDao(),
|
||||
MessageDatabase.Factory.getInstance(context, userId).getDao(),
|
||||
MessageDatabase.Factory.getInstance(context, userId).getConversationDao(),
|
||||
NotificationDatabase.Companion.getInstance(context, userId).getDao(),
|
||||
AttachmentMetadataDatabase.Companion.getInstance(context, userId).getDao(),
|
||||
PendingActionDatabase.Companion.getInstance(context, userId).getDao(),
|
||||
clearDoneListener, clearContacts
|
||||
|
@ -226,19 +223,11 @@ public class AppUtil {
|
|||
notificationManager.cancelAll();
|
||||
final UserManager userManager = ((ProtonMailApplication) context.getApplicationContext()).getUserManager();
|
||||
final UserId userId = userManager.requireCurrentUserId();
|
||||
final NotificationDao notificationDao = NotificationDatabase.Companion
|
||||
.getInstance(context, userId)
|
||||
.getDao();
|
||||
new ClearNotificationsFromDatabaseTask(notificationDao).execute();
|
||||
}
|
||||
|
||||
public static void clearNotifications(Context context, UserId userId) {
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.cancel(userId.hashCode());
|
||||
final NotificationDao notificationDao = NotificationDatabase.Companion
|
||||
.getInstance(context, userId)
|
||||
.getDao();
|
||||
new ClearNotificationsFromDatabaseTask(notificationDao).execute();
|
||||
}
|
||||
|
||||
public static void clearNotifications(Context context, int notificationId) {
|
||||
|
@ -303,7 +292,6 @@ public class AppUtil {
|
|||
final MessageDao messageDao,
|
||||
final MessageDao searchDatabase,
|
||||
final ConversationDao conversationDao,
|
||||
final NotificationDao notificationDao,
|
||||
final AttachmentMetadataDao attachmentMetadataDao,
|
||||
final PendingActionDao pendingActionDao,
|
||||
final boolean clearContacts
|
||||
|
@ -314,7 +302,6 @@ public class AppUtil {
|
|||
contactDao,
|
||||
messageDao,
|
||||
conversationDao,
|
||||
notificationDao,
|
||||
attachmentMetadataDao,
|
||||
pendingActionDao,
|
||||
null,
|
||||
|
@ -329,7 +316,6 @@ public class AppUtil {
|
|||
final ContactDao contactDao,
|
||||
final MessageDao messageDao,
|
||||
final ConversationDao conversationDao,
|
||||
final NotificationDao notificationDao,
|
||||
final AttachmentMetadataDao attachmentMetadataDao,
|
||||
final PendingActionDao pendingActionDao,
|
||||
final IDBClearDone clearDone,
|
||||
|
@ -351,7 +337,6 @@ public class AppUtil {
|
|||
messageDao.clearMessagesCache();
|
||||
messageDao.clearAttachmentsCache();
|
||||
conversationDao.clear();
|
||||
notificationDao.clearNotificationCache();
|
||||
attachmentMetadataDao.clearAttachmentMetadataCache();
|
||||
return null;
|
||||
}
|
||||
|
@ -392,38 +377,6 @@ public class AppUtil {
|
|||
backupSharedPrefs.edit().clear().apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes user's Secure Shared Preferences and preserves some important values.
|
||||
*/
|
||||
public static void deleteSecurePrefs(
|
||||
@NonNull SharedPreferences userPreferences,
|
||||
boolean deletePin
|
||||
) {
|
||||
String mailboxPinBackup = userPreferences.getString(PREF_PIN, null);
|
||||
SharedPreferences.Editor editor = userPreferences.edit()
|
||||
.clear();
|
||||
if (!deletePin) {
|
||||
editor.putString(PREF_PIN, mailboxPinBackup);
|
||||
}
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
// TODO: Rewrite with coroutines after the whole AppUtil file is converted to Kotlin
|
||||
private static class ClearNotificationsFromDatabaseTask extends AsyncTask<Void, Void, Void> {
|
||||
private final NotificationDao notificationDao;
|
||||
|
||||
ClearNotificationsFromDatabaseTask(
|
||||
NotificationDao notificationDao) {
|
||||
this.notificationDao = notificationDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
notificationDao.clearNotificationCache();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IDBClearDone {
|
||||
void onDatabaseClearingCompleted();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.notifications.data.mapper
|
||||
|
||||
import ch.protonmail.android.notifications.data.local.model.NotificationEntity
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotification
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotificationData
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotificationSender
|
||||
import ch.protonmail.android.notifications.domain.model.NotificationType
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
internal class NotificationEntityApiMapperTest {
|
||||
|
||||
private val testUserId = UserId("TestUserId")
|
||||
private val notificationMapper = NotificationApiEntityMapper()
|
||||
|
||||
@Test
|
||||
fun `mapping notification api model to NotificationEntity succeeds when all fields are valid`() {
|
||||
// given
|
||||
val pushNotification = getTestNotificationApiModel(testId = "ID")
|
||||
|
||||
// when
|
||||
val actual = notificationMapper.toEntity(pushNotification, testUserId)
|
||||
|
||||
// then
|
||||
val expected = getTestNotificationEntity(testUserId, testId = "ID")
|
||||
Assert.assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
private fun getTestNotificationApiModel(testId: String) = PushNotification(
|
||||
type = "email",
|
||||
version = 2,
|
||||
data = getTestNotificationDataApiModel(testId),
|
||||
action = "message_created"
|
||||
)
|
||||
|
||||
private fun getTestNotificationDataApiModel(testId: String) = PushNotificationData(
|
||||
title = "ProtonMail",
|
||||
subtitle = "",
|
||||
body = "subject",
|
||||
vibrate = 1,
|
||||
sound = 1,
|
||||
largeIcon = "large_icon",
|
||||
smallIcon = "small_icon",
|
||||
badge = 123,
|
||||
messageId = testId,
|
||||
customId = "123-abc",
|
||||
sender = PushNotificationSender("testUser@protonmail.com", "testUser", ""),
|
||||
url = "https://www.example.com/"
|
||||
)
|
||||
|
||||
private fun getTestNotificationEntity(userId: UserId, testId: String) = NotificationEntity(
|
||||
userId = userId,
|
||||
messageId = testId,
|
||||
notificationTitle = "testUser",
|
||||
notificationBody = "subject",
|
||||
url = "https://www.example.com/",
|
||||
type = NotificationType.EMAIL
|
||||
)
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonMail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.notifications.data.mapper
|
||||
|
||||
import ch.protonmail.android.notifications.data.local.model.NotificationEntity
|
||||
import ch.protonmail.android.notifications.domain.model.Notification
|
||||
import ch.protonmail.android.notifications.domain.model.NotificationId
|
||||
import ch.protonmail.android.notifications.domain.model.NotificationType
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
internal class NotificationEntityDomainMapperTest {
|
||||
|
||||
private val testUserId = UserId("TestUserId")
|
||||
private val notificationMapper = NotificationEntityDomainMapper()
|
||||
|
||||
@Test
|
||||
fun `mapping NotificationEntity to Notification`() {
|
||||
// given
|
||||
val notificationEntity = getTestNotificationEntity(userId = testUserId, testId = "ID")
|
||||
|
||||
// when
|
||||
val actual = notificationMapper.toNotification(notificationEntity)
|
||||
|
||||
// then
|
||||
val expected = getTestNotification(testId = "ID")
|
||||
Assert.assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `mapping Notification to NotificationEntity`() {
|
||||
// given
|
||||
val notification = getTestNotification(testId = "ID")
|
||||
|
||||
// when
|
||||
val actual = notificationMapper.toEntity(notification, userId = testUserId)
|
||||
|
||||
// then
|
||||
val expected = getTestNotificationEntity(userId = testUserId, testId = "ID")
|
||||
Assert.assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
private fun getTestNotificationEntity(userId: UserId, testId: String) = NotificationEntity(
|
||||
userId = userId,
|
||||
messageId = testId,
|
||||
notificationTitle = "testUser",
|
||||
notificationBody = "subject",
|
||||
url = "https://www.example.com/",
|
||||
type = NotificationType.EMAIL
|
||||
)
|
||||
|
||||
private fun getTestNotification(testId: String) = Notification(
|
||||
id = NotificationId(testId),
|
||||
notificationTitle = "testUser",
|
||||
notificationBody = "subject",
|
||||
url = "https://www.example.com/",
|
||||
type = NotificationType.EMAIL
|
||||
)
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.notifications.data.remote.fcm
|
||||
package ch.protonmail.android.notifications.domain
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.ListenableWorker
|
||||
|
@ -25,22 +25,17 @@ import androidx.work.OneTimeWorkRequest
|
|||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import ch.protonmail.android.api.models.DatabaseProvider
|
||||
import ch.protonmail.android.api.models.User
|
||||
import ch.protonmail.android.api.segments.event.AlarmReceiver
|
||||
import ch.protonmail.android.core.QueueNetworkUtil
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.crypto.UserCrypto
|
||||
import ch.protonmail.android.data.local.model.Message
|
||||
import ch.protonmail.android.data.local.model.Notification
|
||||
import ch.protonmail.android.mailbox.presentation.ConversationModeEnabled
|
||||
import ch.protonmail.android.notifications.data.local.model.NotificationEntity
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotification
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotificationData
|
||||
import ch.protonmail.android.notifications.data.remote.model.PushNotificationSender
|
||||
import ch.protonmail.android.notifications.domain.KEY_PROCESS_PUSH_NOTIFICATION_DATA_ERROR
|
||||
import ch.protonmail.android.notifications.domain.KEY_PUSH_NOTIFICATION_ENCRYPTED_MESSAGE
|
||||
import ch.protonmail.android.notifications.domain.KEY_PUSH_NOTIFICATION_UID
|
||||
import ch.protonmail.android.notifications.domain.ProcessPushNotificationDataWorker
|
||||
import ch.protonmail.android.notifications.presentation.utils.NotificationServer
|
||||
import ch.protonmail.android.repository.MessageRepository
|
||||
import ch.protonmail.android.utils.AppUtil
|
||||
|
@ -94,7 +89,7 @@ class ProcessPushNotificationDataWorkerTest {
|
|||
|
||||
private val alarmReceiver: AlarmReceiver = mockk(relaxed = true)
|
||||
|
||||
private val databaseProvider: DatabaseProvider = mockk(relaxed = true)
|
||||
private val notificationRepository: NotificationRepository = mockk(relaxed = true)
|
||||
|
||||
private val messageRepository: MessageRepository = mockk(relaxed = true)
|
||||
|
||||
|
@ -114,7 +109,7 @@ class ProcessPushNotificationDataWorkerTest {
|
|||
alarmReceiver,
|
||||
queueNetworkUtil,
|
||||
userManager,
|
||||
databaseProvider,
|
||||
notificationRepository,
|
||||
messageRepository,
|
||||
sessionManager,
|
||||
conversationModeEnabled
|
||||
|
@ -398,10 +393,8 @@ class ProcessPushNotificationDataWorkerTest {
|
|||
// given
|
||||
mockForCallingSendNotificationSuccessfully()
|
||||
|
||||
val mockNotification = mockk<Notification>()
|
||||
every { databaseProvider.provideNotificationDao(testId) } returns mockk(relaxed = true) {
|
||||
every { insertNewNotificationAndReturnAll(any()) } returns listOf(mockNotification)
|
||||
}
|
||||
val mockNotification = mockk<NotificationEntity>()
|
||||
coEvery { notificationRepository.saveNotification(any(), any()) } returns listOf(mockNotification)
|
||||
val mockMessage = mockk<Message>()
|
||||
coEvery { messageRepository.getMessage(testId, "messageId") } returns mockMessage
|
||||
every {
|
||||
|
@ -460,12 +453,10 @@ class ProcessPushNotificationDataWorkerTest {
|
|||
// given
|
||||
mockForCallingSendNotificationSuccessfully()
|
||||
|
||||
val mockNotification1 = mockk<Notification>()
|
||||
val mockNotification2 = mockk<Notification>()
|
||||
val mockNotification1 = mockk<NotificationEntity>()
|
||||
val mockNotification2 = mockk<NotificationEntity>()
|
||||
val unreadNotifications = listOf(mockNotification1, mockNotification2)
|
||||
every { databaseProvider.provideNotificationDao(testId) } returns mockk(relaxed = true) {
|
||||
every { insertNewNotificationAndReturnAll(any()) } returns unreadNotifications
|
||||
}
|
||||
coEvery { notificationRepository.saveNotification(any(), any()) } returns unreadNotifications
|
||||
val mockMessage = mockk<Message>()
|
||||
coEvery { messageRepository.getMessage(testId, "messageId") } returns mockMessage
|
||||
every { notificationServer.notifyMultipleUnreadEmail(any(), any(), any(), any(), any()) } just runs
|
||||
|
@ -475,7 +466,7 @@ class ProcessPushNotificationDataWorkerTest {
|
|||
|
||||
// then
|
||||
val userSlot = slot<ch.protonmail.android.domain.entity.user.User>()
|
||||
val unreadNotificationsSlot = slot<List<Notification>>()
|
||||
val unreadNotificationsSlot = slot<List<NotificationEntity>>()
|
||||
verify {
|
||||
notificationServer.notifyMultipleUnreadEmail(
|
||||
capture(userSlot),
|
||||
|
@ -496,10 +487,8 @@ class ProcessPushNotificationDataWorkerTest {
|
|||
// given
|
||||
mockForCallingSendNotificationSuccessfully()
|
||||
|
||||
val mockNotification = mockk<Notification>()
|
||||
every { databaseProvider.provideNotificationDao(testId) } returns mockk(relaxed = true) {
|
||||
every { insertNewNotificationAndReturnAll(any()) } returns listOf(mockNotification)
|
||||
}
|
||||
val mockNotification = mockk<NotificationEntity>()
|
||||
coEvery { notificationRepository.saveNotification(any(), any()) } returns listOf(mockNotification)
|
||||
val mockMessage = mockk<Message>()
|
||||
coEvery { messageRepository.getMessage(testId, "messageId") } returns mockMessage
|
||||
every { notificationServer.notifySingleNewEmail(any(), any(), any(), any(), any(), any(), any()) } just runs
|
||||
|
@ -513,4 +502,4 @@ class ProcessPushNotificationDataWorkerTest {
|
|||
assertEquals(expectedResult, workerResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue