ntfy-android/app/src/main/java/io/heckel/ntfy/db/Repository.kt

568 lines
20 KiB
Kotlin
Raw Normal View History

2022-01-19 08:28:48 +13:00
package io.heckel.ntfy.db
2021-10-27 13:34:09 +13:00
import android.content.Context
2021-11-23 09:45:43 +13:00
import android.content.SharedPreferences
2022-11-30 16:46:38 +13:00
import android.media.MediaPlayer
import android.os.Build
2021-10-30 14:13:58 +13:00
import androidx.annotation.WorkerThread
2022-01-20 15:05:41 +13:00
import androidx.appcompat.app.AppCompatDelegate
2021-11-15 15:42:41 +13:00
import androidx.lifecycle.*
import io.heckel.ntfy.util.Log
2022-02-13 13:43:42 +13:00
import io.heckel.ntfy.util.validUrl
2021-11-15 15:42:41 +13:00
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicLong
2021-10-27 15:41:19 +13:00
2022-01-28 13:57:43 +13:00
class Repository(private val sharedPrefs: SharedPreferences, private val database: Database) {
private val subscriptionDao = database.subscriptionDao()
private val notificationDao = database.notificationDao()
private val userDao = database.userDao()
2021-11-15 15:42:41 +13:00
private val connectionStates = ConcurrentHashMap<Long, ConnectionState>()
private val connectionStatesLiveData = MutableLiveData(connectionStates)
2022-11-30 16:46:38 +13:00
// TODO Move these into an ApplicationState singleton
val detailViewSubscriptionId = AtomicLong(0L) // Omg, what a hack ...
2022-11-30 16:46:38 +13:00
val mediaPlayer = MediaPlayer()
2021-11-15 15:42:41 +13:00
init {
Log.d(TAG, "Created $this")
}
fun getSubscriptionsLiveData(): LiveData<List<Subscription>> {
return subscriptionDao
.listFlow()
.asLiveData()
2021-11-15 15:42:41 +13:00
.combineWith(connectionStatesLiveData) { subscriptionsWithMetadata, _ ->
toSubscriptionList(subscriptionsWithMetadata.orEmpty())
}
}
fun getSubscriptionIdsWithInstantStatusLiveData(): LiveData<Set<Pair<Long, Boolean>>> {
2021-11-14 13:26:37 +13:00
return subscriptionDao
.listFlow()
.asLiveData()
.map { list -> list.map { Pair(it.id, it.instant) }.toSet() }
2021-11-14 13:26:37 +13:00
}
2022-03-15 10:10:44 +13:00
suspend fun getSubscriptions(): List<Subscription> {
return toSubscriptionList(subscriptionDao.list())
2021-10-27 15:41:19 +13:00
}
2022-03-15 10:10:44 +13:00
suspend fun getSubscriptionIdsWithInstantStatus(): Set<Pair<Long, Boolean>> {
2021-12-30 11:48:06 +13:00
return subscriptionDao
.list()
.map { Pair(it.id, it.instant) }.toSet()
}
fun getSubscription(subscriptionId: Long): Subscription? {
return toSubscription(subscriptionDao.get(subscriptionId))
}
2021-10-30 14:13:58 +13:00
@Suppress("RedundantSuspendModifier")
@WorkerThread
2021-11-01 08:19:25 +13:00
suspend fun getSubscription(baseUrl: String, topic: String): Subscription? {
return toSubscription(subscriptionDao.get(baseUrl, topic))
2021-10-27 13:34:09 +13:00
}
2021-10-30 14:13:58 +13:00
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun getSubscriptionByConnectorToken(connectorToken: String): Subscription? {
return toSubscription(subscriptionDao.getByConnectorToken(connectorToken))
}
@Suppress("RedundantSuspendModifier")
2021-10-30 14:13:58 +13:00
@WorkerThread
2021-11-01 08:19:25 +13:00
suspend fun addSubscription(subscription: Subscription) {
2021-10-30 14:13:58 +13:00
subscriptionDao.add(subscription)
2021-10-27 13:34:09 +13:00
}
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun updateSubscription(subscription: Subscription) {
subscriptionDao.update(subscription)
}
2021-10-30 14:13:58 +13:00
@Suppress("RedundantSuspendModifier")
@WorkerThread
2021-11-01 08:19:25 +13:00
suspend fun removeSubscription(subscriptionId: Long) {
subscriptionDao.remove(subscriptionId)
}
2022-03-15 10:10:44 +13:00
suspend fun getNotifications(): List<Notification> {
return notificationDao.list()
}
fun getDeletedNotificationsWithAttachments(): List<Notification> {
return notificationDao.listDeletedWithAttachments()
}
fun getActiveIconUris(): Set<String> {
return notificationDao.listActiveIconUris().toSet()
}
fun clearIconUri(uri: String) {
notificationDao.clearIconUri(uri)
2022-07-17 08:32:09 +12:00
}
fun getNotificationsLiveData(subscriptionId: Long): LiveData<List<Notification>> {
2021-11-23 09:45:43 +13:00
return notificationDao.listFlow(subscriptionId).asLiveData()
}
fun clearAllNotificationIds(subscriptionId: Long) {
return notificationDao.clearAllNotificationIds(subscriptionId)
2021-11-01 08:19:25 +13:00
}
2021-11-15 14:22:02 +13:00
fun getNotification(notificationId: String): Notification? {
return notificationDao.get(notificationId)
}
fun onlyNewNotifications(subscriptionId: Long, notifications: List<Notification>): List<Notification> {
val existingIds = notificationDao.listIds(subscriptionId)
return notifications.filterNot { existingIds.contains(it.id) }
2021-11-08 07:13:32 +13:00
}
2021-11-01 08:19:25 +13:00
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun addNotification(notification: Notification): Boolean {
val maybeExistingNotification = notificationDao.get(notification.id)
if (maybeExistingNotification != null) {
return false
}
2022-06-19 13:01:05 +12:00
subscriptionDao.updateLastNotificationId(notification.subscriptionId, notification.id)
notificationDao.add(notification)
return true
2021-11-23 09:45:43 +13:00
}
2022-01-06 13:05:57 +13:00
fun updateNotification(notification: Notification) {
notificationDao.update(notification)
}
2022-02-06 15:02:05 +13:00
fun undeleteNotification(notificationId: String) {
notificationDao.undelete(notificationId)
}
fun markAsDeleted(notificationId: String) {
notificationDao.markAsDeleted(notificationId)
}
fun markAllAsDeleted(subscriptionId: Long) {
notificationDao.markAllAsDeleted(subscriptionId)
2021-11-01 08:19:25 +13:00
}
2022-05-06 08:56:06 +12:00
fun markAsDeletedIfOlderThan(subscriptionId: Long, olderThanTimestamp: Long) {
notificationDao.markAsDeletedIfOlderThan(subscriptionId, olderThanTimestamp)
}
2022-05-06 08:56:06 +12:00
fun removeNotificationsIfOlderThan(subscriptionId: Long, olderThanTimestamp: Long) {
notificationDao.removeIfOlderThan(subscriptionId, olderThanTimestamp)
}
2021-11-01 08:19:25 +13:00
fun removeAllNotifications(subscriptionId: Long) {
notificationDao.removeAll(subscriptionId)
2021-10-27 13:34:09 +13:00
}
2022-01-28 13:57:43 +13:00
suspend fun getUsers(): List<User> {
return userDao.list()
}
2022-03-15 10:10:44 +13:00
fun getUsersLiveData(): LiveData<List<User>> {
return userDao.listFlow().asLiveData()
}
2022-01-28 13:57:43 +13:00
suspend fun addUser(user: User) {
2022-01-30 16:25:39 +13:00
userDao.insert(user)
}
suspend fun updateUser(user: User) {
userDao.update(user)
2022-01-28 13:57:43 +13:00
}
suspend fun getUser(baseUrl: String): User? {
return userDao.get(baseUrl)
2022-01-28 13:57:43 +13:00
}
suspend fun deleteUser(baseUrl: String) {
userDao.delete(baseUrl)
2022-01-30 16:25:39 +13:00
}
2021-11-23 09:45:43 +13:00
fun getPollWorkerVersion(): Int {
return sharedPrefs.getInt(SHARED_PREFS_POLL_WORKER_VERSION, 0)
}
fun setPollWorkerVersion(version: Int) {
sharedPrefs.edit()
.putInt(SHARED_PREFS_POLL_WORKER_VERSION, version)
.apply()
}
fun getDeleteWorkerVersion(): Int {
return sharedPrefs.getInt(SHARED_PREFS_DELETE_WORKER_VERSION, 0)
}
fun setDeleteWorkerVersion(version: Int) {
sharedPrefs.edit()
.putInt(SHARED_PREFS_DELETE_WORKER_VERSION, version)
.apply()
}
2021-12-14 14:54:36 +13:00
fun getAutoRestartWorkerVersion(): Int {
return sharedPrefs.getInt(SHARED_PREFS_AUTO_RESTART_WORKER_VERSION, 0)
}
fun setAutoRestartWorkerVersion(version: Int) {
sharedPrefs.edit()
.putInt(SHARED_PREFS_AUTO_RESTART_WORKER_VERSION, version)
.apply()
}
fun setMinPriority(minPriority: Int) {
2022-05-06 08:56:06 +12:00
if (minPriority <= MIN_PRIORITY_ANY) {
sharedPrefs.edit()
.remove(SHARED_PREFS_MIN_PRIORITY)
.apply()
} else {
sharedPrefs.edit()
.putInt(SHARED_PREFS_MIN_PRIORITY, minPriority)
.apply()
}
}
fun getMinPriority(): Int {
2022-05-06 08:56:06 +12:00
return sharedPrefs.getInt(SHARED_PREFS_MIN_PRIORITY, MIN_PRIORITY_ANY)
}
2022-01-12 13:37:34 +13:00
fun getAutoDownloadMaxSize(): Long {
val defaultValue = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
AUTO_DOWNLOAD_NEVER // Need to request permission on older versions
} else {
AUTO_DOWNLOAD_DEFAULT
}
return sharedPrefs.getLong(SHARED_PREFS_AUTO_DOWNLOAD_MAX_SIZE, defaultValue)
}
2022-01-12 13:37:34 +13:00
fun setAutoDownloadMaxSize(maxSize: Long) {
sharedPrefs.edit()
2022-01-12 13:37:34 +13:00
.putLong(SHARED_PREFS_AUTO_DOWNLOAD_MAX_SIZE, maxSize)
.apply()
}
fun getAutoDeleteSeconds(): Long {
return sharedPrefs.getLong(SHARED_PREFS_AUTO_DELETE_SECONDS, AUTO_DELETE_DEFAULT_SECONDS)
}
fun setAutoDeleteSeconds(seconds: Long) {
sharedPrefs.edit()
.putLong(SHARED_PREFS_AUTO_DELETE_SECONDS, seconds)
.apply()
}
2022-01-20 15:05:41 +13:00
fun setDarkMode(mode: Int) {
if (mode == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) {
sharedPrefs.edit()
.remove(SHARED_PREFS_DARK_MODE)
.apply()
} else {
sharedPrefs.edit()
.putInt(SHARED_PREFS_DARK_MODE, mode)
.apply()
}
}
fun getDarkMode(): Int {
return sharedPrefs.getInt(SHARED_PREFS_DARK_MODE, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
2022-01-16 12:40:38 +13:00
fun setConnectionProtocol(connectionProtocol: String) {
2022-03-21 08:04:26 +13:00
sharedPrefs.edit()
.putString(SHARED_PREFS_CONNECTION_PROTOCOL, connectionProtocol)
.apply()
2022-01-16 12:40:38 +13:00
}
fun getConnectionProtocol(): String {
return sharedPrefs.getString(SHARED_PREFS_CONNECTION_PROTOCOL, null) ?: CONNECTION_PROTOCOL_JSONHTTP
}
fun getBroadcastEnabled(): Boolean {
return sharedPrefs.getBoolean(SHARED_PREFS_BROADCAST_ENABLED, true) // Enabled by default
}
fun setBroadcastEnabled(enabled: Boolean) {
sharedPrefs.edit()
.putBoolean(SHARED_PREFS_BROADCAST_ENABLED, enabled)
.apply()
}
2021-12-31 13:34:25 +13:00
2023-03-04 08:15:38 +13:00
fun getUnifiedPushEnabled(): Boolean {
return sharedPrefs.getBoolean(SHARED_PREFS_UNIFIEDPUSH_ENABLED, true) // Enabled by default
2023-03-04 03:57:36 +13:00
}
2023-03-04 08:15:38 +13:00
fun setUnifiedPushEnabled(enabled: Boolean) {
2023-03-04 03:57:36 +13:00
sharedPrefs.edit()
2023-03-04 08:15:38 +13:00
.putBoolean(SHARED_PREFS_UNIFIEDPUSH_ENABLED, enabled)
2023-03-04 03:57:36 +13:00
.apply()
}
2022-11-30 16:46:38 +13:00
fun getInsistentMaxPriorityEnabled(): Boolean {
return sharedPrefs.getBoolean(SHARED_PREFS_INSISTENT_MAX_PRIORITY_ENABLED, false) // Disabled by default
}
fun setInsistentMaxPriorityEnabled(enabled: Boolean) {
sharedPrefs.edit()
.putBoolean(SHARED_PREFS_INSISTENT_MAX_PRIORITY_ENABLED, enabled)
.apply()
}
fun getRecordLogs(): Boolean {
return sharedPrefs.getBoolean(SHARED_PREFS_RECORD_LOGS_ENABLED, false) // Disabled by default
}
fun setRecordLogsEnabled(enabled: Boolean) {
sharedPrefs.edit()
.putBoolean(SHARED_PREFS_RECORD_LOGS_ENABLED, enabled)
.apply()
}
2022-01-19 10:49:00 +13:00
fun getBatteryOptimizationsRemindTime(): Long {
return sharedPrefs.getLong(SHARED_PREFS_BATTERY_OPTIMIZATIONS_REMIND_TIME, BATTERY_OPTIMIZATIONS_REMIND_TIME_ALWAYS)
}
fun setBatteryOptimizationsRemindTime(timeMillis: Long) {
sharedPrefs.edit()
.putLong(SHARED_PREFS_BATTERY_OPTIMIZATIONS_REMIND_TIME, timeMillis)
.apply()
}
2022-06-20 06:19:27 +12:00
fun getWebSocketRemindTime(): Long {
return sharedPrefs.getLong(SHARED_PREFS_WEBSOCKET_REMIND_TIME, WEBSOCKET_REMIND_TIME_ALWAYS)
2022-03-17 15:41:27 +13:00
}
2022-06-20 06:19:27 +12:00
fun setWebSocketRemindTime(timeMillis: Long) {
2022-03-17 15:41:27 +13:00
sharedPrefs.edit()
2022-06-20 06:19:27 +12:00
.putLong(SHARED_PREFS_WEBSOCKET_REMIND_TIME, timeMillis)
2022-03-17 15:41:27 +13:00
.apply()
}
2022-02-15 16:49:06 +13:00
fun getDefaultBaseUrl(): String? {
return sharedPrefs.getString(SHARED_PREFS_DEFAULT_BASE_URL, null) ?:
sharedPrefs.getString(SHARED_PREFS_UNIFIED_PUSH_BASE_URL, null) // Fall back to UP URL, removed when default is set!
2022-02-15 16:49:06 +13:00
}
fun setDefaultBaseUrl(baseUrl: String) {
if (baseUrl == "") {
sharedPrefs
.edit()
.remove(SHARED_PREFS_UNIFIED_PUSH_BASE_URL) // Remove legacy key
2022-02-15 16:49:06 +13:00
.remove(SHARED_PREFS_DEFAULT_BASE_URL)
.apply()
} else {
sharedPrefs.edit()
.remove(SHARED_PREFS_UNIFIED_PUSH_BASE_URL) // Remove legacy key
2022-02-15 16:49:06 +13:00
.putString(SHARED_PREFS_DEFAULT_BASE_URL, baseUrl)
.apply()
}
}
fun isGlobalMuted(): Boolean {
2021-11-23 09:45:43 +13:00
val mutedUntil = getGlobalMutedUntil()
return mutedUntil == 1L || (mutedUntil > 1L && mutedUntil > System.currentTimeMillis()/1000)
}
fun getGlobalMutedUntil(): Long {
return sharedPrefs.getLong(SHARED_PREFS_MUTED_UNTIL_TIMESTAMP, 0L)
}
fun setGlobalMutedUntil(mutedUntilTimestamp: Long) {
sharedPrefs.edit()
.putLong(SHARED_PREFS_MUTED_UNTIL_TIMESTAMP, mutedUntilTimestamp)
.apply()
}
fun checkGlobalMutedUntil(): Boolean {
val mutedUntil = sharedPrefs.getLong(SHARED_PREFS_MUTED_UNTIL_TIMESTAMP, 0L)
val expired = mutedUntil > 1L && System.currentTimeMillis()/1000 > mutedUntil
if (expired) {
sharedPrefs.edit()
.putLong(SHARED_PREFS_MUTED_UNTIL_TIMESTAMP, 0L)
.apply()
return true
}
return false
}
2022-02-13 13:43:42 +13:00
fun getLastShareTopics(): List<String> {
val topics = sharedPrefs.getString(SHARED_PREFS_LAST_TOPICS, "") ?: ""
return topics.split("\n").filter { validUrl(it) }
}
fun addLastShareTopic(topic: String) {
2022-02-13 17:02:42 +13:00
val topics = (getLastShareTopics().filterNot { it == topic } + topic).takeLast(LAST_TOPICS_COUNT)
2022-02-13 13:43:42 +13:00
sharedPrefs.edit()
.putString(SHARED_PREFS_LAST_TOPICS, topics.joinToString(separator = "\n"))
.apply()
}
private fun toSubscriptionList(list: List<SubscriptionWithMetadata>): List<Subscription> {
return list.map { s ->
2021-11-15 15:42:41 +13:00
val connectionState = connectionStates.getOrElse(s.id) { ConnectionState.NOT_APPLICABLE }
Subscription(
id = s.id,
baseUrl = s.baseUrl,
topic = s.topic,
2021-11-14 13:26:37 +13:00
instant = s.instant,
dedicatedChannels = s.dedicatedChannels,
2021-11-22 08:54:13 +13:00
mutedUntil = s.mutedUntil,
2022-05-06 08:56:06 +12:00
minPriority = s.minPriority,
autoDelete = s.autoDelete,
insistent = s.insistent,
2022-06-19 13:01:05 +12:00
lastNotificationId = s.lastNotificationId,
2022-05-07 13:03:15 +12:00
icon = s.icon,
2021-12-30 08:33:17 +13:00
upAppId = s.upAppId,
upConnectorToken = s.upConnectorToken,
displayName = s.displayName,
totalCount = s.totalCount,
newCount = s.newCount,
lastActive = s.lastActive,
2021-11-15 15:42:41 +13:00
state = connectionState
)
}
}
private fun toSubscription(s: SubscriptionWithMetadata?): Subscription? {
if (s == null) {
return null
}
return Subscription(
id = s.id,
baseUrl = s.baseUrl,
topic = s.topic,
2021-11-14 13:26:37 +13:00
instant = s.instant,
dedicatedChannels = s.dedicatedChannels,
2021-11-22 08:54:13 +13:00
mutedUntil = s.mutedUntil,
2022-05-06 08:56:06 +12:00
minPriority = s.minPriority,
autoDelete = s.autoDelete,
insistent = s.insistent,
2022-06-19 13:01:05 +12:00
lastNotificationId = s.lastNotificationId,
2022-05-07 13:03:15 +12:00
icon = s.icon,
2021-12-30 08:33:17 +13:00
upAppId = s.upAppId,
upConnectorToken = s.upConnectorToken,
displayName = s.displayName,
totalCount = s.totalCount,
newCount = s.newCount,
lastActive = s.lastActive,
2021-11-15 15:42:41 +13:00
state = getState(s.id)
)
}
2021-11-17 08:08:52 +13:00
fun updateState(subscriptionIds: Collection<Long>, newState: ConnectionState) {
var changed = false
subscriptionIds.forEach { subscriptionId ->
val state = connectionStates.getOrElse(subscriptionId) { ConnectionState.NOT_APPLICABLE }
if (state !== newState) {
changed = true
if (newState == ConnectionState.NOT_APPLICABLE) {
connectionStates.remove(subscriptionId)
} else {
connectionStates[subscriptionId] = newState
}
2021-11-15 15:42:41 +13:00
}
2021-11-17 08:08:52 +13:00
}
if (changed) {
2021-11-15 15:42:41 +13:00
connectionStatesLiveData.postValue(connectionStates)
}
}
private fun getState(subscriptionId: Long): ConnectionState {
return connectionStatesLiveData.value!!.getOrElse(subscriptionId) { ConnectionState.NOT_APPLICABLE }
}
2021-10-27 13:34:09 +13:00
companion object {
2021-11-23 09:45:43 +13:00
const val SHARED_PREFS_ID = "MainPreferences"
const val SHARED_PREFS_POLL_WORKER_VERSION = "PollWorkerVersion"
const val SHARED_PREFS_DELETE_WORKER_VERSION = "DeleteWorkerVersion"
2021-12-14 14:54:36 +13:00
const val SHARED_PREFS_AUTO_RESTART_WORKER_VERSION = "AutoRestartWorkerVersion"
2021-11-23 09:45:43 +13:00
const val SHARED_PREFS_MUTED_UNTIL_TIMESTAMP = "MutedUntil"
const val SHARED_PREFS_MIN_PRIORITY = "MinPriority"
2022-01-12 13:37:34 +13:00
const val SHARED_PREFS_AUTO_DOWNLOAD_MAX_SIZE = "AutoDownload"
const val SHARED_PREFS_AUTO_DELETE_SECONDS = "AutoDelete"
2022-01-16 12:40:38 +13:00
const val SHARED_PREFS_CONNECTION_PROTOCOL = "ConnectionProtocol"
2022-01-20 15:05:41 +13:00
const val SHARED_PREFS_DARK_MODE = "DarkMode"
const val SHARED_PREFS_BROADCAST_ENABLED = "BroadcastEnabled"
2023-03-04 08:15:38 +13:00
const val SHARED_PREFS_UNIFIEDPUSH_ENABLED = "UnifiedPushEnabled"
2022-11-30 16:46:38 +13:00
const val SHARED_PREFS_INSISTENT_MAX_PRIORITY_ENABLED = "InsistentMaxPriority"
const val SHARED_PREFS_RECORD_LOGS_ENABLED = "RecordLogs"
2022-01-19 10:49:00 +13:00
const val SHARED_PREFS_BATTERY_OPTIMIZATIONS_REMIND_TIME = "BatteryOptimizationsRemindTime"
2022-06-20 06:19:27 +12:00
const val SHARED_PREFS_WEBSOCKET_REMIND_TIME = "JsonStreamRemindTime" // "Use WebSocket" banner (used to be JSON stream deprecation banner)
2022-02-17 07:46:35 +13:00
const val SHARED_PREFS_UNIFIED_PUSH_BASE_URL = "UnifiedPushBaseURL" // Legacy key required for migration to DefaultBaseURL
2022-02-15 16:49:06 +13:00
const val SHARED_PREFS_DEFAULT_BASE_URL = "DefaultBaseURL"
2022-02-13 13:43:42 +13:00
const val SHARED_PREFS_LAST_TOPICS = "LastTopics"
2022-02-13 17:02:42 +13:00
private const val LAST_TOPICS_COUNT = 3
2021-11-23 09:45:43 +13:00
2022-05-06 08:56:06 +12:00
const val MIN_PRIORITY_USE_GLOBAL = 0
const val MIN_PRIORITY_ANY = 1
2022-01-20 15:05:41 +13:00
const val MUTED_UNTIL_SHOW_ALL = 0L
const val MUTED_UNTIL_FOREVER = 1L
const val MUTED_UNTIL_TOMORROW = 2L
private const val ONE_MB = 1024 * 1024L
const val AUTO_DOWNLOAD_NEVER = 0L // Values must match values.xml
2022-01-12 13:37:34 +13:00
const val AUTO_DOWNLOAD_ALWAYS = 1L
const val AUTO_DOWNLOAD_DEFAULT = ONE_MB
private const val ONE_DAY_SECONDS = 24 * 60 * 60L
2022-05-06 08:56:06 +12:00
const val AUTO_DELETE_USE_GLOBAL = -1L // Values must match values.xml
const val AUTO_DELETE_NEVER = 0L
const val AUTO_DELETE_ONE_DAY_SECONDS = ONE_DAY_SECONDS
const val AUTO_DELETE_THREE_DAYS_SECONDS = 3 * ONE_DAY_SECONDS
const val AUTO_DELETE_ONE_WEEK_SECONDS = 7 * ONE_DAY_SECONDS
const val AUTO_DELETE_ONE_MONTH_SECONDS = 30 * ONE_DAY_SECONDS
const val AUTO_DELETE_THREE_MONTHS_SECONDS = 90 * ONE_DAY_SECONDS
const val AUTO_DELETE_DEFAULT_SECONDS = AUTO_DELETE_ONE_MONTH_SECONDS
2022-01-06 13:05:57 +13:00
const val INSISTENT_MAX_PRIORITY_USE_GLOBAL = -1 // Values must match values.xml
const val INSISTENT_MAX_PRIORITY_ENABLED = 1 // 0 = Disabled (but not needed in code)
2022-01-16 12:40:38 +13:00
const val CONNECTION_PROTOCOL_JSONHTTP = "jsonhttp"
const val CONNECTION_PROTOCOL_WS = "ws"
2022-01-19 10:49:00 +13:00
const val BATTERY_OPTIMIZATIONS_REMIND_TIME_ALWAYS = 1L
const val BATTERY_OPTIMIZATIONS_REMIND_TIME_NEVER = Long.MAX_VALUE
2022-06-20 06:19:27 +12:00
const val WEBSOCKET_REMIND_TIME_ALWAYS = 1L
const val WEBSOCKET_REMIND_TIME_NEVER = Long.MAX_VALUE
2022-03-17 15:41:27 +13:00
2021-11-15 15:42:41 +13:00
private const val TAG = "NtfyRepository"
2021-10-27 14:44:12 +13:00
private var instance: Repository? = null
2021-10-27 13:34:09 +13:00
fun getInstance(context: Context): Repository {
val database = Database.getInstance(context.applicationContext)
val sharedPrefs = context.getSharedPreferences(SHARED_PREFS_ID, Context.MODE_PRIVATE)
2022-01-28 13:57:43 +13:00
return getInstance(sharedPrefs, database)
}
2022-02-13 13:43:42 +13:00
private fun getInstance(sharedPrefs: SharedPreferences, database: Database): Repository {
2021-10-27 14:44:12 +13:00
return synchronized(Repository::class) {
2022-01-28 13:57:43 +13:00
val newInstance = instance ?: Repository(sharedPrefs, database)
2021-10-27 13:34:09 +13:00
instance = newInstance
newInstance
}
}
}
}
2021-11-15 15:42:41 +13:00
/* https://stackoverflow.com/a/57079290/1440785 */
fun <T, K, R> LiveData<T>.combineWith(
liveData: LiveData<K>,
block: (T?, K?) -> R
): LiveData<R> {
val result = MediatorLiveData<R>()
result.addSource(this) {
result.value = block(this.value, liveData.value)
}
result.addSource(liveData) {
result.value = block(this.value, liveData.value)
}
return result
}