Fix coroutine scope (#4820)
* Inject the session scope instead of the application scope where it's possible. * Create AppCoroutineScope annotation to let developers explicitly choose the appropriate CoroutineScope when injecting one.
This commit is contained in:
parent
36c7c7ab9b
commit
5f191d9f9c
58 changed files with 172 additions and 72 deletions
|
|
@ -13,6 +13,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
|||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.CacheDirectory
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
|
@ -24,7 +25,8 @@ import javax.inject.Inject
|
|||
*/
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultCacheCleaner @Inject constructor(
|
||||
private val scope: CoroutineScope,
|
||||
@AppCoroutineScope
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
@CacheDirectory private val cacheDir: File,
|
||||
) : CacheCleaner {
|
||||
|
|
@ -33,7 +35,7 @@ class DefaultCacheCleaner @Inject constructor(
|
|||
}
|
||||
|
||||
override fun clearCache() {
|
||||
scope.launch(dispatchers.io) {
|
||||
coroutineScope.launch(dispatchers.io) {
|
||||
runCatchingExceptions {
|
||||
SUBDIRS_TO_CLEANUP.forEach {
|
||||
File(cacheDir.path, it).apply {
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class DefaultCacheCleanerTest {
|
|||
}
|
||||
|
||||
private fun TestScope.aCacheCleaner() = DefaultCacheCleaner(
|
||||
scope = this,
|
||||
coroutineScope = this,
|
||||
dispatchers = this.testCoroutineDispatchers(true),
|
||||
cacheDir = temporaryFolder.root,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import io.element.android.features.call.impl.di.CallBindings
|
|||
import io.element.android.features.call.impl.notifications.CallNotificationData
|
||||
import io.element.android.features.call.impl.utils.ActiveCallManager
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
|
@ -30,8 +31,8 @@ class DeclineCallBroadcastReceiver : BroadcastReceiver() {
|
|||
@Inject
|
||||
lateinit var activeCallManager: ActiveCallManager
|
||||
|
||||
@Inject
|
||||
lateinit var appCoroutineScope: CoroutineScope
|
||||
@AppCoroutineScope
|
||||
@Inject lateinit var appCoroutineScope: CoroutineScope
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent?) {
|
||||
val notificationData = intent?.let { IntentCompat.getParcelableExtra(it, EXTRA_NOTIFICATION_DATA, CallNotificationData::class.java) }
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import io.element.android.libraries.architecture.AsyncData
|
|||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
|
@ -64,6 +65,7 @@ class CallScreenPresenter @AssistedInject constructor(
|
|||
private val languageTagProvider: LanguageTagProvider,
|
||||
private val appForegroundStateService: AppForegroundStateService,
|
||||
private val activeRoomsHolder: ActiveRoomsHolder,
|
||||
@AppCoroutineScope
|
||||
private val appCoroutineScope: CoroutineScope,
|
||||
) : Presenter<CallScreenState> {
|
||||
@AssistedFactory
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import io.element.android.features.enterprise.api.EnterpriseService
|
|||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.designsystem.theme.ElementThemeApp
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.filter
|
||||
|
|
@ -57,8 +58,8 @@ class IncomingCallActivity : AppCompatActivity() {
|
|||
@Inject
|
||||
lateinit var buildMeta: BuildMeta
|
||||
|
||||
@Inject
|
||||
lateinit var appCoroutineScope: CoroutineScope
|
||||
@AppCoroutineScope
|
||||
@Inject lateinit var appCoroutineScope: CoroutineScope
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import io.element.android.libraries.core.extensions.runCatchingExceptions
|
|||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder
|
||||
|
|
@ -87,6 +88,7 @@ interface ActiveCallManager {
|
|||
@ContributesBinding(AppScope::class)
|
||||
class DefaultActiveCallManager @Inject constructor(
|
||||
@ApplicationContext context: Context,
|
||||
@AppCoroutineScope
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val onMissedCallNotificationHandler: OnMissedCallNotificationHandler,
|
||||
private val ringingCallNotificationCreator: RingingCallNotificationCreator,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import dagger.assisted.Assisted
|
|||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import io.element.android.libraries.permissions.api.PermissionStateProvider
|
||||
import io.element.android.libraries.permissions.api.PermissionsEvents
|
||||
import io.element.android.libraries.permissions.api.PermissionsPresenter
|
||||
|
|
@ -27,6 +28,7 @@ import kotlinx.coroutines.launch
|
|||
class NotificationsOptInPresenter @AssistedInject constructor(
|
||||
permissionsPresenterFactory: PermissionsPresenter.Factory,
|
||||
@Assisted private val callback: NotificationsOptInNode.Callback,
|
||||
@AppCoroutineScope
|
||||
private val appCoroutineScope: CoroutineScope,
|
||||
private val permissionStateProvider: PermissionStateProvider,
|
||||
private val buildVersionSdkIntProvider: BuildVersionSdkIntProvider,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import io.element.android.features.knockrequests.impl.data.KnockRequestPresentab
|
|||
import io.element.android.features.knockrequests.impl.data.KnockRequestsService
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.coroutine.mapState
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
|
|
@ -28,7 +29,8 @@ private const val ACCEPT_ERROR_DISPLAY_DURATION = 1500L
|
|||
|
||||
class KnockRequestsBannerPresenter @Inject constructor(
|
||||
private val knockRequestsService: KnockRequestsService,
|
||||
private val appCoroutineScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
) : Presenter<KnockRequestsBannerState> {
|
||||
@Composable
|
||||
override fun present(): KnockRequestsBannerState {
|
||||
|
|
@ -52,13 +54,13 @@ class KnockRequestsBannerPresenter @Inject constructor(
|
|||
fun handleEvents(event: KnockRequestsBannerEvents) {
|
||||
when (event) {
|
||||
is KnockRequestsBannerEvents.AcceptSingleRequest -> {
|
||||
appCoroutineScope.acceptSingleKnockRequest(
|
||||
sessionCoroutineScope.acceptSingleKnockRequest(
|
||||
knockRequests = knockRequests,
|
||||
displayAcceptError = showAcceptError,
|
||||
)
|
||||
}
|
||||
is KnockRequestsBannerEvents.Dismiss -> {
|
||||
appCoroutineScope.launch {
|
||||
sessionCoroutineScope.launch {
|
||||
knockRequestsService.markAllKnockRequestsAsSeen()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,6 +238,6 @@ private fun TestScope.createKnockRequestsBannerPresenter(
|
|||
)
|
||||
return KnockRequestsBannerPresenter(
|
||||
knockRequestsService = knockRequestsService,
|
||||
appCoroutineScope = this,
|
||||
sessionCoroutineScope = this,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import io.element.android.features.lockscreen.impl.pin.PinCodeManager
|
|||
import io.element.android.features.lockscreen.impl.storage.LockScreenStore
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
|
||||
|
|
@ -42,6 +43,7 @@ class DefaultLockScreenService @Inject constructor(
|
|||
private val featureFlagService: FeatureFlagService,
|
||||
private val lockScreenStore: LockScreenStore,
|
||||
private val pinCodeManager: PinCodeManager,
|
||||
@AppCoroutineScope
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val sessionObserver: SessionObserver,
|
||||
private val appForegroundStateService: AppForegroundStateService,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import io.element.android.libraries.cryptography.api.SecretKeyRepository
|
|||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -47,6 +48,7 @@ class DefaultBiometricAuthenticatorManager @Inject constructor(
|
|||
private val lockScreenConfig: LockScreenConfig,
|
||||
private val encryptionDecryptionService: EncryptionDecryptionService,
|
||||
private val secretKeyRepository: SecretKeyRepository,
|
||||
@AppCoroutineScope
|
||||
private val coroutineScope: CoroutineScope,
|
||||
) : BiometricAuthenticatorManager {
|
||||
private val callbacks = CopyOnWriteArrayList<BiometricAuthenticator.Callback>()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import io.element.android.features.lockscreen.impl.biometric.BiometricAuthentica
|
|||
import io.element.android.features.lockscreen.impl.pin.PinCodeManager
|
||||
import io.element.android.features.lockscreen.impl.storage.LockScreenStore
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
|
@ -29,6 +30,7 @@ class LockScreenSettingsPresenter @Inject constructor(
|
|||
private val pinCodeManager: PinCodeManager,
|
||||
private val lockScreenStore: LockScreenStore,
|
||||
private val biometricAuthenticatorManager: BiometricAuthenticatorManager,
|
||||
@AppCoroutineScope
|
||||
private val coroutineScope: CoroutineScope,
|
||||
) : Presenter<LockScreenSettingsState> {
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import io.element.android.libraries.architecture.AsyncData
|
|||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
|
@ -34,6 +35,7 @@ class PinUnlockPresenter @Inject constructor(
|
|||
private val pinCodeManager: PinCodeManager,
|
||||
private val biometricAuthenticatorManager: BiometricAuthenticatorManager,
|
||||
private val logoutUseCase: LogoutUseCase,
|
||||
@AppCoroutineScope
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val pinUnlockHelper: PinUnlockHelper,
|
||||
) : Presenter<PinUnlockState> {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import io.element.android.libraries.architecture.inputs
|
|||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.analytics.toAnalyticsViewRoom
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
|
@ -69,7 +70,8 @@ import kotlinx.coroutines.launch
|
|||
class MessagesNode @AssistedInject constructor(
|
||||
@Assisted buildContext: BuildContext,
|
||||
@Assisted plugins: List<Plugin>,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
private val room: BaseRoom,
|
||||
private val analyticsService: AnalyticsService,
|
||||
messageComposerPresenterFactory: MessageComposerPresenter.Factory,
|
||||
|
|
@ -115,7 +117,7 @@ class MessagesNode @AssistedInject constructor(
|
|||
super.onBuilt()
|
||||
lifecycle.subscribe(
|
||||
onCreate = {
|
||||
coroutineScope.launch { analyticsService.capture(room.toAnalyticsViewRoom()) }
|
||||
sessionCoroutineScope.launch { analyticsService.capture(room.toAnalyticsViewRoom()) }
|
||||
},
|
||||
onDestroy = {
|
||||
mediaPlayer.close()
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import dagger.assisted.AssistedInject
|
|||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
|
||||
|
|
@ -28,7 +29,8 @@ import kotlinx.coroutines.launch
|
|||
class ForwardMessagesPresenter @AssistedInject constructor(
|
||||
@Assisted eventId: String,
|
||||
@Assisted private val timelineProvider: TimelineProvider,
|
||||
private val appCoroutineScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
) : Presenter<ForwardMessagesState> {
|
||||
private val eventId: EventId = EventId(eventId)
|
||||
|
||||
|
|
@ -40,7 +42,7 @@ class ForwardMessagesPresenter @AssistedInject constructor(
|
|||
private val forwardingActionState: MutableState<AsyncAction<List<RoomId>>> = mutableStateOf(AsyncAction.Uninitialized)
|
||||
|
||||
fun onRoomSelected(roomIds: List<RoomId>) {
|
||||
appCoroutineScope.forwardEvent(eventId, roomIds.toPersistentList(), forwardingActionState)
|
||||
sessionCoroutineScope.forwardEvent(eventId, roomIds.toPersistentList(), forwardingActionState)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import io.element.android.libraries.core.extensions.runCatchingExceptions
|
|||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
|
|
@ -98,7 +99,8 @@ import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes
|
|||
|
||||
class MessageComposerPresenter @AssistedInject constructor(
|
||||
@Assisted private val navigator: MessagesNavigator,
|
||||
private val appCoroutineScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
private val room: JoinedRoom,
|
||||
private val mediaPickerProvider: PickerProvider,
|
||||
private val featureFlagService: FeatureFlagService,
|
||||
|
|
@ -200,7 +202,7 @@ class MessageComposerPresenter @AssistedInject constructor(
|
|||
DisposableEffect(Unit) {
|
||||
// Declare that the user is not typing anymore when the composer is disposed
|
||||
onDispose {
|
||||
appCoroutineScope.launch {
|
||||
sessionCoroutineScope.launch {
|
||||
if (sendTypingNotifications) {
|
||||
room.typingNotice(false)
|
||||
}
|
||||
|
|
@ -236,12 +238,12 @@ class MessageComposerPresenter @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
is MessageComposerEvents.SendMessage -> {
|
||||
appCoroutineScope.sendMessage(
|
||||
sessionCoroutineScope.sendMessage(
|
||||
markdownTextEditorState = markdownTextEditorState,
|
||||
richTextEditorState = richTextEditorState,
|
||||
)
|
||||
}
|
||||
is MessageComposerEvents.SendUri -> appCoroutineScope.sendAttachment(
|
||||
is MessageComposerEvents.SendUri -> sessionCoroutineScope.sendAttachment(
|
||||
attachment = Attachment.Media(
|
||||
localMedia = localMediaFactory.createFromUri(
|
||||
uri = event.uri,
|
||||
|
|
@ -338,7 +340,7 @@ class MessageComposerPresenter @AssistedInject constructor(
|
|||
}
|
||||
MessageComposerEvents.SaveDraft -> {
|
||||
val draft = createDraftFromState(markdownTextEditorState, richTextEditorState)
|
||||
appCoroutineScope.updateDraft(draft, isVolatile = false)
|
||||
sessionCoroutineScope.updateDraft(draft, isVolatile = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import io.element.android.libraries.architecture.AsyncData
|
|||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.canPinUnpin
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther
|
||||
|
|
@ -67,7 +68,8 @@ class PinnedMessagesListPresenter @AssistedInject constructor(
|
|||
private val linkPresenter: Presenter<LinkState>,
|
||||
private val snackbarDispatcher: SnackbarDispatcher,
|
||||
@Assisted private val actionListPresenter: Presenter<ActionListState>,
|
||||
private val appCoroutineScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
private val analyticsService: AnalyticsService,
|
||||
) : Presenter<PinnedMessagesListState> {
|
||||
@AssistedFactory
|
||||
|
|
@ -123,7 +125,7 @@ class PinnedMessagesListPresenter @AssistedInject constructor(
|
|||
|
||||
fun handleEvents(event: PinnedMessagesListEvents) {
|
||||
when (event) {
|
||||
is PinnedMessagesListEvents.HandleAction -> appCoroutineScope.handleTimelineAction(event.action, event.event)
|
||||
is PinnedMessagesListEvents.HandleAction -> sessionCoroutineScope.handleTimelineAction(event.action, event.event)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import io.element.android.features.roomcall.api.RoomCallState
|
|||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.UniqueId
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
|
|
@ -66,7 +67,8 @@ class TimelinePresenter @AssistedInject constructor(
|
|||
timelineItemsFactoryCreator: TimelineItemsFactory.Creator,
|
||||
private val room: JoinedRoom,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
private val appScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
@Assisted private val navigator: MessagesNavigator,
|
||||
private val redactedVoiceMessageManager: RedactedVoiceMessageManager,
|
||||
private val sendPollResponseAction: SendPollResponseAction,
|
||||
|
|
@ -135,7 +137,7 @@ class TimelinePresenter @AssistedInject constructor(
|
|||
newEventState.value = NewEventState.None
|
||||
}
|
||||
Timber.d("## sendReadReceiptIfNeeded firstVisibleIndex: ${event.firstIndex}")
|
||||
appScope.sendReadReceiptIfNeeded(
|
||||
sessionCoroutineScope.sendReadReceiptIfNeeded(
|
||||
firstVisibleIndex = event.firstIndex,
|
||||
timelineItems = timelineItems,
|
||||
lastReadReceiptId = lastReadReceiptId,
|
||||
|
|
@ -145,13 +147,13 @@ class TimelinePresenter @AssistedInject constructor(
|
|||
newEventState.value = NewEventState.None
|
||||
}
|
||||
}
|
||||
is TimelineEvents.SelectPollAnswer -> appScope.launch {
|
||||
is TimelineEvents.SelectPollAnswer -> sessionCoroutineScope.launch {
|
||||
sendPollResponseAction.execute(
|
||||
pollStartId = event.pollStartId,
|
||||
answerId = event.answerId
|
||||
)
|
||||
}
|
||||
is TimelineEvents.EndPoll -> appScope.launch {
|
||||
is TimelineEvents.EndPoll -> sessionCoroutineScope.launch {
|
||||
endPollAction.execute(
|
||||
pollStartId = event.pollStartId,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
package io.element.android.features.messages.impl.voicemessages.composer
|
||||
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.mediaplayer.api.MediaPlayer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
|
|
@ -26,11 +27,12 @@ import javax.inject.Inject
|
|||
* A media player for the voice message composer.
|
||||
*
|
||||
* @param mediaPlayer The [MediaPlayer] to use.
|
||||
* @param coroutineScope
|
||||
* @param sessionCoroutineScope
|
||||
*/
|
||||
class VoiceMessageComposerPlayer @Inject constructor(
|
||||
private val mediaPlayer: MediaPlayer,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
) {
|
||||
companion object {
|
||||
const val MIME_TYPE = MimeTypes.Ogg
|
||||
|
|
@ -116,7 +118,7 @@ class VoiceMessageComposerPlayer @Inject constructor(
|
|||
|
||||
seekJob?.cancelAndJoin()
|
||||
seekingTo.value = position
|
||||
seekJob = coroutineScope.launch {
|
||||
seekJob = sessionCoroutineScope.launch {
|
||||
val mediaState = mediaPlayer.ensureMediaReady(mediaPath)
|
||||
val duration = mediaState.duration ?: return@launch
|
||||
val positionMs = (duration * position).toLong()
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import androidx.lifecycle.Lifecycle
|
|||
import im.vector.app.features.analytics.plan.Composer
|
||||
import io.element.android.features.messages.api.MessageComposerContext
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.mediaupload.api.MediaSender
|
||||
import io.element.android.libraries.permissions.api.PermissionsEvents
|
||||
import io.element.android.libraries.permissions.api.PermissionsPresenter
|
||||
|
|
@ -44,7 +45,8 @@ import kotlin.time.Duration
|
|||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
class VoiceMessageComposerPresenter @Inject constructor(
|
||||
private val appCoroutineScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
private val voiceRecorder: VoiceRecorder,
|
||||
private val analyticsService: AnalyticsService,
|
||||
private val mediaSender: MediaSender,
|
||||
|
|
@ -74,11 +76,11 @@ class VoiceMessageComposerPresenter @Inject constructor(
|
|||
val onLifecycleEvent = { event: Lifecycle.Event ->
|
||||
when (event) {
|
||||
Lifecycle.Event.ON_PAUSE -> {
|
||||
appCoroutineScope.finishRecording()
|
||||
sessionCoroutineScope.finishRecording()
|
||||
player.pause()
|
||||
}
|
||||
Lifecycle.Event.ON_DESTROY -> {
|
||||
appCoroutineScope.cancelRecording()
|
||||
sessionCoroutineScope.cancelRecording()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
|
@ -145,7 +147,7 @@ class VoiceMessageComposerPresenter @Inject constructor(
|
|||
isSending = true
|
||||
player.pause()
|
||||
analyticsService.captureComposerEvent()
|
||||
appCoroutineScope.launch {
|
||||
sessionCoroutineScope.launch {
|
||||
val result = sendMessage(
|
||||
file = finishedState.file,
|
||||
mimeType = finishedState.mimeType,
|
||||
|
|
|
|||
|
|
@ -97,6 +97,6 @@ class ForwardMessagesPresenterTest {
|
|||
) = ForwardMessagesPresenter(
|
||||
eventId = eventId.value,
|
||||
timelineProvider = LiveTimelineProvider(fakeRoom),
|
||||
appCoroutineScope = this,
|
||||
sessionCoroutineScope = this,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1539,7 +1539,7 @@ class MessageComposerPresenterTest {
|
|||
draftService: ComposerDraftService = FakeComposerDraftService(),
|
||||
) = MessageComposerPresenter(
|
||||
navigator = navigator,
|
||||
appCoroutineScope = this,
|
||||
sessionCoroutineScope = this,
|
||||
room = room,
|
||||
mediaPickerProvider = pickerProvider,
|
||||
featureFlagService = featureFlagService,
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ class PinnedMessagesListPresenterTest {
|
|||
actionListPresenter = { anActionListState() },
|
||||
linkPresenter = { aLinkState() },
|
||||
analyticsService = analyticsService,
|
||||
appCoroutineScope = this,
|
||||
sessionCoroutineScope = this,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -727,7 +727,7 @@ class TimelinePresenterTest {
|
|||
timelineItemsFactoryCreator = aTimelineItemsFactoryCreator(),
|
||||
room = room,
|
||||
dispatchers = testCoroutineDispatchers(),
|
||||
appScope = this,
|
||||
sessionCoroutineScope = this,
|
||||
navigator = messagesNavigator,
|
||||
redactedVoiceMessageManager = redactedVoiceMessageManager,
|
||||
endPollAction = endPollAction,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import io.element.android.features.networkmonitor.api.NetworkStatus
|
|||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
|
|
@ -38,6 +39,7 @@ import javax.inject.Inject
|
|||
@SingleIn(AppScope::class)
|
||||
class DefaultNetworkMonitor @Inject constructor(
|
||||
@ApplicationContext context: Context,
|
||||
@AppCoroutineScope
|
||||
appCoroutineScope: CoroutineScope,
|
||||
) : NetworkMonitor {
|
||||
private val connectivityManager: ConnectivityManager = context.getSystemService(ConnectivityManager::class.java)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import io.element.android.features.poll.impl.history.model.PollHistoryFilter
|
|||
import io.element.android.features.poll.impl.history.model.PollHistoryItems
|
||||
import io.element.android.features.poll.impl.history.model.PollHistoryItemsFactory
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -31,7 +32,8 @@ import kotlinx.coroutines.launch
|
|||
import javax.inject.Inject
|
||||
|
||||
class PollHistoryPresenter @Inject constructor(
|
||||
private val appCoroutineScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
private val sendPollResponseAction: SendPollResponseAction,
|
||||
private val endPollAction: EndPollAction,
|
||||
private val pollHistoryItemFactory: PollHistoryItemsFactory,
|
||||
|
|
@ -64,10 +66,10 @@ class PollHistoryPresenter @Inject constructor(
|
|||
is PollHistoryEvents.LoadMore -> {
|
||||
coroutineScope.loadMore(timeline)
|
||||
}
|
||||
is PollHistoryEvents.SelectPollAnswer -> appCoroutineScope.launch {
|
||||
is PollHistoryEvents.SelectPollAnswer -> sessionCoroutineScope.launch {
|
||||
sendPollResponseAction.execute(pollStartId = event.pollStartId, answerId = event.answerId)
|
||||
}
|
||||
is PollHistoryEvents.EndPoll -> appCoroutineScope.launch {
|
||||
is PollHistoryEvents.EndPoll -> sessionCoroutineScope.launch {
|
||||
endPollAction.execute(pollStartId = event.pollStartId)
|
||||
}
|
||||
is PollHistoryEvents.SelectFilter -> {
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ class PollHistoryPresenterTest {
|
|||
),
|
||||
): PollHistoryPresenter {
|
||||
return PollHistoryPresenter(
|
||||
appCoroutineScope = this,
|
||||
sessionCoroutineScope = this,
|
||||
sendPollResponseAction = sendPollResponseAction,
|
||||
endPollAction = endPollAction,
|
||||
pollHistoryItemFactory = pollHistoryItemFactory,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import io.element.android.features.rageshake.impl.crash.CrashDataStore
|
|||
import io.element.android.features.rageshake.impl.screenshot.ScreenshotHolder
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
|
@ -30,6 +31,7 @@ class BugReportPresenter @Inject constructor(
|
|||
private val bugReporter: BugReporter,
|
||||
private val crashDataStore: CrashDataStore,
|
||||
private val screenshotHolder: ScreenshotHolder,
|
||||
@AppCoroutineScope
|
||||
private val appCoroutineScope: CoroutineScope,
|
||||
) : Presenter<BugReportState> {
|
||||
private class BugReporterUploadListener(
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import io.element.android.libraries.androidutils.diff.DiffCacheUpdater
|
|||
import io.element.android.libraries.androidutils.diff.MutableListDiffCache
|
||||
import io.element.android.libraries.androidutils.system.DateTimeObserver
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||
|
|
@ -36,7 +37,8 @@ class RoomListDataSource @Inject constructor(
|
|||
private val roomListRoomSummaryFactory: RoomListRoomSummaryFactory,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
private val notificationSettingsService: NotificationSettingsService,
|
||||
private val appScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
private val dateTimeObserver: DateTimeObserver,
|
||||
) {
|
||||
init {
|
||||
|
|
@ -77,7 +79,7 @@ class RoomListDataSource @Inject constructor(
|
|||
.onEach {
|
||||
roomListService.allRooms.rebuildSummaries()
|
||||
}
|
||||
.launchIn(appScope)
|
||||
.launchIn(sessionCoroutineScope)
|
||||
}
|
||||
|
||||
private fun observeDateTimeChanges() {
|
||||
|
|
@ -88,7 +90,7 @@ class RoomListDataSource @Inject constructor(
|
|||
is DateTimeObserver.Event.DateChanged -> rebuildAllRoomSummaries()
|
||||
}
|
||||
}
|
||||
.launchIn(appScope)
|
||||
.launchIn(sessionCoroutineScope)
|
||||
}
|
||||
|
||||
private suspend fun replaceWith(roomSummaries: List<RoomSummary>) = withContext(coroutineDispatchers.computation) {
|
||||
|
|
|
|||
|
|
@ -701,7 +701,7 @@ class RoomListPresenterTest {
|
|||
),
|
||||
coroutineDispatchers = testCoroutineDispatchers(),
|
||||
notificationSettingsService = client.notificationSettingsService(),
|
||||
appScope = backgroundScope,
|
||||
sessionCoroutineScope = backgroundScope,
|
||||
dateTimeObserver = FakeDateTimeObserver(),
|
||||
),
|
||||
featureFlagService = featureFlagService,
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class RoomListDataSourceTest {
|
|||
roomListRoomSummaryFactory = roomListRoomSummaryFactory,
|
||||
coroutineDispatchers = testCoroutineDispatchers(),
|
||||
notificationSettingsService = notificationSettingsService,
|
||||
appScope = backgroundScope,
|
||||
sessionCoroutineScope = backgroundScope,
|
||||
dateTimeObserver = dateTimeObserver,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import io.element.android.libraries.architecture.BaseFlowNode
|
|||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.designsystem.components.ProgressDialog
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle
|
||||
import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -50,7 +51,8 @@ class ResetIdentityFlowNode @AssistedInject constructor(
|
|||
@Assisted buildContext: BuildContext,
|
||||
@Assisted plugins: List<Plugin>,
|
||||
private val resetIdentityFlowManager: ResetIdentityFlowManager,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
) : BaseFlowNode<ResetIdentityFlowNode.NavTarget>(
|
||||
backstack = BackStack(initialElement = NavTarget.Root, savedStateMap = buildContext.savedStateMap),
|
||||
buildContext = buildContext,
|
||||
|
|
@ -79,7 +81,7 @@ class ResetIdentityFlowNode @AssistedInject constructor(
|
|||
override fun onStart(owner: LifecycleOwner) {
|
||||
// If the custom tab / Web browser was opened, we need to cancel the reset job
|
||||
// when we come back to the node if the reset wasn't successful
|
||||
coroutineScope.launch {
|
||||
sessionCoroutineScope.launch {
|
||||
cancelResetJob()
|
||||
|
||||
resetIdentityFlowManager.whenResetIsDone {
|
||||
|
|
@ -90,7 +92,7 @@ class ResetIdentityFlowNode @AssistedInject constructor(
|
|||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
// Make sure we cancel the reset job when the node is destroyed, just in case
|
||||
coroutineScope.launch { cancelResetJob() }
|
||||
sessionCoroutineScope.launch { cancelResetJob() }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -100,7 +102,7 @@ class ResetIdentityFlowNode @AssistedInject constructor(
|
|||
is NavTarget.Root -> {
|
||||
val callback = object : ResetIdentityRootNode.Callback {
|
||||
override fun onContinue() {
|
||||
coroutineScope.startReset()
|
||||
sessionCoroutineScope.startReset()
|
||||
}
|
||||
}
|
||||
createNode<ResetIdentityRootNode>(buildContext, listOf(callback))
|
||||
|
|
@ -157,7 +159,7 @@ class ResetIdentityFlowNode @AssistedInject constructor(
|
|||
if (startResetState.isLoading()) {
|
||||
ProgressDialog(
|
||||
properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = true),
|
||||
onDismissRequest = { coroutineScope.launch { cancelResetJob() } }
|
||||
onDismissRequest = { sessionCoroutineScope.launch { cancelResetJob() } }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import io.element.android.libraries.architecture.AsyncAction
|
|||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
|
|
@ -31,7 +32,8 @@ import kotlin.coroutines.cancellation.CancellationException
|
|||
|
||||
class SharePresenter @AssistedInject constructor(
|
||||
@Assisted private val intent: Intent,
|
||||
private val appCoroutineScope: CoroutineScope,
|
||||
@SessionCoroutineScope
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
private val shareIntentHandler: ShareIntentHandler,
|
||||
private val matrixClient: MatrixClient,
|
||||
private val mediaPreProcessor: MediaPreProcessor,
|
||||
|
|
@ -46,7 +48,7 @@ class SharePresenter @AssistedInject constructor(
|
|||
private val shareActionState: MutableState<AsyncAction<List<RoomId>>> = mutableStateOf(AsyncAction.Uninitialized)
|
||||
|
||||
fun onRoomSelected(roomIds: List<RoomId>) {
|
||||
appCoroutineScope.share(intent, roomIds)
|
||||
sessionCoroutineScope.share(intent, roomIds)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ class SharePresenterTest {
|
|||
): SharePresenter {
|
||||
return SharePresenter(
|
||||
intent = intent,
|
||||
appCoroutineScope = this,
|
||||
sessionCoroutineScope = this,
|
||||
shareIntentHandler = shareIntentHandler,
|
||||
matrixClient = matrixClient,
|
||||
mediaPreProcessor = mediaPreProcessor,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue