From f9c35e6bcba071b544cc46d06cd0be002a46904a Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 6 Oct 2020 11:15:00 +0300 Subject: [PATCH 01/27] If there is a pending email validation continue on this step --- CHANGES.md | 1 + .../im/vector/app/features/login/LoginAction.kt | 2 +- .../im/vector/app/features/login/LoginActivity.kt | 14 +++++++------- .../im/vector/app/features/login/LoginViewModel.kt | 7 +++++++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 754fb35612..697aa17b35 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ Improvements 🙌: - Small optimisation of scrolling experience in timeline (#2114) - Allow user to reset cross signing if he has no way to recover (#2052) - Create home shortcut for any room (#1525) + - Can't confirm email due to killing by Android (#2021) Bugfix 🐛: - Improve support for image/audio/video/file selection with intent changes (#1376) diff --git a/vector/src/main/java/im/vector/app/features/login/LoginAction.kt b/vector/src/main/java/im/vector/app/features/login/LoginAction.kt index 9067984852..9788060ad3 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginAction.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginAction.kt @@ -27,7 +27,7 @@ sealed class LoginAction : VectorViewModelAction { data class UpdateSignMode(val signMode: SignMode) : LoginAction() data class LoginWithToken(val loginToken: String) : LoginAction() data class WebLoginSuccess(val credentials: Credentials) : LoginAction() - data class InitWith(val loginConfig: LoginConfig) : LoginAction() + data class InitWith(val loginConfig: LoginConfig?) : LoginAction() data class ResetPassword(val email: String, val newPassword: String) : LoginAction() object ResetPasswordMailConfirmed : LoginAction() diff --git a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt index 0eb4ef3e32..01e835b4e3 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt @@ -91,19 +91,19 @@ open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable, UnlockedAc addFirstFragment() } - // Get config extra - val loginConfig = intent.getParcelableExtra(EXTRA_CONFIG) - if (loginConfig != null && isFirstCreation()) { - // TODO Check this - loginViewModel.handle(LoginAction.InitWith(loginConfig)) - } - loginViewModel .subscribe(this) { updateWithState(it) } loginViewModel.observeViewEvents { handleLoginViewEvents(it) } + + // Get config extra + val loginConfig = intent.getParcelableExtra(EXTRA_CONFIG) + if (isFirstCreation()) { + // TODO Check this + loginViewModel.handle(LoginAction.InitWith(loginConfig)) + } } protected open fun addFirstFragment() { diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt index f986227961..dc513d1666 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt @@ -417,6 +417,13 @@ class LoginViewModel @AssistedInject constructor( private fun handleInitWith(action: LoginAction.InitWith) { loginConfig = action.loginConfig + + // If there is a pending email validation continue on this step + currentThreePid?.let { + if (isRegistrationStarted) { + handle(LoginAction.PostViewEvent(LoginViewEvents.OnSendEmailSuccess(it))) + } + } } private fun handleResetPassword(action: LoginAction.ResetPassword) { From 3877b2f58ea3b39cc5b5d3590dcc5a7b403475c4 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 6 Oct 2020 17:02:49 +0300 Subject: [PATCH 02/27] Delete pending session store and states after session is created. --- CHANGES.md | 1 + .../im/vector/app/features/login/LoginViewModel.kt | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 85eb76f5f2..d2767d0174 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,7 @@ Improvements 🙌: Bugfix 🐛: - Improve support for image/audio/video/file selection with intent changes (#1376) - Fix Splash layout on small screens + - Invalid popup when pressing back (#1635) Translations 🗣: - diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt index dc513d1666..81d6a78123 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt @@ -419,10 +419,15 @@ class LoginViewModel @AssistedInject constructor( loginConfig = action.loginConfig // If there is a pending email validation continue on this step - currentThreePid?.let { - if (isRegistrationStarted) { - handle(LoginAction.PostViewEvent(LoginViewEvents.OnSendEmailSuccess(it))) + try { + if (registrationWizard?.isRegistrationStarted == true) { + currentThreePid?.let { + handle(LoginAction.PostViewEvent(LoginViewEvents.OnSendEmailSuccess(it))) + } } + } catch (e: Throwable) { + // NOOP. API is designed to use wizards in a login/registration flow, + // but we need to check the state anyway. } } @@ -679,6 +684,7 @@ class LoginViewModel @AssistedInject constructor( private fun onSessionCreated(session: Session) { activeSessionHolder.setActiveSession(session) + authenticationService.reset() session.configureAndStart(applicationContext) setState { copy( @@ -747,7 +753,7 @@ class LoginViewModel @AssistedInject constructor( override fun onSuccess(data: LoginFlowResult) { when (data) { - is LoginFlowResult.Success -> { + is LoginFlowResult.Success -> { val loginMode = when { // SSO login is taken first data.supportedLoginTypes.contains(LoginFlowTypes.SSO) -> LoginMode.Sso From cb33b9f15847f3d100ccd8e4b965242abeb08e87 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 1 Oct 2020 21:18:18 +0200 Subject: [PATCH 03/27] cleanup --- .../sdk/internal/network/ssl/TLSSocketFactory.kt | 4 ---- .../gplay/push/fcm/VectorFirebaseMessagingService.kt | 12 +++++++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/TLSSocketFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/TLSSocketFactory.kt index a5c711a3f0..c4dbce6240 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/TLSSocketFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/TLSSocketFactory.kt @@ -113,8 +113,4 @@ constructor(trustPinned: Array, acceptedTlsVersions: List Date: Fri, 2 Oct 2020 11:55:41 +0200 Subject: [PATCH 04/27] Add script to test PUSH token --- tools/tests/test_push.sh | 46 ++++++++++++++++++++++++++++ tools/tests/test_push_unsafe.sh | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100755 tools/tests/test_push.sh create mode 100755 tools/tests/test_push_unsafe.sh diff --git a/tools/tests/test_push.sh b/tools/tests/test_push.sh new file mode 100755 index 0000000000..0da02e2d0a --- /dev/null +++ b/tools/tests/test_push.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Some doc +# https://firebase.google.com/docs/cloud-messaging/android/first-message +# http://bulkpush.com/pushnotification/guidedetail/s-4/android-gcm-api-configuration +# http://www.feelzdroid.com/2016/02/android-google-cloud-messaging-push-notifications-gcm-tutorial.html + +# Ask for parameter +read -p "Enter the server API key: " SERVER_KEY + +echo +echo "Check validity of API key, InvalidRegistration error is OK" +# https://developers.google.com/cloud-messaging/http + +curl -H "Authorization: key=$SERVER_KEY" \ + -H Content-Type:"application/json" \ + -d "{\"registration_ids\":[\"ABC\"]}" \ + -s \ + https://fcm.googleapis.com/fcm/send \ + | python -m json.tool + +# should obtain something like this: +# {"multicast_id":5978845027639121780,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]} + +read -p "Enter the FCM token: " FCM_TOKEN + +# content of the notification +DATA="{\"message\":\"Message of PUSH!\"}" + +echo +echo +echo "Send a push, you should see success:1..." + +curl -H "Authorization: key=$SERVER_KEY" \ + -H Content-Type:"application/json" \ + -d "{ \"data\" : $DATA, \"to\":\"$FCM_TOKEN\" }" \ + -s \ + https://fcm.googleapis.com/fcm/send \ + | python -m json.tool + +echo +echo + +# should obtain something like this: +# {"multicast_id":7967233883611790812,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1472636210339069%84ac25d9f9fd7ecd"}]} + diff --git a/tools/tests/test_push_unsafe.sh b/tools/tests/test_push_unsafe.sh new file mode 100755 index 0000000000..62ec3759f4 --- /dev/null +++ b/tools/tests/test_push_unsafe.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +# Copy and adaptation of ./test_push.sh, which takes 2 params: server key and fcm token. +# It's unsafe to use it because it takes server key as parameter, that will remain in the terminal history. + +# Some doc +# https://firebase.google.com/docs/cloud-messaging/android/first-message +# http://bulkpush.com/pushnotification/guidedetail/s-4/android-gcm-api-configuration +# http://www.feelzdroid.com/2016/02/android-google-cloud-messaging-push-notifications-gcm-tutorial.html + +if [[ "$#" -ne 2 ]]; then + echo "Usage: $0 SERVER_KEY FCM_TOKEN" >&2 + exit 1 +fi + +# Get the command line parameters +SERVER_KEY=$1 +FCM_TOKEN=$2 + +echo +echo "Check validity of API key, InvalidRegistration error is OK" +# https://developers.google.com/cloud-messaging/http + +curl -H "Authorization: key=$SERVER_KEY" \ + -H Content-Type:"application/json" \ + -d "{\"registration_ids\":[\"ABC\"]}" \ + -s \ + https://fcm.googleapis.com/fcm/send \ + | python -m json.tool + +# should obtain something like this: +# {"multicast_id":5978845027639121780,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]} + +# content of the notification +DATA="{\"message\":\"Message of PUSH!\"}" + +echo +echo +echo "Send a push, you should see success:1..." + +curl -H "Authorization: key=$SERVER_KEY" \ + -H Content-Type:"application/json" \ + -d "{ \"data\" : $DATA, \"to\":\"$FCM_TOKEN\" }" \ + -s \ + https://fcm.googleapis.com/fcm/send \ + | python -m json.tool + +echo +echo + +# should obtain something like this: +# {"multicast_id":7967233883611790812,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1472636210339069%84ac25d9f9fd7ecd"}]} + From 7d53dfeca45d2ac590c1d0f6739bf89ecf5c4bb4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 2 Oct 2020 12:06:06 +0200 Subject: [PATCH 05/27] Add Sygnal API implementation to test is Push are correctly received --- .idea/dictionaries/bmarty.xml | 1 + CHANGES.md | 1 + .../sdk/api/session/pushers/PushersService.kt | 13 ++++ .../sdk/internal/network/NetworkConstants.kt | 6 +- .../session/pushers/DefaultPushersService.kt | 13 ++++ .../internal/session/pushers/PushersModule.kt | 5 ++ .../session/pushers/sygnal/SygnalAPI.kt | 32 +++++++++ .../session/pushers/sygnal/SygnalDevice.kt | 34 ++++++++++ .../pushers/sygnal/SygnalNotification.kt | 29 +++++++++ .../pushers/sygnal/SygnalNotifyBody.kt | 29 +++++++++ .../pushers/sygnal/SygnalNotifyResponse.kt | 26 ++++++++ .../pushers/sygnal/SygnalNotifyTask.kt | 65 +++++++++++++++++++ .../troubleshoot/TestPushFromSygnal.kt | 52 +++++++++++++++ ...ificationTroubleshootTestManagerFactory.kt | 19 ++++-- .../vector/app/core/pushers/PushersManager.kt | 10 +++ vector/src/main/res/values/strings.xml | 4 ++ 16 files changed, 331 insertions(+), 8 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalAPI.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalDevice.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyBody.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyResponse.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt create mode 100644 vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt diff --git a/.idea/dictionaries/bmarty.xml b/.idea/dictionaries/bmarty.xml index 5c27da044e..d13e40248f 100644 --- a/.idea/dictionaries/bmarty.xml +++ b/.idea/dictionaries/bmarty.xml @@ -29,6 +29,7 @@ signout signup ssss + sygnal threepid unwedging diff --git a/CHANGES.md b/CHANGES.md index 05d189ed12..e365768f86 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,7 @@ Improvements 🙌: - Drawer: move settings access and add sign out action (#2171) - Filter room member (and banned users) by name (#2184) - Implement "Jump to read receipt" and "Mention" actions on the room member profile screen + - Add Sygnal API implementation to test is Push are correctly received Bugfix 🐛: - Improve support for image/audio/video/file selection with intent changes (#1376) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt index 0e33be400c..8284b50332 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt @@ -66,6 +66,19 @@ interface PushersService { append: Boolean, withEventIdOnly: Boolean): UUID + /** + * Directly ask Sygnal to send a push to this device + * @param url the Sygnal url (full path) + * @param appId the application id + * @param pushkey the FCM token + * @param callback callback to know if Sygnal has accepted the request. In this case, the app should receive a Push with the provided data (TODO) + * + */ + fun testPush(url: String, + appId: String, + pushkey: String, + callback: MatrixCallback) + /** * Remove the http pusher */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt index 1154d1967c..0dfdec1804 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.network internal object NetworkConstants { - + // Homeserver private const val URI_API_PREFIX_PATH = "_matrix/client" const val URI_API_PREFIX_PATH_ = "$URI_API_PREFIX_PATH/" const val URI_API_PREFIX_PATH_R0 = "$URI_API_PREFIX_PATH/r0/" @@ -31,5 +31,9 @@ internal object NetworkConstants { const val URI_IDENTITY_PREFIX_PATH = "_matrix/identity/v2" const val URI_IDENTITY_PATH_V2 = "$URI_IDENTITY_PREFIX_PATH/" + // Sygnal + const val URI_SYGNAL_PREFIX_PATH = "_matrix/push/v1/" + + // Integration const val URI_INTEGRATION_MANAGER_PATH = "_matrix/integrations/v1/" } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt index 8f80ac46e4..c7d5e1f8b8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt @@ -28,6 +28,7 @@ import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.WorkManagerProvider +import org.matrix.android.sdk.internal.session.pushers.sygnal.SygnalNotifyTask import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.worker.WorkerParamsFactory @@ -41,10 +42,22 @@ internal class DefaultPushersService @Inject constructor( @SessionDatabase private val monarchy: Monarchy, @SessionId private val sessionId: String, private val getPusherTask: GetPushersTask, + private val sygnalNotifyTask: SygnalNotifyTask, private val removePusherTask: RemovePusherTask, private val taskExecutor: TaskExecutor ) : PushersService { + override fun testPush(url: String, + appId: String, + pushkey: String, + callback: MatrixCallback) { + sygnalNotifyTask + .configureWith(SygnalNotifyTask.Params(url, appId, pushkey)) { + this.callback = callback + } + .executeBy(taskExecutor) + } + override fun refreshPushers() { getPusherTask .configureWith() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt index a6042b27a2..5810f26c85 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt @@ -25,6 +25,8 @@ import org.matrix.android.sdk.api.session.pushers.PushersService import org.matrix.android.sdk.internal.session.notification.DefaultProcessEventForPushTask import org.matrix.android.sdk.internal.session.notification.DefaultPushRuleService import org.matrix.android.sdk.internal.session.notification.ProcessEventForPushTask +import org.matrix.android.sdk.internal.session.pushers.sygnal.DefaultSygnalNotifyTask +import org.matrix.android.sdk.internal.session.pushers.sygnal.SygnalNotifyTask import org.matrix.android.sdk.internal.session.room.notification.DefaultSetRoomNotificationStateTask import org.matrix.android.sdk.internal.session.room.notification.SetRoomNotificationStateTask import retrofit2.Retrofit @@ -86,4 +88,7 @@ internal abstract class PushersModule { @Binds abstract fun bindProcessEventForPushTask(task: DefaultProcessEventForPushTask): ProcessEventForPushTask + + @Binds + abstract fun bindSygnalNotifyTask(task: DefaultSygnalNotifyTask): SygnalNotifyTask } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalAPI.kt new file mode 100644 index 0000000000..7550e14a97 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalAPI.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 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 org.matrix.android.sdk.internal.session.pushers.sygnal + +import org.matrix.android.sdk.internal.network.NetworkConstants +import retrofit2.Call +import retrofit2.http.Body +import retrofit2.http.POST + +internal interface SygnalAPI { + /** + * Ask Sygnal to send a push to the current device. + * + * Ref: https://matrix.org/docs/spec/push_gateway/r0.1.1#post-matrix-push-v1-notify + */ + @POST(NetworkConstants.URI_SYGNAL_PREFIX_PATH + "notify") + fun notify(@Body body: SygnalNotifyBody): Call +} + diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalDevice.kt new file mode 100644 index 0000000000..a5cfe389cc --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalDevice.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 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 org.matrix.android.sdk.internal.session.pushers.sygnal + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +internal data class SygnalDevice( + /** + * Required. The app_id given when the pusher was created. + */ + @Json(name = "app_id") + val appId: String, + /** + * Required. The pushkey given when the pusher was created. + */ + @Json(name = "pushkey") + val pushKey: String +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt new file mode 100644 index 0000000000..b28449a481 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 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 org.matrix.android.sdk.internal.session.pushers.sygnal + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +internal data class SygnalNotification( + /** + * Required. This is an array of devices that the notification should be sent to. + */ + @Json(name = "devices") + val devices: List +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyBody.kt new file mode 100644 index 0000000000..7b13d8ff79 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyBody.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 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 org.matrix.android.sdk.internal.session.pushers.sygnal + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +internal data class SygnalNotifyBody( + /** + * Required. Information about the push notification + */ + @Json(name = "notification") + val notification: SygnalNotification +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyResponse.kt new file mode 100644 index 0000000000..73d5aa1e2c --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyResponse.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020 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 org.matrix.android.sdk.internal.session.pushers.sygnal + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +internal data class SygnalNotifyResponse( + @Json(name = "rejected") + val rejectedPushKey: List +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt new file mode 100644 index 0000000000..eb3cd433a9 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020 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 org.matrix.android.sdk.internal.session.pushers.sygnal + +import okhttp3.OkHttpClient +import org.matrix.android.sdk.internal.di.Unauthenticated +import org.matrix.android.sdk.internal.network.NetworkConstants +import org.matrix.android.sdk.internal.network.RetrofitFactory +import org.matrix.android.sdk.internal.network.executeRequest +import org.matrix.android.sdk.internal.task.Task +import javax.inject.Inject + +internal interface SygnalNotifyTask : Task { + data class Params( + val url: String, + val appId: String, + val pushKey: String + ) +} + +internal class DefaultSygnalNotifyTask @Inject constructor( + private val retrofitFactory: RetrofitFactory, + @Unauthenticated private val unauthenticatedOkHttpClient: OkHttpClient +) : SygnalNotifyTask { + + override suspend fun execute(params: SygnalNotifyTask.Params) { + val sygnalApi = retrofitFactory.create( + unauthenticatedOkHttpClient, + params.url.substringBefore(NetworkConstants.URI_SYGNAL_PREFIX_PATH) + ) + .create(SygnalAPI::class.java) + + val response = executeRequest(null) { + apiCall = sygnalApi.notify( + SygnalNotifyBody( + SygnalNotification( + devices = listOf( + SygnalDevice( + params.appId, + params.pushKey + ) + ) + ) + ) + ) + } + + if (response.rejectedPushKey.contains(params.pushKey)) { + throw IllegalStateException("Failure") + } + } +} diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt new file mode 100644 index 0000000000..b291b750b4 --- /dev/null +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2020 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 im.vector.app.gplay.features.settings.troubleshoot + +import androidx.appcompat.app.AppCompatActivity +import im.vector.app.R +import im.vector.app.core.pushers.PushersManager +import im.vector.app.core.resources.StringProvider +import im.vector.app.features.settings.troubleshoot.TroubleshootTest +import im.vector.app.push.fcm.FcmHelper +import org.matrix.android.sdk.api.MatrixCallback +import javax.inject.Inject + +/** + * Test Push by asking Sygnal to send a Push back + */ +class TestPushFromSygnal @Inject constructor(private val context: AppCompatActivity, + private val stringProvider: StringProvider, + private val pushersManager: PushersManager) + : TroubleshootTest(R.string.settings_troubleshoot_test_push_loop_title) { + + override fun perform() { + val fcmToken = FcmHelper.getFcmToken(context) ?: run { + status = TestStatus.FAILED + return + } + pushersManager.testPush(fcmToken, object : MatrixCallback { + override fun onFailure(failure: Throwable) { + description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_failed) + status = TestStatus.FAILED + } + + override fun onSuccess(data: Unit) { + description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_success) + status = TestStatus.SUCCESS + } + }) + } +} diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt index b2dad09483..06d3283afa 100644 --- a/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt @@ -23,16 +23,20 @@ import im.vector.app.features.settings.troubleshoot.TestPushRulesSettings import im.vector.app.features.settings.troubleshoot.TestSystemSettings import im.vector.app.gplay.features.settings.troubleshoot.TestFirebaseToken import im.vector.app.gplay.features.settings.troubleshoot.TestPlayServices +import im.vector.app.gplay.features.settings.troubleshoot.TestPushFromSygnal import im.vector.app.gplay.features.settings.troubleshoot.TestTokenRegistration import javax.inject.Inject -class NotificationTroubleshootTestManagerFactory @Inject constructor(private val testSystemSettings: TestSystemSettings, - private val testAccountSettings: TestAccountSettings, - private val testDeviceSettings: TestDeviceSettings, - private val testBingRulesSettings: TestPushRulesSettings, - private val testPlayServices: TestPlayServices, - private val testFirebaseToken: TestFirebaseToken, - private val testTokenRegistration: TestTokenRegistration) { +class NotificationTroubleshootTestManagerFactory @Inject constructor( + private val testSystemSettings: TestSystemSettings, + private val testAccountSettings: TestAccountSettings, + private val testDeviceSettings: TestDeviceSettings, + private val testBingRulesSettings: TestPushRulesSettings, + private val testPlayServices: TestPlayServices, + private val testFirebaseToken: TestFirebaseToken, + private val testTokenRegistration: TestTokenRegistration, + private val testPushFromSygnal: TestPushFromSygnal +) { fun create(fragment: Fragment): NotificationTroubleshootTestManager { val mgr = NotificationTroubleshootTestManager(fragment) @@ -43,6 +47,7 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor(private val mgr.addTest(testPlayServices) mgr.addTest(testFirebaseToken) mgr.addTest(testTokenRegistration) + mgr.addTest(testPushFromSygnal) return mgr } } diff --git a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt index f0d27182e7..e86ff104b7 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt @@ -34,6 +34,16 @@ class PushersManager @Inject constructor( private val stringProvider: StringProvider, private val appNameProvider: AppNameProvider ) { + fun testPush(pushKey: String, callback: MatrixCallback) { + val currentSession = activeSessionHolder.getActiveSession() + + currentSession.testPush( + stringProvider.getString(R.string.pusher_http_url), + stringProvider.getString(R.string.pusher_app_id), + pushKey, + callback + ) + } fun registerPusherWithFcmKey(pushKey: String): UUID { val currentSession = activeSessionHolder.getActiveSession() diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index d48162de29..be83a6dc50 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -749,6 +749,10 @@ FCM token successfully registered to HomeServer. Failed to register FCM token to HomeServer:\n%1$s + Test Push + The application is receiving PUSH, you should see a notification. + Failed to receive push. Solution could be to reinstall the application. + Notifications Service Notifications Service is running. Notifications Service is not running.\nTry to restart the application. From 02f1dab9b2ee71fb17630869ced03c9d62bd93fe Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 2 Oct 2020 15:23:42 +0200 Subject: [PATCH 06/27] Push test: better error handling --- .../sdk/api/session/pushers/PushersService.kt | 6 ++-- .../sdk/api/session/pushers/SygnalFailure.kt | 23 +++++++++++++ .../session/pushers/DefaultPushersService.kt | 3 +- .../pushers/sygnal/SygnalNotification.kt | 3 ++ .../pushers/sygnal/SygnalNotifyTask.kt | 7 ++-- .../troubleshoot/TestPushFromSygnal.kt | 9 +++++- .../fcm/VectorFirebaseMessagingService.kt | 7 ++++ .../vector/app/core/pushers/PushersManager.kt | 5 +++ .../NotificationDrawerManager.kt | 4 +++ .../notifications/NotificationUtils.kt | 32 +++++++++++++++++-- vector/src/main/res/values/strings.xml | 1 + 11 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/SygnalFailure.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt index 8284b50332..3832bc5af4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt @@ -71,12 +71,14 @@ interface PushersService { * @param url the Sygnal url (full path) * @param appId the application id * @param pushkey the FCM token - * @param callback callback to know if Sygnal has accepted the request. In this case, the app should receive a Push with the provided data (TODO) - * + * @param eventId the eventId which will be sent in the Push message. Use a fake eventId. + * @param callback callback to know if Sygnal has accepted the request. In this case, the app should receive a Push with the provided eventId. + * In case of error, PusherRejected failure can happen. In this case it means that the pushkey is not valid. */ fun testPush(url: String, appId: String, pushkey: String, + eventId: String, callback: MatrixCallback) /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/SygnalFailure.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/SygnalFailure.kt new file mode 100644 index 0000000000..ebedba9d92 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/SygnalFailure.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020 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 org.matrix.android.sdk.api.session.pushers + +import org.matrix.android.sdk.api.failure.Failure + +sealed class SygnalFailure : Failure.FeatureFailure() { + object PusherRejected : SygnalFailure() +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt index c7d5e1f8b8..02f147f815 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt @@ -50,9 +50,10 @@ internal class DefaultPushersService @Inject constructor( override fun testPush(url: String, appId: String, pushkey: String, + eventId: String, callback: MatrixCallback) { sygnalNotifyTask - .configureWith(SygnalNotifyTask.Params(url, appId, pushkey)) { + .configureWith(SygnalNotifyTask.Params(url, appId, pushkey, eventId)) { this.callback = callback } .executeBy(taskExecutor) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt index b28449a481..a2c016feb8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt @@ -21,6 +21,9 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) internal data class SygnalNotification( + @Json(name = "event_id") + val eventId: String, + /** * Required. This is an array of devices that the notification should be sent to. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt index eb3cd433a9..663d0cd3c2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt @@ -16,6 +16,7 @@ package org.matrix.android.sdk.internal.session.pushers.sygnal import okhttp3.OkHttpClient +import org.matrix.android.sdk.api.session.pushers.SygnalFailure import org.matrix.android.sdk.internal.di.Unauthenticated import org.matrix.android.sdk.internal.network.NetworkConstants import org.matrix.android.sdk.internal.network.RetrofitFactory @@ -27,7 +28,8 @@ internal interface SygnalNotifyTask : Task { data class Params( val url: String, val appId: String, - val pushKey: String + val pushKey: String, + val eventId: String ) } @@ -47,6 +49,7 @@ internal class DefaultSygnalNotifyTask @Inject constructor( apiCall = sygnalApi.notify( SygnalNotifyBody( SygnalNotification( + eventId = params.eventId, devices = listOf( SygnalDevice( params.appId, @@ -59,7 +62,7 @@ internal class DefaultSygnalNotifyTask @Inject constructor( } if (response.rejectedPushKey.contains(params.pushKey)) { - throw IllegalStateException("Failure") + throw SygnalFailure.PusherRejected } } } diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt index b291b750b4..105c54c64f 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt @@ -17,11 +17,13 @@ package im.vector.app.gplay.features.settings.troubleshoot import androidx.appcompat.app.AppCompatActivity import im.vector.app.R +import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.pushers.PushersManager import im.vector.app.core.resources.StringProvider import im.vector.app.features.settings.troubleshoot.TroubleshootTest import im.vector.app.push.fcm.FcmHelper import org.matrix.android.sdk.api.MatrixCallback +import org.matrix.android.sdk.api.session.pushers.SygnalFailure import javax.inject.Inject /** @@ -29,6 +31,7 @@ import javax.inject.Inject */ class TestPushFromSygnal @Inject constructor(private val context: AppCompatActivity, private val stringProvider: StringProvider, + private val errorFormatter: ErrorFormatter, private val pushersManager: PushersManager) : TroubleshootTest(R.string.settings_troubleshoot_test_push_loop_title) { @@ -39,7 +42,11 @@ class TestPushFromSygnal @Inject constructor(private val context: AppCompatActiv } pushersManager.testPush(fcmToken, object : MatrixCallback { override fun onFailure(failure: Throwable) { - description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_failed) + description = if (failure is SygnalFailure.PusherRejected) { + stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_failed) + } else { + errorFormatter.toHumanReadable(failure) + } status = TestStatus.FAILED } diff --git a/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt b/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt index ba58ef6677..801b85ce0c 100755 --- a/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt @@ -75,6 +75,13 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { * @param message the message */ override fun onMessageReceived(message: RemoteMessage) { + // Diagnostic Push + if (message.data["event_id"] == PushersManager.TEST_EVENT_ID) { + // Display the notification right now + notificationDrawerManager.displayDiagnosticNotification() + return + } + if (!vectorPreferences.areNotificationEnabledForDevice()) { Timber.i("Notification are disabled for this device") return diff --git a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt index e86ff104b7..cfdc61a045 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt @@ -41,6 +41,7 @@ class PushersManager @Inject constructor( stringProvider.getString(R.string.pusher_http_url), stringProvider.getString(R.string.pusher_app_id), pushKey, + TEST_EVENT_ID, callback ) } @@ -66,4 +67,8 @@ class PushersManager @Inject constructor( val currentSession = activeSessionHolder.getSafeActiveSession() ?: return currentSession.removeHttpPusher(pushKey, stringProvider.getString(R.string.pusher_app_id), callback) } + + companion object { + const val TEST_EVENT_ID = "\$THIS_IS_A_FAKE_EVENT_ID" + } } diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt index 26f00fcef9..7147968d49 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt @@ -590,6 +590,10 @@ class NotificationDrawerManager @Inject constructor(private val context: Context } } + fun displayDiagnosticNotification() { + notificationUtils.displayDiagnosticNotification() + } + companion object { private const val SUMMARY_NOTIFICATION_ID = 0 private const val ROOM_MESSAGES_NOTIFICATION_ID = 1 diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt index 9d89168bb8..7e7fd60b59 100755 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt @@ -27,8 +27,10 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import android.graphics.Bitmap +import android.graphics.Canvas import android.net.Uri import android.os.Build +import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat @@ -36,6 +38,7 @@ import androidx.core.app.RemoteInput import androidx.core.app.TaskStackBuilder import androidx.core.content.ContextCompat import androidx.core.content.getSystemService +import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.drawable.IconCompat import androidx.fragment.app.Fragment import im.vector.app.BuildConfig @@ -47,7 +50,6 @@ import im.vector.app.features.call.service.CallHeadsUpActionReceiver import im.vector.app.features.home.HomeActivity import im.vector.app.features.home.room.detail.RoomDetailActivity import im.vector.app.features.home.room.detail.RoomDetailArgs -import im.vector.app.features.pin.PinLocker import im.vector.app.features.settings.VectorPreferences import timber.log.Timber import javax.inject.Inject @@ -61,7 +63,6 @@ import kotlin.random.Random @Singleton class NotificationUtils @Inject constructor(private val context: Context, private val stringProvider: StringProvider, - private val pinLocker: PinLocker, private val vectorPreferences: VectorPreferences) { companion object { @@ -845,6 +846,33 @@ class NotificationUtils @Inject constructor(private val context: Context, } } + fun displayDiagnosticNotification() { + notificationManager.notify( + "DIAGNOSTIC", + 888, + NotificationCompat.Builder(context, NOISY_NOTIFICATION_CHANNEL_ID) + .setContentTitle(stringProvider.getString(R.string.app_name)) + .setContentText(stringProvider.getString(R.string.settings_troubleshoot_test_push_notification_content)) + .setSmallIcon(R.drawable.ic_status_bar) + .setLargeIcon(getBitmap(context, R.drawable.element_logo_green)) + .setColor(ContextCompat.getColor(context, R.color.notification_accent_color)) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setCategory(NotificationCompat.CATEGORY_STATUS) + .setAutoCancel(true) + .build() + ) + } + + private fun getBitmap(context: Context, @DrawableRes drawableRes: Int): Bitmap? { + val drawable = ResourcesCompat.getDrawable(context.resources, drawableRes, null) ?: return null + val canvas = Canvas() + val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888) + canvas.setBitmap(bitmap) + drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight) + drawable.draw(canvas) + return bitmap + } + /** * Return true it the user has enabled the do not disturb mode */ diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index be83a6dc50..d5e590375c 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -752,6 +752,7 @@ Test Push The application is receiving PUSH, you should see a notification. Failed to receive push. Solution could be to reinstall the application. + You are receiving PUSH! Notifications Service Notifications Service is running. From e926326fcafd1bfeaf09a01dd491b7078e25e536 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 2 Oct 2020 15:32:29 +0200 Subject: [PATCH 07/27] Better handling of network error. Entering a wrong homeserver URL is now a specific error. --- .../java/im/vector/app/core/error/ErrorFormatter.kt | 5 +---- .../app/features/login/LoginServerUrlFormFragment.kt | 10 +++++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt index 43395b97f7..790f19a133 100644 --- a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt +++ b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt @@ -45,15 +45,12 @@ class DefaultErrorFormatter @Inject constructor( when (throwable.ioException) { is SocketTimeoutException -> stringProvider.getString(R.string.error_network_timeout) - is UnknownHostException -> - // Invalid homeserver? - // TODO Check network state, airplane mode, etc. - stringProvider.getString(R.string.login_error_unknown_host) is SSLPeerUnverifiedException -> stringProvider.getString(R.string.login_error_ssl_peer_unverified) is SSLException -> stringProvider.getString(R.string.login_error_ssl_other) else -> + // TODO Check network state, airplane mode, etc. stringProvider.getString(R.string.error_no_network) } } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginServerUrlFormFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginServerUrlFormFragment.kt index 4b9f528254..af959fecd4 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginServerUrlFormFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginServerUrlFormFragment.kt @@ -28,6 +28,8 @@ import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.utils.ensureProtocol import im.vector.app.core.utils.openUrlInChromeCustomTab import kotlinx.android.synthetic.main.fragment_login_server_url_form.* +import org.matrix.android.sdk.api.failure.Failure +import java.net.UnknownHostException import javax.inject.Inject /** @@ -115,7 +117,13 @@ class LoginServerUrlFormFragment @Inject constructor() : AbstractLoginFragment() } override fun onError(throwable: Throwable) { - loginServerUrlFormHomeServerUrlTil.error = errorFormatter.toHumanReadable(throwable) + loginServerUrlFormHomeServerUrlTil.error = if (throwable is Failure.NetworkConnection + && throwable.ioException is UnknownHostException) { + // Invalid homeserver? + getString(R.string.login_error_homeserver_not_found) + } else { + errorFormatter.toHumanReadable(throwable) + } } override fun updateWithState(state: LoginViewState) { From d1fb1614a3c523fc226a5896be7e936a06d2b330 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 2 Oct 2020 16:13:14 +0200 Subject: [PATCH 08/27] Make the app react to test push --- tools/tests/test_push.sh | 2 +- tools/tests/test_push_unsafe.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/tests/test_push.sh b/tools/tests/test_push.sh index 0da02e2d0a..08348497ae 100755 --- a/tools/tests/test_push.sh +++ b/tools/tests/test_push.sh @@ -25,7 +25,7 @@ curl -H "Authorization: key=$SERVER_KEY" \ read -p "Enter the FCM token: " FCM_TOKEN # content of the notification -DATA="{\"message\":\"Message of PUSH!\"}" +DATA='{"event_id":"$THIS_IS_A_FAKE_EVENT_ID"}' echo echo diff --git a/tools/tests/test_push_unsafe.sh b/tools/tests/test_push_unsafe.sh index 62ec3759f4..77c198197f 100755 --- a/tools/tests/test_push_unsafe.sh +++ b/tools/tests/test_push_unsafe.sh @@ -32,7 +32,7 @@ curl -H "Authorization: key=$SERVER_KEY" \ # {"multicast_id":5978845027639121780,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]} # content of the notification -DATA="{\"message\":\"Message of PUSH!\"}" +DATA='{"event_id":"$THIS_IS_A_FAKE_EVENT_ID"}' echo echo From 48ca1384f8af1affa113b1c6249d256a269c5731 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 2 Oct 2020 16:46:40 +0200 Subject: [PATCH 09/27] Do some renaming, Sygnal is an implementation of a PushGateway. --- CHANGES.md | 1 + ...SygnalFailure.kt => PushGatewayFailure.kt} | 4 +-- .../sdk/api/session/pushers/PushersService.kt | 6 ++-- .../sdk/internal/network/NetworkConstants.kt | 4 +-- .../session/pushers/DefaultPushersService.kt | 8 +++--- .../internal/session/pushers/PushersModule.kt | 6 ++-- .../PushGatewayAPI.kt} | 10 +++---- .../PushGatewayDevice.kt} | 4 +-- .../PushGatewayNotification.kt} | 6 ++-- .../PushGatewayNotifyBody.kt} | 6 ++-- .../PushGatewayNotifyResponse.kt} | 6 ++-- .../PushGatewayNotifyTask.kt} | 28 +++++++++---------- ...omSygnal.kt => TestPushFromPushGateway.kt} | 14 +++++----- ...ificationTroubleshootTestManagerFactory.kt | 6 ++-- 14 files changed, 55 insertions(+), 54 deletions(-) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/{SygnalFailure.kt => PushGatewayFailure.kt} (86%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/{sygnal/SygnalAPI.kt => gateway/PushGatewayAPI.kt} (73%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/{sygnal/SygnalDevice.kt => gateway/PushGatewayDevice.kt} (90%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/{sygnal/SygnalNotification.kt => gateway/PushGatewayNotification.kt} (85%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/{sygnal/SygnalNotifyBody.kt => gateway/PushGatewayNotifyBody.kt} (84%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/{sygnal/SygnalNotifyResponse.kt => gateway/PushGatewayNotifyResponse.kt} (82%) rename matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/{sygnal/SygnalNotifyTask.kt => gateway/PushGatewayNotifyTask.kt} (69%) rename vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/{TestPushFromSygnal.kt => TestPushFromPushGateway.kt} (76%) diff --git a/CHANGES.md b/CHANGES.md index e365768f86..6c6a0d6dd8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,7 @@ Improvements 🙌: - Filter room member (and banned users) by name (#2184) - Implement "Jump to read receipt" and "Mention" actions on the room member profile screen - Add Sygnal API implementation to test is Push are correctly received + - Add PushGateway API implementation to test if Push are correctly received Bugfix 🐛: - Improve support for image/audio/video/file selection with intent changes (#1376) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/SygnalFailure.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushGatewayFailure.kt similarity index 86% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/SygnalFailure.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushGatewayFailure.kt index ebedba9d92..f5b9d7ea8d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/SygnalFailure.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushGatewayFailure.kt @@ -18,6 +18,6 @@ package org.matrix.android.sdk.api.session.pushers import org.matrix.android.sdk.api.failure.Failure -sealed class SygnalFailure : Failure.FeatureFailure() { - object PusherRejected : SygnalFailure() +sealed class PushGatewayFailure : Failure.FeatureFailure() { + object PusherRejected : PushGatewayFailure() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt index 3832bc5af4..09cbe5a89b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt @@ -67,12 +67,12 @@ interface PushersService { withEventIdOnly: Boolean): UUID /** - * Directly ask Sygnal to send a push to this device - * @param url the Sygnal url (full path) + * Directly ask the push gateway to send a push to this device + * @param url the push gateway url (full path) * @param appId the application id * @param pushkey the FCM token * @param eventId the eventId which will be sent in the Push message. Use a fake eventId. - * @param callback callback to know if Sygnal has accepted the request. In this case, the app should receive a Push with the provided eventId. + * @param callback callback to know if the push gateway has accepted the request. In this case, the app should receive a Push with the provided eventId. * In case of error, PusherRejected failure can happen. In this case it means that the pushkey is not valid. */ fun testPush(url: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt index 0dfdec1804..a14c86efb6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConstants.kt @@ -31,8 +31,8 @@ internal object NetworkConstants { const val URI_IDENTITY_PREFIX_PATH = "_matrix/identity/v2" const val URI_IDENTITY_PATH_V2 = "$URI_IDENTITY_PREFIX_PATH/" - // Sygnal - const val URI_SYGNAL_PREFIX_PATH = "_matrix/push/v1/" + // Push Gateway + const val URI_PUSH_GATEWAY_PREFIX_PATH = "_matrix/push/v1/" // Integration const val URI_INTEGRATION_MANAGER_PATH = "_matrix/integrations/v1/" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt index 02f147f815..1ded11de8f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt @@ -28,7 +28,7 @@ import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.WorkManagerProvider -import org.matrix.android.sdk.internal.session.pushers.sygnal.SygnalNotifyTask +import org.matrix.android.sdk.internal.session.pushers.gateway.PushGatewayNotifyTask import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.worker.WorkerParamsFactory @@ -42,7 +42,7 @@ internal class DefaultPushersService @Inject constructor( @SessionDatabase private val monarchy: Monarchy, @SessionId private val sessionId: String, private val getPusherTask: GetPushersTask, - private val sygnalNotifyTask: SygnalNotifyTask, + private val pushGatewayNotifyTask: PushGatewayNotifyTask, private val removePusherTask: RemovePusherTask, private val taskExecutor: TaskExecutor ) : PushersService { @@ -52,8 +52,8 @@ internal class DefaultPushersService @Inject constructor( pushkey: String, eventId: String, callback: MatrixCallback) { - sygnalNotifyTask - .configureWith(SygnalNotifyTask.Params(url, appId, pushkey, eventId)) { + pushGatewayNotifyTask + .configureWith(PushGatewayNotifyTask.Params(url, appId, pushkey, eventId)) { this.callback = callback } .executeBy(taskExecutor) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt index 5810f26c85..4030c63514 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/PushersModule.kt @@ -25,8 +25,8 @@ import org.matrix.android.sdk.api.session.pushers.PushersService import org.matrix.android.sdk.internal.session.notification.DefaultProcessEventForPushTask import org.matrix.android.sdk.internal.session.notification.DefaultPushRuleService import org.matrix.android.sdk.internal.session.notification.ProcessEventForPushTask -import org.matrix.android.sdk.internal.session.pushers.sygnal.DefaultSygnalNotifyTask -import org.matrix.android.sdk.internal.session.pushers.sygnal.SygnalNotifyTask +import org.matrix.android.sdk.internal.session.pushers.gateway.DefaultPushGatewayNotifyTask +import org.matrix.android.sdk.internal.session.pushers.gateway.PushGatewayNotifyTask import org.matrix.android.sdk.internal.session.room.notification.DefaultSetRoomNotificationStateTask import org.matrix.android.sdk.internal.session.room.notification.SetRoomNotificationStateTask import retrofit2.Retrofit @@ -90,5 +90,5 @@ internal abstract class PushersModule { abstract fun bindProcessEventForPushTask(task: DefaultProcessEventForPushTask): ProcessEventForPushTask @Binds - abstract fun bindSygnalNotifyTask(task: DefaultSygnalNotifyTask): SygnalNotifyTask + abstract fun bindPushGatewayNotifyTask(task: DefaultPushGatewayNotifyTask): PushGatewayNotifyTask } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt similarity index 73% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalAPI.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt index 7550e14a97..75946780f6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt @@ -13,20 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.session.pushers.sygnal +package org.matrix.android.sdk.internal.session.pushers.gateway import org.matrix.android.sdk.internal.network.NetworkConstants import retrofit2.Call import retrofit2.http.Body import retrofit2.http.POST -internal interface SygnalAPI { +internal interface PushGatewayAPI { /** - * Ask Sygnal to send a push to the current device. + * Ask the Push Gateway to send a push to the current device. * * Ref: https://matrix.org/docs/spec/push_gateway/r0.1.1#post-matrix-push-v1-notify */ - @POST(NetworkConstants.URI_SYGNAL_PREFIX_PATH + "notify") - fun notify(@Body body: SygnalNotifyBody): Call + @POST(NetworkConstants.URI_PUSH_GATEWAY_PREFIX_PATH + "notify") + fun notify(@Body body: PushGatewayNotifyBody): Call } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayDevice.kt similarity index 90% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalDevice.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayDevice.kt index a5cfe389cc..a513448014 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalDevice.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayDevice.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.pushers.sygnal +package org.matrix.android.sdk.internal.session.pushers.gateway import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -internal data class SygnalDevice( +internal data class PushGatewayDevice( /** * Required. The app_id given when the pusher was created. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotification.kt similarity index 85% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotification.kt index a2c016feb8..aa6519e216 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotification.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotification.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.pushers.sygnal +package org.matrix.android.sdk.internal.session.pushers.gateway import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -internal data class SygnalNotification( +internal data class PushGatewayNotification( @Json(name = "event_id") val eventId: String, @@ -28,5 +28,5 @@ internal data class SygnalNotification( * Required. This is an array of devices that the notification should be sent to. */ @Json(name = "devices") - val devices: List + val devices: List ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyBody.kt similarity index 84% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyBody.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyBody.kt index 7b13d8ff79..112267aeba 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyBody.kt @@ -14,16 +14,16 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.pushers.sygnal +package org.matrix.android.sdk.internal.session.pushers.gateway import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -internal data class SygnalNotifyBody( +internal data class PushGatewayNotifyBody( /** * Required. Information about the push notification */ @Json(name = "notification") - val notification: SygnalNotification + val notification: PushGatewayNotification ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyResponse.kt similarity index 82% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyResponse.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyResponse.kt index 73d5aa1e2c..bad1c08465 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyResponse.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.pushers.sygnal +package org.matrix.android.sdk.internal.session.pushers.gateway import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -internal data class SygnalNotifyResponse( +internal data class PushGatewayNotifyResponse( @Json(name = "rejected") - val rejectedPushKey: List + val rejectedPushKeys: List ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyTask.kt similarity index 69% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyTask.kt index 663d0cd3c2..fba3a881d8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/sygnal/SygnalNotifyTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyTask.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.session.pushers.sygnal +package org.matrix.android.sdk.internal.session.pushers.gateway import okhttp3.OkHttpClient -import org.matrix.android.sdk.api.session.pushers.SygnalFailure +import org.matrix.android.sdk.api.session.pushers.PushGatewayFailure import org.matrix.android.sdk.internal.di.Unauthenticated import org.matrix.android.sdk.internal.network.NetworkConstants import org.matrix.android.sdk.internal.network.RetrofitFactory @@ -24,7 +24,7 @@ import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import javax.inject.Inject -internal interface SygnalNotifyTask : Task { +internal interface PushGatewayNotifyTask : Task { data class Params( val url: String, val appId: String, @@ -33,25 +33,25 @@ internal interface SygnalNotifyTask : Task { ) } -internal class DefaultSygnalNotifyTask @Inject constructor( +internal class DefaultPushGatewayNotifyTask @Inject constructor( private val retrofitFactory: RetrofitFactory, @Unauthenticated private val unauthenticatedOkHttpClient: OkHttpClient -) : SygnalNotifyTask { +) : PushGatewayNotifyTask { - override suspend fun execute(params: SygnalNotifyTask.Params) { + override suspend fun execute(params: PushGatewayNotifyTask.Params) { val sygnalApi = retrofitFactory.create( unauthenticatedOkHttpClient, - params.url.substringBefore(NetworkConstants.URI_SYGNAL_PREFIX_PATH) + params.url.substringBefore(NetworkConstants.URI_PUSH_GATEWAY_PREFIX_PATH) ) - .create(SygnalAPI::class.java) + .create(PushGatewayAPI::class.java) - val response = executeRequest(null) { + val response = executeRequest(null) { apiCall = sygnalApi.notify( - SygnalNotifyBody( - SygnalNotification( + PushGatewayNotifyBody( + PushGatewayNotification( eventId = params.eventId, devices = listOf( - SygnalDevice( + PushGatewayDevice( params.appId, params.pushKey ) @@ -61,8 +61,8 @@ internal class DefaultSygnalNotifyTask @Inject constructor( ) } - if (response.rejectedPushKey.contains(params.pushKey)) { - throw SygnalFailure.PusherRejected + if (response.rejectedPushKeys.contains(params.pushKey)) { + throw PushGatewayFailure.PusherRejected } } } diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt similarity index 76% rename from vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt rename to vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt index 105c54c64f..21bbc96f08 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromSygnal.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt @@ -23,16 +23,16 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.features.settings.troubleshoot.TroubleshootTest import im.vector.app.push.fcm.FcmHelper import org.matrix.android.sdk.api.MatrixCallback -import org.matrix.android.sdk.api.session.pushers.SygnalFailure +import org.matrix.android.sdk.api.session.pushers.PushGatewayFailure import javax.inject.Inject /** - * Test Push by asking Sygnal to send a Push back + * Test Push by asking the Push Gateway to send a Push back */ -class TestPushFromSygnal @Inject constructor(private val context: AppCompatActivity, - private val stringProvider: StringProvider, - private val errorFormatter: ErrorFormatter, - private val pushersManager: PushersManager) +class TestPushFromPushGateway @Inject constructor(private val context: AppCompatActivity, + private val stringProvider: StringProvider, + private val errorFormatter: ErrorFormatter, + private val pushersManager: PushersManager) : TroubleshootTest(R.string.settings_troubleshoot_test_push_loop_title) { override fun perform() { @@ -42,7 +42,7 @@ class TestPushFromSygnal @Inject constructor(private val context: AppCompatActiv } pushersManager.testPush(fcmToken, object : MatrixCallback { override fun onFailure(failure: Throwable) { - description = if (failure is SygnalFailure.PusherRejected) { + description = if (failure is PushGatewayFailure.PusherRejected) { stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_failed) } else { errorFormatter.toHumanReadable(failure) diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt index 06d3283afa..46c78a9872 100644 --- a/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt @@ -23,7 +23,7 @@ import im.vector.app.features.settings.troubleshoot.TestPushRulesSettings import im.vector.app.features.settings.troubleshoot.TestSystemSettings import im.vector.app.gplay.features.settings.troubleshoot.TestFirebaseToken import im.vector.app.gplay.features.settings.troubleshoot.TestPlayServices -import im.vector.app.gplay.features.settings.troubleshoot.TestPushFromSygnal +import im.vector.app.gplay.features.settings.troubleshoot.TestPushFromPushGateway import im.vector.app.gplay.features.settings.troubleshoot.TestTokenRegistration import javax.inject.Inject @@ -35,7 +35,7 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( private val testPlayServices: TestPlayServices, private val testFirebaseToken: TestFirebaseToken, private val testTokenRegistration: TestTokenRegistration, - private val testPushFromSygnal: TestPushFromSygnal + private val testPushFromPushGateway: TestPushFromPushGateway ) { fun create(fragment: Fragment): NotificationTroubleshootTestManager { @@ -47,7 +47,7 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( mgr.addTest(testPlayServices) mgr.addTest(testFirebaseToken) mgr.addTest(testTokenRegistration) - mgr.addTest(testPushFromSygnal) + mgr.addTest(testPushFromPushGateway) return mgr } } From 5397700ab4fcf4ab15ef9451b3d0a183cf6c4156 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 5 Oct 2020 15:54:42 +0200 Subject: [PATCH 10/27] cleanup --- .../sdk/internal/session/pushers/gateway/PushGatewayAPI.kt | 1 - vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt | 1 - 2 files changed, 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt index 75946780f6..a031a8a307 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt @@ -29,4 +29,3 @@ internal interface PushGatewayAPI { @POST(NetworkConstants.URI_PUSH_GATEWAY_PREFIX_PATH + "notify") fun notify(@Body body: PushGatewayNotifyBody): Call } - diff --git a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt index 790f19a133..1e7d662793 100644 --- a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt +++ b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt @@ -24,7 +24,6 @@ import org.matrix.android.sdk.api.failure.isInvalidPassword import org.matrix.android.sdk.api.session.identity.IdentityServiceError import java.net.HttpURLConnection import java.net.SocketTimeoutException -import java.net.UnknownHostException import javax.inject.Inject import javax.net.ssl.SSLException import javax.net.ssl.SSLPeerUnverifiedException From f860cfd8a3111fab584ea9e7b6220349b83c0794 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Oct 2020 14:08:35 +0200 Subject: [PATCH 11/27] Fix compilation issue after rebase --- .../features/settings/troubleshoot/TestPushFromPushGateway.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt index 21bbc96f08..d52f41dacf 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt @@ -15,6 +15,8 @@ */ package im.vector.app.gplay.features.settings.troubleshoot +import android.content.Intent +import androidx.activity.result.ActivityResultLauncher import androidx.appcompat.app.AppCompatActivity import im.vector.app.R import im.vector.app.core.error.ErrorFormatter @@ -35,7 +37,7 @@ class TestPushFromPushGateway @Inject constructor(private val context: AppCompat private val pushersManager: PushersManager) : TroubleshootTest(R.string.settings_troubleshoot_test_push_loop_title) { - override fun perform() { + override fun perform(activityResultLauncher: ActivityResultLauncher) { val fcmToken = FcmHelper.getFcmToken(context) ?: run { status = TestStatus.FAILED return From be62d65c98170afc898107d66074fe52075cf4ed Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Oct 2020 14:09:19 +0200 Subject: [PATCH 12/27] Some cleanup on the layout --- vector/src/main/res/layout/activity_jitsi.xml | 6 +- .../main/res/layout/view_avatar_selector.xml | 68 ------------------- 2 files changed, 4 insertions(+), 70 deletions(-) delete mode 100644 vector/src/main/res/layout/view_avatar_selector.xml diff --git a/vector/src/main/res/layout/activity_jitsi.xml b/vector/src/main/res/layout/activity_jitsi.xml index e0359d220d..de0c0271bc 100644 --- a/vector/src/main/res/layout/activity_jitsi.xml +++ b/vector/src/main/res/layout/activity_jitsi.xml @@ -1,11 +1,12 @@ - + + android:orientation="vertical" + tools:ignore="UselessParent"> - - - - - - - - - - - - - - - - - - - - - - - - - - From 5e45f5c3eacf71c7e071830795506f082f4a6ef3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Oct 2020 15:22:02 +0200 Subject: [PATCH 13/27] Copyright for SDK --- .../android/sdk/api/session/pushers/PushGatewayFailure.kt | 2 +- .../sdk/internal/session/pushers/gateway/PushGatewayAPI.kt | 2 +- .../sdk/internal/session/pushers/gateway/PushGatewayDevice.kt | 2 +- .../internal/session/pushers/gateway/PushGatewayNotification.kt | 2 +- .../internal/session/pushers/gateway/PushGatewayNotifyBody.kt | 2 +- .../session/pushers/gateway/PushGatewayNotifyResponse.kt | 2 +- .../internal/session/pushers/gateway/PushGatewayNotifyTask.kt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushGatewayFailure.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushGatewayFailure.kt index f5b9d7ea8d..b15147161f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushGatewayFailure.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushGatewayFailure.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 New Vector Ltd + * Copyright 2020 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt index a031a8a307..d95587fc22 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayAPI.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 New Vector Ltd + * Copyright 2020 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayDevice.kt index a513448014..5490fed7a7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayDevice.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayDevice.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 New Vector Ltd + * Copyright 2020 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotification.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotification.kt index aa6519e216..b9c8a35afc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotification.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotification.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 New Vector Ltd + * Copyright 2020 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyBody.kt index 112267aeba..751414d2fe 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyBody.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 New Vector Ltd + * Copyright 2020 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyResponse.kt index bad1c08465..50401ef6e9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyResponse.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 New Vector Ltd + * Copyright 2020 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyTask.kt index fba3a881d8..df6f46fa81 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/gateway/PushGatewayNotifyTask.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 New Vector Ltd + * Copyright 2020 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From dbb77d9dc12e42e69f0133a3c2f358346f1d6e29 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Oct 2020 17:46:21 +0200 Subject: [PATCH 14/27] Push test: success if user click on the notification --- .../troubleshoot/TestPushFromPushGateway.kt | 8 ++++- vector/src/main/AndroidManifest.xml | 4 +++ .../notifications/NotificationUtils.kt | 12 ++++++++ ...ttingsNotificationsTroubleshootFragment.kt | 30 +++++++++++++++++++ .../NotificationTroubleshootTestManager.kt | 6 ++++ .../troubleshoot/TestNotificationReceiver.kt | 30 +++++++++++++++++++ .../settings/troubleshoot/TroubleshootTest.kt | 3 ++ vector/src/main/res/values/strings.xml | 5 ++-- 8 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotificationReceiver.kt diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt index d52f41dacf..19a4e3a841 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt @@ -53,9 +53,15 @@ class TestPushFromPushGateway @Inject constructor(private val context: AppCompat } override fun onSuccess(data: Unit) { + // Wait for user to click on the notification description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_success) - status = TestStatus.SUCCESS + status = TestStatus.RUNNING } }) } + + override fun onNotificationClicked() { + description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_notification_clicked) + status = TestStatus.SUCCESS + } } diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 3f178a3d20..d8ae90a33c 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -252,6 +252,10 @@ android:name=".features.call.service.CallHeadsUpActionReceiver" android:exported="false" /> + + { // check if there are quick fixes + // TODO Rewrite using firstOrNull var hasQuickFix = false testManager?.testList?.let { for (test in it) { @@ -161,6 +172,25 @@ class VectorSettingsNotificationsTroubleshootFragment @Inject constructor( override fun onResume() { super.onResume() (activity as? VectorBaseActivity)?.supportActionBar?.setTitle(R.string.settings_notification_troubleshoot) + + tryOrNull("Unable to register the receiver") { + LocalBroadcastManager.getInstance(requireContext()) + .registerReceiver(broadcastReceiver, IntentFilter(NotificationUtils.DIAGNOSTIC_ACTION)) + } + } + + override fun onPause() { + super.onPause() + tryOrNull { + LocalBroadcastManager.getInstance(requireContext()) + .unregisterReceiver(broadcastReceiver) + } + } + + private val broadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + testManager?.onDiagnosticNotificationClicked() + } } override fun onAttach(context: Context) { diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt index e977dc5963..0c77caf635 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt @@ -94,4 +94,10 @@ class NotificationTroubleshootTestManager(val fragment: Fragment) { test.cancel() } } + + fun onDiagnosticNotificationClicked() { + testList.forEach { + it.onNotificationClicked() + } + } } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotificationReceiver.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotificationReceiver.kt new file mode 100644 index 0000000000..7dec870d3d --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotificationReceiver.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020 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 im.vector.app.features.settings.troubleshoot + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import androidx.localbroadcastmanager.content.LocalBroadcastManager + +class TestNotificationReceiver : BroadcastReceiver() { + + override fun onReceive(context: Context, intent: Intent) { + // Internal broadcast to any one interested + LocalBroadcastManager.getInstance(context).sendBroadcast(intent) + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt index f894fcc0ef..aedca5e356 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt @@ -51,4 +51,7 @@ abstract class TroubleshootTest(@StringRes val titleResId: Int) { open fun cancel() { } + + open fun onNotificationClicked() { + } } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index d5e590375c..004da5e15e 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -750,9 +750,10 @@ Failed to register FCM token to HomeServer:\n%1$s Test Push - The application is receiving PUSH, you should see a notification. + The application is receiving PUSH, please click on the test notification you just receive. + The notification has been clicked! Failed to receive push. Solution could be to reinstall the application. - You are receiving PUSH! + You are receiving PUSH! Click me! Notifications Service Notifications Service is running. From ab9bbe9a4862b8450ec90803325ee76341056b02 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Oct 2020 21:40:53 +0200 Subject: [PATCH 15/27] Cleanup and cancel request properly --- .../sdk/api/session/pushers/PushersService.kt | 2 +- .../session/pushers/DefaultPushersService.kt | 4 +-- .../troubleshoot/TestPushFromPushGateway.kt | 9 ++++- .../vector/app/core/pushers/PushersManager.kt | 5 +-- ...ttingsNotificationsTroubleshootFragment.kt | 20 +++-------- .../NotificationTroubleshootTestManager.kt | 35 ++++++++++++------- 6 files changed, 41 insertions(+), 34 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt index 09cbe5a89b..3993422b1d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushers/PushersService.kt @@ -79,7 +79,7 @@ interface PushersService { appId: String, pushkey: String, eventId: String, - callback: MatrixCallback) + callback: MatrixCallback): Cancelable /** * Remove the http pusher diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt index 1ded11de8f..e239182b4a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/pushers/DefaultPushersService.kt @@ -51,8 +51,8 @@ internal class DefaultPushersService @Inject constructor( appId: String, pushkey: String, eventId: String, - callback: MatrixCallback) { - pushGatewayNotifyTask + callback: MatrixCallback): Cancelable { + return pushGatewayNotifyTask .configureWith(PushGatewayNotifyTask.Params(url, appId, pushkey, eventId)) { this.callback = callback } diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt index 19a4e3a841..bbe3f35fb5 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt @@ -26,6 +26,7 @@ import im.vector.app.features.settings.troubleshoot.TroubleshootTest import im.vector.app.push.fcm.FcmHelper import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.session.pushers.PushGatewayFailure +import org.matrix.android.sdk.api.util.Cancelable import javax.inject.Inject /** @@ -37,12 +38,14 @@ class TestPushFromPushGateway @Inject constructor(private val context: AppCompat private val pushersManager: PushersManager) : TroubleshootTest(R.string.settings_troubleshoot_test_push_loop_title) { + private var action: Cancelable? = null + override fun perform(activityResultLauncher: ActivityResultLauncher) { val fcmToken = FcmHelper.getFcmToken(context) ?: run { status = TestStatus.FAILED return } - pushersManager.testPush(fcmToken, object : MatrixCallback { + action = pushersManager.testPush(fcmToken, object : MatrixCallback { override fun onFailure(failure: Throwable) { description = if (failure is PushGatewayFailure.PusherRejected) { stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_failed) @@ -64,4 +67,8 @@ class TestPushFromPushGateway @Inject constructor(private val context: AppCompat description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_notification_clicked) status = TestStatus.SUCCESS } + + override fun cancel() { + action?.cancel() + } } diff --git a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt index cfdc61a045..5fe30141d9 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/PushersManager.kt @@ -22,6 +22,7 @@ import im.vector.app.core.resources.AppNameProvider import im.vector.app.core.resources.LocaleProvider import im.vector.app.core.resources.StringProvider import org.matrix.android.sdk.api.MatrixCallback +import org.matrix.android.sdk.api.util.Cancelable import java.util.UUID import javax.inject.Inject import kotlin.math.abs @@ -34,10 +35,10 @@ class PushersManager @Inject constructor( private val stringProvider: StringProvider, private val appNameProvider: AppNameProvider ) { - fun testPush(pushKey: String, callback: MatrixCallback) { + fun testPush(pushKey: String, callback: MatrixCallback): Cancelable { val currentSession = activeSessionHolder.getActiveSession() - currentSession.testPush( + return currentSession.testPush( stringProvider.getString(R.string.pusher_http_url), stringProvider.getString(R.string.pusher_app_id), pushKey, diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt index 2adc6ccdcf..ea9e73f160 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt @@ -41,6 +41,7 @@ import im.vector.app.features.rageshake.BugReporter import im.vector.app.features.settings.troubleshoot.NotificationTroubleshootTestManager import im.vector.app.features.settings.troubleshoot.TroubleshootTest import im.vector.app.push.fcm.NotificationTroubleshootTestManagerFactory +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull import javax.inject.Inject @@ -92,8 +93,7 @@ class VectorSettingsNotificationsTroubleshootFragment @Inject constructor( } private fun startUI() { - mSummaryDescription.text = getString(R.string.settings_troubleshoot_diagnostic_running_status, - 0, 0) + mSummaryDescription.text = getString(R.string.settings_troubleshoot_diagnostic_running_status, 0, 0) testManager = testManagerFactory.create(this) testManager?.statusListener = { troubleshootTestManager -> if (isAdded) { @@ -105,9 +105,8 @@ class VectorSettingsNotificationsTroubleshootFragment @Inject constructor( mRunButton.visibility = View.VISIBLE } TroubleshootTest.TestStatus.RUNNING -> { - // Forces int type because it's breaking lint - val size: Int = troubleshootTestManager.testList.size - val currentTestIndex: Int = troubleshootTestManager.currentTestIndex + val size = troubleshootTestManager.testListSize + val currentTestIndex = troubleshootTestManager.currentTestIndex mSummaryDescription.text = getString( R.string.settings_troubleshoot_diagnostic_running_status, currentTestIndex, @@ -118,16 +117,7 @@ class VectorSettingsNotificationsTroubleshootFragment @Inject constructor( } TroubleshootTest.TestStatus.FAILED -> { // check if there are quick fixes - // TODO Rewrite using firstOrNull - var hasQuickFix = false - testManager?.testList?.let { - for (test in it) { - if (test.status == TroubleshootTest.TestStatus.FAILED && test.quickFix != null) { - hasQuickFix = true - break - } - } - } + val hasQuickFix = testManager?.hasQuickFix().orFalse() if (hasQuickFix) { mSummaryDescription.text = getString(R.string.settings_troubleshoot_diagnostic_failure_status_with_quickfix) } else { diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt index 0c77caf635..566cb6d846 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt @@ -23,13 +23,19 @@ import androidx.fragment.app.Fragment import kotlin.properties.Delegates class NotificationTroubleshootTestManager(val fragment: Fragment) { + private val testList = ArrayList() + + val testListSize: Int + get() = testList.size - val testList = ArrayList() var isCancelled = false + private set var currentTestIndex by Delegates.observable(0) { _, _, _ -> statusListener?.invoke(this) } + private set + val adapter = NotificationTroubleshootRecyclerViewAdapter(testList) var statusListener: ((NotificationTroubleshootTestManager) -> Unit)? = null @@ -37,6 +43,7 @@ class NotificationTroubleshootTestManager(val fragment: Fragment) { var diagStatus: TroubleshootTest.TestStatus by Delegates.observable(TroubleshootTest.TestStatus.NOT_STARTED) { _, _, _ -> statusListener?.invoke(this) } + private set fun addTest(test: TroubleshootTest) { testList.add(test) @@ -79,25 +86,27 @@ class NotificationTroubleshootTestManager(val fragment: Fragment) { } fun retry(activityResultLauncher: ActivityResultLauncher) { - for (test in testList) { - test.cancel() - test.description = null - test.quickFix = null - test.status = TroubleshootTest.TestStatus.NOT_STARTED + testList.forEach { + it.cancel() + it.description = null + it.quickFix = null + it.status = TroubleshootTest.TestStatus.NOT_STARTED } runDiagnostic(activityResultLauncher) } - fun cancel() { - isCancelled = true - for (test in testList) { - test.cancel() + fun hasQuickFix(): Boolean { + return testList.any { test -> + test.status == TroubleshootTest.TestStatus.FAILED && test.quickFix != null } } + fun cancel() { + isCancelled = true + testList.forEach { it.cancel() } + } + fun onDiagnosticNotificationClicked() { - testList.forEach { - it.onNotificationClicked() - } + testList.forEach { it.onNotificationClicked() } } } From 3714e4e7874f0f68e9225c5ef3ca99c92ad11200 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Oct 2020 21:55:16 +0200 Subject: [PATCH 16/27] Add a Waiting for user state --- .../settings/troubleshoot/TestPushFromPushGateway.kt | 2 +- .../VectorSettingsNotificationsTroubleshootFragment.kt | 3 ++- .../NotificationTroubleshootRecyclerViewAdapter.kt | 10 ++++++++++ .../features/settings/troubleshoot/TroubleshootTest.kt | 1 + vector/src/main/res/values/strings.xml | 2 +- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt index bbe3f35fb5..ce94244ee6 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt @@ -58,7 +58,7 @@ class TestPushFromPushGateway @Inject constructor(private val context: AppCompat override fun onSuccess(data: Unit) { // Wait for user to click on the notification description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_success) - status = TestStatus.RUNNING + status = TestStatus.WAITING_FOR_USER } }) } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt index ea9e73f160..4843c1446a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt @@ -104,7 +104,8 @@ class VectorSettingsNotificationsTroubleshootFragment @Inject constructor( mSummaryButton.visibility = View.GONE mRunButton.visibility = View.VISIBLE } - TroubleshootTest.TestStatus.RUNNING -> { + TroubleshootTest.TestStatus.RUNNING, + TroubleshootTest.TestStatus.WAITING_FOR_USER -> { val size = troubleshootTestManager.testListSize val currentTestIndex = troubleshootTestManager.currentTestIndex mSummaryDescription.text = getString( diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootRecyclerViewAdapter.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootRecyclerViewAdapter.kt index 1ccd7b6735..633d9d05fe 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootRecyclerViewAdapter.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootRecyclerViewAdapter.kt @@ -77,6 +77,16 @@ class NotificationTroubleshootRecyclerViewAdapter(val tests: ArrayList { + progressBar.visibility = View.INVISIBLE + statusIconImage.visibility = View.VISIBLE + val infoColor = ContextCompat.getColor(context, R.color.vector_info_color) + val drawable = ContextCompat.getDrawable(itemView.context, R.drawable.ic_notification_privacy_warning)?.apply { + ThemeUtils.tintDrawableWithColor(this, infoColor) + } + statusIconImage.setImageDrawable(drawable) + descriptionText.setTextColor(infoColor) + } TroubleshootTest.TestStatus.RUNNING -> { progressBar.visibility = View.VISIBLE statusIconImage.visibility = View.INVISIBLE diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt index aedca5e356..c775c8c827 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt @@ -25,6 +25,7 @@ abstract class TroubleshootTest(@StringRes val titleResId: Int) { enum class TestStatus { NOT_STARTED, RUNNING, + WAITING_FOR_USER, FAILED, SUCCESS } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 004da5e15e..ef6b63aeb0 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -750,7 +750,7 @@ Failed to register FCM token to HomeServer:\n%1$s Test Push - The application is receiving PUSH, please click on the test notification you just receive. + The application is receiving PUSH, please click on the test notification you just received. The notification has been clicked! Failed to receive push. Solution could be to reinstall the application. You are receiving PUSH! Click me! From 4f92db76511a0b63d2555bc85d7abc8a9c141aa7 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Fri, 9 Oct 2020 14:45:36 +0300 Subject: [PATCH 17/27] Make long topic expandable. --- .../app/core/epoxy/ExpandableTextItem.kt | 86 +++++++++++++++++++ .../roomprofile/RoomProfileController.kt | 15 ++++ .../roomprofile/RoomProfileFragment.kt | 2 - .../src/main/res/drawable/ic_expand_less.xml | 9 ++ .../src/main/res/drawable/ic_expand_more.xml | 9 ++ .../res/layout/item_expandable_textview.xml | 33 +++++++ .../layout/view_stub_room_profile_header.xml | 18 ---- vector/src/main/res/values/strings.xml | 1 + 8 files changed, 153 insertions(+), 20 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt create mode 100644 vector/src/main/res/drawable/ic_expand_less.xml create mode 100644 vector/src/main/res/drawable/ic_expand_more.xml create mode 100644 vector/src/main/res/layout/item_expandable_textview.xml diff --git a/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt new file mode 100644 index 0000000000..b55861571b --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020 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 im.vector.app.core.epoxy + +import android.animation.ObjectAnimator +import android.widget.ImageView +import android.widget.TextView +import androidx.core.view.doOnPreDraw +import androidx.core.view.isVisible +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.app.R +import im.vector.app.core.extensions.copyOnLongClick + +@EpoxyModelClass(layout = R.layout.item_expandable_textview) +abstract class ExpandableTextItem : VectorEpoxyModel() { + + @EpoxyAttribute + lateinit var content: String + + @EpoxyAttribute + var maxLines: Int = 3 + + private var isExpanded = false + private var expandedLines = 0 + + override fun bind(holder: Holder) { + super.bind(holder) + holder.content.text = content + holder.content.copyOnLongClick() + + holder.content.doOnPreDraw { + if (holder.content.lineCount > maxLines) { + expandedLines = holder.content.lineCount + holder.content.maxLines = maxLines + + holder.view.setOnClickListener { + if (isExpanded) { + collapse(holder) + } else { + expand(holder) + } + } + } else { + holder.arrow.isVisible = false + } + } + } + + private fun expand(holder: Holder) { + ObjectAnimator.ofInt(holder.content, "maxLines", expandedLines) + .apply { duration = 500 } + .also { it.start() } + + holder.arrow.setImageResource(R.drawable.ic_expand_less) + isExpanded = true + } + + private fun collapse(holder: Holder) { + ObjectAnimator.ofInt(holder.content, "maxLines", maxLines) + .apply { duration = 500 } + .also { it.start() } + + holder.arrow.setImageResource(R.drawable.ic_expand_more) + isExpanded = false + } + + class Holder : VectorEpoxyHolder() { + val content by bind(R.id.expandableContent) + val arrow by bind(R.id.expandableArrow) + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt index 160ebd56be..ad774fbeef 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt @@ -19,6 +19,7 @@ package im.vector.app.features.roomprofile import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R +import im.vector.app.core.epoxy.expandableTextItem import im.vector.app.core.epoxy.profiles.buildProfileAction import im.vector.app.core.epoxy.profiles.buildProfileSection import im.vector.app.core.resources.ColorProvider @@ -57,6 +58,20 @@ class RoomProfileController @Inject constructor( return } val roomSummary = data.roomSummary() ?: return + + // Topic + roomSummary + .topic + .takeIf { it.isNotBlank() } + ?.let { + buildProfileSection(stringProvider.getString(R.string.room_profile_section_topic)) + expandableTextItem { + id("topic") + content(roomSummary.topic) + maxLines(2) + } + } + // Security buildProfileSection(stringProvider.getString(R.string.room_profile_section_security)) val learnMoreSubtitle = if (roomSummary.isEncrypted) { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt index 399c1ecf32..c2f25c08d3 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt @@ -129,7 +129,6 @@ class RoomProfileFragment @Inject constructor( private fun setupLongClicks() { roomProfileNameView.copyOnLongClick() roomProfileAliasView.copyOnLongClick() - roomProfileTopicView.copyOnLongClick() } override fun onOptionsItemSelected(item: MenuItem): Boolean { @@ -187,7 +186,6 @@ class RoomProfileFragment @Inject constructor( roomProfileNameView.text = it.displayName matrixProfileToolbarTitleView.text = it.displayName roomProfileAliasView.setTextOrHide(it.canonicalAlias) - roomProfileTopicView.setTextOrHide(it.topic) val matrixItem = it.toMatrixItem() avatarRenderer.render(matrixItem, roomProfileAvatarView) avatarRenderer.render(matrixItem, matrixProfileToolbarAvatarImageView) diff --git a/vector/src/main/res/drawable/ic_expand_less.xml b/vector/src/main/res/drawable/ic_expand_less.xml new file mode 100644 index 0000000000..92bc86da08 --- /dev/null +++ b/vector/src/main/res/drawable/ic_expand_less.xml @@ -0,0 +1,9 @@ + + + diff --git a/vector/src/main/res/drawable/ic_expand_more.xml b/vector/src/main/res/drawable/ic_expand_more.xml new file mode 100644 index 0000000000..22c401f0c3 --- /dev/null +++ b/vector/src/main/res/drawable/ic_expand_more.xml @@ -0,0 +1,9 @@ + + + diff --git a/vector/src/main/res/layout/item_expandable_textview.xml b/vector/src/main/res/layout/item_expandable_textview.xml new file mode 100644 index 0000000000..34fbaf7ec0 --- /dev/null +++ b/vector/src/main/res/layout/item_expandable_textview.xml @@ -0,0 +1,33 @@ + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/layout/view_stub_room_profile_header.xml b/vector/src/main/res/layout/view_stub_room_profile_header.xml index f7ae1c77a5..ecb7174f0e 100644 --- a/vector/src/main/res/layout/view_stub_room_profile_header.xml +++ b/vector/src/main/res/layout/view_stub_room_profile_header.xml @@ -54,27 +54,9 @@ android:textAppearance="@style/Vector.Toolbar.Title" android:textSize="14sp" android:textStyle="bold" - app:layout_constraintBottom_toTopOf="@+id/roomProfileTopicView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/roomProfileNameView" tools:text="@sample/matrix.json/data/roomAlias" /> - - diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index d48162de29..709bf4f4a1 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2124,6 +2124,7 @@ Messages here are not end-to-end encrypted. Messages in this room are end-to-end encrypted.\n\nYour messages are secured with locks and only you and the recipient have the unique keys to unlock them. Messages here are end-to-end encrypted.\n\nYour messages are secured with locks and only you and the recipient have the unique keys to unlock them. + Topic Security Learn more More From c3a423fdbe1c5e388174d76ee19be60559760972 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Fri, 9 Oct 2020 14:53:02 +0300 Subject: [PATCH 18/27] Changelog added. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index ec853d96ef..0762a207ce 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,7 @@ Bugfix 🐛: - Improve support for image/audio/video/file selection with intent changes (#1376) - Fix Splash layout on small screens - Simplifies draft management and should fix bunch of draft issues (#952, #683) + - Very long topic cannot be fully visible (#1957) Translations 🗣: - From beeb84043620fb39a876f582e44cca2996395884 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Fri, 9 Oct 2020 15:06:54 +0300 Subject: [PATCH 19/27] Do not ellipsize content while expanding. --- .../java/im/vector/app/core/epoxy/ExpandableTextItem.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt index b55861571b..7e1114660f 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt @@ -17,6 +17,7 @@ package im.vector.app.core.epoxy import android.animation.ObjectAnimator +import android.text.TextUtils import android.widget.ImageView import android.widget.TextView import androidx.core.view.doOnPreDraw @@ -63,19 +64,21 @@ abstract class ExpandableTextItem : VectorEpoxyModel( private fun expand(holder: Holder) { ObjectAnimator.ofInt(holder.content, "maxLines", expandedLines) - .apply { duration = 500 } + .apply { duration = 200 } .also { it.start() } + holder.content.ellipsize = null holder.arrow.setImageResource(R.drawable.ic_expand_less) isExpanded = true } private fun collapse(holder: Holder) { ObjectAnimator.ofInt(holder.content, "maxLines", maxLines) - .apply { duration = 500 } + .apply { duration = 200 } .also { it.start() } - holder.arrow.setImageResource(R.drawable.ic_expand_more) + holder.content.ellipsize = TextUtils.TruncateAt.END + holder.arrow.setImageResource(R.drawable.ic_expand_more) isExpanded = false } From b12c4f854c63180a57944be3dd2223877e4e5c4e Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 9 Oct 2020 15:40:30 +0200 Subject: [PATCH 20/27] Fix / Moshi Cannot serialize kotlin --- .../android/sdk/internal/crypto/DefaultCryptoService.kt | 4 ++-- .../sdk/internal/crypto/model/rest/SendToDeviceBody.kt | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index 37886a7d77..c77ac70124 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -50,7 +50,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent -import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary +import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction import org.matrix.android.sdk.internal.crypto.actions.MegolmSessionDataImporter import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter @@ -953,7 +953,7 @@ internal class DefaultCryptoService @Inject constructor( roomEncryptorsStore.get(roomId) ?: /* No encrypting in this room */ return event.stateKey?.let { userId -> - val roomMember: RoomMemberSummary? = event.content.toModel() + val roomMember: RoomMemberContent? = event.content.toModel() val membership = roomMember?.membership if (membership == Membership.JOIN) { // make sure we are tracking the deviceList for this user. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SendToDeviceBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SendToDeviceBody.kt index e252abfb04..868f7aa943 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SendToDeviceBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SendToDeviceBody.kt @@ -16,6 +16,9 @@ package org.matrix.android.sdk.internal.crypto.model.rest +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) internal data class SendToDeviceBody( /** * `Any` should implement [SendToDeviceObject], but we cannot use interface here because of Json serialization From cb1addd5e3d77e1c9bcef19a7290e1c6a2956f62 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 9 Oct 2020 18:33:32 +0200 Subject: [PATCH 21/27] Push test now does not display notification anymore. Add a dedicated test to do it --- ...ificationTroubleshootTestManagerFactory.kt | 19 ++++--- .../troubleshoot/TestPushFromPushGateway.kt | 10 ++-- .../fcm/VectorFirebaseMessagingService.kt | 7 ++- ...ificationTroubleshootTestManagerFactory.kt | 5 +- .../im/vector/app/core/utils/SystemUtils.kt | 8 +-- .../notifications/NotificationUtils.kt | 1 + ...ttingsNotificationsTroubleshootFragment.kt | 20 +++++-- .../NotificationTroubleshootTestManager.kt | 4 ++ .../settings/troubleshoot/TestNotification.kt | 54 +++++++++++++++++++ .../troubleshoot/TestSystemSettings.kt | 4 +- .../settings/troubleshoot/TroubleshootTest.kt | 3 ++ vector/src/main/res/values/strings.xml | 9 ++-- 12 files changed, 117 insertions(+), 27 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotification.kt diff --git a/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt index 65b8609446..6236aad65c 100644 --- a/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt @@ -22,17 +22,21 @@ import im.vector.app.fdroid.features.settings.troubleshoot.TestBatteryOptimizati import im.vector.app.features.settings.troubleshoot.NotificationTroubleshootTestManager import im.vector.app.features.settings.troubleshoot.TestAccountSettings import im.vector.app.features.settings.troubleshoot.TestDeviceSettings +import im.vector.app.features.settings.troubleshoot.TestNotification import im.vector.app.features.settings.troubleshoot.TestPushRulesSettings import im.vector.app.features.settings.troubleshoot.TestSystemSettings import javax.inject.Inject -class NotificationTroubleshootTestManagerFactory @Inject constructor(private val testSystemSettings: TestSystemSettings, - private val testAccountSettings: TestAccountSettings, - private val testDeviceSettings: TestDeviceSettings, - private val testPushRulesSettings: TestPushRulesSettings, - private val testAutoStartBoot: TestAutoStartBoot, - private val testBackgroundRestrictions: TestBackgroundRestrictions, - private val testBatteryOptimization: TestBatteryOptimization) { +class NotificationTroubleshootTestManagerFactory @Inject constructor( + private val testSystemSettings: TestSystemSettings, + private val testAccountSettings: TestAccountSettings, + private val testDeviceSettings: TestDeviceSettings, + private val testPushRulesSettings: TestPushRulesSettings, + private val testAutoStartBoot: TestAutoStartBoot, + private val testBackgroundRestrictions: TestBackgroundRestrictions, + private val testBatteryOptimization: TestBatteryOptimization, + private val testNotification: TestNotification +) { fun create(fragment: Fragment): NotificationTroubleshootTestManager { val mgr = NotificationTroubleshootTestManager(fragment) @@ -43,6 +47,7 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor(private val mgr.addTest(testAutoStartBoot) mgr.addTest(testBackgroundRestrictions) mgr.addTest(testBatteryOptimization) + mgr.addTest(testNotification) return mgr } } diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt index ce94244ee6..da93d54075 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestPushFromPushGateway.kt @@ -56,15 +56,15 @@ class TestPushFromPushGateway @Inject constructor(private val context: AppCompat } override fun onSuccess(data: Unit) { - // Wait for user to click on the notification - description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_success) - status = TestStatus.WAITING_FOR_USER + // Wait for the push to be received + description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_waiting_for_push) + status = TestStatus.RUNNING } }) } - override fun onNotificationClicked() { - description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_notification_clicked) + override fun onPushReceived() { + description = stringProvider.getString(R.string.settings_troubleshoot_test_push_loop_success) status = TestStatus.SUCCESS } diff --git a/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt b/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt index 801b85ce0c..cfd241d4f9 100755 --- a/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt @@ -19,10 +19,12 @@ package im.vector.app.gplay.push.fcm +import android.content.Intent import android.os.Handler import android.os.Looper import androidx.lifecycle.Lifecycle import androidx.lifecycle.ProcessLifecycleOwner +import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import im.vector.app.BuildConfig @@ -34,6 +36,7 @@ import im.vector.app.features.badge.BadgeProxy import im.vector.app.features.notifications.NotifiableEventResolver import im.vector.app.features.notifications.NotifiableMessageEvent import im.vector.app.features.notifications.NotificationDrawerManager +import im.vector.app.features.notifications.NotificationUtils import im.vector.app.features.notifications.SimpleNotifiableEvent import im.vector.app.features.settings.VectorPreferences import im.vector.app.push.fcm.FcmHelper @@ -77,8 +80,8 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { override fun onMessageReceived(message: RemoteMessage) { // Diagnostic Push if (message.data["event_id"] == PushersManager.TEST_EVENT_ID) { - // Display the notification right now - notificationDrawerManager.displayDiagnosticNotification() + val intent = Intent(NotificationUtils.PUSH_ACTION) + LocalBroadcastManager.getInstance(this).sendBroadcast(intent) return } diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt index 46c78a9872..e96c603e60 100644 --- a/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt @@ -19,6 +19,7 @@ import androidx.fragment.app.Fragment import im.vector.app.features.settings.troubleshoot.NotificationTroubleshootTestManager import im.vector.app.features.settings.troubleshoot.TestAccountSettings import im.vector.app.features.settings.troubleshoot.TestDeviceSettings +import im.vector.app.features.settings.troubleshoot.TestNotification import im.vector.app.features.settings.troubleshoot.TestPushRulesSettings import im.vector.app.features.settings.troubleshoot.TestSystemSettings import im.vector.app.gplay.features.settings.troubleshoot.TestFirebaseToken @@ -35,7 +36,8 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( private val testPlayServices: TestPlayServices, private val testFirebaseToken: TestFirebaseToken, private val testTokenRegistration: TestTokenRegistration, - private val testPushFromPushGateway: TestPushFromPushGateway + private val testPushFromPushGateway: TestPushFromPushGateway, + private val testNotification: TestNotification ) { fun create(fragment: Fragment): NotificationTroubleshootTestManager { @@ -48,6 +50,7 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( mgr.addTest(testFirebaseToken) mgr.addTest(testTokenRegistration) mgr.addTest(testPushFromPushGateway) + mgr.addTest(testNotification) return mgr } } diff --git a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt index 5e722ae209..2b8df67012 100644 --- a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt +++ b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt @@ -97,15 +97,15 @@ fun copyToClipboard(context: Context, text: CharSequence, showToast: Boolean = t * Shows notification settings for the current app. * In android O will directly opens the notification settings, in lower version it will show the App settings */ -fun startNotificationSettingsIntent(activity: AppCompatActivity, activityResultLauncher: ActivityResultLauncher) { +fun startNotificationSettingsIntent(context: Context, activityResultLauncher: ActivityResultLauncher) { val intent = Intent() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS - intent.putExtra(Settings.EXTRA_APP_PACKAGE, activity.packageName) + intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) } else { intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS - intent.putExtra("app_package", activity.packageName) - intent.putExtra("app_uid", activity.applicationInfo?.uid) + intent.putExtra("app_package", context.packageName) + intent.putExtra("app_uid", context.applicationInfo?.uid) } activityResultLauncher.launch(intent) } diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt index a30d4302f2..44eb278c64 100755 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt @@ -92,6 +92,7 @@ class NotificationUtils @Inject constructor(private val context: Context, const val DISMISS_ROOM_NOTIF_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.DISMISS_ROOM_NOTIF_ACTION" private const val TAP_TO_VIEW_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.TAP_TO_VIEW_ACTION" const val DIAGNOSTIC_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationActions.DIAGNOSTIC" + const val PUSH_ACTION = "${BuildConfig.APPLICATION_ID}.PUSH" /* ========================================================================================== * IDs for channels diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt index 4843c1446a..9dc6dc1751 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsNotificationsTroubleshootFragment.kt @@ -166,7 +166,11 @@ class VectorSettingsNotificationsTroubleshootFragment @Inject constructor( tryOrNull("Unable to register the receiver") { LocalBroadcastManager.getInstance(requireContext()) - .registerReceiver(broadcastReceiver, IntentFilter(NotificationUtils.DIAGNOSTIC_ACTION)) + .registerReceiver(broadcastReceiverPush, IntentFilter(NotificationUtils.PUSH_ACTION)) + } + tryOrNull("Unable to register the receiver") { + LocalBroadcastManager.getInstance(requireContext()) + .registerReceiver(broadcastReceiverNotification, IntentFilter(NotificationUtils.DIAGNOSTIC_ACTION)) } } @@ -174,11 +178,21 @@ class VectorSettingsNotificationsTroubleshootFragment @Inject constructor( super.onPause() tryOrNull { LocalBroadcastManager.getInstance(requireContext()) - .unregisterReceiver(broadcastReceiver) + .unregisterReceiver(broadcastReceiverPush) + } + tryOrNull { + LocalBroadcastManager.getInstance(requireContext()) + .unregisterReceiver(broadcastReceiverNotification) } } - private val broadcastReceiver = object : BroadcastReceiver() { + private val broadcastReceiverPush = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + testManager?.onDiagnosticPushReceived() + } + } + + private val broadcastReceiverNotification = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { testManager?.onDiagnosticNotificationClicked() } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt index 566cb6d846..7e7ca57243 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/NotificationTroubleshootTestManager.kt @@ -106,6 +106,10 @@ class NotificationTroubleshootTestManager(val fragment: Fragment) { testList.forEach { it.cancel() } } + fun onDiagnosticPushReceived() { + testList.forEach { it.onPushReceived() } + } + fun onDiagnosticNotificationClicked() { testList.forEach { it.onNotificationClicked() } } diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotification.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotification.kt new file mode 100644 index 0000000000..6f25ecfe39 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestNotification.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2018 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 im.vector.app.features.settings.troubleshoot + +import android.content.Context +import android.content.Intent +import androidx.activity.result.ActivityResultLauncher +import im.vector.app.R +import im.vector.app.core.resources.StringProvider +import im.vector.app.core.utils.startNotificationSettingsIntent +import im.vector.app.features.notifications.NotificationUtils +import javax.inject.Inject + +/** + * Checks if notifications can be displayed and clicked by the user + */ +class TestNotification @Inject constructor(private val context: Context, + private val notificationUtils: NotificationUtils, + private val stringProvider: StringProvider) + : TroubleshootTest(R.string.settings_troubleshoot_test_notification_title) { + + override fun perform(activityResultLauncher: ActivityResultLauncher) { + // Display the notification right now + notificationUtils.displayDiagnosticNotification() + description = stringProvider.getString(R.string.settings_troubleshoot_test_notification_notice) + + quickFix = object : TroubleshootQuickFix(R.string.open_settings) { + override fun doFix() { + startNotificationSettingsIntent(context, activityResultLauncher) + } + } + + status = TestStatus.WAITING_FOR_USER + } + + override fun onNotificationClicked() { + description = stringProvider.getString(R.string.settings_troubleshoot_test_notification_notification_clicked) + quickFix = null + status = TestStatus.SUCCESS + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestSystemSettings.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestSystemSettings.kt index 8e64514e7f..ee652288be 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestSystemSettings.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestSystemSettings.kt @@ -15,9 +15,9 @@ */ package im.vector.app.features.settings.troubleshoot +import android.content.Context import android.content.Intent import androidx.activity.result.ActivityResultLauncher -import androidx.appcompat.app.AppCompatActivity import androidx.core.app.NotificationManagerCompat import im.vector.app.R import im.vector.app.core.resources.StringProvider @@ -27,7 +27,7 @@ import javax.inject.Inject /** * Checks if notifications are enable in the system settings for this app. */ -class TestSystemSettings @Inject constructor(private val context: AppCompatActivity, +class TestSystemSettings @Inject constructor(private val context: Context, private val stringProvider: StringProvider) : TroubleshootTest(R.string.settings_troubleshoot_test_system_settings_title) { diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt index c775c8c827..76ba2378a0 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TroubleshootTest.kt @@ -53,6 +53,9 @@ abstract class TroubleshootTest(@StringRes val titleResId: Int) { open fun cancel() { } + open fun onPushReceived() { + } + open fun onNotificationClicked() { } } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index ef6b63aeb0..e400f7fe64 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -750,10 +750,13 @@ Failed to register FCM token to HomeServer:\n%1$s Test Push - The application is receiving PUSH, please click on the test notification you just received. - The notification has been clicked! + The application is waiting for the PUSH + The application is receiving PUSH Failed to receive push. Solution could be to reinstall the application. - You are receiving PUSH! Click me! + You are viewing the notification! Click me! + Notification Display + Please click on the notification. If you do not see the notification, please check the system settings. + The notification has been clicked! Notifications Service Notifications Service is running. From f8f091fa280926b394e34089d1f5117f741bef8c Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Mon, 12 Oct 2020 14:26:06 +0300 Subject: [PATCH 22/27] Benoit code review fixes. --- .../app/core/epoxy/ExpandableTextItem.kt | 19 ++++++++++++------- .../roomprofile/RoomProfileController.kt | 6 +++--- .../res/layout/item_expandable_textview.xml | 5 +++++ vector/src/main/res/values/strings.xml | 1 - 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt index 7e1114660f..3dceec48ef 100644 --- a/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt +++ b/vector/src/main/java/im/vector/app/core/epoxy/ExpandableTextItem.kt @@ -56,6 +56,7 @@ abstract class ExpandableTextItem : VectorEpoxyModel( expand(holder) } } + holder.arrow.isVisible = true } else { holder.arrow.isVisible = false } @@ -63,22 +64,26 @@ abstract class ExpandableTextItem : VectorEpoxyModel( } private fun expand(holder: Holder) { - ObjectAnimator.ofInt(holder.content, "maxLines", expandedLines) - .apply { duration = 200 } - .also { it.start() } + ObjectAnimator + .ofInt(holder.content, "maxLines", expandedLines) + .setDuration(200) + .start() holder.content.ellipsize = null holder.arrow.setImageResource(R.drawable.ic_expand_less) + holder.arrow.contentDescription = holder.view.context.getString(R.string.merged_events_collapse) isExpanded = true } private fun collapse(holder: Holder) { - ObjectAnimator.ofInt(holder.content, "maxLines", maxLines) - .apply { duration = 200 } - .also { it.start() } + ObjectAnimator + .ofInt(holder.content, "maxLines", maxLines) + .setDuration(200) + .start() holder.content.ellipsize = TextUtils.TruncateAt.END - holder.arrow.setImageResource(R.drawable.ic_expand_more) + holder.arrow.setImageResource(R.drawable.ic_expand_more) + holder.arrow.contentDescription = holder.view.context.getString(R.string.merged_events_expand) isExpanded = false } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt index ad774fbeef..7dc744da31 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt @@ -62,12 +62,12 @@ class RoomProfileController @Inject constructor( // Topic roomSummary .topic - .takeIf { it.isNotBlank() } + .takeIf { it.isNotEmpty() } ?.let { - buildProfileSection(stringProvider.getString(R.string.room_profile_section_topic)) + buildProfileSection(stringProvider.getString(R.string.room_settings_topic)) expandableTextItem { id("topic") - content(roomSummary.topic) + content(it) maxLines(2) } } diff --git a/vector/src/main/res/layout/item_expandable_textview.xml b/vector/src/main/res/layout/item_expandable_textview.xml index 34fbaf7ec0..b0c232d77e 100644 --- a/vector/src/main/res/layout/item_expandable_textview.xml +++ b/vector/src/main/res/layout/item_expandable_textview.xml @@ -23,7 +23,12 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" + android:autoLink="web" + android:fontFamily="sans-serif" + android:gravity="center" android:src="@drawable/ic_expand_more" + android:textSize="14sp" + android:textStyle="normal" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/expandableContent" diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 709bf4f4a1..d48162de29 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2124,7 +2124,6 @@ Messages here are not end-to-end encrypted. Messages in this room are end-to-end encrypted.\n\nYour messages are secured with locks and only you and the recipient have the unique keys to unlock them. Messages here are end-to-end encrypted.\n\nYour messages are secured with locks and only you and the recipient have the unique keys to unlock them. - Topic Security Learn more More From 17f0c2926409fee6ce33530d30f23bea6f553d34 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 12 Oct 2020 14:12:44 +0200 Subject: [PATCH 23/27] Fix lint false positive --- vector/src/main/AndroidManifest.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index 3f178a3d20..bc5577b467 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -94,9 +94,11 @@ + + android:theme="@style/AppTheme.Transparent" + tools:ignore="Instantiatable" /> Date: Mon, 12 Oct 2020 14:49:04 +0200 Subject: [PATCH 24/27] ktlint --- vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt index 2b8df67012..d228adab12 100644 --- a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt +++ b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt @@ -30,7 +30,6 @@ import android.provider.Settings import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.annotation.StringRes -import androidx.appcompat.app.AppCompatActivity import androidx.core.content.getSystemService import androidx.fragment.app.Fragment import im.vector.app.R From 69e624df4151a9dc66f0a474e093c4b37b2fa519 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 12 Oct 2020 17:10:22 +0200 Subject: [PATCH 25/27] Cross signing: we should not show the verify with other sessions when there is not --- .../VerificationBottomSheetViewModel.kt | 12 +++++-- .../request/VerificationRequestController.kt | 32 ++++++++++++------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt index 3c00478ab0..e65fb6042b 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt @@ -76,7 +76,8 @@ data class VerificationBottomSheetViewState( val userWantsToCancel: Boolean = false, val userThinkItsNotHim: Boolean = false, val quadSContainsSecrets: Boolean = true, - val quadSHasBeenReset: Boolean = false + val quadSHasBeenReset: Boolean = false, + val hasAnyOtherSession: Boolean = false ) : MvRxState class VerificationBottomSheetViewModel @AssistedInject constructor( @@ -119,6 +120,12 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( session.cryptoService().verificationService().getExistingTransaction(args.otherUserId, it) as? QrCodeVerificationTransaction } + val hasAnyOtherSession = session.cryptoService() + .getCryptoDeviceInfo(session.myUserId) + .any { + it.deviceId != session.sessionParams.deviceId + } + setState { copy( otherUserMxItem = userItem?.toMatrixItem(), @@ -130,7 +137,8 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( roomId = args.roomId, isMe = args.otherUserId == session.myUserId, currentDeviceCanCrossSign = session.cryptoService().crossSigningService().canCrossSign(), - quadSContainsSecrets = session.sharedSecretStorageService.isRecoverySetup() + quadSContainsSecrets = session.sharedSecretStorageService.isRecoverySetup(), + hasAnyOtherSession = hasAnyOtherSession ) } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt index 3f4c3120e7..1b2c32a7e4 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt @@ -52,25 +52,33 @@ class VerificationRequestController @Inject constructor( val matrixItem = viewState?.otherUserMxItem ?: return if (state.selfVerificationMode) { - bottomSheetVerificationNoticeItem { - id("notice") - notice(stringProvider.getString(R.string.verification_open_other_to_verify)) - } + if (state.hasAnyOtherSession) { - bottomSheetSelfWaitItem { - id("waiting") - } + bottomSheetVerificationNoticeItem { + id("notice") + notice(stringProvider.getString(R.string.verification_open_other_to_verify)) + } - dividerItem { - id("sep") + bottomSheetSelfWaitItem { + id("waiting") + } + + dividerItem { + id("sep") + } } if (state.quadSContainsSecrets) { + val subtitle = if (state.hasAnyOtherSession) { + stringProvider.getString(R.string.verification_use_passphrase) + } else { + null + } bottomSheetVerificationActionItem { id("passphrase") title(stringProvider.getString(R.string.verification_cannot_access_other_session)) titleColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)) - subTitle(stringProvider.getString(R.string.verification_use_passphrase)) + subTitle(subtitle) iconRes(R.drawable.ic_arrow_right) iconColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary)) listener { listener?.onClickRecoverFromPassphrase() } @@ -122,13 +130,13 @@ class VerificationRequestController @Inject constructor( listener { listener?.onClickOnVerificationStart() } } } - is Loading -> { + is Loading -> { bottomSheetVerificationWaitingItem { id("waiting") title(stringProvider.getString(R.string.verification_request_waiting_for, matrixItem.getBestName())) } } - is Success -> { + is Success -> { if (!pr.invoke().isReady) { if (state.isMe) { bottomSheetVerificationWaitingItem { From d8e9d363fa72733c833afac8b1fb365a411e9366 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 12 Oct 2020 17:15:38 +0200 Subject: [PATCH 26/27] Cross signing: update CHANGES and clean --- CHANGES.md | 1 + .../crypto/verification/request/VerificationRequestController.kt | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 74aaa8cee3..3bda0d9084 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Improvements 🙌: - Implement "Jump to read receipt" and "Mention" actions on the room member profile screen - Add Sygnal API implementation to test is Push are correctly received - Add PushGateway API implementation to test if Push are correctly received + - Cross signing: shouldn't offer to verify with other session when there is not. Bugfix 🐛: - Improve support for image/audio/video/file selection with intent changes (#1376) diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt index 1b2c32a7e4..6e98d924e7 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/request/VerificationRequestController.kt @@ -53,7 +53,6 @@ class VerificationRequestController @Inject constructor( if (state.selfVerificationMode) { if (state.hasAnyOtherSession) { - bottomSheetVerificationNoticeItem { id("notice") notice(stringProvider.getString(R.string.verification_open_other_to_verify)) From 5ad46d251daa6b0c8e68802921866295c75a951b Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 12 Oct 2020 17:57:09 +0200 Subject: [PATCH 27/27] Update CHANGES.md Co-authored-by: Benoit Marty --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 3bda0d9084..257837dc6a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,7 +19,7 @@ Improvements 🙌: - Implement "Jump to read receipt" and "Mention" actions on the room member profile screen - Add Sygnal API implementation to test is Push are correctly received - Add PushGateway API implementation to test if Push are correctly received - - Cross signing: shouldn't offer to verify with other session when there is not. + - Cross signing: shouldn't offer to verify with other session when there is not. (#2227) Bugfix 🐛: - Improve support for image/audio/video/file selection with intent changes (#1376)