mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Add ability to share profile by QR code
This commit is contained in:
parent
5b278f704c
commit
e8d084b855
@ -39,7 +39,7 @@ We do not forget all translators, for their work of translating Element into man
|
||||
|
||||
Feel free to add your name below, when you contribute to the project!
|
||||
|
||||
Name | Matrix ID | GitHub
|
||||
--------|---------------------|--------------------------------------
|
||||
gjpower | @gjpower:matrix.org | [gjpower](https://github.com/gjpower)
|
||||
|
||||
Name | Matrix ID | GitHub
|
||||
----------|-----------------------------|--------------------------------------
|
||||
gjpower | @gjpower:matrix.org | [gjpower](https://github.com/gjpower)
|
||||
TR_SLimey | @tr_slimey:an-atom-in.space | [TR-SLimey](https://github.com/TR-SLimey)
|
||||
|
@ -2,7 +2,7 @@ Changes in Element 1.0.11 (2020-XX-XX)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
-
|
||||
- Create DMs with users by scanning their QR code (#2025)
|
||||
|
||||
Improvements 🙌:
|
||||
- New room creation tile with quick action (#2346)
|
||||
|
@ -22,6 +22,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.Fail
|
||||
@ -37,6 +38,8 @@ import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.SimpleFragmentActivity
|
||||
import im.vector.app.core.platform.WaitingViewData
|
||||
import im.vector.app.core.utils.PERMISSIONS_FOR_MEMBERS_SEARCH
|
||||
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
|
||||
import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_CAMERA
|
||||
import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_READ_CONTACTS
|
||||
import im.vector.app.core.utils.allGranted
|
||||
import im.vector.app.core.utils.checkPermissions
|
||||
@ -72,35 +75,45 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
toolbar.visibility = View.GONE
|
||||
sharedActionViewModel = viewModelProvider.get(UserDirectorySharedActionViewModel::class.java)
|
||||
sharedActionViewModel
|
||||
.observe()
|
||||
.subscribe { sharedAction ->
|
||||
when (sharedAction) {
|
||||
UserDirectorySharedAction.OpenUsersDirectory ->
|
||||
addFragmentToBackstack(R.id.container, UserDirectoryFragment::class.java)
|
||||
UserDirectorySharedAction.Close -> finish()
|
||||
UserDirectorySharedAction.GoBack -> onBackPressed()
|
||||
is UserDirectorySharedAction.OnMenuItemSelected -> onMenuItemSelected(sharedAction)
|
||||
UserDirectorySharedAction.OpenPhoneBook -> openPhoneBook()
|
||||
}.exhaustive
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
if (isFirstCreation()) {
|
||||
addFragment(
|
||||
R.id.container,
|
||||
KnownUsersFragment::class.java,
|
||||
KnownUsersFragmentArgs(
|
||||
title = getString(R.string.fab_menu_create_chat),
|
||||
menuResId = R.menu.vector_create_direct_room,
|
||||
isCreatingRoom = true
|
||||
)
|
||||
)
|
||||
if (intent?.getBooleanExtra(BY_QR_CODE, false)!!) {
|
||||
if (isFirstCreation()) { openAddByQrCode() }
|
||||
} else {
|
||||
sharedActionViewModel
|
||||
.observe()
|
||||
.subscribe { sharedAction ->
|
||||
when (sharedAction) {
|
||||
UserDirectorySharedAction.OpenUsersDirectory ->
|
||||
addFragmentToBackstack(R.id.container, UserDirectoryFragment::class.java)
|
||||
UserDirectorySharedAction.Close -> finish()
|
||||
UserDirectorySharedAction.GoBack -> onBackPressed()
|
||||
is UserDirectorySharedAction.OnMenuItemSelected -> onMenuItemSelected(sharedAction)
|
||||
UserDirectorySharedAction.OpenPhoneBook -> openPhoneBook()
|
||||
}.exhaustive
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
if (isFirstCreation()) {
|
||||
addFragment(
|
||||
R.id.container,
|
||||
KnownUsersFragment::class.java,
|
||||
KnownUsersFragmentArgs(
|
||||
title = getString(R.string.fab_menu_create_chat),
|
||||
menuResId = R.menu.vector_create_direct_room,
|
||||
isCreatingRoom = true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
viewModel.selectSubscribe(this, CreateDirectRoomViewState::createAndInviteState) {
|
||||
renderCreateAndInviteState(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun openAddByQrCode() {
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this, PERMISSION_REQUEST_CODE_LAUNCH_CAMERA, 0)) {
|
||||
addFragment(R.id.container, CreateDirectRoomByQrCodeFragment::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private fun openPhoneBook() {
|
||||
// Check permission first
|
||||
if (checkPermissions(PERMISSIONS_FOR_MEMBERS_SEARCH,
|
||||
@ -116,6 +129,13 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
|
||||
if (allGranted(grantResults)) {
|
||||
if (requestCode == PERMISSION_REQUEST_CODE_READ_CONTACTS) {
|
||||
doOnPostResume { addFragmentToBackstack(R.id.container, ContactsBookFragment::class.java) }
|
||||
} else if (requestCode == PERMISSION_REQUEST_CODE_LAUNCH_CAMERA && intent?.getBooleanExtra(BY_QR_CODE, false)!!) {
|
||||
addFragment(R.id.container, CreateDirectRoomByQrCodeFragment::class.java)
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(baseContext, R.string.missing_permissions_error, Toast.LENGTH_SHORT).show()
|
||||
if (requestCode == PERMISSION_REQUEST_CODE_LAUNCH_CAMERA && intent?.getBooleanExtra(BY_QR_CODE, false)!!) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,8 +198,12 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context): Intent {
|
||||
return Intent(context, CreateDirectRoomActivity::class.java)
|
||||
private const val BY_QR_CODE = "BY_QR_CODE"
|
||||
|
||||
fun getIntent(context: Context, byQrCode: Boolean = false): Intent {
|
||||
return Intent(context, CreateDirectRoomActivity::class.java).apply {
|
||||
putExtra(BY_QR_CODE, byQrCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2020 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.createdirect
|
||||
|
||||
import android.widget.Toast
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.google.zxing.Result
|
||||
import com.google.zxing.ResultMetadataType
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.features.userdirectory.PendingInvitee
|
||||
import kotlinx.android.synthetic.main.fragment_qr_code_scanner.*
|
||||
import me.dm7.barcodescanner.zxing.ZXingScannerView
|
||||
import org.matrix.android.sdk.api.session.permalinks.PermalinkData
|
||||
import org.matrix.android.sdk.api.session.permalinks.PermalinkParser
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import javax.inject.Inject
|
||||
|
||||
class CreateDirectRoomByQrCodeFragment @Inject constructor() : VectorBaseFragment(), ZXingScannerView.ResultHandler {
|
||||
|
||||
private val viewModel: CreateDirectRoomViewModel by activityViewModel()
|
||||
|
||||
override fun getLayoutResId() = R.layout.fragment_qr_code_scanner
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
// Register ourselves as a handler for scan results.
|
||||
scannerView.setResultHandler(null)
|
||||
// Start camera on resume
|
||||
scannerView.startCamera()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
// Stop camera on pause
|
||||
scannerView.stopCamera()
|
||||
}
|
||||
|
||||
// Copied from https://github.com/markusfisch/BinaryEye/blob/
|
||||
// 9d57889b810dcaa1a91d7278fc45c262afba1284/app/src/main/kotlin/de/markusfisch/android/binaryeye/activity/CameraActivity.kt#L434
|
||||
private fun getRawBytes(result: Result): ByteArray? {
|
||||
val metadata = result.resultMetadata ?: return null
|
||||
val segments = metadata[ResultMetadataType.BYTE_SEGMENTS] ?: return null
|
||||
var bytes = ByteArray(0)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
for (seg in segments as Iterable<ByteArray>) {
|
||||
bytes += seg
|
||||
}
|
||||
// byte segments can never be shorter than the text.
|
||||
// Zxing cuts off content prefixes like "WIFI:"
|
||||
return if (bytes.size >= result.text.length) bytes else null
|
||||
}
|
||||
|
||||
private fun addByQrCode(value: String) {
|
||||
val mxid = (PermalinkParser.parse(value) as? PermalinkData.UserLink)?.userId
|
||||
|
||||
if (mxid === null) {
|
||||
Toast.makeText(requireContext(), R.string.invalid_qr_code_uri, Toast.LENGTH_SHORT).show()
|
||||
requireActivity().finish()
|
||||
} else {
|
||||
val existingDm = viewModel.session.getExistingDirectRoomWithUser(mxid)
|
||||
|
||||
if (existingDm === null) {
|
||||
// The following assumes MXIDs are case insensitive
|
||||
if (mxid.equals(other = viewModel.session.myUserId, ignoreCase = true)) {
|
||||
Toast.makeText(requireContext(), R.string.cannot_dm_self, Toast.LENGTH_SHORT).show()
|
||||
requireActivity().finish()
|
||||
} else {
|
||||
// Try to get user from known users and fall back to creating a User object from MXID
|
||||
val qrInvitee = if (viewModel.session.getUser(mxid) != null) viewModel.session.getUser(mxid)!! else User(mxid, null, null)
|
||||
|
||||
viewModel.handle(
|
||||
CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers(setOf(PendingInvitee.UserPendingInvitee(qrInvitee)))
|
||||
)
|
||||
}
|
||||
} else {
|
||||
navigator.openRoom(requireContext(), existingDm, null, false)
|
||||
requireActivity().finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleResult(result: Result?) {
|
||||
if (result === null) {
|
||||
Toast.makeText(requireContext(), R.string.qr_code_not_scanned, Toast.LENGTH_SHORT).show()
|
||||
requireActivity().finish()
|
||||
} else {
|
||||
val rawBytes = getRawBytes(result)
|
||||
val rawBytesStr = rawBytes?.toString(Charsets.ISO_8859_1)
|
||||
val value = rawBytesStr ?: result.text
|
||||
addByQrCode(value)
|
||||
}
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@ import org.matrix.android.sdk.rx.rx
|
||||
class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted
|
||||
initialState: CreateDirectRoomViewState,
|
||||
private val rawService: RawService,
|
||||
private val session: Session)
|
||||
val session: Session)
|
||||
: VectorViewModel<CreateDirectRoomViewState, CreateDirectRoomAction, CreateDirectRoomViewEvents>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
|
@ -22,7 +22,7 @@ import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.features.home.room.list.widget.FabMenuView
|
||||
import im.vector.app.features.home.room.list.widget.NotifsFabMenuView
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_room_filter_footer)
|
||||
abstract class FilteredRoomFooterItem : VectorEpoxyModel<FilteredRoomFooterItem.Holder>() {
|
||||
@ -46,7 +46,7 @@ abstract class FilteredRoomFooterItem : VectorEpoxyModel<FilteredRoomFooterItem.
|
||||
val openRoomDirectory by bind<Button>(R.id.roomFilterFooterOpenRoomDirectory)
|
||||
}
|
||||
|
||||
interface FilteredRoomFooterItemListener : FabMenuView.Listener {
|
||||
interface FilteredRoomFooterItemListener : NotifsFabMenuView.Listener {
|
||||
fun createRoom(initialName: String)
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,8 @@ import im.vector.app.features.home.room.list.actions.RoomListActionsArgs
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
||||
import im.vector.app.features.home.room.list.widget.FabMenuView
|
||||
import im.vector.app.features.home.room.list.widget.DmsFabMenuView
|
||||
import im.vector.app.features.home.room.list.widget.NotifsFabMenuView
|
||||
import im.vector.app.features.notifications.NotificationDrawerManager
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.fragment_room_list.*
|
||||
@ -66,8 +67,7 @@ class RoomListFragment @Inject constructor(
|
||||
val roomListViewModelFactory: RoomListViewModel.Factory,
|
||||
private val notificationDrawerManager: NotificationDrawerManager,
|
||||
private val sharedViewPool: RecyclerView.RecycledViewPool
|
||||
|
||||
) : VectorBaseFragment(), RoomSummaryController.Listener, OnBackPressed, FabMenuView.Listener {
|
||||
) : VectorBaseFragment(), RoomSummaryController.Listener, OnBackPressed, DmsFabMenuView.Listener, NotifsFabMenuView.Listener {
|
||||
|
||||
private var modelBuildListener: OnModelBuildFinishedListener? = null
|
||||
private lateinit var sharedActionViewModel: RoomListQuickActionsSharedActionViewModel
|
||||
@ -111,6 +111,7 @@ class RoomListFragment @Inject constructor(
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
createDmFabMenu.listener = this
|
||||
createChatFabMenu.listener = this
|
||||
|
||||
sharedActionViewModel
|
||||
@ -129,6 +130,7 @@ class RoomListFragment @Inject constructor(
|
||||
roomListView.cleanup()
|
||||
roomController.listener = null
|
||||
stateRestorer.clear()
|
||||
createDmFabMenu.listener = null
|
||||
createChatFabMenu.listener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
@ -140,33 +142,32 @@ class RoomListFragment @Inject constructor(
|
||||
private fun setupCreateRoomButton() {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.isVisible = true
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.isVisible = true
|
||||
RoomListDisplayMode.PEOPLE -> createDmFabMenu.isVisible = true
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.isVisible = true
|
||||
else -> Unit // No button in this mode
|
||||
}
|
||||
|
||||
createChatRoomButton.debouncedClicks {
|
||||
createDirectChat()
|
||||
}
|
||||
createGroupRoomButton.debouncedClicks {
|
||||
openRoomDirectory()
|
||||
}
|
||||
|
||||
// Hide FAB when list is scrolling
|
||||
// Hide FABs when list is scrolling
|
||||
roomListView.addOnScrollListener(
|
||||
object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
createDmFabMenu.removeCallbacks(showFabRunnable)
|
||||
createChatFabMenu.removeCallbacks(showFabRunnable)
|
||||
|
||||
when (newState) {
|
||||
RecyclerView.SCROLL_STATE_IDLE -> {
|
||||
createDmFabMenu.postDelayed(showFabRunnable, 250)
|
||||
createChatFabMenu.postDelayed(showFabRunnable, 250)
|
||||
}
|
||||
RecyclerView.SCROLL_STATE_DRAGGING,
|
||||
RecyclerView.SCROLL_STATE_SETTLING -> {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.hide()
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.hide()
|
||||
RoomListDisplayMode.PEOPLE -> createDmFabMenu.hide()
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.hide()
|
||||
else -> Unit
|
||||
}
|
||||
@ -191,6 +192,10 @@ class RoomListFragment @Inject constructor(
|
||||
navigator.openCreateDirectRoom(requireActivity())
|
||||
}
|
||||
|
||||
override fun createDirectChatByQrCode() {
|
||||
navigator.openCreateDirectRoom(requireContext(), true)
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
stateRestorer = LayoutManagerStateRestorer(layoutManager).register()
|
||||
@ -209,7 +214,7 @@ class RoomListFragment @Inject constructor(
|
||||
if (isAdded) {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.show()
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.show()
|
||||
RoomListDisplayMode.PEOPLE -> createDmFabMenu.show()
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.show()
|
||||
else -> Unit
|
||||
}
|
||||
@ -338,6 +343,9 @@ class RoomListFragment @Inject constructor(
|
||||
}
|
||||
|
||||
override fun onBackPressed(toolbarButton: Boolean): Boolean {
|
||||
if (createDmFabMenu.onBackPressed()) {
|
||||
return true
|
||||
}
|
||||
if (createChatFabMenu.onBackPressed()) {
|
||||
return true
|
||||
}
|
||||
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.list.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import im.vector.app.R
|
||||
import kotlinx.android.synthetic.main.motion_dms_fab_menu_merge.view.*
|
||||
|
||||
class DmsFabMenuView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0) : MotionLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.motion_dms_fab_menu_merge, this)
|
||||
}
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
|
||||
listOf(createDmByMxid, createDmByMxidLabel)
|
||||
.forEach {
|
||||
it.setOnClickListener {
|
||||
closeFabMenu()
|
||||
listener?.createDirectChat()
|
||||
}
|
||||
}
|
||||
listOf(createDmByQrCode, createDmByQrCodeLabel)
|
||||
.forEach {
|
||||
it.setOnClickListener {
|
||||
closeFabMenu()
|
||||
listener?.createDirectChatByQrCode()
|
||||
}
|
||||
}
|
||||
|
||||
dmsCreateRoomTouchGuard.setOnClickListener {
|
||||
closeFabMenu()
|
||||
}
|
||||
}
|
||||
|
||||
override fun transitionToEnd() {
|
||||
super.transitionToEnd()
|
||||
|
||||
dmsCreateRoomButton.contentDescription = context.getString(R.string.a11y_create_menu_close)
|
||||
}
|
||||
|
||||
override fun transitionToStart() {
|
||||
super.transitionToStart()
|
||||
|
||||
dmsCreateRoomButton.contentDescription = context.getString(R.string.a11y_create_menu_open)
|
||||
}
|
||||
|
||||
fun show() {
|
||||
isVisible = true
|
||||
dmsCreateRoomButton.show()
|
||||
}
|
||||
|
||||
fun hide() {
|
||||
dmsCreateRoomButton.hide(object : FloatingActionButton.OnVisibilityChangedListener() {
|
||||
override fun onHidden(fab: FloatingActionButton?) {
|
||||
super.onHidden(fab)
|
||||
isVisible = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun closeFabMenu() {
|
||||
transitionToStart()
|
||||
}
|
||||
|
||||
fun onBackPressed(): Boolean {
|
||||
if (currentState == R.id.constraint_set_fab_menu_open) {
|
||||
closeFabMenu()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun createDirectChat()
|
||||
fun createDirectChatByQrCode()
|
||||
}
|
||||
}
|
@ -22,15 +22,15 @@ import androidx.constraintlayout.motion.widget.MotionLayout
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import im.vector.app.R
|
||||
import kotlinx.android.synthetic.main.motion_fab_menu_merge.view.*
|
||||
import kotlinx.android.synthetic.main.motion_notifs_fab_menu_merge.view.*
|
||||
|
||||
class FabMenuView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0) : MotionLayout(context, attrs, defStyleAttr) {
|
||||
class NotifsFabMenuView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0) : MotionLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.motion_fab_menu_merge, this)
|
||||
inflate(context, R.layout.motion_notifs_fab_menu_merge, this)
|
||||
}
|
||||
|
||||
override fun onFinishInflate() {
|
@ -203,8 +203,8 @@ class DefaultNavigator @Inject constructor(
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
override fun openCreateDirectRoom(context: Context) {
|
||||
val intent = CreateDirectRoomActivity.getIntent(context)
|
||||
override fun openCreateDirectRoom(context: Context, byQrCode: Boolean) {
|
||||
val intent = CreateDirectRoomActivity.getIntent(context, byQrCode)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ interface Navigator {
|
||||
|
||||
fun openCreateRoom(context: Context, initialName: String = "")
|
||||
|
||||
fun openCreateDirectRoom(context: Context)
|
||||
fun openCreateDirectRoom(context: Context, byQrCode: Boolean = false)
|
||||
|
||||
fun openInviteUsersToRoom(context: Context, roomId: String)
|
||||
|
||||
|
@ -62,7 +62,7 @@ abstract class RoomDirectoryItem : VectorEpoxyModel<RoomDirectoryItem.Holder>()
|
||||
holder.avatarView.isInvisible = directoryAvatarUrl.isNullOrBlank() && includeAllNetworks
|
||||
|
||||
holder.nameView.text = directoryName
|
||||
holder.descritionView.setTextOrHide(directoryDescription)
|
||||
holder.descriptionView.setTextOrHide(directoryDescription)
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
@ -70,6 +70,6 @@ abstract class RoomDirectoryItem : VectorEpoxyModel<RoomDirectoryItem.Holder>()
|
||||
|
||||
val avatarView by bind<ImageView>(R.id.itemRoomDirectoryAvatar)
|
||||
val nameView by bind<TextView>(R.id.itemRoomDirectoryName)
|
||||
val descritionView by bind<TextView>(R.id.itemRoomDirectoryDescription)
|
||||
val descriptionView by bind<TextView>(R.id.itemRoomDirectoryDescription)
|
||||
}
|
||||
}
|
||||
|
@ -294,12 +294,20 @@ class RoomMemberProfileFragment @Inject constructor(
|
||||
}
|
||||
|
||||
private fun handleShareRoomMemberProfile(permalink: String) {
|
||||
startSharePlainTextIntent(
|
||||
fragment = this,
|
||||
activityResultLauncher = null,
|
||||
chooserTitle = null,
|
||||
text = permalink
|
||||
)
|
||||
val view = layoutInflater.inflate(R.layout.dialog_share_qr_code, null)
|
||||
val qrCode = view.findViewById<im.vector.app.core.ui.views.QrCodeImageView>(R.id.itemShareQrCodeImage)
|
||||
qrCode.setData(permalink)
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setView(view)
|
||||
.setNeutralButton(R.string.ok, null)
|
||||
.setPositiveButton(R.string.share_by_text) { _, _ ->
|
||||
startSharePlainTextIntent(
|
||||
fragment = this,
|
||||
activityResultLauncher = null,
|
||||
chooserTitle = null,
|
||||
text = permalink
|
||||
)
|
||||
}.show()
|
||||
}
|
||||
|
||||
private fun onAvatarClicked(view: View, userMatrixItem: MatrixItem) {
|
||||
|
30
vector/src/main/res/drawable/ic_fab_add_by_mxid.xml
Normal file
30
vector/src/main/res/drawable/ic_fab_add_by_mxid.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="37dp"
|
||||
android:height="36dp"
|
||||
android:viewportWidth="37"
|
||||
android:viewportHeight="36">
|
||||
<path
|
||||
android:pathData="M17.5911,26.2922C15.9951,27.3704 14.0711,28 12,28C9.7488,28 7.6713,27.2561 6,26.0007C3.5711,24.1763 2,21.2716 2,18C2,12.4772 6.4771,8 12,8C17.5228,8 22,12.4772 22,18C22,21.4518 20.2511,24.4951 17.5911,26.2922ZM12,18.5C13.6569,18.5 15,17.0449 15,15.25C15,13.4551 13.6569,12 12,12C10.3431,12 9,13.4551 9,15.25C9,17.0449 10.3431,18.5 12,18.5ZM12,26C14.162,26 16.1236,25.1424 17.5634,23.7488C16.673,21.5506 14.5176,20 12,20C9.4824,20 7.327,21.5506 6.4366,23.7488C7.8763,25.1424 9.838,26 12,26Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M17.5911,26.2922C15.9951,27.3704 14.0711,28 12,28C9.7488,28 7.6713,27.2561 6,26.0007C3.5711,24.1763 2,21.2716 2,18C2,12.4772 6.4771,8 12,8C17.5228,8 22,12.4772 22,18C22,21.4518 20.2511,24.4951 17.5911,26.2922ZM12,18.5C13.6569,18.5 15,17.0449 15,15.25C15,13.4551 13.6569,12 12,12C10.3431,12 9,13.4551 9,15.25C9,17.0449 10.3431,18.5 12,18.5ZM12,26C14.162,26 16.1236,25.1424 17.5634,23.7488C16.673,21.5506 14.5176,20 12,20C9.4824,20 7.327,21.5506 6.4366,23.7488C7.8763,25.1424 9.838,26 12,26Z"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M17.5911,26.2922L16.4715,24.6349L17.5911,26.2922ZM6,26.0007L4.7989,27.5999L4.7989,27.5999L6,26.0007ZM17.5634,23.7488L18.9544,25.1859L19.9234,24.2479L19.4171,22.998L17.5634,23.7488ZM6.4366,23.7488L4.5829,22.998L4.0766,24.2479L5.0456,25.1859L6.4366,23.7488ZM12,30C14.4825,30 16.7945,29.244 18.7107,27.9494L16.4715,24.6349C15.1957,25.4968 13.6596,26 12,26V30ZM4.7989,27.5999C6.8046,29.1065 9.3008,30 12,30V26C10.1967,26 8.538,25.4058 7.2011,24.4016L4.7989,27.5999ZM0,18C0,21.9273 1.8887,25.414 4.7989,27.5999L7.2011,24.4016C5.2535,22.9387 4,20.616 4,18H0ZM12,6C5.3726,6 0,11.3726 0,18H4C4,13.5817 7.5817,10 12,10V6ZM24,18C24,11.3726 18.6274,6 12,6V10C16.4183,10 20,13.5817 20,18H24ZM18.7107,27.9494C21.8977,25.7963 24,22.144 24,18H20C20,20.7596 18.6045,23.1939 16.4715,24.6349L18.7107,27.9494ZM13,15.25C13,16.0941 12.4046,16.5 12,16.5V20.5C14.9091,20.5 17,17.9958 17,15.25H13ZM12,14C12.4046,14 13,14.4059 13,15.25H17C17,12.5042 14.9091,10 12,10V14ZM11,15.25C11,14.4059 11.5954,14 12,14V10C9.0909,10 7,12.5042 7,15.25H11ZM12,16.5C11.5954,16.5 11,16.0941 11,15.25H7C7,17.9958 9.0909,20.5 12,20.5V16.5ZM16.1724,22.3118C15.0906,23.3588 13.6223,24 12,24V28C14.7017,28 17.1567,26.926 18.9544,25.1859L16.1724,22.3118ZM12,22C13.6752,22 15.1146,23.0305 15.7097,24.4996L19.4171,22.998C18.2314,20.0707 15.3599,18 12,18V22ZM8.2903,24.4996C8.8854,23.0305 10.3248,22 12,22V18C8.6401,18 5.7686,20.0707 4.5829,22.998L8.2903,24.4996ZM12,24C10.3777,24 8.9094,23.3588 7.8276,22.3118L5.0456,25.1859C6.8433,26.926 9.2983,28 12,28V24Z"
|
||||
android:fillColor="#000000"/>
|
||||
</group>
|
||||
<path
|
||||
android:pathData="M27,18H35"
|
||||
android:strokeWidth="2.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M31,14L31,22"
|
||||
android:strokeWidth="2.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
30
vector/src/main/res/drawable/ic_fab_add_by_qr_code.xml
Normal file
30
vector/src/main/res/drawable/ic_fab_add_by_qr_code.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="37dp"
|
||||
android:height="36dp"
|
||||
android:viewportWidth="37"
|
||||
android:viewportHeight="36">
|
||||
<path
|
||||
android:pathData="M17.5911,26.2922C15.9951,27.3704 14.0711,28 12,28C9.7488,28 7.6713,27.2561 6,26.0007C3.5711,24.1763 2,21.2716 2,18C2,12.4772 6.4771,8 12,8C17.5228,8 22,12.4772 22,18C22,21.4518 20.2511,24.4951 17.5911,26.2922ZM12,18.5C13.6569,18.5 15,17.0449 15,15.25C15,13.4551 13.6569,12 12,12C10.3431,12 9,13.4551 9,15.25C9,17.0449 10.3431,18.5 12,18.5ZM12,26C14.162,26 16.1236,25.1424 17.5634,23.7488C16.673,21.5506 14.5176,20 12,20C9.4824,20 7.327,21.5506 6.4366,23.7488C7.8763,25.1424 9.838,26 12,26Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M17.5911,26.2922C15.9951,27.3704 14.0711,28 12,28C9.7488,28 7.6713,27.2561 6,26.0007C3.5711,24.1763 2,21.2716 2,18C2,12.4772 6.4771,8 12,8C17.5228,8 22,12.4772 22,18C22,21.4518 20.2511,24.4951 17.5911,26.2922ZM12,18.5C13.6569,18.5 15,17.0449 15,15.25C15,13.4551 13.6569,12 12,12C10.3431,12 9,13.4551 9,15.25C9,17.0449 10.3431,18.5 12,18.5ZM12,26C14.162,26 16.1236,25.1424 17.5634,23.7488C16.673,21.5506 14.5176,20 12,20C9.4824,20 7.327,21.5506 6.4366,23.7488C7.8763,25.1424 9.838,26 12,26Z"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M17.5911,26.2922L16.4715,24.6349L17.5911,26.2922ZM6,26.0007L4.7989,27.5999L4.7989,27.5999L6,26.0007ZM17.5634,23.7488L18.9544,25.1859L19.9234,24.2479L19.4171,22.998L17.5634,23.7488ZM6.4366,23.7488L4.5829,22.998L4.0766,24.2479L5.0456,25.1859L6.4366,23.7488ZM12,30C14.4825,30 16.7945,29.244 18.7107,27.9494L16.4715,24.6349C15.1957,25.4968 13.6596,26 12,26V30ZM4.7989,27.5999C6.8046,29.1065 9.3008,30 12,30V26C10.1967,26 8.538,25.4058 7.2011,24.4016L4.7989,27.5999ZM0,18C0,21.9273 1.8887,25.414 4.7989,27.5999L7.2011,24.4016C5.2535,22.9387 4,20.616 4,18H0ZM12,6C5.3726,6 0,11.3726 0,18H4C4,13.5817 7.5817,10 12,10V6ZM24,18C24,11.3726 18.6274,6 12,6V10C16.4183,10 20,13.5817 20,18H24ZM18.7107,27.9494C21.8977,25.7963 24,22.144 24,18H20C20,20.7596 18.6045,23.1939 16.4715,24.6349L18.7107,27.9494ZM13,15.25C13,16.0941 12.4046,16.5 12,16.5V20.5C14.9091,20.5 17,17.9958 17,15.25H13ZM12,14C12.4046,14 13,14.4059 13,15.25H17C17,12.5042 14.9091,10 12,10V14ZM11,15.25C11,14.4059 11.5954,14 12,14V10C9.0909,10 7,12.5042 7,15.25H11ZM12,16.5C11.5954,16.5 11,16.0941 11,15.25H7C7,17.9958 9.0909,20.5 12,20.5V16.5ZM16.1724,22.3118C15.0906,23.3588 13.6223,24 12,24V28C14.7017,28 17.1567,26.926 18.9544,25.1859L16.1724,22.3118ZM12,22C13.6752,22 15.1146,23.0305 15.7097,24.4996L19.4171,22.998C18.2314,20.0707 15.3599,18 12,18V22ZM8.2903,24.4996C8.8854,23.0305 10.3248,22 12,22V18C8.6401,18 5.7686,20.0707 4.5829,22.998L8.2903,24.4996ZM12,24C10.3777,24 8.9094,23.3588 7.8276,22.3118L5.0456,25.1859C6.8433,26.926 9.2983,28 12,28V24Z"
|
||||
android:fillColor="#000000"/>
|
||||
</group>
|
||||
<path
|
||||
android:pathData="M27,18H35"
|
||||
android:strokeWidth="2.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M31,14L31,22"
|
||||
android:strokeWidth="2.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
16
vector/src/main/res/layout/dialog_share_qr_code.xml
Normal file
16
vector/src/main/res/layout/dialog_share_qr_code.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp">
|
||||
|
||||
<im.vector.app.core.ui.views.QrCodeImageView
|
||||
android:id="@+id/itemShareQrCodeImage"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="300dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:contentDescription="@string/a11y_qr_code_for_verification"
|
||||
tools:src="@color/riotx_header_panel_background_black" />
|
||||
|
||||
</FrameLayout>
|
@ -14,29 +14,25 @@
|
||||
android:overScrollMode="always"
|
||||
tools:listitem="@layout/item_room" />
|
||||
|
||||
<im.vector.app.features.home.room.list.widget.FabMenuView
|
||||
<im.vector.app.features.home.room.list.widget.NotifsFabMenuView
|
||||
android:id="@+id/createChatFabMenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
app:layoutDescription="@xml/motion_scene_fab_menu"
|
||||
app:layoutDescription="@xml/motion_scene_notifs_fab_menu"
|
||||
tools:showPaths="true"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/createChatRoomButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:accessibilityTraversalBefore="@+id/roomListView"
|
||||
<im.vector.app.features.home.room.list.widget.DmsFabMenuView
|
||||
android:id="@+id/createDmFabMenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/a11y_create_direct_message"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_fab_add_chat"
|
||||
android:visibility="gone"
|
||||
app:maxImageSize="34dp"
|
||||
tools:layout_marginEnd="80dp"
|
||||
app:layoutDescription="@xml/motion_scene_dms_fab_menu"
|
||||
tools:showPaths="true"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
|
79
vector/src/main/res/layout/motion_dms_fab_menu_merge.xml
Normal file
79
vector/src/main/res/layout/motion_dms_fab_menu_merge.xml
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layoutDescription="@xml/motion_scene_dms_fab_menu"
|
||||
tools:motionProgress="0.65"
|
||||
tools:parentTag="androidx.constraintlayout.motion.widget.MotionLayout"
|
||||
tools:showPaths="true">
|
||||
|
||||
<View
|
||||
android:id="@+id/dmsCreateRoomTouchGuard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?riotx_touch_guard_bg"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/a11y_create_menu_close"
|
||||
android:focusable="true" />
|
||||
|
||||
<!-- Sub menu item 2 -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/createDmByQrCode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:accessibilityTraversalBefore="@+id/roomListView"
|
||||
android:contentDescription="@string/a11y_create_direct_message_by_qr_code"
|
||||
android:src="@drawable/ic_fab_add_by_qr_code"
|
||||
app:backgroundTint="#FFFFFF"
|
||||
app:fabCustomSize="48dp"
|
||||
app:maxImageSize="26dp"
|
||||
app:tint="@color/black" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/createDmByQrCodeLabel"
|
||||
style="@style/VectorLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:importantForAccessibility="no"
|
||||
android:text="@string/add_by_qr_code" />
|
||||
|
||||
<!-- Sub menu item 1 -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/createDmByMxid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:accessibilityTraversalBefore="@+id/createDmByQrCode"
|
||||
android:contentDescription="@string/a11y_create_direct_message_by_mxid"
|
||||
android:src="@drawable/ic_fab_add_by_mxid"
|
||||
app:backgroundTint="#FFFFFF"
|
||||
app:fabCustomSize="48dp"
|
||||
app:maxImageSize="29dp"
|
||||
app:tint="@color/black" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/createDmByMxidLabel"
|
||||
style="@style/VectorLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:importantForAccessibility="no"
|
||||
android:text="@string/add_by_matrix_id" />
|
||||
|
||||
<!-- Menu -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/dmsCreateRoomButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:accessibilityTraversalBefore="@+id/createDmByMxid"
|
||||
android:contentDescription="@string/a11y_create_menu_open"
|
||||
android:src="@drawable/ic_fab_add"
|
||||
app:maxImageSize="14dp" />
|
||||
|
||||
</merge>
|
@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layoutDescription="@xml/motion_scene_fab_menu"
|
||||
app:layoutDescription="@xml/motion_scene_notifs_fab_menu"
|
||||
tools:motionProgress="0.65"
|
||||
tools:parentTag="androidx.constraintlayout.motion.widget.MotionLayout"
|
||||
tools:showPaths="true">
|
@ -1761,6 +1761,7 @@
|
||||
<string name="link_copied_to_clipboard">Link copied to clipboard</string>
|
||||
|
||||
<string name="add_by_matrix_id">Add by matrix ID</string>
|
||||
<string name="add_by_qr_code">Add by QR code</string>
|
||||
<string name="creating_direct_room">"Creating room…"</string>
|
||||
<string name="direct_room_no_known_users">"No result found, use Add by matrix ID to search on server."</string>
|
||||
<string name="direct_room_start_search">"Start typing to get results"</string>
|
||||
@ -1828,6 +1829,8 @@
|
||||
<string name="a11y_create_menu_open">Open the create room menu</string>
|
||||
<string name="a11y_create_menu_close">Close the create room menu…</string>
|
||||
<string name="a11y_create_direct_message">Create a new direct conversation</string>
|
||||
<string name="a11y_create_direct_message_by_mxid">Create a new direct conversation by Matrix ID</string>
|
||||
<string name="a11y_create_direct_message_by_qr_code">Create a new direct conversation by scanning a QR code</string>
|
||||
<string name="a11y_create_room">Create a new room</string>
|
||||
<string name="a11y_close_keys_backup_banner">Close keys backup banner</string>
|
||||
<string name="a11y_show_password">Show password</string>
|
||||
@ -2674,4 +2677,10 @@
|
||||
<string name="warning_room_not_created_yet">The room is not yet created. Cancel the room creation?</string>
|
||||
<string name="warning_unsaved_change">There are unsaved changes. Discard the changes?</string>
|
||||
<string name="warning_unsaved_change_discard">Discard changes</string>
|
||||
|
||||
<!-- Add by QR code -->
|
||||
<string name="share_by_text">Share by text</string>
|
||||
<string name="cannot_dm_self">Cannot DM yourself!</string>
|
||||
<string name="invalid_qr_code_uri">Invalid QR code (Invalid URI)!</string>
|
||||
<string name="qr_code_not_scanned">QR code not scanned!</string>
|
||||
</resources>
|
||||
|
199
vector/src/main/res/xml/motion_scene_dms_fab_menu.xml
Normal file
199
vector/src/main/res/xml/motion_scene_dms_fab_menu.xml
Normal file
@ -0,0 +1,199 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:motion="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<!-- Click on main FAB: toggle -->
|
||||
<Transition
|
||||
motion:constraintSetEnd="@+id/constraint_set_fab_menu_open"
|
||||
motion:constraintSetStart="@+id/constraint_set_fab_menu_close"
|
||||
motion:duration="300"
|
||||
motion:motionInterpolator="easeInOut">
|
||||
|
||||
<OnClick
|
||||
motion:clickAction="toggle"
|
||||
motion:targetId="@+id/dmsCreateRoomButton" />
|
||||
|
||||
<KeyFrameSet>
|
||||
|
||||
<!-- First icon goes up quickly to let room for other-->
|
||||
<KeyPosition
|
||||
motion:framePosition="50"
|
||||
motion:keyPositionType="deltaRelative"
|
||||
motion:motionTarget="@id/createDmByQrCode"
|
||||
motion:percentX="0.8"
|
||||
motion:percentY="0.8" />
|
||||
<KeyPosition
|
||||
motion:framePosition="50"
|
||||
motion:keyPositionType="deltaRelative"
|
||||
motion:motionTarget="@id/createDmByQrCodeLabel"
|
||||
motion:percentX="0.9"
|
||||
motion:percentY="0.8" />
|
||||
|
||||
<!-- Delay apparition of labels-->
|
||||
<KeyAttribute
|
||||
android:alpha="0.4"
|
||||
motion:framePosition="80"
|
||||
motion:motionTarget="@id/createDmByMxidLabel" />
|
||||
<KeyAttribute
|
||||
android:alpha="0.4"
|
||||
motion:framePosition="80"
|
||||
motion:motionTarget="@id/createDmByQrCodeLabel" />
|
||||
|
||||
</KeyFrameSet>
|
||||
</Transition>
|
||||
|
||||
<ConstraintSet android:id="@+id/constraint_set_fab_menu_close">
|
||||
|
||||
<Constraint
|
||||
android:id="@+id/dmsCreateRoomTouchGuard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?riotx_touch_guard_bg"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<!-- Sub menu item 2 -->
|
||||
<Constraint
|
||||
android:id="@+id/createDmByQrCode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:src="@drawable/ic_fab_add_room"
|
||||
android:visibility="invisible"
|
||||
motion:backgroundTint="#FFFFFF"
|
||||
motion:fabCustomSize="48dp"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/dmsCreateRoomButton"
|
||||
motion:layout_constraintEnd_toEndOf="@+id/dmsCreateRoomButton"
|
||||
motion:layout_constraintStart_toStartOf="@+id/dmsCreateRoomButton"
|
||||
motion:layout_constraintTop_toTopOf="@+id/dmsCreateRoomButton"
|
||||
motion:maxImageSize="26dp"
|
||||
motion:tint="@color/black" />
|
||||
|
||||
<Constraint
|
||||
android:id="@+id/createDmByQrCodeLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@string/fab_menu_create_room"
|
||||
android:visibility="invisible"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/createDmByQrCode"
|
||||
motion:layout_constraintEnd_toEndOf="@+id/createDmByQrCode"
|
||||
motion:layout_constraintTop_toTopOf="@+id/createDmByQrCode" />
|
||||
|
||||
<!-- Sub menu item 1 -->
|
||||
<Constraint
|
||||
android:id="@+id/createDmByMxid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:src="@drawable/ic_fab_add_chat"
|
||||
android:visibility="invisible"
|
||||
motion:backgroundTint="#FFFFFF"
|
||||
motion:fabCustomSize="48dp"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/dmsCreateRoomButton"
|
||||
motion:layout_constraintEnd_toEndOf="@+id/dmsCreateRoomButton"
|
||||
motion:layout_constraintStart_toStartOf="@+id/dmsCreateRoomButton"
|
||||
motion:layout_constraintTop_toTopOf="@+id/dmsCreateRoomButton"
|
||||
motion:maxImageSize="29dp"
|
||||
motion:tint="@color/black" />
|
||||
|
||||
<Constraint
|
||||
android:id="@+id/createDmByMxidLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@string/fab_menu_create_chat"
|
||||
android:visibility="invisible"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/createDmByMxid"
|
||||
motion:layout_constraintEnd_toEndOf="@+id/createDmByMxid"
|
||||
motion:layout_constraintTop_toTopOf="@+id/createDmByMxid" />
|
||||
|
||||
<!-- Menu -->
|
||||
<Constraint
|
||||
android:id="@+id/dmsCreateRoomButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:src="@drawable/ic_fab_add"
|
||||
motion:layout_constraintBottom_toBottomOf="parent"
|
||||
motion:layout_constraintEnd_toEndOf="parent"
|
||||
motion:maxImageSize="14dp" />
|
||||
|
||||
</ConstraintSet>
|
||||
|
||||
<ConstraintSet android:id="@+id/constraint_set_fab_menu_open">
|
||||
|
||||
<Constraint
|
||||
android:id="@+id/dmsCreateRoomTouchGuard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?riotx_touch_guard_bg" />
|
||||
|
||||
<!-- Sub menu item 2 -->
|
||||
<Constraint
|
||||
android:id="@+id/createDmByQrCode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginBottom="14dp"
|
||||
android:src="@drawable/ic_fab_add_room"
|
||||
motion:backgroundTint="#FFFFFF"
|
||||
motion:fabCustomSize="48dp"
|
||||
motion:layout_constraintBottom_toTopOf="@+id/createDmByMxid"
|
||||
motion:layout_constraintEnd_toEndOf="@+id/dmsCreateRoomButton"
|
||||
motion:layout_constraintStart_toStartOf="@+id/dmsCreateRoomButton"
|
||||
motion:maxImageSize="26dp"
|
||||
motion:tint="@color/black" />
|
||||
|
||||
<Constraint
|
||||
android:id="@+id/createDmByQrCodeLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@string/fab_menu_create_room"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/createDmByQrCode"
|
||||
motion:layout_constraintEnd_toStartOf="@+id/createDmByQrCode"
|
||||
motion:layout_constraintTop_toTopOf="@+id/createDmByQrCode" />
|
||||
|
||||
<!-- Sub menu item 1 -->
|
||||
<Constraint
|
||||
android:id="@+id/createDmByMxid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginBottom="25dp"
|
||||
android:src="@drawable/ic_fab_add_chat"
|
||||
motion:backgroundTint="#FFFFFF"
|
||||
motion:fabCustomSize="48dp"
|
||||
motion:layout_constraintBottom_toTopOf="@+id/dmsCreateRoomButton"
|
||||
motion:layout_constraintEnd_toEndOf="@+id/dmsCreateRoomButton"
|
||||
motion:layout_constraintStart_toStartOf="@+id/dmsCreateRoomButton"
|
||||
motion:maxImageSize="29dp"
|
||||
motion:tint="@color/black" />
|
||||
|
||||
<Constraint
|
||||
android:id="@+id/createDmByMxidLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@string/fab_menu_create_chat"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/createDmByMxid"
|
||||
motion:layout_constraintEnd_toStartOf="@+id/createDmByMxid"
|
||||
motion:layout_constraintTop_toTopOf="@+id/createDmByMxid" />
|
||||
|
||||
<!-- Menu -->
|
||||
<Constraint
|
||||
android:id="@+id/dmsCreateRoomButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:rotation="135"
|
||||
android:src="@drawable/ic_fab_add"
|
||||
motion:layout_constraintBottom_toBottomOf="parent"
|
||||
motion:layout_constraintEnd_toEndOf="parent"
|
||||
motion:maxImageSize="14dp" />
|
||||
|
||||
</ConstraintSet>
|
||||
|
||||
</MotionScene>
|
Loading…
Reference in New Issue
Block a user