Benoit Marty
1 year ago
29 changed files with 351 additions and 202 deletions
@ -1,49 +0,0 @@
@@ -1,49 +0,0 @@
|
||||
/* |
||||
* Copyright (c) 2021 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.push.impl |
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding |
||||
import io.element.android.libraries.di.AppScope |
||||
import javax.inject.Inject |
||||
|
||||
// TODO Move away |
||||
/** |
||||
* This interface defines 2 flags so you can handle auto accept invites. |
||||
* At the moment we only have [CompileTimeAutoAcceptInvites] implementation. |
||||
*/ |
||||
interface AutoAcceptInvites { |
||||
/** |
||||
* Enable auto-accept invites. It means, as soon as you got an invite from the sync, it will try to join it. |
||||
*/ |
||||
val isEnabled: Boolean |
||||
|
||||
/** |
||||
* Hide invites from the UI (from notifications, notification count and room list). By default invites are hidden when [isEnabled] is true |
||||
*/ |
||||
val hideInvites: Boolean |
||||
get() = isEnabled |
||||
} |
||||
|
||||
fun AutoAcceptInvites.showInvites() = !hideInvites |
||||
|
||||
/** |
||||
* Simple compile time implementation of AutoAcceptInvites flags. |
||||
*/ |
||||
@ContributesBinding(AppScope::class) |
||||
class CompileTimeAutoAcceptInvites @Inject constructor() : AutoAcceptInvites { |
||||
override val isEnabled = false |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
/* |
||||
* Copyright (c) 2022 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.push.impl.firebase |
||||
|
||||
import io.element.android.libraries.core.data.tryOrNull |
||||
import io.element.android.libraries.push.impl.push.PushData |
||||
import javax.inject.Inject |
||||
|
||||
class FirebasePushParser @Inject constructor() { |
||||
fun parse(message: Map<String, String?>): PushData { |
||||
val pushDataFirebase = PushDataFirebase( |
||||
eventId = message["event_id"], |
||||
roomId = message["room_id"], |
||||
unread = message["unread"]?.let { tryOrNull { Integer.parseInt(it) } }, |
||||
clientSecret = message["cs"], |
||||
) |
||||
return pushDataFirebase.toPushData() |
||||
} |
||||
} |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.push.impl.log |
||||
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag |
||||
|
||||
internal val pushLoggerTag = LoggerTag("Push") |
@ -1,57 +0,0 @@
@@ -1,57 +0,0 @@
|
||||
/* |
||||
* Copyright (c) 2022 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.push.impl.parser |
||||
|
||||
import io.element.android.libraries.core.data.tryOrNull |
||||
import io.element.android.libraries.push.impl.model.PushData |
||||
import io.element.android.libraries.push.impl.model.PushDataFcm |
||||
import io.element.android.libraries.push.impl.model.PushDataUnifiedPush |
||||
import io.element.android.libraries.push.impl.model.toPushData |
||||
import kotlinx.serialization.decodeFromString |
||||
import kotlinx.serialization.json.Json |
||||
import javax.inject.Inject |
||||
|
||||
/** |
||||
* Parse the received data from Push. Json format are different depending on the source. |
||||
* |
||||
* Notifications received by FCM are formatted by the matrix gateway [1]. The data send to FCM is the content |
||||
* of the "notification" attribute of the json sent to the gateway [2][3]. |
||||
* On the other side, with UnifiedPush, the content of the message received is the content posted to the push |
||||
* gateway endpoint [3]. |
||||
* |
||||
* *Note*: If we want to get the same content with FCM and unifiedpush, we can do a new sygnal pusher [4]. |
||||
* |
||||
* [1] https://github.com/matrix-org/sygnal/blob/main/sygnal/gcmpushkin.py |
||||
* [2] https://github.com/matrix-org/sygnal/blob/main/sygnal/gcmpushkin.py#L366 |
||||
* [3] https://spec.matrix.org/latest/push-gateway-api/ |
||||
* [4] https://github.com/p1gp1g/sygnal/blob/unifiedpush/sygnal/upfcmpushkin.py (Not tested for a while) |
||||
*/ |
||||
class PushParser @Inject constructor() { |
||||
fun parsePushDataUnifiedPush(message: ByteArray): PushData? { |
||||
return tryOrNull { Json.decodeFromString<PushDataUnifiedPush>(String(message)) }?.toPushData() |
||||
} |
||||
|
||||
fun parsePushDataFcm(message: Map<String, String?>): PushData { |
||||
val pushDataFcm = PushDataFcm( |
||||
eventId = message["event_id"], |
||||
roomId = message["room_id"], |
||||
unread = message["unread"]?.let { tryOrNull { Integer.parseInt(it) } }, |
||||
clientSecret = message["cs"], |
||||
) |
||||
return pushDataFcm.toPushData() |
||||
} |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
/* |
||||
* Copyright (c) 2022 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.push.impl.unifiedpush |
||||
|
||||
import io.element.android.libraries.core.data.tryOrNull |
||||
import io.element.android.libraries.push.impl.push.PushData |
||||
import kotlinx.serialization.decodeFromString |
||||
import kotlinx.serialization.json.Json |
||||
import javax.inject.Inject |
||||
|
||||
class UnifiedPushParser @Inject constructor() { |
||||
fun parse(message: ByteArray): PushData? { |
||||
return tryOrNull { Json.decodeFromString<PushDataUnifiedPush>(String(message)) }?.toPushData() |
||||
} |
||||
} |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.push.impl.userpushstore |
||||
|
||||
const val NOTIFICATION_METHOD_FIREBASE = "NOTIFICATION_METHOD_FIREBASE" |
||||
const val NOTIFICATION_METHOD_UNIFIEDPUSH = "NOTIFICATION_METHOD_UNIFIEDPUSH" |
||||
|
||||
/** |
||||
* Store data related to push about a user. |
||||
*/ |
||||
interface UserPushStore { |
||||
/** |
||||
* NOTIFICATION_METHOD_FIREBASE or NOTIFICATION_METHOD_UNIFIEDPUSH |
||||
*/ |
||||
suspend fun getNotificationMethod(): String |
||||
|
||||
suspend fun setNotificationMethod(value: String) |
||||
|
||||
suspend fun getCurrentRegisteredPushKey(): String? |
||||
|
||||
suspend fun setCurrentRegisteredPushKey(value: String) |
||||
|
||||
suspend fun reset() |
||||
} |
||||
|
||||
suspend fun UserPushStore.isFirebase(): Boolean = getNotificationMethod() == NOTIFICATION_METHOD_FIREBASE |
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.push.impl.userpushstore |
||||
|
||||
import android.content.Context |
||||
import androidx.datastore.core.DataStore |
||||
import androidx.datastore.preferences.core.Preferences |
||||
import androidx.datastore.preferences.core.edit |
||||
import androidx.datastore.preferences.core.stringPreferencesKey |
||||
import androidx.datastore.preferences.preferencesDataStore |
||||
import kotlinx.coroutines.flow.first |
||||
|
||||
/** |
||||
* Store data related to push about a user. |
||||
*/ |
||||
class UserPushStoreDataStore( |
||||
private val context: Context, |
||||
userId: String, |
||||
) : UserPushStore { |
||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "push_store_$userId") |
||||
private val notificationMethod = stringPreferencesKey("notificationMethod") |
||||
private val currentPushKey = stringPreferencesKey("currentPushKey") |
||||
|
||||
override suspend fun getNotificationMethod(): String { |
||||
return context.dataStore.data.first()[notificationMethod] ?: NOTIFICATION_METHOD_FIREBASE |
||||
} |
||||
|
||||
override suspend fun setNotificationMethod(value: String) { |
||||
context.dataStore.edit { |
||||
it[notificationMethod] = value |
||||
} |
||||
} |
||||
|
||||
override suspend fun getCurrentRegisteredPushKey(): String? { |
||||
return context.dataStore.data.first()[currentPushKey] |
||||
} |
||||
|
||||
override suspend fun setCurrentRegisteredPushKey(value: String) { |
||||
context.dataStore.edit { |
||||
it[currentPushKey] = value |
||||
} |
||||
} |
||||
|
||||
override suspend fun reset() { |
||||
context.dataStore.edit { |
||||
it.clear() |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.push.impl.userpushstore |
||||
|
||||
import android.content.Context |
||||
import io.element.android.libraries.di.ApplicationContext |
||||
import javax.inject.Inject |
||||
|
||||
class UserPushStoreFactory @Inject constructor( |
||||
@ApplicationContext private val context: Context, |
||||
) { |
||||
fun create(userId: String): UserPushStore { |
||||
return UserPushStoreDataStore( |
||||
context = context, |
||||
userId = userId |
||||
) |
||||
} |
||||
} |
Loading…
Reference in new issue