forked from dsutanto/bChot-android
First Commit
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
plugins {
|
||||
id("io.element.android-compose-library")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.libraries.push.api"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.androidx.corektx)
|
||||
implementation(libs.coroutines.core)
|
||||
implementation(libs.coil.compose)
|
||||
implementation(projects.libraries.designsystem)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
implementation(projects.libraries.matrixmedia.api)
|
||||
implementation(projects.libraries.pushproviders.api)
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2024, 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
|
||||
interface GetCurrentPushProvider {
|
||||
suspend fun getCurrentPushProvider(sessionId: SessionId): String?
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.push.api.history.PushHistoryItem
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface PushService {
|
||||
/**
|
||||
* Return the current push provider, or null if none.
|
||||
*/
|
||||
suspend fun getCurrentPushProvider(sessionId: SessionId): PushProvider?
|
||||
|
||||
/**
|
||||
* Return the list of push providers, available at compile time, sorted by index.
|
||||
*/
|
||||
fun getAvailablePushProviders(): List<PushProvider>
|
||||
|
||||
/**
|
||||
* Will unregister any previous pusher and register a new one with the provided [PushProvider].
|
||||
*
|
||||
* The method has effect only if the [PushProvider] is different than the current one.
|
||||
*/
|
||||
suspend fun registerWith(
|
||||
matrixClient: MatrixClient,
|
||||
pushProvider: PushProvider,
|
||||
distributor: Distributor,
|
||||
): Result<Unit>
|
||||
|
||||
/**
|
||||
* Ensure that the pusher with the current push provider and distributor is registered.
|
||||
* If there is no current config, the default push provider with the default distributor will be used.
|
||||
* Error can be [PusherRegistrationFailure].
|
||||
*/
|
||||
suspend fun ensurePusherIsRegistered(
|
||||
matrixClient: MatrixClient,
|
||||
): Result<Unit>
|
||||
|
||||
/**
|
||||
* Store the given push provider as the current one, but do not register.
|
||||
* To be used when there is no distributor available.
|
||||
*/
|
||||
suspend fun selectPushProvider(
|
||||
sessionId: SessionId,
|
||||
pushProvider: PushProvider,
|
||||
)
|
||||
|
||||
fun ignoreRegistrationError(sessionId: SessionId): Flow<Boolean>
|
||||
suspend fun setIgnoreRegistrationError(sessionId: SessionId, ignore: Boolean)
|
||||
|
||||
/**
|
||||
* Return false in case of early error.
|
||||
*/
|
||||
suspend fun testPush(sessionId: SessionId): Boolean
|
||||
|
||||
/**
|
||||
* Get a flow of total number of received Push.
|
||||
*/
|
||||
val pushCounter: Flow<Int>
|
||||
|
||||
/**
|
||||
* Get a flow of list of [PushHistoryItem].
|
||||
*/
|
||||
fun getPushHistoryItemsFlow(): Flow<List<PushHistoryItem>>
|
||||
|
||||
/**
|
||||
* Reset the push history, including the push counter.
|
||||
*/
|
||||
suspend fun resetPushHistory()
|
||||
|
||||
/**
|
||||
* Reset the battery optimization state.
|
||||
*/
|
||||
suspend fun resetBatteryOptimizationState()
|
||||
|
||||
/**
|
||||
* Notify the user that the service is un-registered.
|
||||
*/
|
||||
suspend fun onServiceUnregistered(userId: UserId)
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2024, 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.exception.ClientException
|
||||
|
||||
sealed class PusherRegistrationFailure : Exception() {
|
||||
class AccountNotVerified : PusherRegistrationFailure()
|
||||
class NoProvidersAvailable : PusherRegistrationFailure()
|
||||
class NoDistributorsAvailable : PusherRegistrationFailure()
|
||||
|
||||
/**
|
||||
* @param clientException the failure that occurred.
|
||||
* @param isRegisteringAgain true if the server should already have a the same pusher registered.
|
||||
*/
|
||||
class RegistrationFailure(
|
||||
val clientException: ClientException,
|
||||
val isRegisteringAgain: Boolean,
|
||||
) : PusherRegistrationFailure()
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.battery
|
||||
|
||||
sealed interface BatteryOptimizationEvents {
|
||||
data object Dismiss : BatteryOptimizationEvents
|
||||
data object RequestDisableOptimizations : BatteryOptimizationEvents
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.battery
|
||||
|
||||
data class BatteryOptimizationState(
|
||||
val shouldDisplayBanner: Boolean,
|
||||
val eventSink: (BatteryOptimizationEvents) -> Unit,
|
||||
)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.battery
|
||||
|
||||
fun aBatteryOptimizationState(
|
||||
shouldDisplayBanner: Boolean = false,
|
||||
eventSink: (BatteryOptimizationEvents) -> Unit = {},
|
||||
) = BatteryOptimizationState(
|
||||
shouldDisplayBanner = shouldDisplayBanner,
|
||||
eventSink = eventSink,
|
||||
)
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.gateway
|
||||
|
||||
sealed class PushGatewayFailure : Exception() {
|
||||
class PusherRejected : PushGatewayFailure()
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.history
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
|
||||
/**
|
||||
* Data class representing a push history item.
|
||||
* @property pushDate Date (timestamp).
|
||||
* @property formattedDate Formatted date.
|
||||
* @property providerInfo Push provider name / info
|
||||
* @property eventId EventId from the push, can be null if the received data are not correct.
|
||||
* @property roomId RoomId from the push, can be null if the received data are not correct.
|
||||
* @property sessionId The session Id, can be null if the session cannot be retrieved
|
||||
* @property hasBeenResolved Result of resolving the event
|
||||
* @property comment Comment. Can contains an error message if the event could not be resolved, or other any information.
|
||||
*/
|
||||
data class PushHistoryItem(
|
||||
val pushDate: Long,
|
||||
val formattedDate: String,
|
||||
val providerInfo: String,
|
||||
val eventId: EventId?,
|
||||
val roomId: RoomId?,
|
||||
val sessionId: SessionId?,
|
||||
val hasBeenResolved: Boolean,
|
||||
val comment: String?,
|
||||
)
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2024, 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.notifications
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import coil3.ImageLoader
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.matrix.ui.media.AVATAR_THUMBNAIL_SIZE_IN_PIXEL
|
||||
|
||||
interface NotificationBitmapLoader {
|
||||
/**
|
||||
* Get icon of a room.
|
||||
* @param avatarData the data related to the Avatar
|
||||
* @param imageLoader Coil image loader
|
||||
* @param targetSize The size we want the bitmap to be resized to
|
||||
*/
|
||||
suspend fun getRoomBitmap(
|
||||
avatarData: AvatarData,
|
||||
imageLoader: ImageLoader,
|
||||
targetSize: Long = AVATAR_THUMBNAIL_SIZE_IN_PIXEL,
|
||||
): Bitmap?
|
||||
|
||||
/**
|
||||
* Get icon of a user.
|
||||
* Before Android P, this does nothing because the icon won't be used
|
||||
* @param avatarData the data related to the Avatar
|
||||
* @param imageLoader Coil image loader
|
||||
*/
|
||||
suspend fun getUserIcon(
|
||||
avatarData: AvatarData,
|
||||
imageLoader: ImageLoader,
|
||||
): IconCompat?
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.notifications
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
|
||||
interface NotificationCleaner {
|
||||
fun clearAllMessagesEvents(sessionId: SessionId)
|
||||
fun clearMessagesForRoom(sessionId: SessionId, roomId: RoomId)
|
||||
fun clearMessagesForThread(sessionId: SessionId, roomId: RoomId, threadId: ThreadId)
|
||||
fun clearEvent(sessionId: SessionId, eventId: EventId)
|
||||
|
||||
fun clearMembershipNotificationForSession(sessionId: SessionId)
|
||||
fun clearMembershipNotificationForRoom(sessionId: SessionId, roomId: RoomId)
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2024, 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.notifications
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import kotlin.math.abs
|
||||
|
||||
object NotificationIdProvider {
|
||||
fun getSummaryNotificationId(sessionId: SessionId): Int {
|
||||
return getOffset(sessionId) + SUMMARY_NOTIFICATION_ID
|
||||
}
|
||||
|
||||
fun getRoomMessagesNotificationId(sessionId: SessionId): Int {
|
||||
return getOffset(sessionId) + ROOM_MESSAGES_NOTIFICATION_ID
|
||||
}
|
||||
|
||||
fun getRoomEventNotificationId(sessionId: SessionId): Int {
|
||||
return getOffset(sessionId) + ROOM_EVENT_NOTIFICATION_ID
|
||||
}
|
||||
|
||||
fun getRoomInvitationNotificationId(sessionId: SessionId): Int {
|
||||
return getOffset(sessionId) + ROOM_INVITATION_NOTIFICATION_ID
|
||||
}
|
||||
|
||||
fun getFallbackNotificationId(sessionId: SessionId): Int {
|
||||
return getOffset(sessionId) + FALLBACK_NOTIFICATION_ID
|
||||
}
|
||||
|
||||
fun getForegroundServiceNotificationId(type: ForegroundServiceType): Int {
|
||||
return type.ordinal * 10 + FOREGROUND_SERVICE_NOTIFICATION_ID
|
||||
}
|
||||
|
||||
private fun getOffset(sessionId: SessionId): Int {
|
||||
// Compute a int from a string with a low risk of collision.
|
||||
return abs(sessionId.value.hashCode() % 100_000) * 10
|
||||
}
|
||||
|
||||
private const val FALLBACK_NOTIFICATION_ID = -1
|
||||
private const val SUMMARY_NOTIFICATION_ID = 0
|
||||
private const val ROOM_MESSAGES_NOTIFICATION_ID = 1
|
||||
private const val ROOM_EVENT_NOTIFICATION_ID = 2
|
||||
private const val ROOM_INVITATION_NOTIFICATION_ID = 3
|
||||
|
||||
private const val FOREGROUND_SERVICE_NOTIFICATION_ID = 4
|
||||
}
|
||||
|
||||
enum class ForegroundServiceType {
|
||||
INCOMING_CALL,
|
||||
ONGOING_CALL,
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2024, 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.notifications
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
|
||||
/**
|
||||
* Handles missed calls by creating a new notification.
|
||||
*/
|
||||
interface OnMissedCallNotificationHandler {
|
||||
/**
|
||||
* Adds a missed call notification.
|
||||
*/
|
||||
suspend fun addMissedCallNotification(
|
||||
sessionId: SessionId,
|
||||
roomId: RoomId,
|
||||
eventId: EventId,
|
||||
)
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.notifications.conversations
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
|
||||
/**
|
||||
* Service to handle conversation-related notifications.
|
||||
*/
|
||||
interface NotificationConversationService {
|
||||
/**
|
||||
* Called when a new message is received in a room.
|
||||
* It should create a new conversation shortcut for this room.
|
||||
*/
|
||||
suspend fun onSendMessage(
|
||||
sessionId: SessionId,
|
||||
roomId: RoomId,
|
||||
roomName: String,
|
||||
roomIsDirect: Boolean,
|
||||
roomAvatarUrl: String?,
|
||||
)
|
||||
|
||||
/**
|
||||
* Called when a room is left.
|
||||
* It should remove the conversation shortcut for this room.
|
||||
*/
|
||||
suspend fun onLeftRoom(sessionId: SessionId, roomId: RoomId)
|
||||
|
||||
/**
|
||||
* Called when the list of available rooms changes.
|
||||
* It should update the conversation shortcuts accordingly, removing shortcuts for no longer joined rooms.
|
||||
*/
|
||||
suspend fun onAvailableRoomsChanged(sessionId: SessionId, roomIds: Set<RoomId>)
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.push
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
|
||||
data class NotificationEventRequest(
|
||||
val sessionId: SessionId,
|
||||
val roomId: RoomId,
|
||||
val eventId: EventId,
|
||||
val providerInfo: String,
|
||||
)
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.api.push
|
||||
|
||||
fun interface SyncOnNotifiableEvent {
|
||||
suspend operator fun invoke(requests: List<NotificationEventRequest>)
|
||||
}
|
||||
Reference in New Issue
Block a user