diff --git a/app/src/main/java/com/futo/circles/extensions/SearchViewExtensions.kt b/app/src/main/java/com/futo/circles/extensions/SearchViewExtensions.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a76978cbb59f59bf2124d69eee4945cc5b20d611
--- /dev/null
+++ b/app/src/main/java/com/futo/circles/extensions/SearchViewExtensions.kt
@@ -0,0 +1,24 @@
+package com.futo.circles.extensions
+
+import androidx.appcompat.widget.SearchView
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+fun SearchView.getQueryTextChangeStateFlow(): StateFlow<String> {
+
+    val query = MutableStateFlow("")
+
+    setOnQueryTextListener(object : SearchView.OnQueryTextListener {
+        override fun onQueryTextSubmit(query: String?): Boolean {
+            return true
+        }
+
+        override fun onQueryTextChange(newText: String): Boolean {
+            query.value = newText
+            return true
+        }
+    })
+
+    return query
+
+}
diff --git a/app/src/main/java/com/futo/circles/feature/group_invite/InviteMembersDialogFragment.kt b/app/src/main/java/com/futo/circles/feature/group_invite/InviteMembersDialogFragment.kt
index 22853086f350afbbfb8354cc1e0a4910c1adfce1..ecbb830d94cb106b5142b2d8544da016a98c944c 100644
--- a/app/src/main/java/com/futo/circles/feature/group_invite/InviteMembersDialogFragment.kt
+++ b/app/src/main/java/com/futo/circles/feature/group_invite/InviteMembersDialogFragment.kt
@@ -6,6 +6,7 @@ import androidx.navigation.fragment.navArgs
 import com.futo.circles.R
 import com.futo.circles.base.BaseFullscreenDialogFragment
 import com.futo.circles.databinding.InviteMembersDialogFragmentBinding
+import com.futo.circles.extensions.getQueryTextChangeStateFlow
 import com.futo.circles.extensions.observeData
 import com.futo.circles.feature.group_invite.list.InviteMembersListAdapter
 import com.futo.circles.model.RoomMemberListItem
@@ -35,6 +36,7 @@ class InviteMembersDialogFragment :
         super.onViewCreated(view, savedInstanceState)
         binding.toolbar.setNavigationOnClickListener { activity?.onBackPressed() }
         binding.rvUsers.adapter = listAdapter
+        viewModel.initSearchListener(binding.searchView.getQueryTextChangeStateFlow())
         setupObservers()
     }
 
@@ -42,6 +44,10 @@ class InviteMembersDialogFragment :
         viewModel.titleLiveData.observeData(this) {
             binding.toolbar.title = it
         }
+
+        viewModel.usersLiveData.observeData(this) { users ->
+            setUserList(users)
+        }
     }
 
     private fun setUserList(users: List<RoomMemberListItem>) {
diff --git a/app/src/main/java/com/futo/circles/feature/group_invite/InviteMembersViewModel.kt b/app/src/main/java/com/futo/circles/feature/group_invite/InviteMembersViewModel.kt
index dc3a86c9f8d0705acdc06fac1706a88fc3bf0aaf..380096d8c8709ed691f95decc2903c51d453bbb1 100644
--- a/app/src/main/java/com/futo/circles/feature/group_invite/InviteMembersViewModel.kt
+++ b/app/src/main/java/com/futo/circles/feature/group_invite/InviteMembersViewModel.kt
@@ -1,8 +1,12 @@
 package com.futo.circles.feature.group_invite
 
+import android.util.Log
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
+import com.futo.circles.extensions.launchUi
 import com.futo.circles.feature.group_invite.data_source.InviteMembersDataSource
+import com.futo.circles.model.RoomMemberListItem
+import kotlinx.coroutines.flow.*
 
 class InviteMembersViewModel(
     private val dataSource: InviteMembersDataSource
@@ -10,5 +14,20 @@ class InviteMembersViewModel(
 
     val titleLiveData = MutableLiveData(dataSource.getInviteTitle())
 
+    val usersLiveData = MutableLiveData<List<RoomMemberListItem>>()
+
+    fun initSearchListener(queryFlow: StateFlow<String>) {
+        launchUi {
+            queryFlow
+                .debounce(500)
+                .distinctUntilChanged()
+                .flatMapLatest { query -> dataSource.search(query) }
+                .collectLatest { members ->
+                    usersLiveData.postValue(members)
+                    Log.d("MyLog", members.size.toString())
+                }
+        }
+    }
+
 
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/futo/circles/feature/group_invite/data_source/InviteMembersDataSource.kt b/app/src/main/java/com/futo/circles/feature/group_invite/data_source/InviteMembersDataSource.kt
index 2772decb8043f5dd2a5c2685012f00ac306b7036..258a426ea509cc34d01ddcc923ddb8902f33abdc 100644
--- a/app/src/main/java/com/futo/circles/feature/group_invite/data_source/InviteMembersDataSource.kt
+++ b/app/src/main/java/com/futo/circles/feature/group_invite/data_source/InviteMembersDataSource.kt
@@ -1,20 +1,54 @@
 package com.futo.circles.feature.group_invite.data_source
 
 import android.content.Context
+import androidx.lifecycle.asFlow
 import com.futo.circles.R
 import com.futo.circles.extensions.nameOrId
+import com.futo.circles.mapping.toRoomMember
 import com.futo.circles.provider.MatrixSessionProvider
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.*
+import org.matrix.android.sdk.api.session.user.model.User
 
 class InviteMembersDataSource(
     private val roomId: String,
     private val context: Context
 ) {
 
-    private val room = MatrixSessionProvider.currentSession?.getRoom(roomId)
+    private val session = MatrixSessionProvider.currentSession
+    private val room = session?.getRoom(roomId)
+
+    private val existingMembersIds = room?.roomSummary()?.otherMemberIds?.toSet().orEmpty()
 
     fun getInviteTitle() = context.getString(
         R.string.invite_members_to_format,
         room?.roomSummary()?.nameOrId() ?: roomId
     )
 
+    suspend fun search(query: String) = combine(searchKnownUsers(query), searchSuggestions(query))
+    { knowUsers, suggestions ->
+        (knowUsers + suggestions).distinctBy { it.userId }.map { it.toRoomMember() }
+    }.flowOn(Dispatchers.IO).distinctUntilChanged()
+
+
+    private fun searchKnownUsers(query: String) = session?.getUsersLive()?.asFlow()
+        ?.map { list ->
+            list.filter { user ->
+                (user.displayName?.contains(query, true) ?: false
+                        || user.userId.contains(query, true))
+                        && existingMembersIds.contains(user.userId).not()
+            }
+        } ?: flowOf()
+
+
+    private suspend fun searchSuggestions(query: String): Flow<List<User>> = flow {
+        val users = session?.searchUsersDirectory(query, MAX_SUGGESTION_COUNT, existingMembersIds)
+        emit(users ?: emptyList())
+    }
+
+
+    private companion object {
+        private const val MAX_SUGGESTION_COUNT = 50
+    }
+
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/futo/circles/mapping/MatrixUserMapping.kt b/app/src/main/java/com/futo/circles/mapping/MatrixUserMapping.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a837f77804001e64997ffcd6735d4e0dd6369f9c
--- /dev/null
+++ b/app/src/main/java/com/futo/circles/mapping/MatrixUserMapping.kt
@@ -0,0 +1,10 @@
+package com.futo.circles.mapping
+
+import com.futo.circles.model.RoomMemberListItem
+import org.matrix.android.sdk.api.session.user.model.User
+
+fun User.toRoomMember() = RoomMemberListItem(
+    id = userId,
+    name = displayName ?: userId,
+    avatarUrl = avatarUrl ?: ""
+)
\ No newline at end of file
diff --git a/app/src/main/res/layout/invite_members_dialog_fragment.xml b/app/src/main/res/layout/invite_members_dialog_fragment.xml
index 6f4c00da1b9a0bf44e754b8a1f42f655f3e86256..cb3fc58240255f7c106b51f81380dc6e4ae6f522 100644
--- a/app/src/main/res/layout/invite_members_dialog_fragment.xml
+++ b/app/src/main/res/layout/invite_members_dialog_fragment.xml
@@ -30,6 +30,7 @@
         android:layout_height="wrap_content"
         android:layout_margin="8dp"
         android:background="@drawable/bg_border"
+        app:iconifiedByDefault="false"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@id/toolbarDivider"