diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt
index 99f6a254b8..e5ebce0c11 100644
--- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt
@@ -32,13 +32,11 @@ import im.vector.app.features.analytics.plan.Interaction
 import im.vector.app.features.invite.AutoAcceptInvites
 import im.vector.app.features.session.coroutineScope
 import im.vector.app.features.settings.VectorPreferences
-import kotlinx.coroutines.Dispatchers
+import im.vector.app.features.spaces.notification.GetNotificationCountForSpacesUseCase
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.flow.sample
 import kotlinx.coroutines.launch
 import org.matrix.android.sdk.api.extensions.tryOrNull
 import org.matrix.android.sdk.api.query.QueryStringValue
@@ -48,12 +46,9 @@ import org.matrix.android.sdk.api.session.events.model.toContent
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.getRoom
 import org.matrix.android.sdk.api.session.getUserOrDefault
-import org.matrix.android.sdk.api.session.room.RoomSortOrder
 import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataTypes
 import org.matrix.android.sdk.api.session.room.model.Membership
-import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
 import org.matrix.android.sdk.api.session.room.spaceSummaryQueryParams
-import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
 import org.matrix.android.sdk.api.session.space.SpaceOrderUtils
 import org.matrix.android.sdk.api.session.space.model.SpaceOrderContent
 import org.matrix.android.sdk.api.session.space.model.TopLevelSpaceComparator
@@ -67,6 +62,7 @@ class SpaceListViewModel @AssistedInject constructor(
         private val vectorPreferences: VectorPreferences,
         private val autoAcceptInvites: AutoAcceptInvites,
         private val analyticsTracker: AnalyticsTracker,
+        private val getNotificationCountForSpacesUseCase: GetNotificationCountForSpacesUseCase,
 ) : VectorViewModel<SpaceListViewState, SpaceListAction, SpaceListViewEvents>(initialState) {
 
     @AssistedFactory
@@ -92,39 +88,14 @@ class SpaceListViewModel @AssistedInject constructor(
                     copy(selectedSpace = selectedSpaceOption.orNull())
                 }
 
-        // XXX there should be a way to refactor this and share it
-        session.roomService().getPagedRoomSummariesLive(
-                roomSummaryQueryParams {
-                    this.memberships = listOf(Membership.JOIN)
-                    this.spaceFilter = roomsInSpaceFilter()
-                }, sortOrder = RoomSortOrder.NONE
-        ).asFlow()
-                .sample(300)
-                .onEach {
-                    val inviteCount = if (autoAcceptInvites.hideInvites) {
-                        0
-                    } else {
-                        session.roomService().getRoomSummaries(
-                                roomSummaryQueryParams { this.memberships = listOf(Membership.INVITE) }
-                        ).size
-                    }
-                    val totalCount = session.roomService().getNotificationCountForRooms(
-                            roomSummaryQueryParams {
-                                this.memberships = listOf(Membership.JOIN)
-                                this.spaceFilter = roomsInSpaceFilter()
-                            }
-                    )
-                    val counts = RoomAggregateNotificationCount(
-                            totalCount.notificationCount + inviteCount,
-                            totalCount.highlightCount + inviteCount
-                    )
+        getNotificationCountForSpacesUseCase.execute(roomsInSpaceFilter())
+                .onEach { counts ->
                     setState {
                         copy(
                                 homeAggregateCount = counts
                         )
                     }
                 }
-                .flowOn(Dispatchers.Default)
                 .launchIn(viewModelScope)
     }
 
diff --git a/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt b/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
new file mode 100644
index 0000000000..5f79619c92
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/spaces/notification/GetNotificationCountForSpacesUseCase.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.spaces.notification
+
+import androidx.lifecycle.asFlow
+import im.vector.app.core.di.ActiveSessionHolder
+import im.vector.app.features.invite.AutoAcceptInvites
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.sample
+import org.matrix.android.sdk.api.query.SpaceFilter
+import org.matrix.android.sdk.api.session.room.RoomSortOrder
+import org.matrix.android.sdk.api.session.room.model.Membership
+import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
+import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount
+import javax.inject.Inject
+
+// TODO add unit tests
+class GetNotificationCountForSpacesUseCase @Inject constructor(
+        private val activeSessionHolder: ActiveSessionHolder,
+        private val autoAcceptInvites: AutoAcceptInvites,
+) {
+
+    fun execute(spaceFilter: SpaceFilter): Flow<RoomAggregateNotificationCount> {
+        val session = activeSessionHolder.getSafeActiveSession()
+
+        val spaceQueryParams = roomSummaryQueryParams {
+            this.memberships = listOf(Membership.JOIN)
+            this.spaceFilter = spaceFilter
+        }
+        return session
+                ?.roomService()
+                ?.getPagedRoomSummariesLive(queryParams = spaceQueryParams, sortOrder = RoomSortOrder.NONE)
+                ?.asFlow()
+                ?.sample(300)
+                ?.mapLatest {
+                    val inviteCount = if (autoAcceptInvites.hideInvites) {
+                        0
+                    } else {
+                        session.roomService().getRoomSummaries(
+                                roomSummaryQueryParams { this.memberships = listOf(Membership.INVITE) }
+                        ).size
+                    }
+                    val totalCount = session.roomService().getNotificationCountForRooms(spaceQueryParams)
+                    RoomAggregateNotificationCount(
+                            notificationCount = totalCount.notificationCount + inviteCount,
+                            highlightCount = totalCount.highlightCount + inviteCount,
+                    )
+                }
+                ?.flowOn(Dispatchers.Default)
+                ?: emptyFlow()
+    }
+}