Merge remote-tracking branch 'origin/develop' into bugfix/eric/new-layout-open-invite

This commit is contained in:
ericdecanini 2022-09-07 14:03:54 +02:00
commit 3b2fa0d563
34 changed files with 246 additions and 170 deletions

View File

@ -27,7 +27,7 @@ jobs:
- uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488 - uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
with: with:
project: Android App Team project: Android App Team
column: P1 column: Important Issues & Topics (P1)
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }} repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
P1_issues_to_crypto_team_workboard: P1_issues_to_crypto_team_workboard:

View File

@ -45,7 +45,7 @@ plugins {
id "io.gitlab.arturbosch.detekt" version "1.21.0" id "io.gitlab.arturbosch.detekt" version "1.21.0"
// Dependency Analysis // Dependency Analysis
id 'com.autonomousapps.dependency-analysis' version "1.12.0" id 'com.autonomousapps.dependency-analysis' version "1.13.1"
} }
// https://github.com/jeremylong/DependencyCheck // https://github.com/jeremylong/DependencyCheck

1
changelog.d/7039.wip Normal file
View File

@ -0,0 +1 @@
[New Layout] Changes space icon in fab and in release notes screen

1
changelog.d/7054.bugfix Normal file
View File

@ -0,0 +1 @@
Fix invite to room when in a space buttons not working.

View File

@ -101,11 +101,11 @@ class UiAllScreensSanityTest {
val spaceName = UUID.randomUUID().toString() val spaceName = UUID.randomUUID().toString()
elementRobot.space { elementRobot.space {
createSpace { createSpace(true) {
createAndCrawl(spaceName) createAndCrawl(spaceName)
} }
val publicSpaceName = UUID.randomUUID().toString() val publicSpaceName = UUID.randomUUID().toString()
createSpace { createSpace(false) {
createPublicSpace(publicSpaceName) createPublicSpace(publicSpaceName)
} }

View File

@ -51,8 +51,7 @@ import im.vector.app.withIdlingResource
import timber.log.Timber import timber.log.Timber
class ElementRobot { class ElementRobot {
private val features: VectorFeatures = DefaultVectorFeatures()
var features: VectorFeatures = DefaultVectorFeatures()
fun onboarding(block: OnboardingRobot.() -> Unit) { fun onboarding(block: OnboardingRobot.() -> Unit) {
block(OnboardingRobot()) block(OnboardingRobot())
@ -84,33 +83,56 @@ class ElementRobot {
} }
fun settings(shouldGoBack: Boolean = true, block: SettingsRobot.() -> Unit) { fun settings(shouldGoBack: Boolean = true, block: SettingsRobot.() -> Unit) {
openDrawer() if (features.isNewAppLayoutEnabled()) {
clickOn(R.id.homeDrawerHeaderSettingsView) onView(withId((R.id.avatar))).perform(click())
} else {
openDrawer()
clickOn(R.id.homeDrawerHeaderSettingsView)
}
block(SettingsRobot()) block(SettingsRobot())
if (shouldGoBack) pressBack() if (shouldGoBack) pressBack()
waitUntilViewVisible(withId(R.id.roomListContainer)) waitUntilViewVisible(withId(R.id.roomListContainer))
} }
fun newDirectMessage(block: NewDirectMessageRobot.() -> Unit) { fun newDirectMessage(block: NewDirectMessageRobot.() -> Unit) {
clickOn(R.id.bottom_action_people) if (features.isNewAppLayoutEnabled()) {
clickOn(R.id.createChatRoomButton) clickOn(R.id.newLayoutCreateChatButton)
waitUntilDialogVisible(withId(R.id.start_chat))
clickOn(R.id.start_chat)
} else {
clickOn(R.id.bottom_action_people)
clickOn(R.id.createChatRoomButton)
}
waitUntilActivityVisible<CreateDirectRoomActivity> { waitUntilActivityVisible<CreateDirectRoomActivity> {
waitUntilViewVisible(withId(R.id.userListSearch)) waitUntilViewVisible(withId(R.id.userListSearch))
} }
closeSoftKeyboard() closeSoftKeyboard()
block(NewDirectMessageRobot()) block(NewDirectMessageRobot())
pressBack() pressBack()
if (features.isNewAppLayoutEnabled()) {
pressBack() // close create dialog
}
waitUntilViewVisible(withId(R.id.roomListContainer)) waitUntilViewVisible(withId(R.id.roomListContainer))
} }
fun newRoom(block: NewRoomRobot.() -> Unit) { fun newRoom(block: NewRoomRobot.() -> Unit) {
clickOn(R.id.bottom_action_rooms) if (!features.isNewAppLayoutEnabled()) {
clickOn(R.id.bottom_action_rooms)
}
RoomListRobot().newRoom { block() } RoomListRobot().newRoom { block() }
if (features.isNewAppLayoutEnabled()) {
pressBack() // close create dialog
}
waitUntilViewVisible(withId(R.id.roomListContainer)) waitUntilViewVisible(withId(R.id.roomListContainer))
} }
fun roomList(block: RoomListRobot.() -> Unit) { fun roomList(block: RoomListRobot.() -> Unit) {
clickOn(R.id.bottom_action_rooms) if (!features.isNewAppLayoutEnabled()) {
clickOn(R.id.bottom_action_rooms)
}
block(RoomListRobot()) block(RoomListRobot())
waitUntilViewVisible(withId(R.id.roomListContainer)) waitUntilViewVisible(withId(R.id.roomListContainer))
} }

View File

@ -21,13 +21,18 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import im.vector.app.R import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.espresso.tools.waitUntilViewVisible
import im.vector.app.features.DefaultVectorFeatures
import im.vector.app.features.VectorFeatures
class NewRoomRobot( class NewRoomRobot(
var createdRoom: Boolean = false var createdRoom: Boolean = false
) { ) {
private val features: VectorFeatures = DefaultVectorFeatures()
fun createNewRoom(block: CreateNewRoomRobot.() -> Unit) { fun createNewRoom(block: CreateNewRoomRobot.() -> Unit) {
clickOn(R.string.create_new_room) if (features.isNewAppLayoutEnabled()) {
clickOn(R.string.create_new_room)
}
waitUntilViewVisible(withId(R.id.createRoomForm)) waitUntilViewVisible(withId(R.id.createRoomForm))
val createNewRoomRobot = CreateNewRoomRobot() val createNewRoomRobot = CreateNewRoomRobot()
block(createNewRoomRobot) block(createNewRoomRobot)

View File

@ -33,7 +33,6 @@ import im.vector.app.features.DefaultVectorFeatures
import im.vector.app.waitForView import im.vector.app.waitForView
class OnboardingRobot { class OnboardingRobot {
private val defaultVectorFeatures = DefaultVectorFeatures() private val defaultVectorFeatures = DefaultVectorFeatures()
fun crawl() { fun crawl() {

View File

@ -27,9 +27,13 @@ import com.adevinta.android.barista.assertion.BaristaVisibilityAssertions
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
import im.vector.app.R import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilActivityVisible import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.espresso.tools.waitUntilDialogVisible
import im.vector.app.features.DefaultVectorFeatures
import im.vector.app.features.VectorFeatures
import im.vector.app.features.roomdirectory.RoomDirectoryActivity import im.vector.app.features.roomdirectory.RoomDirectoryActivity
class RoomListRobot { class RoomListRobot {
private val features: VectorFeatures = DefaultVectorFeatures()
fun openRoom(roomName: String, block: RoomDetailRobot.() -> Unit) { fun openRoom(roomName: String, block: RoomDetailRobot.() -> Unit) {
clickOn(roomName) clickOn(roomName)
@ -49,9 +53,15 @@ class RoomListRobot {
} }
fun newRoom(block: NewRoomRobot.() -> Unit) { fun newRoom(block: NewRoomRobot.() -> Unit) {
clickOn(R.id.createGroupRoomButton) if (features.isNewAppLayoutEnabled()) {
waitUntilActivityVisible<RoomDirectoryActivity> { clickOn(R.id.newLayoutCreateChatButton)
BaristaVisibilityAssertions.assertDisplayed(R.id.publicRoomsList) waitUntilDialogVisible(ViewMatchers.withId(R.id.create_room))
clickOn(R.id.create_room)
} else {
clickOn(R.id.createGroupRoomButton)
waitUntilActivityVisible<RoomDirectoryActivity> {
BaristaVisibilityAssertions.assertDisplayed(R.id.publicRoomsList)
}
} }
val newRoomRobot = NewRoomRobot() val newRoomRobot = NewRoomRobot()
block(newRoomRobot) block(newRoomRobot)

View File

@ -31,6 +31,7 @@ import im.vector.app.espresso.tools.waitUntilActivityVisible
import im.vector.app.espresso.tools.waitUntilDialogVisible import im.vector.app.espresso.tools.waitUntilDialogVisible
import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.espresso.tools.waitUntilViewVisible
import im.vector.app.features.home.HomeActivity import im.vector.app.features.home.HomeActivity
import im.vector.app.features.home.room.detail.RoomDetailActivity
import im.vector.app.features.spaces.manage.SpaceManageActivity import im.vector.app.features.spaces.manage.SpaceManageActivity
class SpaceCreateRobot { class SpaceCreateRobot {
@ -85,7 +86,9 @@ class SpaceCreateRobot {
clickOn(R.id.nextButton) clickOn(R.id.nextButton)
waitUntilViewVisible(withId(R.id.recyclerView)) waitUntilViewVisible(withId(R.id.recyclerView))
clickOn(R.id.nextButton) clickOn(R.id.nextButton)
waitUntilDialogVisible(withId(R.id.inviteByMxidButton)) waitUntilActivityVisible<RoomDetailActivity> {
waitUntilDialogVisible(withId(R.id.inviteByMxidButton))
}
// close invite dialog // close invite dialog
pressBack() pressBack()
waitUntilViewVisible(withId(R.id.timelineRecyclerView)) waitUntilViewVisible(withId(R.id.timelineRecyclerView))

View File

@ -18,6 +18,8 @@ package im.vector.app.ui.robot.space
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso import androidx.test.espresso.Espresso
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.contrib.RecyclerViewActions import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers
import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn
@ -26,18 +28,43 @@ import com.adevinta.android.barista.internal.viewaction.ClickChildAction
import im.vector.app.R import im.vector.app.R
import im.vector.app.espresso.tools.waitUntilDialogVisible import im.vector.app.espresso.tools.waitUntilDialogVisible
import im.vector.app.espresso.tools.waitUntilViewVisible import im.vector.app.espresso.tools.waitUntilViewVisible
import im.vector.app.features.DefaultVectorFeatures
import im.vector.app.features.VectorFeatures
import org.hamcrest.Matchers import org.hamcrest.Matchers
class SpaceRobot { class SpaceRobot {
private val features: VectorFeatures = DefaultVectorFeatures()
fun createSpace(block: SpaceCreateRobot.() -> Unit) { fun createSpace(isFirstSpace: Boolean, block: SpaceCreateRobot.() -> Unit) {
openDrawer() if (features.isNewAppLayoutEnabled()) {
clickOn(R.string.create_space) clickOn(R.id.newLayoutOpenSpacesButton)
if (isFirstSpace) {
waitUntilDialogVisible(ViewMatchers.withId(R.id.spaces_empty_group))
clickOn(R.id.spaces_empty_button)
} else {
waitUntilDialogVisible(ViewMatchers.withId(R.id.groupListView))
Espresso.onView(ViewMatchers.withId(R.id.groupListView))
.perform(
RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
ViewMatchers.hasDescendant(ViewMatchers.withId(R.id.plus)),
click()
).atPosition(0)
)
}
} else {
openDrawer()
clickOn(R.string.create_space)
}
block(SpaceCreateRobot()) block(SpaceCreateRobot())
} }
fun spaceMenu(spaceName: String, block: SpaceMenuRobot.() -> Unit) { fun spaceMenu(spaceName: String, block: SpaceMenuRobot.() -> Unit) {
openDrawer() if (features.isNewAppLayoutEnabled()) {
clickOn(R.id.newLayoutOpenSpacesButton)
waitUntilDialogVisible(ViewMatchers.withId(R.id.groupListView))
} else {
openDrawer()
}
with(SpaceMenuRobot()) { with(SpaceMenuRobot()) {
openMenu(spaceName) openMenu(spaceName)
block() block()
@ -46,19 +73,32 @@ class SpaceRobot {
fun openMenu(spaceName: String) { fun openMenu(spaceName: String) {
waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView)) waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView))
Espresso.onView(ViewMatchers.withId(R.id.groupListView)) if (features.isNewAppLayoutEnabled()) {
.perform( Espresso.onView(ViewMatchers.withId(R.id.groupListView))
RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>( .perform(
ViewMatchers.hasDescendant(Matchers.allOf(ViewMatchers.withId(R.id.groupNameView), ViewMatchers.withText(spaceName))), RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
ClickChildAction.clickChildWithId(R.id.groupTmpLeave) ViewMatchers.hasDescendant(Matchers.allOf(ViewMatchers.withId(R.id.name), ViewMatchers.withText(spaceName))),
).atPosition(0) longClick()
) ).atPosition(0)
)
} else {
Espresso.onView(ViewMatchers.withId(R.id.groupListView))
.perform(
RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
ViewMatchers.hasDescendant(Matchers.allOf(ViewMatchers.withId(R.id.groupNameView), ViewMatchers.withText(spaceName))),
ClickChildAction.clickChildWithId(R.id.groupTmpLeave)
).atPosition(0)
)
}
waitUntilDialogVisible(ViewMatchers.withId(R.id.spaceNameView)) waitUntilDialogVisible(ViewMatchers.withId(R.id.spaceNameView))
} }
fun selectSpace(spaceName: String) { fun selectSpace(spaceName: String) {
openDrawer() if (!features.isNewAppLayoutEnabled()) {
waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView)) openDrawer()
waitUntilViewVisible(ViewMatchers.withId(R.id.groupListView))
}
clickOn(spaceName) clickOn(spaceName)
} }
} }

View File

@ -377,7 +377,7 @@ class HomeActivity :
lifecycleScope.launch { lifecycleScope.launch {
val isHandled = permalinkHandler.launch( val isHandled = permalinkHandler.launch(
context = this@HomeActivity, fragmentActivity = this@HomeActivity,
deepLink = resolvedLink, deepLink = resolvedLink,
navigationInterceptor = this@HomeActivity, navigationInterceptor = this@HomeActivity,
buildTask = true buildTask = true

View File

@ -232,9 +232,10 @@ class HomeDetailFragment :
viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer) viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer)
colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary) colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary)
contentAction = Runnable { contentAction = Runnable {
(weakCurrentActivity?.get() as? VectorBaseActivity<*>) (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { vectorBaseActivity ->
?.navigator vectorBaseActivity.navigator
?.requestSessionVerification(requireContext(), newest.deviceId ?: "") .requestSessionVerification(vectorBaseActivity, newest.deviceId ?: "")
}
unknownDeviceDetectorSharedViewModel.handle( unknownDeviceDetectorSharedViewModel.handle(
UnknownDeviceDetectorSharedViewModel.Action.IgnoreDevice(newest.deviceId?.let { listOf(it) }.orEmpty()) UnknownDeviceDetectorSharedViewModel.Action.IgnoreDevice(newest.deviceId?.let { listOf(it) }.orEmpty())
) )

View File

@ -250,9 +250,10 @@ class NewHomeDetailFragment :
viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer) viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer)
colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary) colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary)
contentAction = Runnable { contentAction = Runnable {
(weakCurrentActivity?.get() as? VectorBaseActivity<*>) (weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let { vectorBaseActivity ->
?.navigator vectorBaseActivity.navigator
?.requestSessionVerification(requireContext(), newest.deviceId ?: "") .requestSessionVerification(vectorBaseActivity, newest.deviceId ?: "")
}
unknownDeviceDetectorSharedViewModel.handle( unknownDeviceDetectorSharedViewModel.handle(
UnknownDeviceDetectorSharedViewModel.Action.IgnoreDevice(newest.deviceId?.let { listOf(it) }.orEmpty()) UnknownDeviceDetectorSharedViewModel.Action.IgnoreDevice(newest.deviceId?.let { listOf(it) }.orEmpty())
) )

View File

@ -497,7 +497,7 @@ class TimelineFragment :
RoomDetailViewEvents.HideWaitingView -> vectorBaseActivity.hideWaitingView() RoomDetailViewEvents.HideWaitingView -> vectorBaseActivity.hideWaitingView()
is RoomDetailViewEvents.RequestNativeWidgetPermission -> requestNativeWidgetPermission(it) is RoomDetailViewEvents.RequestNativeWidgetPermission -> requestNativeWidgetPermission(it)
is RoomDetailViewEvents.OpenRoom -> handleOpenRoom(it) is RoomDetailViewEvents.OpenRoom -> handleOpenRoom(it)
RoomDetailViewEvents.OpenInvitePeople -> navigator.openInviteUsersToRoom(requireContext(), timelineArgs.roomId) RoomDetailViewEvents.OpenInvitePeople -> navigator.openInviteUsersToRoom(requireActivity(), timelineArgs.roomId)
RoomDetailViewEvents.OpenSetRoomAvatarDialog -> galleryOrCameraDialogHelper.show() RoomDetailViewEvents.OpenSetRoomAvatarDialog -> galleryOrCameraDialogHelper.show()
RoomDetailViewEvents.OpenRoomSettings -> handleOpenRoomSettings(RoomProfileActivity.EXTRA_DIRECT_ACCESS_ROOM_SETTINGS) RoomDetailViewEvents.OpenRoomSettings -> handleOpenRoomSettings(RoomProfileActivity.EXTRA_DIRECT_ACCESS_ROOM_SETTINGS)
RoomDetailViewEvents.OpenRoomProfile -> handleOpenRoomSettings() RoomDetailViewEvents.OpenRoomProfile -> handleOpenRoomSettings()
@ -2190,7 +2190,7 @@ class TimelineFragment :
override fun onRoomCreateLinkClicked(url: String) { override fun onRoomCreateLinkClicked(url: String) {
viewLifecycleOwner.lifecycleScope.launchWhenResumed { viewLifecycleOwner.lifecycleScope.launchWhenResumed {
permalinkHandler permalinkHandler
.launch(requireContext(), url, object : NavigationInterceptor { .launch(requireActivity(), url, object : NavigationInterceptor {
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean { override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean {
requireActivity().finish() requireActivity().finish()
return false return false

View File

@ -188,7 +188,7 @@ class RoomListFragment :
} }
private fun handleShowMxToLink(link: String) { private fun handleShowMxToLink(link: String) {
navigator.openMatrixToBottomSheet(requireContext(), link, OriginOfMatrixTo.ROOM_LIST) navigator.openMatrixToBottomSheet(requireActivity(), link, OriginOfMatrixTo.ROOM_LIST)
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -41,7 +41,7 @@ class RecentRoomCarouselController @Inject constructor(
private val hPadding = TypedValue.applyDimension( private val hPadding = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, TypedValue.COMPLEX_UNIT_DIP,
16f, 4f,
resources.displayMetrics resources.displayMetrics
).toInt() ).toInt()
@ -51,12 +51,6 @@ class RecentRoomCarouselController @Inject constructor(
resources.displayMetrics resources.displayMetrics
).toInt() ).toInt()
private val itemSpacing = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
24f,
resources.displayMetrics
).toInt()
fun submitList(recentList: List<RoomSummary>) { fun submitList(recentList: List<RoomSummary>) {
this.data = recentList this.data = recentList
requestModelBuild() requestModelBuild()
@ -72,7 +66,8 @@ class RecentRoomCarouselController @Inject constructor(
host.topPadding, host.topPadding,
host.hPadding, host.hPadding,
0, 0,
host.itemSpacing) 0,
)
) )
onBind { _, view, _ -> onBind { _, view, _ ->
val colorSurface = MaterialColors.getColor(view, R.attr.vctr_toolbar_background) val colorSurface = MaterialColors.getColor(view, R.attr.vctr_toolbar_background)

View File

@ -25,11 +25,11 @@ import android.view.View
import android.view.Window import android.view.Window
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityOptionsCompat import androidx.core.app.ActivityOptionsCompat
import androidx.core.app.TaskStackBuilder import androidx.core.app.TaskStackBuilder
import androidx.core.util.Pair import androidx.core.util.Pair
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.fragment.app.FragmentActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R import im.vector.app.R
import im.vector.app.SpaceStateHandler import im.vector.app.SpaceStateHandler
@ -224,75 +224,65 @@ class DefaultNavigator @Inject constructor(
startActivity(context, SpacePreviewActivity.newIntent(context, spaceId), false) startActivity(context, SpacePreviewActivity.newIntent(context, spaceId), false)
} }
override fun performDeviceVerification(context: Context, otherUserId: String, sasTransactionId: String) { override fun performDeviceVerification(fragmentActivity: FragmentActivity, otherUserId: String, sasTransactionId: String) {
val session = sessionHolder.getSafeActiveSession() ?: return val session = sessionHolder.getSafeActiveSession() ?: return
val tx = session.cryptoService().verificationService().getExistingTransaction(otherUserId, sasTransactionId) val tx = session.cryptoService().verificationService().getExistingTransaction(otherUserId, sasTransactionId)
?: return ?: return
(tx as? IncomingSasVerificationTransaction)?.performAccept() (tx as? IncomingSasVerificationTransaction)?.performAccept()
if (context is AppCompatActivity) { VerificationBottomSheet.withArgs(
VerificationBottomSheet.withArgs( roomId = null,
roomId = null, otherUserId = otherUserId,
otherUserId = otherUserId, transactionId = sasTransactionId
transactionId = sasTransactionId ).show(fragmentActivity.supportFragmentManager, "REQPOP")
).show(context.supportFragmentManager, "REQPOP")
}
} }
override fun requestSessionVerification(context: Context, otherSessionId: String) { override fun requestSessionVerification(fragmentActivity: FragmentActivity, otherSessionId: String) {
val session = sessionHolder.getSafeActiveSession() ?: return val session = sessionHolder.getSafeActiveSession() ?: return
val pr = session.cryptoService().verificationService().requestKeyVerification( val pr = session.cryptoService().verificationService().requestKeyVerification(
supportedVerificationMethodsProvider.provide(), supportedVerificationMethodsProvider.provide(),
session.myUserId, session.myUserId,
listOf(otherSessionId) listOf(otherSessionId)
) )
if (context is AppCompatActivity) { VerificationBottomSheet.withArgs(
VerificationBottomSheet.withArgs( roomId = null,
roomId = null, otherUserId = session.myUserId,
otherUserId = session.myUserId, transactionId = pr.transactionId
transactionId = pr.transactionId ).show(fragmentActivity.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
).show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
}
} }
override fun requestSelfSessionVerification(context: Context) { override fun requestSelfSessionVerification(fragmentActivity: FragmentActivity) {
val session = sessionHolder.getSafeActiveSession() ?: return val session = sessionHolder.getSafeActiveSession() ?: return
val otherSessions = session.cryptoService() val otherSessions = session.cryptoService()
.getCryptoDeviceInfo(session.myUserId) .getCryptoDeviceInfo(session.myUserId)
.filter { it.deviceId != session.sessionParams.deviceId } .filter { it.deviceId != session.sessionParams.deviceId }
.map { it.deviceId } .map { it.deviceId }
if (context is AppCompatActivity) { if (otherSessions.isNotEmpty()) {
if (otherSessions.isNotEmpty()) { val pr = session.cryptoService().verificationService().requestKeyVerification(
val pr = session.cryptoService().verificationService().requestKeyVerification( supportedVerificationMethodsProvider.provide(),
supportedVerificationMethodsProvider.provide(), session.myUserId,
session.myUserId, otherSessions
otherSessions
)
VerificationBottomSheet.forSelfVerification(session, pr.transactionId ?: pr.localId)
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
} else {
VerificationBottomSheet.forSelfVerification(session)
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
}
}
}
override fun waitSessionVerification(context: Context) {
val session = sessionHolder.getSafeActiveSession() ?: return
if (context is AppCompatActivity) {
VerificationBottomSheet.forSelfVerification(session)
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
}
}
override fun upgradeSessionSecurity(context: Context, initCrossSigningOnly: Boolean) {
if (context is AppCompatActivity) {
BootstrapBottomSheet.show(
context.supportFragmentManager,
if (initCrossSigningOnly) SetupMode.CROSS_SIGNING_ONLY else SetupMode.NORMAL
) )
VerificationBottomSheet.forSelfVerification(session, pr.transactionId ?: pr.localId)
.show(fragmentActivity.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
} else {
VerificationBottomSheet.forSelfVerification(session)
.show(fragmentActivity.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
} }
} }
override fun waitSessionVerification(fragmentActivity: FragmentActivity) {
val session = sessionHolder.getSafeActiveSession() ?: return
VerificationBottomSheet.forSelfVerification(session)
.show(fragmentActivity.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
}
override fun upgradeSessionSecurity(fragmentActivity: FragmentActivity, initCrossSigningOnly: Boolean) {
BootstrapBottomSheet.show(
fragmentActivity.supportFragmentManager,
if (initCrossSigningOnly) SetupMode.CROSS_SIGNING_ONLY else SetupMode.NORMAL
)
}
override fun openRoomMemberProfile(userId: String, roomId: String?, context: Context, buildTask: Boolean) { override fun openRoomMemberProfile(userId: String, roomId: String?, context: Context, buildTask: Boolean) {
val args = RoomMemberProfileArgs(userId = userId, roomId = roomId) val args = RoomMemberProfileArgs(userId = userId, roomId = roomId)
val intent = RoomMemberProfileActivity.newIntent(context, args) val intent = RoomMemberProfileActivity.newIntent(context, args)
@ -316,16 +306,14 @@ class DefaultNavigator @Inject constructor(
context.startActivity(intent) context.startActivity(intent)
} }
override fun openMatrixToBottomSheet(context: Context, link: String, origin: OriginOfMatrixTo) { override fun openMatrixToBottomSheet(fragmentActivity: FragmentActivity, link: String, origin: OriginOfMatrixTo) {
if (context is AppCompatActivity) { if (fragmentActivity !is MatrixToBottomSheet.InteractionListener) {
if (context !is MatrixToBottomSheet.InteractionListener) { fatalError("Caller context should implement MatrixToBottomSheet.InteractionListener", vectorPreferences.failFast())
fatalError("Caller context should implement MatrixToBottomSheet.InteractionListener", vectorPreferences.failFast()) return
return
}
// TODO check if there is already one??
MatrixToBottomSheet.withLink(link, origin)
.show(context.supportFragmentManager, "HA#MatrixToBottomSheet")
} }
// TODO check if there is already one??
MatrixToBottomSheet.withLink(link, origin)
.show(fragmentActivity.supportFragmentManager, "HA#MatrixToBottomSheet")
} }
override fun openRoomDirectory(context: Context, initialFilter: String) { override fun openRoomDirectory(context: Context, initialFilter: String) {
@ -347,18 +335,16 @@ class DefaultNavigator @Inject constructor(
}.start(context) }.start(context)
} }
override fun openInviteUsersToRoom(context: Context, roomId: String) { override fun openInviteUsersToRoom(fragmentActivity: FragmentActivity, roomId: String) {
when (val currentSpace = spaceStateHandler.getCurrentSpace()) { when (val currentSpace = spaceStateHandler.getCurrentSpace()) {
null -> InviteUsersToRoomActivity.getIntent(context, roomId).start(context) null -> InviteUsersToRoomActivity.getIntent(fragmentActivity, roomId).start(fragmentActivity)
else -> showInviteToDialog(context, currentSpace, roomId) else -> showInviteToDialog(fragmentActivity, currentSpace, roomId)
} }
} }
private fun showInviteToDialog(context: Context, currentSpace: RoomSummary, roomId: String) { private fun showInviteToDialog(fragmentActivity: FragmentActivity, currentSpace: RoomSummary, roomId: String) {
(context as? AppCompatActivity)?.supportFragmentManager?.let { fragmentManager -> InviteRoomSpaceChooserBottomSheet.showInstance(fragmentActivity.supportFragmentManager, currentSpace.roomId, roomId) { itemId ->
InviteRoomSpaceChooserBottomSheet.showInstance(fragmentManager, currentSpace.roomId, roomId) { itemId -> InviteUsersToRoomActivity.getIntent(fragmentActivity, itemId).start(fragmentActivity)
InviteUsersToRoomActivity.getIntent(context, itemId).start(context)
}
} }
} }
@ -381,24 +367,20 @@ class DefaultNavigator @Inject constructor(
debugNavigator.openDebugMenu(context) debugNavigator.openDebugMenu(context)
} }
override fun openKeysBackupSetup(context: Context, showManualExport: Boolean) { override fun openKeysBackupSetup(fragmentActivity: FragmentActivity, showManualExport: Boolean) {
// if cross signing is enabled and trusted or not set up at all we should propose full 4S // if cross signing is enabled and trusted or not set up at all we should propose full 4S
sessionHolder.getSafeActiveSession()?.let { session -> sessionHolder.getSafeActiveSession()?.let { session ->
if (session.cryptoService().crossSigningService().getMyCrossSigningKeys() == null || if (session.cryptoService().crossSigningService().getMyCrossSigningKeys() == null ||
session.cryptoService().crossSigningService().canCrossSign()) { session.cryptoService().crossSigningService().canCrossSign()) {
(context as? AppCompatActivity)?.let { BootstrapBottomSheet.show(fragmentActivity.supportFragmentManager, SetupMode.NORMAL)
BootstrapBottomSheet.show(it.supportFragmentManager, SetupMode.NORMAL)
}
} else { } else {
context.startActivity(KeysBackupSetupActivity.intent(context, showManualExport)) fragmentActivity.startActivity(KeysBackupSetupActivity.intent(fragmentActivity, showManualExport))
} }
} }
} }
override fun open4SSetup(context: Context, setupMode: SetupMode) { override fun open4SSetup(fragmentActivity: FragmentActivity, setupMode: SetupMode) {
if (context is AppCompatActivity) { BootstrapBottomSheet.show(fragmentActivity.supportFragmentManager, setupMode)
BootstrapBottomSheet.show(context.supportFragmentManager, setupMode)
}
} }
override fun openKeysBackupManager(context: Context) { override fun openKeysBackupManager(context: Context) {

View File

@ -23,6 +23,7 @@ import android.net.Uri
import android.view.View import android.view.View
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.core.util.Pair import androidx.core.util.Pair
import androidx.fragment.app.FragmentActivity
import im.vector.app.features.analytics.plan.ViewRoom import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.crypto.recover.SetupMode
import im.vector.app.features.displayname.getBestName import im.vector.app.features.displayname.getBestName
@ -76,15 +77,15 @@ interface Navigator {
fun openSpacePreview(context: Context, spaceId: String) fun openSpacePreview(context: Context, spaceId: String)
fun performDeviceVerification(context: Context, otherUserId: String, sasTransactionId: String) fun performDeviceVerification(fragmentActivity: FragmentActivity, otherUserId: String, sasTransactionId: String)
fun requestSessionVerification(context: Context, otherSessionId: String) fun requestSessionVerification(fragmentActivity: FragmentActivity, otherSessionId: String)
fun requestSelfSessionVerification(context: Context) fun requestSelfSessionVerification(fragmentActivity: FragmentActivity)
fun waitSessionVerification(context: Context) fun waitSessionVerification(fragmentActivity: FragmentActivity)
fun upgradeSessionSecurity(context: Context, initCrossSigningOnly: Boolean) fun upgradeSessionSecurity(fragmentActivity: FragmentActivity, initCrossSigningOnly: Boolean)
fun openRoomForSharingAndFinish(activity: Activity, roomId: String, sharedData: SharedData) fun openRoomForSharingAndFinish(activity: Activity, roomId: String, sharedData: SharedData)
@ -92,13 +93,13 @@ interface Navigator {
fun openRoomPreview(context: Context, roomPreviewData: RoomPreviewData, fromEmailInviteLink: PermalinkData.RoomEmailInviteLink? = null) fun openRoomPreview(context: Context, roomPreviewData: RoomPreviewData, fromEmailInviteLink: PermalinkData.RoomEmailInviteLink? = null)
fun openMatrixToBottomSheet(context: Context, link: String, origin: OriginOfMatrixTo) fun openMatrixToBottomSheet(fragmentActivity: FragmentActivity, link: String, origin: OriginOfMatrixTo)
fun openCreateRoom(context: Context, initialName: String = "", openAfterCreate: Boolean = true) fun openCreateRoom(context: Context, initialName: String = "", openAfterCreate: Boolean = true)
fun openCreateDirectRoom(context: Context) fun openCreateDirectRoom(context: Context)
fun openInviteUsersToRoom(context: Context, roomId: String) fun openInviteUsersToRoom(fragmentActivity: FragmentActivity, roomId: String)
fun openRoomDirectory(context: Context, initialFilter: String = "") fun openRoomDirectory(context: Context, initialFilter: String = "")
@ -110,9 +111,9 @@ interface Navigator {
fun openDebug(context: Context) fun openDebug(context: Context)
fun openKeysBackupSetup(context: Context, showManualExport: Boolean) fun openKeysBackupSetup(fragmentActivity: FragmentActivity, showManualExport: Boolean)
fun open4SSetup(context: Context, setupMode: SetupMode) fun open4SSetup(fragmentActivity: FragmentActivity, setupMode: SetupMode)
fun openKeysBackupManager(context: Context) fun openKeysBackupManager(context: Context)

View File

@ -19,6 +19,7 @@ package im.vector.app.features.permalink
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.fragment.app.FragmentActivity
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.isIgnored import im.vector.app.core.extensions.isIgnored
@ -52,17 +53,17 @@ class PermalinkHandler @Inject constructor(
) { ) {
suspend fun launch( suspend fun launch(
context: Context, fragmentActivity: FragmentActivity,
deepLink: String?, deepLink: String?,
navigationInterceptor: NavigationInterceptor? = null, navigationInterceptor: NavigationInterceptor? = null,
buildTask: Boolean = false buildTask: Boolean = false
): Boolean { ): Boolean {
val uri = deepLink?.let { Uri.parse(it) } val uri = deepLink?.let { Uri.parse(it) }
return launch(context, uri, navigationInterceptor, buildTask) return launch(fragmentActivity, uri, navigationInterceptor, buildTask)
} }
suspend fun launch( suspend fun launch(
context: Context, fragmentActivity: FragmentActivity,
deepLink: Uri?, deepLink: Uri?,
navigationInterceptor: NavigationInterceptor? = null, navigationInterceptor: NavigationInterceptor? = null,
buildTask: Boolean = false buildTask: Boolean = false
@ -70,12 +71,12 @@ class PermalinkHandler @Inject constructor(
return when { return when {
deepLink == null -> false deepLink == null -> false
deepLink.isIgnored() -> true deepLink.isIgnored() -> true
!isPermalinkSupported(context, deepLink.toString()) -> false !isPermalinkSupported(fragmentActivity, deepLink.toString()) -> false
else -> { else -> {
tryOrNull { tryOrNull {
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
val permalinkData = PermalinkParser.parse(deepLink) val permalinkData = PermalinkParser.parse(deepLink)
handlePermalink(permalinkData, deepLink, context, navigationInterceptor, buildTask) handlePermalink(permalinkData, deepLink, fragmentActivity, navigationInterceptor, buildTask)
} }
} ?: false } ?: false
} }
@ -85,22 +86,22 @@ class PermalinkHandler @Inject constructor(
private suspend fun handlePermalink( private suspend fun handlePermalink(
permalinkData: PermalinkData, permalinkData: PermalinkData,
rawLink: Uri, rawLink: Uri,
context: Context, fragmentActivity: FragmentActivity,
navigationInterceptor: NavigationInterceptor?, navigationInterceptor: NavigationInterceptor?,
buildTask: Boolean buildTask: Boolean
): Boolean { ): Boolean {
return when (permalinkData) { return when (permalinkData) {
is PermalinkData.RoomLink -> handleRoomLink(permalinkData, rawLink, context, navigationInterceptor, buildTask) is PermalinkData.RoomLink -> handleRoomLink(permalinkData, rawLink, fragmentActivity, navigationInterceptor, buildTask)
is PermalinkData.UserLink -> handleUserLink(permalinkData, rawLink, context, navigationInterceptor, buildTask) is PermalinkData.UserLink -> handleUserLink(permalinkData, rawLink, fragmentActivity, navigationInterceptor, buildTask)
is PermalinkData.FallbackLink -> handleFallbackLink(permalinkData, context) is PermalinkData.FallbackLink -> handleFallbackLink(permalinkData, fragmentActivity)
is PermalinkData.RoomEmailInviteLink -> handleRoomInviteLink(permalinkData, context) is PermalinkData.RoomEmailInviteLink -> handleRoomInviteLink(permalinkData, fragmentActivity)
} }
} }
private suspend fun handleRoomLink( private suspend fun handleRoomLink(
permalinkData: PermalinkData.RoomLink, permalinkData: PermalinkData.RoomLink,
rawLink: Uri, rawLink: Uri,
context: Context, fragmentActivity: FragmentActivity,
navigationInterceptor: NavigationInterceptor?, navigationInterceptor: NavigationInterceptor?,
buildTask: Boolean buildTask: Boolean
): Boolean { ): Boolean {
@ -119,7 +120,7 @@ class PermalinkHandler @Inject constructor(
} }
openRoom( openRoom(
navigationInterceptor, navigationInterceptor,
context = context, fragmentActivity = fragmentActivity,
roomId = roomId, roomId = roomId,
permalinkData = permalinkData, permalinkData = permalinkData,
rawLink = rawLink, rawLink = rawLink,
@ -200,7 +201,7 @@ class PermalinkHandler @Inject constructor(
*/ */
private fun openRoom( private fun openRoom(
navigationInterceptor: NavigationInterceptor?, navigationInterceptor: NavigationInterceptor?,
context: Context, fragmentActivity: FragmentActivity,
roomId: String?, roomId: String?,
permalinkData: PermalinkData.RoomLink, permalinkData: PermalinkData.RoomLink,
rawLink: Uri, rawLink: Uri,
@ -209,7 +210,7 @@ class PermalinkHandler @Inject constructor(
) { ) {
val session = activeSessionHolder.getSafeActiveSession() ?: return val session = activeSessionHolder.getSafeActiveSession() ?: return
if (roomId == null) { if (roomId == null) {
context.toast(R.string.room_error_not_found) fragmentActivity.toast(R.string.room_error_not_found)
return return
} }
val roomSummary = session.getRoomSummary(roomId) val roomSummary = session.getRoomSummary(roomId)
@ -218,19 +219,19 @@ class PermalinkHandler @Inject constructor(
// val roomAlias = permalinkData.getRoomAliasOrNull() // val roomAlias = permalinkData.getRoomAliasOrNull()
val isSpace = roomSummary?.roomType == RoomType.SPACE val isSpace = roomSummary?.roomType == RoomType.SPACE
return when { return when {
membership == Membership.BAN -> context.toast(R.string.error_opening_banned_room) membership == Membership.BAN -> fragmentActivity.toast(R.string.error_opening_banned_room)
membership?.isActive().orFalse() -> { membership?.isActive().orFalse() -> {
if (!isSpace && membership == Membership.JOIN) { if (!isSpace && membership == Membership.JOIN) {
// If it's a room you're in, let's just open it, you can tap back if needed // If it's a room you're in, let's just open it, you can tap back if needed
navigationInterceptor.openJoinedRoomScreen(buildTask, roomId, eventId, rawLink, context, rootThreadEventId, roomSummary) navigationInterceptor.openJoinedRoomScreen(buildTask, roomId, eventId, rawLink, fragmentActivity, rootThreadEventId, roomSummary)
} else { } else {
// maybe open space preview navigator.openSpacePreview(context, roomId)? if already joined? // maybe open space preview navigator.openSpacePreview(fragmentActivity, roomId)? if already joined?
navigator.openMatrixToBottomSheet(context, rawLink.toString(), OriginOfMatrixTo.LINK) navigator.openMatrixToBottomSheet(fragmentActivity, rawLink.toString(), OriginOfMatrixTo.LINK)
} }
} }
else -> { else -> {
// XXX this could trigger another server load // XXX this could trigger another server load
navigator.openMatrixToBottomSheet(context, rawLink.toString(), OriginOfMatrixTo.LINK) navigator.openMatrixToBottomSheet(fragmentActivity, rawLink.toString(), OriginOfMatrixTo.LINK)
} }
} }
} }

View File

@ -130,7 +130,7 @@ class PublicRoomsFragment :
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
val permalink = session.permalinkService().createPermalink(roomIdOrAlias) val permalink = session.permalinkService().createPermalink(roomIdOrAlias)
val isHandled = permalinkHandler val isHandled = permalinkHandler
.launch(requireContext(), permalink, object : NavigationInterceptor { .launch(requireActivity(), permalink, object : NavigationInterceptor {
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean { override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean {
requireActivity().finish() requireActivity().finish()
return false return false

View File

@ -76,7 +76,7 @@ class RoomMemberListFragment :
private fun setupInviteUsersButton() { private fun setupInviteUsersButton() {
views.inviteUsersButton.debouncedClicks { views.inviteUsersButton.debouncedClicks {
navigator.openInviteUsersToRoom(requireContext(), roomProfileArgs.roomId) navigator.openInviteUsersToRoom(requireActivity(), roomProfileArgs.roomId)
} }
// Hide FAB when list is scrolling // Hide FAB when list is scrolling
views.roomSettingGeneric.roomSettingsRecyclerView.addOnScrollListener( views.roomSettingGeneric.roomSettingsRecyclerView.addOnScrollListener(

View File

@ -94,7 +94,7 @@ class VectorSettingsDevicesFragment :
} }
} }
is DevicesViewEvents.PromptResetSecrets -> { is DevicesViewEvents.PromptResetSecrets -> {
navigator.open4SSetup(requireContext(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET) navigator.open4SSetup(requireActivity(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET)
} }
} }
} }

View File

@ -99,7 +99,7 @@ class VectorSettingsDevicesFragment :
} }
} }
is DevicesViewEvents.PromptResetSecrets -> { is DevicesViewEvents.PromptResetSecrets -> {
navigator.open4SSetup(requireContext(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET) navigator.open4SSetup(requireActivity(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET)
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<group>
<clip-path
android:pathData="M1,0C0.448,0 0,0.448 0,1V7.889C0,8.441 0.448,8.889 1,8.889H7.889C8.441,8.889 8.889,8.441 8.889,7.889V1C8.889,0.448 8.441,0 7.889,0H1ZM12.111,0C11.559,0 11.111,0.448 11.111,1V7.889C11.111,8.441 11.559,8.889 12.111,8.889H19C19.552,8.889 20,8.441 20,7.889V1C20,0.448 19.552,0 19,0H12.111ZM0,12.111C0,11.559 0.448,11.111 1,11.111H7.889C8.441,11.111 8.889,11.559 8.889,12.111V19C8.889,19.552 8.441,20 7.889,20H1C0.448,20 0,19.552 0,19V12.111ZM12.111,11.111C11.559,11.111 11.111,11.559 11.111,12.111V19C11.111,19.552 11.559,20 12.111,20H19C19.552,20 20,19.552 20,19V12.111C20,11.559 19.552,11.111 19,11.111H12.111Z"
android:fillType="evenOdd"/>
<path
android:pathData="M2,1C2,1.552 1.552,2 1,2V-2C-0.657,-2 -2,-0.657 -2,1H2ZM2,7.889V1H-2V7.889H2ZM1,6.889C1.552,6.889 2,7.337 2,7.889H-2C-2,9.546 -0.657,10.889 1,10.889V6.889ZM7.889,6.889H1V10.889H7.889V6.889ZM6.889,7.889C6.889,7.337 7.337,6.889 7.889,6.889V10.889C9.546,10.889 10.889,9.546 10.889,7.889H6.889ZM6.889,1V7.889H10.889V1H6.889ZM7.889,2C7.337,2 6.889,1.552 6.889,1H10.889C10.889,-0.657 9.546,-2 7.889,-2V2ZM1,2H7.889V-2H1V2ZM13.111,1C13.111,1.552 12.663,2 12.111,2V-2C10.454,-2 9.111,-0.657 9.111,1H13.111ZM13.111,7.889V1H9.111V7.889H13.111ZM12.111,6.889C12.663,6.889 13.111,7.337 13.111,7.889H9.111C9.111,9.546 10.454,10.889 12.111,10.889V6.889ZM19,6.889H12.111V10.889H19V6.889ZM18,7.889C18,7.337 18.448,6.889 19,6.889V10.889C20.657,10.889 22,9.546 22,7.889H18ZM18,1V7.889H22V1H18ZM19,2C18.448,2 18,1.552 18,1H22C22,-0.657 20.657,-2 19,-2V2ZM12.111,2H19V-2H12.111V2ZM1,9.111C-0.657,9.111 -2,10.454 -2,12.111H2C2,12.663 1.552,13.111 1,13.111V9.111ZM7.889,9.111H1V13.111H7.889V9.111ZM10.889,12.111C10.889,10.454 9.546,9.111 7.889,9.111V13.111C7.337,13.111 6.889,12.663 6.889,12.111H10.889ZM10.889,19V12.111H6.889V19H10.889ZM7.889,22C9.546,22 10.889,20.657 10.889,19H6.889C6.889,18.448 7.337,18 7.889,18V22ZM1,22H7.889V18H1V22ZM-2,19C-2,20.657 -0.657,22 1,22V18C1.552,18 2,18.448 2,19H-2ZM-2,12.111V19H2V12.111H-2ZM13.111,12.111C13.111,12.663 12.663,13.111 12.111,13.111V9.111C10.454,9.111 9.111,10.454 9.111,12.111H13.111ZM13.111,19V12.111H9.111V19H13.111ZM12.111,18C12.663,18 13.111,18.448 13.111,19H9.111C9.111,20.657 10.454,22 12.111,22V18ZM19,18H12.111V22H19V18ZM18,19C18,18.448 18.448,18 19,18V22C20.657,22 22,20.657 22,19H18ZM18,12.111V19H22V12.111H18ZM19,13.111C18.448,13.111 18,12.663 18,12.111H22C22,10.454 20.657,9.111 19,9.111V13.111ZM12.111,13.111H19V9.111H12.111V13.111Z"
android:fillColor="#0DBD8B"/>
</group>
</vector>

View File

@ -0,0 +1,26 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M2,1L7,1A1,1 0,0 1,8 2L8,7A1,1 0,0 1,7 8L2,8A1,1 0,0 1,1 7L1,2A1,1 0,0 1,2 1z"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#0DBD8B"/>
<path
android:pathData="M13,1L18,1A1,1 0,0 1,19 2L19,7A1,1 0,0 1,18 8L13,8A1,1 0,0 1,12 7L12,2A1,1 0,0 1,13 1z"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#0DBD8B"/>
<path
android:pathData="M15.5,12L15.5,12A3.5,3.5 0,0 1,19 15.5L19,15.5A3.5,3.5 0,0 1,15.5 19L15.5,19A3.5,3.5 0,0 1,12 15.5L12,15.5A3.5,3.5 0,0 1,15.5 12z"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#0DBD8B"/>
<path
android:pathData="M2,12L7,12A1,1 0,0 1,8 13L8,18A1,1 0,0 1,7 19L2,19A1,1 0,0 1,1 18L1,13A1,1 0,0 1,2 12z"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#0DBD8B"/>
</vector>

View File

@ -109,7 +109,7 @@
android:layout_marginBottom="20dp" android:layout_marginBottom="20dp"
android:accessibilityTraversalAfter="@id/newLayoutCreateChatButton" android:accessibilityTraversalAfter="@id/newLayoutCreateChatButton"
android:contentDescription="@string/a11y_open_spaces" android:contentDescription="@string/a11y_open_spaces"
android:src="@drawable/ic_open_spaces" android:src="@drawable/ic_spaces"
android:visibility="gone" android:visibility="gone"
app:backgroundTint="?attr/vctr_toolbar_background" app:backgroundTint="?attr/vctr_toolbar_background"
app:fabSize="mini" app:fabSize="mini"

View File

@ -9,6 +9,7 @@
android:id="@+id/groupListView" android:id="@+id/groupListView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:minHeight="195dp"
android:overScrollMode="always" android:overScrollMode="always"
tools:listitem="@layout/item_space" /> tools:listitem="@layout/item_space" />

View File

@ -3,12 +3,13 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recentRoot" android:id="@+id/recentRoot"
android:layout_width="60dp" android:layout_width="84dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?vctr_toolbar_background" android:background="?vctr_toolbar_background"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:foreground="?attr/selectableItemBackground" android:foreground="?attr/selectableItemBackground"
android:paddingHorizontal="12dp"
tools:viewBindingIgnore="true"> tools:viewBindingIgnore="true">
<ImageView <ImageView