From 1fa7b7367a71d9373b2c1c387c94796ed0783060 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 27 Jun 2019 15:25:01 +0200 Subject: [PATCH] Dagger: merge develop compiling now. --- .../java/im/vector/matrix/rx/RxSession.kt | 5 + .../matrix/android/api/session/Session.kt | 4 + .../internal/session/SessionComponent.kt | 17 +- .../notification/DefaultPushRuleService.kt | 5 +- .../internal/session/sync/job/SyncService.kt | 22 +- .../OnApplicationUpgradeOrRebootReceiver.kt | 8 +- .../vector/riotredesign/VectorApplication.kt | 7 +- .../riotredesign/core/di/ScreenComponent.kt | 3 + .../riotredesign/core/di/VectorComponent.kt | 6 + .../riotredesign/core/di/ViewModelModule.kt | 1 + .../core/pushers/PushersManager.kt | 3 +- .../core/resources/AppNameProvider.kt | 3 +- .../services/AlarmSyncBroadcastReceiver.kt | 16 +- .../core/services/EventStreamServiceX.kt | 587 ------------------ .../features/home/HomePermalinkHandler.kt | 57 -- .../features/home/PermalinkHandler.kt | 5 +- .../timeline/factory/EncryptedItemFactory.kt | 11 +- .../notifications/NotifiableEventResolver.kt | 27 +- .../NotificationBroadcastReceiver.kt | 12 +- .../notifications/OutdatedEventDetector.kt | 6 +- .../VectorSettingsNotificationFragment.kt | 19 +- .../VectorSettingsPreferencesFragment.kt | 44 +- .../settings/push/PushGatewaysFragment.kt | 3 +- .../settings/push/PushGatewaysViewModel.kt | 46 +- .../settings/push/PushRulesViewModel.kt | 7 +- 25 files changed, 192 insertions(+), 732 deletions(-) delete mode 100644 vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt delete mode 100644 vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index 4205b049..af149116 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -18,6 +18,7 @@ package im.vector.matrix.rx import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.group.model.GroupSummary +import im.vector.matrix.android.api.session.pushers.Pusher import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.sync.SyncState import io.reactivex.Observable @@ -36,6 +37,10 @@ class RxSession(private val session: Session) { return session.syncState().asObservable() } + fun livePushers(): Observable> { + return session.livePushers().asObservable() + } + } fun Session.rx(): RxSession { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt index ac412678..d947e593 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt @@ -54,6 +54,10 @@ interface Session : */ val sessionParams: SessionParams + val myUserId : String + get() = sessionParams.credentials.userId + + /** * This method allow to open a session. It does start some service on the background. */ diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt index 0cb78026..fc23b780 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionComponent.kt @@ -22,6 +22,7 @@ import im.vector.matrix.android.api.auth.data.SessionParams import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.internal.crypto.CryptoModule import im.vector.matrix.android.internal.di.MatrixComponent +import im.vector.matrix.android.internal.network.NetworkConnectivityChecker import im.vector.matrix.android.internal.session.cache.CacheModule import im.vector.matrix.android.internal.session.content.ContentModule import im.vector.matrix.android.internal.session.content.UploadContentWorker @@ -37,8 +38,11 @@ import im.vector.matrix.android.internal.session.room.send.RedactEventWorker import im.vector.matrix.android.internal.session.room.send.SendEventWorker import im.vector.matrix.android.internal.session.signout.SignOutModule import im.vector.matrix.android.internal.session.sync.SyncModule +import im.vector.matrix.android.internal.session.sync.SyncTask +import im.vector.matrix.android.internal.session.sync.SyncTokenStore import im.vector.matrix.android.internal.session.sync.job.SyncWorker import im.vector.matrix.android.internal.session.user.UserModule +import im.vector.matrix.android.internal.task.TaskExecutor @Component(dependencies = [MatrixComponent::class], modules = [ @@ -61,6 +65,14 @@ internal interface SessionComponent { fun session(): Session + fun syncTask(): SyncTask + + fun syncTokenStore(): SyncTokenStore + + fun networkConnectivityChecker(): NetworkConnectivityChecker + + fun taskExecutor(): TaskExecutor + fun inject(sendEventWorker: SendEventWorker) fun inject(sendEventWorker: SendRelationWorker) @@ -77,7 +89,6 @@ internal interface SessionComponent { fun inject(addHttpPusherWorker: AddHttpPusherWorker) - @Component.Factory interface Factory { fun create( @@ -86,4 +97,6 @@ internal interface SessionComponent { } -} \ No newline at end of file +} + + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt index 9b947829..e8ef2f7d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/notification/DefaultPushRuleService.kt @@ -27,6 +27,7 @@ import im.vector.matrix.android.internal.database.mapper.PushRulesMapper import im.vector.matrix.android.internal.database.model.PushRulesEntity import im.vector.matrix.android.internal.database.model.PusherEntityFields import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.pushers.GetPushRulesTask import im.vector.matrix.android.internal.session.pushers.UpdatePushRuleEnableStatusTask import im.vector.matrix.android.internal.task.TaskExecutor @@ -34,7 +35,7 @@ import im.vector.matrix.android.internal.task.configureWith import timber.log.Timber import javax.inject.Inject - +@SessionScope internal class DefaultPushRuleService @Inject constructor( private val sessionParams: SessionParams, private val pushRulesTask: GetPushRulesTask, @@ -43,10 +44,8 @@ internal class DefaultPushRuleService @Inject constructor( private val monarchy: Monarchy ) : PushRuleService { - private var listeners = ArrayList() - override fun fetchPushRules(scope: String) { pushRulesTask .configureWith(Unit) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt index a1872d0a..2fa0d494 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncService.kt @@ -19,7 +19,9 @@ import android.app.Service import android.content.Intent import android.os.Binder import android.os.IBinder +import androidx.work.ListenableWorker import com.squareup.moshi.JsonEncodingException +import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.failure.MatrixError @@ -31,6 +33,7 @@ import im.vector.matrix.android.internal.session.sync.model.SyncResponse import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskThread import im.vector.matrix.android.internal.task.configureWith +import im.vector.matrix.android.internal.worker.getSessionComponent import timber.log.Timber import java.net.SocketTimeoutException import java.util.* @@ -46,15 +49,15 @@ private const val BACKGROUND_LONG_POOL_TIMEOUT = 0L * in order to be able to perform a sync even if the app is not running. * The and must be declared in the Manifest or the app using the SDK */ -internal open class SyncService : Service() { +open class SyncService : Service() { private var mIsSelfDestroyed: Boolean = false private var cancelableTask: Cancelable? = null - @Inject lateinit var syncTokenStore: SyncTokenStore - @Inject lateinit var syncTask: SyncTask - @Inject lateinit var networkConnectivityChecker: NetworkConnectivityChecker - @Inject lateinit var taskExecutor: TaskExecutor + private lateinit var syncTokenStore: SyncTokenStore + private lateinit var syncTask: SyncTask + private lateinit var networkConnectivityChecker: NetworkConnectivityChecker + private lateinit var taskExecutor: TaskExecutor private var localBinder = LocalBinder() @@ -68,6 +71,12 @@ internal open class SyncService : Service() { nextBatchDelay = 60_000L timeout = 0 intent?.let { + val userId = it.getStringExtra(EXTRA_USER_ID) + val sessionComponent = Matrix.getInstance(applicationContext).sessionManager.getSessionComponent(userId) ?: return@let + syncTokenStore = sessionComponent.syncTokenStore() + syncTask = sessionComponent.syncTask() + networkConnectivityChecker = sessionComponent.networkConnectivityChecker() + taskExecutor = sessionComponent.taskExecutor() if (cancelableTask == null) { timer.cancel() timer = Timer() @@ -191,7 +200,6 @@ internal open class SyncService : Service() { } internal fun notifySyncFinish() { - listeners.forEach { try { it.onSyncFinsh() @@ -235,6 +243,8 @@ internal open class SyncService : Service() { companion object { + const val EXTRA_USER_ID = "EXTRA_USER_ID" + fun startLongPool(delay: Long) { } diff --git a/vector/src/fdroid/java/im/vector/riotredesign/receiver/OnApplicationUpgradeOrRebootReceiver.kt b/vector/src/fdroid/java/im/vector/riotredesign/receiver/OnApplicationUpgradeOrRebootReceiver.kt index a13bc71a..c8a64e39 100644 --- a/vector/src/fdroid/java/im/vector/riotredesign/receiver/OnApplicationUpgradeOrRebootReceiver.kt +++ b/vector/src/fdroid/java/im/vector/riotredesign/receiver/OnApplicationUpgradeOrRebootReceiver.kt @@ -20,6 +20,7 @@ package im.vector.riotredesign.receiver import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import im.vector.riotredesign.core.di.HasVectorInjector import im.vector.riotredesign.core.services.AlarmSyncBroadcastReceiver import timber.log.Timber @@ -27,6 +28,11 @@ class OnApplicationUpgradeOrRebootReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Timber.v("## onReceive() ${intent.action}") - AlarmSyncBroadcastReceiver.scheduleAlarm(context, 10) + if (context is HasVectorInjector) { + val activeSession = context.injector().activeSessionHolder().getSafeActiveSession() + if (activeSession != null) { + AlarmSyncBroadcastReceiver.scheduleAlarm(context, activeSession.myUserId, 10) + } + } } } diff --git a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt index 61754276..e6f65fbc 100644 --- a/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt +++ b/vector/src/main/java/im/vector/riotredesign/VectorApplication.kt @@ -114,7 +114,7 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration. @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun entersForeground() { AlarmSyncBroadcastReceiver.cancelAlarm(appContext) - activeSessionHolder.getActiveSession().also { + activeSessionHolder.getSafeActiveSession()?.also { it.stopAnyBackgroundSync() } } @@ -128,8 +128,9 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration. } else { //TODO check if notifications are enabled for this device //We need to use alarm in this mode - if (PreferencesManager.areNotificationEnabledForDevice(applicationContext)) { - AlarmSyncBroadcastReceiver.scheduleAlarm(applicationContext, 4_000L) + val activeSession = activeSessionHolder.getSafeActiveSession() + if (activeSession != null && PreferencesManager.areNotificationEnabledForDevice(applicationContext)) { + AlarmSyncBroadcastReceiver.scheduleAlarm(applicationContext, activeSession.myUserId, 4_000L) Timber.i("Alarm scheduled to restart service") } } diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt index 7bceedc8..8f3a3180 100644 --- a/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt +++ b/vector/src/main/java/im/vector/riotredesign/core/di/ScreenComponent.kt @@ -53,6 +53,7 @@ import im.vector.riotredesign.features.roomdirectory.createroom.CreateRoomFragme import im.vector.riotredesign.features.roomdirectory.picker.RoomDirectoryPickerFragment import im.vector.riotredesign.features.roomdirectory.roompreview.RoomPreviewNoPreviewFragment import im.vector.riotredesign.features.settings.VectorSettingsActivity +import im.vector.riotredesign.features.settings.VectorSettingsNotificationPreferenceFragment import im.vector.riotredesign.features.settings.VectorSettingsPreferencesFragment @Component(dependencies = [VectorComponent::class], modules = [ViewModelModule::class, HomeModule::class]) @@ -133,6 +134,8 @@ interface ScreenComponent { fun inject(videoMediaViewerActivity: VideoMediaViewerActivity) + fun inject(vectorSettingsNotificationPreferenceFragment: VectorSettingsNotificationPreferenceFragment) + @Component.Factory interface Factory { fun create(vectorComponent: VectorComponent, diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt index 54321160..5be30bb0 100644 --- a/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt +++ b/vector/src/main/java/im/vector/riotredesign/core/di/VectorComponent.kt @@ -33,7 +33,9 @@ import im.vector.riotredesign.features.home.HomeNavigator import im.vector.riotredesign.features.home.HomeRoomListObservableStore import im.vector.riotredesign.features.home.group.SelectedGroupStore import im.vector.riotredesign.features.navigation.Navigator +import im.vector.riotredesign.features.notifications.NotificationBroadcastReceiver import im.vector.riotredesign.features.notifications.NotificationDrawerManager +import im.vector.riotredesign.features.notifications.PushRuleTriggerListener import im.vector.riotredesign.features.rageshake.BugReporter import im.vector.riotredesign.features.rageshake.RageShake import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler @@ -43,6 +45,8 @@ import javax.inject.Singleton @Singleton interface VectorComponent { + fun inject(vectorApplication: NotificationBroadcastReceiver) + fun inject(vectorApplication: VectorApplication) fun matrix(): Matrix @@ -79,6 +83,8 @@ interface VectorComponent { fun vectorUncaughtExceptionHandler(): VectorUncaughtExceptionHandler + fun pushRuleTriggerListener(): PushRuleTriggerListener + @Component.Factory interface Factory { fun create(@BindsInstance context: Context): VectorComponent diff --git a/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt b/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt index 34b3e150..df984d23 100644 --- a/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt +++ b/vector/src/main/java/im/vector/riotredesign/core/di/ViewModelModule.kt @@ -57,6 +57,7 @@ import im.vector.riotredesign.features.workers.signout.SignOutViewModel @Module interface ViewModelModule { + @Binds fun bindViewModelFactory(factory: VectorViewModelFactory): ViewModelProvider.Factory diff --git a/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt b/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt index 1182efb1..777e04ca 100644 --- a/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt +++ b/vector/src/main/java/im/vector/riotredesign/core/pushers/PushersManager.kt @@ -6,10 +6,11 @@ import im.vector.riotredesign.R import im.vector.riotredesign.core.resources.AppNameProvider import im.vector.riotredesign.core.resources.LocaleProvider import im.vector.riotredesign.core.resources.StringProvider +import javax.inject.Inject private const val DEFAULT_PUSHER_FILE_TAG = "mobile" -class PushersManager( +class PushersManager @Inject constructor( private val currentSession: Session, private val localeProvider: LocaleProvider, private val stringProvider: StringProvider, diff --git a/vector/src/main/java/im/vector/riotredesign/core/resources/AppNameProvider.kt b/vector/src/main/java/im/vector/riotredesign/core/resources/AppNameProvider.kt index 4adfde79..1c7b9225 100644 --- a/vector/src/main/java/im/vector/riotredesign/core/resources/AppNameProvider.kt +++ b/vector/src/main/java/im/vector/riotredesign/core/resources/AppNameProvider.kt @@ -2,9 +2,10 @@ package im.vector.riotredesign.core.resources import android.content.Context import timber.log.Timber +import javax.inject.Inject -class AppNameProvider(private val context: Context) { +class AppNameProvider @Inject constructor(private val context: Context) { fun getAppName(): String { try { diff --git a/vector/src/main/java/im/vector/riotredesign/core/services/AlarmSyncBroadcastReceiver.kt b/vector/src/main/java/im/vector/riotredesign/core/services/AlarmSyncBroadcastReceiver.kt index f89f39e3..6c6a3f67 100644 --- a/vector/src/main/java/im/vector/riotredesign/core/services/AlarmSyncBroadcastReceiver.kt +++ b/vector/src/main/java/im/vector/riotredesign/core/services/AlarmSyncBroadcastReceiver.kt @@ -8,6 +8,7 @@ import android.content.Intent import android.os.Build import android.os.PowerManager import androidx.core.content.ContextCompat +import im.vector.matrix.android.internal.session.sync.job.SyncService import timber.log.Timber class AlarmSyncBroadcastReceiver : BroadcastReceiver() { @@ -22,11 +23,12 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() { } } - + val userId = intent.getStringExtra(SyncService.EXTRA_USER_ID) // This method is called when the BroadcastReceiver is receiving an Intent broadcast. Timber.d("RestartBroadcastReceiver received intent") Intent(context, VectorSyncService::class.java).also { it.action = "SLOW" + it.putExtra(SyncService.EXTRA_USER_ID, userId) context.startService(it) try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -40,7 +42,7 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() { } } - scheduleAlarm(context, 30_000L) + scheduleAlarm(context, userId, 30_000L) Timber.i("Alarm scheduled to restart service") } @@ -48,11 +50,13 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() { companion object { const val REQUEST_CODE = 0 - fun scheduleAlarm(context: Context, delay: Long) { + fun scheduleAlarm(context: Context, userId: String, delay: Long) { //Reschedule - val intent = Intent(context, AlarmSyncBroadcastReceiver::class.java) + val intent = Intent(context, AlarmSyncBroadcastReceiver::class.java).apply { + putExtra(SyncService.EXTRA_USER_ID, userId) + } val pIntent = PendingIntent.getBroadcast(context, AlarmSyncBroadcastReceiver.REQUEST_CODE, - intent, PendingIntent.FLAG_UPDATE_CURRENT) + intent, PendingIntent.FLAG_UPDATE_CURRENT) val firstMillis = System.currentTimeMillis() + delay val alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { @@ -65,7 +69,7 @@ class AlarmSyncBroadcastReceiver : BroadcastReceiver() { fun cancelAlarm(context: Context) { val intent = Intent(context, AlarmSyncBroadcastReceiver::class.java) val pIntent = PendingIntent.getBroadcast(context, AlarmSyncBroadcastReceiver.REQUEST_CODE, - intent, PendingIntent.FLAG_UPDATE_CURRENT) + intent, PendingIntent.FLAG_UPDATE_CURRENT) val alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmMgr.cancel(pIntent) } diff --git a/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt b/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt deleted file mode 100644 index 6c4b7043..00000000 --- a/vector/src/main/java/im/vector/riotredesign/core/services/EventStreamServiceX.kt +++ /dev/null @@ -1,587 +0,0 @@ -/* - * Copyright 2019 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.riotredesign.core.services - -import android.content.Context -import android.content.Intent -import androidx.core.content.ContextCompat -import androidx.work.Constraints -import androidx.work.NetworkType -import androidx.work.OneTimeWorkRequestBuilder -import androidx.work.WorkManager -import im.vector.matrix.android.api.session.Session -import im.vector.matrix.android.api.session.events.model.Event -import im.vector.riotredesign.R -import im.vector.riotredesign.features.notifications.NotifiableEventResolver -import im.vector.riotredesign.features.notifications.NotificationUtils -import timber.log.Timber -import java.util.concurrent.TimeUnit -import javax.inject.Inject - -/** - * A service in charge of controlling whether the event stream is running or not. - * - * It manages messages notifications displayed to the end user. - */ -class EventStreamServiceX : VectorService() { - - /** - * Managed session (no multi session for Riot) - */ - @Inject lateinit var session: Session - - /** - * Set to true to simulate a push immediately when service is destroyed - */ - private var mSimulatePushImmediate = false - - /** - * The current state. - */ - private var serviceState = ServiceState.INIT - set(newServiceState) { - Timber.i("setServiceState from $field to $newServiceState") - field = newServiceState - } - - /** - * Push manager - */ - // TODO private var mPushManager: PushManager? = null - - private var mNotifiableEventResolver: NotifiableEventResolver? = null - - /** - * Live events listener - */ - /* TODO - private val mEventsListener = object : MXEventListener() { - override fun onBingEvent(event: Event, roomState: RoomState, bingRule: BingRule) { - if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) { - Timber.i("%%%%%%%% MXEventListener: the event $event") - } - - Timber.i("prepareNotification : " + event.eventId + " in " + roomState.roomId) - val session = Matrix.getMXSession(applicationContext, event.matrixId) - - // invalid session ? - // should never happen. - // But it could be triggered because of multi accounts management. - // The dedicated account is removing but some pushes are still received. - if (null == session || !session.isAlive) { - Timber.i("prepareNotification : don't bing - no session") - return - } - - if (EventType.CALL_INVITE == event.getClearType()) { - handleCallInviteEvent(event) - return - } - - - val notifiableEvent = mNotifiableEventResolver!!.resolveEvent(event, roomState, bingRule, session) - if (notifiableEvent != null) { - VectorApp.getInstance().notificationDrawerManager.onNotifiableEventReceived(notifiableEvent) - } - } - - override fun onLiveEventsChunkProcessed(fromToken: String, toToken: String) { - Timber.i("%%%%%%%% MXEventListener: onLiveEventsChunkProcessed[$fromToken->$toToken]") - - VectorApp.getInstance().notificationDrawerManager.refreshNotificationDrawer(OutdatedEventDetector(this@EventStreamServiceX)) - - // do not suspend the application if there is some active calls - if (ServiceState.CATCHUP == serviceState) { - val hasActiveCalls = session?.mCallsManager?.hasActiveCalls() == true - - // if there are some active calls, the catchup should not be stopped. - // because an user could answer to a call from another device. - // there will no push because it is his own message. - // so, the client has no choice to catchup until the ring is shutdown - if (hasActiveCalls) { - Timber.i("onLiveEventsChunkProcessed : Catchup again because there are active calls") - catchup(false) - } else if (ServiceState.CATCHUP == serviceState) { - Timber.i("onLiveEventsChunkProcessed : no Active call") - CallsManager.getSharedInstance().checkDeadCalls() - stop() - } - } - } - } */ - - /** - * Service internal state - */ - private enum class ServiceState { - // Initial state - INIT, - // Service is started for a Catchup. Once the catchup is finished the service will be stopped - CATCHUP, - // Service is started, and session is monitored - STARTED - } - - override fun onCreate() { - //setup injector - super.onCreate() - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - // Cancel any previous worker - cancelAnySimulatedPushSchedule() - - // no intent : restarted by Android - if (null == intent) { - // Cannot happen anymore - Timber.e("onStartCommand : null intent") - myStopSelf() - return START_NOT_STICKY - } - - val action = intent.action - - Timber.i("onStartCommand with action : $action (current state $serviceState)") - - // Manage foreground notification - when (action) { - ACTION_BOOT_COMPLETE, - ACTION_APPLICATION_UPGRADE, - ACTION_SIMULATED_PUSH_RECEIVED -> { - // Display foreground notification - Timber.i("startForeground") - val notification = NotificationUtils.buildForegroundServiceNotification(this, R.string.notification_sync_in_progress) - startForeground(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification) - } - ACTION_GO_TO_FOREGROUND -> { - // Stop foreground notification display - Timber.i("stopForeground") - stopForeground(true) - } - } - - if (null == session) { - Timber.e("onStartCommand : no sessions") - myStopSelf() - return START_NOT_STICKY - } - - when (action) { - ACTION_START, - ACTION_GO_TO_FOREGROUND -> - when (serviceState) { - ServiceState.INIT -> - start(false) - ServiceState.CATCHUP -> - // A push has been received before, just change state, to avoid stopping the service when catchup is over - serviceState = ServiceState.STARTED - ServiceState.STARTED -> { - // Nothing to do - } - } - ACTION_STOP, - ACTION_GO_TO_BACKGROUND, - ACTION_LOGOUT -> - stop() - ACTION_PUSH_RECEIVED, - ACTION_SIMULATED_PUSH_RECEIVED -> - when (serviceState) { - ServiceState.INIT -> - start(true) - ServiceState.CATCHUP -> - catchup(true) - ServiceState.STARTED -> - // Nothing to do - Unit - } - ACTION_PUSH_UPDATE -> pushStatusUpdate() - ACTION_BOOT_COMPLETE -> { - // No FCM only - mSimulatePushImmediate = true - stop() - } - ACTION_APPLICATION_UPGRADE -> { - // FDroid only - catchup(true) - } - else -> { - // Should not happen - } - } - - // We don't want the service to be restarted automatically by the System - return START_NOT_STICKY - } - - override fun onDestroy() { - super.onDestroy() - - // Schedule worker? - scheduleSimulatedPushIfNeeded() - } - - /** - * Tell the WorkManager to cancel any schedule of push simulation - */ - private fun cancelAnySimulatedPushSchedule() { - WorkManager.getInstance().cancelAllWorkByTag(PUSH_SIMULATOR_REQUEST_TAG) - } - - /** - * Configure the WorkManager to schedule a simulated push, if necessary - */ - private fun scheduleSimulatedPushIfNeeded() { - if (shouldISimulatePush()) { - val delay = if (mSimulatePushImmediate) 0 else 60_000 // TODO mPushManager?.backgroundSyncDelay ?: let { 60_000 } - Timber.i("## service is schedule to restart in $delay millis, if network is connected") - - val pushSimulatorRequest = OneTimeWorkRequestBuilder() - .setInitialDelay(delay.toLong(), TimeUnit.MILLISECONDS) - .setConstraints(Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build()) - .addTag(PUSH_SIMULATOR_REQUEST_TAG) - .build() - - WorkManager.getInstance().let { - // Cancel any previous worker - it.cancelAllWorkByTag(PUSH_SIMULATOR_REQUEST_TAG) - it.enqueue(pushSimulatorRequest) - } - } - } - - /** - * Start the even stream. - * - * @param session the session - */ - private fun startEventStream(session: Session) { - /* TODO - // resume if it was only suspended - if (null != session.currentSyncToken) { - session.resumeEventStream() - } else { - session.startEventStream(store?.eventStreamToken) - } - */ - } - - /** - * Monitor the provided session. - * - * @param session the session - */ - private fun monitorSession(session: Session) { - /* TODO - session.dataHandler.addListener(mEventsListener) - CallsManager.getSharedInstance().addSession(session) - - val store = session.dataHandler.store - - // the store is ready (no data loading in progress...) - if (store!!.isReady) { - startEventStream(session, store) - } else { - // wait that the store is ready before starting the events stream - store.addMXStoreListener(object : MXStoreListener() { - override fun onStoreReady(accountId: String) { - startEventStream(session, store) - - store.removeMXStoreListener(this) - } - - override fun onStoreCorrupted(accountId: String, description: String) { - // start a new initial sync - if (null == store.eventStreamToken) { - startEventStream(session, store) - } else { - // the data are out of sync - Matrix.getInstance(applicationContext)!!.reloadSessions(applicationContext) - } - - store.removeMXStoreListener(this) - } - - override fun onStoreOOM(accountId: String, description: String) { - val uiHandler = Handler(mainLooper) - - uiHandler.post { - Toast.makeText(applicationContext, "$accountId : $description", Toast.LENGTH_LONG).show() - Matrix.getInstance(applicationContext)!!.reloadSessions(applicationContext) - } - } - }) - - store.open() - } - */ - } - - /** - * internal start. - */ - private fun start(forPush: Boolean) { - val applicationContext = applicationContext - // TODO mPushManager = Matrix.getInstance(applicationContext)!!.pushManager - mNotifiableEventResolver = NotifiableEventResolver(applicationContext) - - monitorSession(session!!) - - serviceState = if (forPush) { - ServiceState.CATCHUP - } else { - ServiceState.STARTED - } - } - - /** - * internal stop. - */ - private fun stop() { - Timber.i("## stop(): the service is stopped") - - /* TODO - if (null != session && session!!.isAlive) { - session!!.stopEventStream() - session!!.dataHandler.removeListener(mEventsListener) - CallsManager.getSharedInstance().removeSession(session) - } - session = null - */ - - // Stop the service - myStopSelf() - } - - /** - * internal catchup method. - * - * @param checkState true to check if the current state allow to perform a catchup - */ - private fun catchup(checkState: Boolean) { - var canCatchup = true - - if (!checkState) { - Timber.i("catchup without checking serviceState ") - } else { - Timber.i("catchup with serviceState " + serviceState + " CurrentActivity ") // TODO + VectorApp.getCurrentActivity()) - - /* TODO - // the catchup should only be done - // 1- the serviceState is in catchup : the event stream might have gone to sleep between two catchups - // 2- the thread is suspended - // 3- the application has been launched by a push so there is no displayed activity - canCatchup = (serviceState == ServiceState.CATCHUP - //|| (serviceState == ServiceState.PAUSE) - || ServiceState.STARTED == serviceState && null == VectorApp.getCurrentActivity()) - */ - } - - if (canCatchup) { - if (session != null) { - // TODO session!!.catchupEventStream() - } else { - Timber.i("catchup no session") - } - - serviceState = ServiceState.CATCHUP - } else { - Timber.i("No catchup is triggered because there is already a running event thread") - } - } - - /** - * The push status has been updated (i.e disabled or enabled). - * TODO Useless now? - */ - private fun pushStatusUpdate() { - Timber.i("## pushStatusUpdate") - } - - /* ========================================================================================== - * Push simulator - * ========================================================================================== */ - - /** - * @return true if the FCM is disable or not setup, user allowed background sync, user wants notification - */ - private fun shouldISimulatePush(): Boolean { - return false - - /* TODO - - if (Matrix.getInstance(applicationContext)?.defaultSession == null) { - Timber.i("## shouldISimulatePush: NO: no session") - - return false - } - - mPushManager?.let { pushManager -> - if (pushManager.useFcm() - && !TextUtils.isEmpty(pushManager.currentRegistrationToken) - && pushManager.isServerRegistered) { - // FCM is ok - Timber.i("## shouldISimulatePush: NO: FCM is up") - return false - } - - if (!pushManager.isBackgroundSyncAllowed) { - // User has disabled background sync - Timber.i("## shouldISimulatePush: NO: background sync not allowed") - return false - } - - if (!pushManager.areDeviceNotificationsAllowed()) { - // User does not want notifications - Timber.i("## shouldISimulatePush: NO: user does not want notification") - return false - } - } - - // Lets simulate push - Timber.i("## shouldISimulatePush: YES") - return true - */ - } - - - //================================================================================ - // Call management - //================================================================================ - - private fun handleCallInviteEvent(event: Event) { - /* - TODO - val session = Matrix.getMXSession(applicationContext, event.matrixId) - - // invalid session ? - // should never happen. - // But it could be triggered because of multi accounts management. - // The dedicated account is removing but some pushes are still received. - if (null == session || !session.isAlive) { - Timber.v("prepareCallNotification : don't bing - no session") - return - } - - val room: Room? = session.dataHandler.getRoom(event.roomId) - - // invalid room ? - if (null == room) { - Timber.i("prepareCallNotification : don't bing - the room does not exist") - return - } - - var callId: String? = null - var isVideo = false - - try { - callId = event.contentAsJsonObject?.get("call_id")?.asString - - // Check if it is a video call - val offer = event.contentAsJsonObject?.get("offer")?.asJsonObject - val sdp = offer?.get("sdp") - val sdpValue = sdp?.asString - - isVideo = sdpValue?.contains("m=video") == true - } catch (e: Exception) { - Timber.e(e, "prepareNotification : getContentAsJsonObject") - } - - if (!TextUtils.isEmpty(callId)) { - CallService.onIncomingCall(this, - isVideo, - room.getRoomDisplayName(this), - room.roomId, - session.myUserId!!, - callId!!) - } - */ - } - - companion object { - private const val PUSH_SIMULATOR_REQUEST_TAG = "PUSH_SIMULATOR_REQUEST_TAG" - - private const val ACTION_START = "im.vector.riotredesign.core.services.EventStreamServiceX.START" - private const val ACTION_LOGOUT = "im.vector.riotredesign.core.services.EventStreamServiceX.LOGOUT" - private const val ACTION_GO_TO_FOREGROUND = "im.vector.riotredesign.core.services.EventStreamServiceX.GO_TO_FOREGROUND" - private const val ACTION_GO_TO_BACKGROUND = "im.vector.riotredesign.core.services.EventStreamServiceX.GO_TO_BACKGROUND" - private const val ACTION_PUSH_UPDATE = "im.vector.riotredesign.core.services.EventStreamServiceX.PUSH_UPDATE" - private const val ACTION_PUSH_RECEIVED = "im.vector.riotredesign.core.services.EventStreamServiceX.PUSH_RECEIVED" - private const val ACTION_SIMULATED_PUSH_RECEIVED = "im.vector.riotredesign.core.services.EventStreamServiceX.SIMULATED_PUSH_RECEIVED" - private const val ACTION_STOP = "im.vector.riotredesign.core.services.EventStreamServiceX.STOP" - private const val ACTION_BOOT_COMPLETE = "im.vector.riotredesign.core.services.EventStreamServiceX.BOOT_COMPLETE" - private const val ACTION_APPLICATION_UPGRADE = "im.vector.riotredesign.core.services.EventStreamServiceX.APPLICATION_UPGRADE" - - /* ========================================================================================== - * Events sent to the service - * ========================================================================================== */ - - fun onApplicationStarted(context: Context) { - sendAction(context, ACTION_START) - } - - fun onLogout(context: Context) { - sendAction(context, ACTION_LOGOUT) - } - - fun onAppGoingToForeground(context: Context) { - sendAction(context, ACTION_GO_TO_FOREGROUND) - } - - fun onAppGoingToBackground(context: Context) { - sendAction(context, ACTION_GO_TO_BACKGROUND) - } - - fun onPushUpdate(context: Context) { - sendAction(context, ACTION_PUSH_UPDATE) - } - - fun onPushReceived(context: Context) { - sendAction(context, ACTION_PUSH_RECEIVED) - } - - fun onSimulatedPushReceived(context: Context) { - sendAction(context, ACTION_SIMULATED_PUSH_RECEIVED, true) - } - - fun onApplicationStopped(context: Context) { - sendAction(context, ACTION_STOP) - } - - fun onBootComplete(context: Context) { - sendAction(context, ACTION_BOOT_COMPLETE, true) - } - - fun onApplicationUpgrade(context: Context) { - sendAction(context, ACTION_APPLICATION_UPGRADE, true) - } - - private fun sendAction(context: Context, action: String, foreground: Boolean = false) { - Timber.i("sendAction $action") - - val intent = Intent(context, EventStreamServiceX::class.java) - intent.action = action - - if (foreground) { - ContextCompat.startForegroundService(context, intent) - } else { - context.startService(intent) - } - } - } -} diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt deleted file mode 100644 index 9041dec1..00000000 --- a/vector/src/main/java/im/vector/riotredesign/features/home/HomePermalinkHandler.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2019 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.riotredesign.features.home - -import android.net.Uri -import im.vector.matrix.android.api.permalinks.PermalinkData -import im.vector.matrix.android.api.permalinks.PermalinkParser -import im.vector.riotredesign.features.navigation.Navigator -import javax.inject.Inject - -class HomePermalinkHandler @Inject constructor(private val homeNavigator: HomeNavigator, - private val navigator: Navigator) { - - fun launch(deepLink: String?) { - val uri = deepLink?.let { Uri.parse(it) } - launch(uri) - } - - fun launch(deepLink: Uri?) { - if (deepLink == null) { - return - } - val permalinkData = PermalinkParser.parse(deepLink) - when (permalinkData) { - is PermalinkData.EventLink -> { - homeNavigator.openRoomDetail(permalinkData.roomIdOrAlias, permalinkData.eventId, navigator) - } - is PermalinkData.RoomLink -> { - homeNavigator.openRoomDetail(permalinkData.roomIdOrAlias, null, navigator) - } - is PermalinkData.GroupLink -> { - homeNavigator.openGroupDetail(permalinkData.groupId) - } - is PermalinkData.UserLink -> { - homeNavigator.openUserDetail(permalinkData.userId) - } - is PermalinkData.FallbackLink -> { - - } - } - } - -} \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/PermalinkHandler.kt b/vector/src/main/java/im/vector/riotredesign/features/home/PermalinkHandler.kt index 537f7f93..825e9748 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/home/PermalinkHandler.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/home/PermalinkHandler.kt @@ -22,9 +22,10 @@ import im.vector.matrix.android.api.permalinks.PermalinkData import im.vector.matrix.android.api.permalinks.PermalinkParser import im.vector.matrix.android.api.session.Session import im.vector.riotredesign.features.navigation.Navigator +import javax.inject.Inject -class PermalinkHandler(private val session: Session, - private val navigator: Navigator) { +class PermalinkHandler @Inject constructor(private val session: Session, + private val navigator: Navigator) { fun launch(context: Context, deepLink: String?, navigateToRoomInterceptor: NavigateToRoomInterceptor? = null): Boolean { val uri = deepLink?.let { Uri.parse(it) } diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt index c71d4a4c..44b1ed69 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt @@ -31,12 +31,13 @@ import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageTex import im.vector.riotredesign.features.home.room.detail.timeline.item.NoticeItem_ import im.vector.riotredesign.features.home.room.detail.timeline.util.MessageInformationDataFactory import me.gujun.android.span.span +import javax.inject.Inject // This class handles timeline events who haven't been successfully decrypted -class EncryptedItemFactory(private val messageInformationDataFactory: MessageInformationDataFactory, - private val colorProvider: ColorProvider, - private val stringProvider: StringProvider, - private val avatarRenderer: AvatarRenderer) { +class EncryptedItemFactory @Inject constructor(private val messageInformationDataFactory: MessageInformationDataFactory, + private val colorProvider: ColorProvider, + private val stringProvider: StringProvider, + private val avatarRenderer: AvatarRenderer) { fun create(event: TimelineEvent, nextEvent: TimelineEvent?, @@ -79,7 +80,7 @@ class EncryptedItemFactory(private val messageInformationDataFactory: MessageInf })) .longClickListener { view -> return@longClickListener callback?.onEventLongClicked(informationData, null, view) - ?: false + ?: false } } else -> null diff --git a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotifiableEventResolver.kt b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotifiableEventResolver.kt index ca2ec614..821ad181 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotifiableEventResolver.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotifiableEventResolver.kt @@ -30,6 +30,7 @@ import im.vector.riotredesign.R import im.vector.riotredesign.core.resources.StringProvider import im.vector.riotredesign.features.home.room.detail.timeline.format.NoticeEventFormatter import timber.log.Timber +import javax.inject.Inject /** * The notifiable event resolver is able to create a NotifiableEvent (view model for notifications) from an sdk Event. @@ -37,8 +38,8 @@ import timber.log.Timber * The NotifiableEventResolver is the only aware of session/store, the NotificationDrawerManager has no knowledge of that, * this pattern allow decoupling between the object responsible of displaying notifications and the matrix sdk. */ -class NotifiableEventResolver(private val stringProvider: StringProvider, - private val noticeEventFormatter: NoticeEventFormatter) { +class NotifiableEventResolver @Inject constructor(private val stringProvider: StringProvider, + private val noticeEventFormatter: NoticeEventFormatter) { //private val eventDisplay = RiotEventDisplay(context) @@ -95,8 +96,8 @@ class NotifiableEventResolver(private val stringProvider: StringProvider, // Ok room is not known in store, but we can still display something val body = event.annotations?.editSummary?.aggregatedContent?.toModel()?.body - ?: event.root.getClearContent().toModel()?.body - ?: stringProvider.getString(R.string.notification_unknown_new_event) + ?: event.root.getClearContent().toModel()?.body + ?: stringProvider.getString(R.string.notification_unknown_new_event) val roomName = stringProvider.getString(R.string.notification_unknown_room_name) val senderDisplayName = event.senderName @@ -114,8 +115,8 @@ class NotifiableEventResolver(private val stringProvider: StringProvider, return notifiableEvent } else { val body = event.annotations?.editSummary?.aggregatedContent?.toModel()?.body - ?: event.root.getClearContent().toModel()?.body - ?: stringProvider.getString(R.string.notification_unknown_new_event) + ?: event.root.getClearContent().toModel()?.body + ?: stringProvider.getString(R.string.notification_unknown_new_event) val roomName = room.roomSummary?.displayName ?: "" val senderDisplayName = event.senderName ?: "" @@ -137,15 +138,15 @@ class NotifiableEventResolver(private val stringProvider: StringProvider, // TODO They will be not displayed the first time (known limitation) notifiableEvent.roomAvatarPath = session.contentUrlResolver() .resolveThumbnail(room.roomSummary?.avatarUrl, - 250, - 250, - ContentUrlResolver.ThumbnailMethod.SCALE) + 250, + 250, + ContentUrlResolver.ThumbnailMethod.SCALE) notifiableEvent.senderAvatarPath = session.contentUrlResolver() .resolveThumbnail(event.senderAvatar, - 250, - 250, - ContentUrlResolver.ThumbnailMethod.SCALE) + 250, + 250, + ContentUrlResolver.ThumbnailMethod.SCALE) return notifiableEvent } @@ -158,7 +159,7 @@ class NotifiableEventResolver(private val stringProvider: StringProvider, val dName = event.senderId?.let { session.getUser(it)?.displayName } if (Membership.INVITE == content.membership) { val body = noticeEventFormatter.format(event, dName) - ?: stringProvider.getString(R.string.notification_new_invitation) + ?: stringProvider.getString(R.string.notification_new_invitation) return InviteNotifiableEvent( session.sessionParams.credentials.userId, eventId = event.eventId!!, diff --git a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt index b73ee6a6..0c04eba0 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/notifications/NotificationBroadcastReceiver.kt @@ -20,12 +20,12 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import androidx.core.app.RemoteInput -import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.room.Room import im.vector.riotredesign.R import im.vector.riotredesign.core.di.ActiveSessionHolder +import im.vector.riotredesign.core.di.HasVectorInjector import timber.log.Timber import java.util.* import javax.inject.Inject @@ -38,10 +38,14 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { @Inject lateinit var notificationDrawerManager: NotificationDrawerManager @Inject lateinit var activeSessionHolder: ActiveSessionHolder + override fun onReceive(context: Context?, intent: Intent?) { if (intent == null || context == null) return Timber.v("NotificationBroadcastReceiver received : $intent") - + val appContext = context.applicationContext + if (appContext is HasVectorInjector) { + appContext.injector().inject(this) + } when (intent.action) { NotificationUtils.SMART_REPLY_ACTION -> handleSmartReply(intent, context) @@ -60,7 +64,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { } private fun handleMarkAsRead(context: Context, roomId: String) { - activeSessionHolder.getActiveSession().let { session -> + activeSessionHolder.getActiveSession().let { session -> session.getRoom(roomId) ?.markAllAsRead(object : MatrixCallback {}) } @@ -95,7 +99,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { false, System.currentTimeMillis(), session.getUser(session.sessionParams.credentials.userId)?.displayName - ?: context?.getString(R.string.notification_sender_me), + ?: context?.getString(R.string.notification_sender_me), session.sessionParams.credentials.userId, message, room.roomId, diff --git a/vector/src/main/java/im/vector/riotredesign/features/notifications/OutdatedEventDetector.kt b/vector/src/main/java/im/vector/riotredesign/features/notifications/OutdatedEventDetector.kt index a51178a4..05bbc2ea 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/notifications/OutdatedEventDetector.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/notifications/OutdatedEventDetector.kt @@ -15,10 +15,10 @@ */ package im.vector.riotredesign.features.notifications -import im.vector.matrix.android.api.session.Session +import im.vector.riotredesign.core.di.ActiveSessionHolder import javax.inject.Inject -class OutdatedEventDetector @Inject constructor(private val session: Session) { +class OutdatedEventDetector @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) { /** * Returns true if the given event is outdated. @@ -29,7 +29,7 @@ class OutdatedEventDetector @Inject constructor(private val session: Session) { if (notifiableEvent is NotifiableMessageEvent) { val eventID = notifiableEvent.eventId val roomID = notifiableEvent.roomId - val room = session.getRoom(roomID) ?: return false + val room = activeSessionHolder.getSafeActiveSession()?.getRoom(roomID) ?: return false return room.isEventRead(eventID) } return false diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationFragment.kt index 1a967db0..7b94dedd 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationFragment.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsNotificationFragment.kt @@ -16,32 +16,43 @@ package im.vector.riotredesign.features.settings +import android.content.Context import android.os.Bundle import androidx.preference.Preference import androidx.preference.SwitchPreference import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.MatrixCallback import im.vector.riotredesign.R +import im.vector.riotredesign.core.di.ActiveSessionHolder +import im.vector.riotredesign.core.di.DaggerScreenComponent import im.vector.riotredesign.core.platform.VectorPreferenceFragment import im.vector.riotredesign.core.pushers.PushersManager import im.vector.riotredesign.push.fcm.FcmHelper -import org.koin.android.ext.android.inject +import javax.inject.Inject // Referenced in vector_settings_preferences_root.xml class VectorSettingsNotificationPreferenceFragment : VectorPreferenceFragment() { + override var titleRes: Int = R.string.settings_notifications - val pushManager: PushersManager by inject() - + @Inject lateinit var pushManager: PushersManager + @Inject lateinit var activeSessionHolder: ActiveSessionHolder override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { addPreferencesFromResource(R.xml.vector_settings_notifications) } + override fun onAttach(context: Context) { + val screenComponent = DaggerScreenComponent.factory().create(vectorActivity.getVectorComponent(), vectorActivity) + super.onAttach(context) + screenComponent.inject(this) + } + + override fun onResume() { super.onResume() - Matrix.getInstance().currentSession?.refreshPushers() + activeSessionHolder.getSafeActiveSession()?.refreshPushers() } override fun onPreferenceTreeClick(preference: Preference?): Boolean { diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt index dd53396f..4d9abbe0 100755 --- a/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/settings/VectorSettingsPreferencesFragment.kt @@ -35,12 +35,21 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.view.inputmethod.InputMethodManager -import android.widget.* +import android.widget.Button +import android.widget.CheckedTextView +import android.widget.EditText +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat import androidx.core.content.edit import androidx.core.view.isVisible -import androidx.preference.* +import androidx.preference.EditTextPreference +import androidx.preference.Preference +import androidx.preference.PreferenceCategory +import androidx.preference.PreferenceManager +import androidx.preference.SwitchPreference import com.google.android.gms.oss.licenses.OssLicensesMenuActivity import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputLayout @@ -68,7 +77,19 @@ import im.vector.riotredesign.core.preference.BingRule import im.vector.riotredesign.core.preference.ProgressBarPreference import im.vector.riotredesign.core.preference.UserAvatarPreference import im.vector.riotredesign.core.preference.VectorPreference -import im.vector.riotredesign.core.utils.* +import im.vector.riotredesign.core.utils.PERMISSIONS_FOR_WRITING_FILES +import im.vector.riotredesign.core.utils.PERMISSION_REQUEST_CODE_EXPORT_KEYS +import im.vector.riotredesign.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_CAMERA +import im.vector.riotredesign.core.utils.allGranted +import im.vector.riotredesign.core.utils.checkPermissions +import im.vector.riotredesign.core.utils.copyToClipboard +import im.vector.riotredesign.core.utils.displayInWebView +import im.vector.riotredesign.core.utils.getCallRingtoneName +import im.vector.riotredesign.core.utils.getCallRingtoneUri +import im.vector.riotredesign.core.utils.openFileSelection +import im.vector.riotredesign.core.utils.setCallRingtoneUri +import im.vector.riotredesign.core.utils.setUseRiotDefaultRingtone +import im.vector.riotredesign.core.utils.toast import im.vector.riotredesign.features.MainActivity import im.vector.riotredesign.features.configuration.VectorConfiguration import im.vector.riotredesign.features.crypto.keys.KeysExporter @@ -76,7 +97,6 @@ import im.vector.riotredesign.features.crypto.keys.KeysImporter import im.vector.riotredesign.features.crypto.keysbackup.settings.KeysBackupManageActivity import im.vector.riotredesign.features.themes.ThemeUtils import im.vector.riotredesign.features.version.getVersion -import org.koin.android.ext.android.inject import timber.log.Timber import java.lang.ref.WeakReference import java.text.DateFormat @@ -314,7 +334,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref // It does not work on XML, do it here it.icon = activity?.let { ThemeUtils.tintDrawable(it, - ContextCompat.getDrawable(it, R.drawable.ic_add_black)!!, R.attr.vctr_settings_icon_tint_color) + ContextCompat.getDrawable(it, R.drawable.ic_add_black)!!, R.attr.vctr_settings_icon_tint_color) } // Unfortunately, this is not supported in lib v7 @@ -331,7 +351,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref // It does not work on XML, do it here it.icon = activity?.let { ThemeUtils.tintDrawable(it, - ContextCompat.getDrawable(it, R.drawable.ic_add_black)!!, R.attr.vctr_settings_icon_tint_color) + ContextCompat.getDrawable(it, R.drawable.ic_add_black)!!, R.attr.vctr_settings_icon_tint_color) } it.setOnPreferenceClickListener { @@ -713,7 +733,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref context?.let { context: Context -> AlertDialog.Builder(context) .setSingleChoiceItems(R.array.media_saving_choice, - PreferencesManager.getSelectedMediasSavingPeriod(activity)) { d, n -> + PreferencesManager.getSelectedMediasSavingPeriod(activity)) { d, n -> PreferencesManager.setSelectedMediasSavingPeriod(activity, n) d.cancel() @@ -1773,7 +1793,7 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref mDisplayedEmails = newEmailsList val addEmailBtn = mUserSettingsCategory.findPreference(ADD_EMAIL_PREFERENCE_KEY) - ?: return + ?: return var order = addEmailBtn.order @@ -2449,7 +2469,9 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref // disable the deletion for our own device if (!TextUtils.equals(session.getMyDevice()?.deviceId, aDeviceInfo.deviceId)) { - builder.setNegativeButton(R.string.delete) { _, _ -> displayDeviceDeletionDialog(aDeviceInfo) } + builder.setNegativeButton(R.string.delete) { _, _ -> + //displayDeviceDeletionDialog(aDeviceInfo) + } } builder.setNeutralButton(R.string.cancel, null) .setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, event -> @@ -2746,8 +2768,8 @@ class VectorSettingsPreferencesFragment : VectorPreferenceFragment(), SharedPref AlertDialog.Builder(thisActivity) .setMessage(getString(R.string.encryption_import_room_keys_success, - data.successfullyNumberOfImportedKeys, - data.totalNumberOfKeys)) + data.successfullyNumberOfImportedKeys, + data.totalNumberOfKeys)) .setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() } .show() } diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysFragment.kt index 1ea57264..b51c131c 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysFragment.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysFragment.kt @@ -29,14 +29,15 @@ import im.vector.riotredesign.core.platform.VectorBaseFragment import im.vector.riotredesign.core.resources.StringProvider import im.vector.riotredesign.core.ui.list.genericFooterItem import kotlinx.android.synthetic.main.fragment_generic_recycler_epoxy.* +import javax.inject.Inject // Referenced in vector_settings_notifications.xml class PushGatewaysFragment : VectorBaseFragment() { override fun getLayoutResId(): Int = R.layout.fragment_generic_recycler_epoxy + @Inject lateinit var pushGatewaysViewModelFactory: PushGatewaysViewModel.Factory private val viewModel: PushGatewaysViewModel by fragmentViewModel(PushGatewaysViewModel::class) - private val epoxyController by lazy { PushGateWayController(StringProvider(requireContext().resources)) } override fun onResume() { diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysViewModel.kt index edb032a0..70bbd17a 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysViewModel.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushGatewaysViewModel.kt @@ -16,38 +16,50 @@ package im.vector.riotredesign.features.settings.push -import androidx.lifecycle.Observer -import com.airbnb.mvrx.* +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.FragmentViewModelContext +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.MvRxViewModelFactory +import com.airbnb.mvrx.Uninitialized +import com.airbnb.mvrx.ViewModelContext +import com.squareup.inject.assisted.Assisted +import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.pushers.Pusher +import im.vector.matrix.rx.RxSession import im.vector.riotredesign.core.platform.VectorViewModel -import org.koin.android.ext.android.get data class PushGatewayViewState( val pushGateways: Async> = Uninitialized ) : MvRxState -class PushGatewaysViewModel(initialState: PushGatewayViewState) : VectorViewModel(initialState) { +class PushGatewaysViewModel @AssistedInject constructor(@Assisted initialState: PushGatewayViewState, + private val session: Session) : VectorViewModel(initialState) { + + @AssistedInject.Factory + interface Factory { + fun create(initialState: PushGatewayViewState): PushGatewaysViewModel + } companion object : MvRxViewModelFactory { override fun create(viewModelContext: ViewModelContext, state: PushGatewayViewState): PushGatewaysViewModel? { - val session = viewModelContext.activity.get() - val fragment = (viewModelContext as FragmentViewModelContext).fragment - - val livePushers = session.livePushers() - - val viewModel = PushGatewaysViewModel(state) - - livePushers.observe(fragment, Observer { - viewModel.setState { - PushGatewayViewState(Success(it)) - } - }) - return viewModel + val fragment: PushGatewaysFragment = (viewModelContext as FragmentViewModelContext).fragment() + return fragment.pushGatewaysViewModelFactory.create(state) } + } + init { + observePushers() + } + + private fun observePushers() { + RxSession(session) + .livePushers() + .execute { + copy(pushGateways = it) + } } } \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushRulesViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushRulesViewModel.kt index 03a2e600..24294353 100644 --- a/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushRulesViewModel.kt +++ b/vector/src/main/java/im/vector/riotredesign/features/settings/push/PushRulesViewModel.kt @@ -19,23 +19,20 @@ import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext import im.vector.matrix.android.api.pushrules.rest.PushRule -import im.vector.matrix.android.api.session.Session +import im.vector.riotredesign.core.di.HasScreenInjector import im.vector.riotredesign.core.platform.VectorViewModel -import org.koin.android.ext.android.get data class PushRulesViewState( val rules: List = emptyList() ) : MvRxState - class PushRulesViewModel(initialState: PushRulesViewState) : VectorViewModel(initialState) { companion object : MvRxViewModelFactory { override fun initialState(viewModelContext: ViewModelContext): PushRulesViewState? { - val session = viewModelContext.activity.get() + val session = (viewModelContext.activity as HasScreenInjector).injector().session() val rules = session.getPushRules() - return PushRulesViewState(rules) }