mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-09 08:38:43 +01:00
Post Creation Share flow
This commit is contained in:
parent
7d2d7b411e
commit
a901e1d179
@ -77,6 +77,7 @@ import im.vector.app.features.settings.VectorSettingsActivity
|
||||
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheet
|
||||
import im.vector.app.features.share.IncomingShareActivity
|
||||
import im.vector.app.features.signout.soft.SoftLogoutActivity
|
||||
import im.vector.app.features.spaces.ShareSpaceBottomSheet
|
||||
import im.vector.app.features.spaces.SpaceCreationActivity
|
||||
import im.vector.app.features.terms.ReviewTermsActivity
|
||||
import im.vector.app.features.ui.UiStateRepository
|
||||
@ -175,6 +176,7 @@ interface ScreenComponent {
|
||||
fun inject(bottomSheet: CallControlsBottomSheet)
|
||||
fun inject(bottomSheet: SignOutBottomSheetDialogFragment)
|
||||
fun inject(bottomSheet: MatrixToBottomSheet)
|
||||
fun inject(bottomSheet: ShareSpaceBottomSheet)
|
||||
|
||||
/* ==========================================================================================
|
||||
* Others
|
||||
|
@ -22,6 +22,7 @@ import android.util.TypedValue
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
@ -48,12 +49,14 @@ abstract class HomeSpaceSummaryItem : VectorEpoxyModel<HomeSpaceSummaryItem.Hold
|
||||
holder.avatarImageView.background = ContextCompat.getDrawable(holder.view.context, R.drawable.space_home_background)
|
||||
holder.avatarImageView.setImageResource(R.drawable.ic_space_home)
|
||||
holder.avatarImageView.scaleType = ImageView.ScaleType.CENTER_INSIDE
|
||||
holder.leaveView.isVisible = false
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val avatarImageView by bind<ImageView>(R.id.groupAvatarImageView)
|
||||
val groupNameView by bind<TextView>(R.id.groupNameView)
|
||||
val rootView by bind<CheckableConstraintLayout>(R.id.itemGroupLayout)
|
||||
val leaveView by bind<ImageView>(R.id.groupTmpLeave)
|
||||
}
|
||||
|
||||
fun dpToPx(resources: Resources, dp: Int): Int {
|
||||
|
@ -111,14 +111,10 @@ class HomeActivity :
|
||||
val defaultRoomsId = activityResult.data?.extras?.getString(SpaceCreationActivity.RESULT_DATA_DEFAULT_ROOM_ID)
|
||||
views.drawerLayout.closeDrawer(GravityCompat.START)
|
||||
|
||||
// Here we want to change current space to the newly created one, and then immediatly open the default room
|
||||
// Here we want to change current space to the newly created one, and then immediately open the default room
|
||||
if (spaceId != null) {
|
||||
navigator.switchToSpace(this, spaceId, defaultRoomsId)
|
||||
navigator.switchToSpace(this, spaceId, defaultRoomsId, true)
|
||||
}
|
||||
|
||||
// Also we should show the share space bottomsheet
|
||||
} else {
|
||||
// viewModel.handle(CrossSigningSettingsAction.ReAuthCancelled)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,9 @@ import im.vector.app.core.intent.getMimeTypeFromUri
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.platform.showOptimizedSnackbar
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.ui.views.ActiveConferenceView
|
||||
import im.vector.app.core.ui.views.CurrentCallsView
|
||||
import im.vector.app.core.ui.views.JumpToReadMarkerView
|
||||
import im.vector.app.core.ui.views.KnownCallsViewHolder
|
||||
import im.vector.app.core.ui.views.ActiveConferenceView
|
||||
import im.vector.app.core.ui.views.FailedMessagesWarningView
|
||||
@ -163,6 +165,7 @@ import im.vector.app.features.roomprofile.RoomProfileActivity
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.app.features.settings.VectorSettingsActivity
|
||||
import im.vector.app.features.share.SharedData
|
||||
import im.vector.app.features.spaces.ShareSpaceBottomSheet
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.app.features.widgets.WidgetActivity
|
||||
import im.vector.app.features.widgets.WidgetArgs
|
||||
@ -210,7 +213,8 @@ import javax.inject.Inject
|
||||
data class RoomDetailArgs(
|
||||
val roomId: String,
|
||||
val eventId: String? = null,
|
||||
val sharedData: SharedData? = null
|
||||
val sharedData: SharedData? = null,
|
||||
val openShareSpaceForId: String? = null
|
||||
) : Parcelable
|
||||
|
||||
class RoomDetailFragment @Inject constructor(
|
||||
@ -293,7 +297,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
|
||||
private lateinit var attachmentsHelper: AttachmentsHelper
|
||||
private lateinit var keyboardStateUtils: KeyboardStateUtils
|
||||
private lateinit var callActionsHandler : StartCallActionsHandler
|
||||
private lateinit var callActionsHandler: StartCallActionsHandler
|
||||
|
||||
private lateinit var attachmentTypeSelector: AttachmentTypeSelectorView
|
||||
|
||||
@ -358,9 +362,9 @@ class RoomDetailFragment @Inject constructor(
|
||||
}
|
||||
when (mode) {
|
||||
is SendMode.REGULAR -> renderRegularMode(mode.text)
|
||||
is SendMode.EDIT -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_edit, R.string.edit, mode.text)
|
||||
is SendMode.QUOTE -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_quote, R.string.quote, mode.text)
|
||||
is SendMode.REPLY -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_reply, R.string.reply, mode.text)
|
||||
is SendMode.EDIT -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_edit, R.string.edit, mode.text)
|
||||
is SendMode.QUOTE -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_quote, R.string.quote, mode.text)
|
||||
is SendMode.REPLY -> renderSpecialMode(mode.timelineEvent, R.drawable.ic_reply, R.string.reply, mode.text)
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,29 +388,30 @@ class RoomDetailFragment @Inject constructor(
|
||||
RoomDetailViewEvents.DisplayPromptForIntegrationManager -> displayPromptForIntegrationManager()
|
||||
is RoomDetailViewEvents.OpenStickerPicker -> openStickerPicker(it)
|
||||
is RoomDetailViewEvents.DisplayEnableIntegrationsWarning -> displayDisabledIntegrationDialog()
|
||||
is RoomDetailViewEvents.OpenIntegrationManager -> openIntegrationManager()
|
||||
is RoomDetailViewEvents.OpenFile -> startOpenFileIntent(it)
|
||||
RoomDetailViewEvents.OpenActiveWidgetBottomSheet -> onViewWidgetsClicked()
|
||||
is RoomDetailViewEvents.ShowInfoOkDialog -> showDialogWithMessage(it.message)
|
||||
is RoomDetailViewEvents.JoinJitsiConference -> joinJitsiRoom(it.widget, it.withVideo)
|
||||
RoomDetailViewEvents.ShowWaitingView -> vectorBaseActivity.showWaitingView()
|
||||
RoomDetailViewEvents.HideWaitingView -> vectorBaseActivity.hideWaitingView()
|
||||
is RoomDetailViewEvents.RequestNativeWidgetPermission -> requestNativeWidgetPermission(it)
|
||||
is RoomDetailViewEvents.OpenRoom -> handleOpenRoom(it)
|
||||
RoomDetailViewEvents.OpenInvitePeople -> navigator.openInviteUsersToRoom(requireContext(), roomDetailArgs.roomId)
|
||||
RoomDetailViewEvents.OpenSetRoomAvatarDialog -> galleryOrCameraDialogHelper.show()
|
||||
RoomDetailViewEvents.OpenRoomSettings -> handleOpenRoomSettings()
|
||||
is RoomDetailViewEvents.ShowRoomAvatarFullScreen -> it.matrixItem?.let { item ->
|
||||
is RoomDetailViewEvents.OpenIntegrationManager -> openIntegrationManager()
|
||||
is RoomDetailViewEvents.OpenFile -> startOpenFileIntent(it)
|
||||
RoomDetailViewEvents.OpenActiveWidgetBottomSheet -> onViewWidgetsClicked()
|
||||
is RoomDetailViewEvents.ShowInfoOkDialog -> showDialogWithMessage(it.message)
|
||||
is RoomDetailViewEvents.JoinJitsiConference -> joinJitsiRoom(it.widget, it.withVideo)
|
||||
RoomDetailViewEvents.ShowWaitingView -> vectorBaseActivity.showWaitingView()
|
||||
RoomDetailViewEvents.HideWaitingView -> vectorBaseActivity.hideWaitingView()
|
||||
is RoomDetailViewEvents.RequestNativeWidgetPermission -> requestNativeWidgetPermission(it)
|
||||
is RoomDetailViewEvents.OpenRoom -> handleOpenRoom(it)
|
||||
RoomDetailViewEvents.OpenInvitePeople -> navigator.openInviteUsersToRoom(requireContext(), roomDetailArgs.roomId)
|
||||
RoomDetailViewEvents.OpenSetRoomAvatarDialog -> galleryOrCameraDialogHelper.show()
|
||||
RoomDetailViewEvents.OpenRoomSettings -> handleOpenRoomSettings()
|
||||
is RoomDetailViewEvents.ShowRoomAvatarFullScreen -> it.matrixItem?.let { item ->
|
||||
navigator.openBigImageViewer(requireActivity(), it.view, item)
|
||||
}
|
||||
is RoomDetailViewEvents.StartChatEffect -> handleChatEffect(it.type)
|
||||
RoomDetailViewEvents.StopChatEffects -> handleStopChatEffects()
|
||||
is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it)
|
||||
is RoomDetailViewEvents.StartChatEffect -> handleChatEffect(it.type)
|
||||
RoomDetailViewEvents.StopChatEffects -> handleStopChatEffects()
|
||||
is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
handleShareData()
|
||||
handleSpaceShare()
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,7 +424,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
private fun handleChatEffect(chatEffect: ChatEffect) {
|
||||
private fun handleChatEffect(chatEffect: ChatEffect) {
|
||||
when (chatEffect) {
|
||||
ChatEffect.CONFETTI -> {
|
||||
views.viewKonfetti.isVisible = true
|
||||
@ -434,7 +439,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
.setPosition(-50f, views.viewKonfetti.width + 50f, -50f, -50f)
|
||||
.streamFor(150, 3000L)
|
||||
}
|
||||
ChatEffect.SNOW -> {
|
||||
ChatEffect.SNOW -> {
|
||||
views.viewSnowFall.isVisible = true
|
||||
views.viewSnowFall.restartFalling()
|
||||
}
|
||||
@ -627,17 +632,26 @@ class RoomDetailFragment @Inject constructor(
|
||||
|
||||
private fun handleShareData() {
|
||||
when (val sharedData = roomDetailArgs.sharedData) {
|
||||
is SharedData.Text -> {
|
||||
is SharedData.Text -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterRegularMode(sharedData.text, fromSharing = true))
|
||||
}
|
||||
is SharedData.Attachments -> {
|
||||
// open share edition
|
||||
onContentAttachmentsReady(sharedData.attachmentData)
|
||||
}
|
||||
null -> Timber.v("No share data to process")
|
||||
null -> Timber.v("No share data to process")
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleSpaceShare() {
|
||||
roomDetailArgs.openShareSpaceForId?.let { spaceId ->
|
||||
ShareSpaceBottomSheet.show(childFragmentManager, spaceId)
|
||||
view?.post {
|
||||
handleChatEffect(ChatEffect.CONFETTI)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
timelineEventController.callback = null
|
||||
timelineEventController.removeModelBuildListener(modelBuildListener)
|
||||
@ -760,8 +774,8 @@ class RoomDetailFragment @Inject constructor(
|
||||
withState(roomDetailViewModel) { state ->
|
||||
// Set the visual state of the call buttons (voice/video) to enabled/disabled according to user permissions
|
||||
val callButtonsEnabled = when (state.asyncRoomSummary.invoke()?.joinedMembersCount) {
|
||||
1 -> false
|
||||
2 -> state.isAllowedToStartWebRTCCall
|
||||
1 -> false
|
||||
2 -> state.isAllowedToStartWebRTCCall
|
||||
else -> state.isAllowedToManageWidgets
|
||||
}
|
||||
setOf(R.id.voice_call, R.id.video_call).forEach {
|
||||
@ -791,7 +805,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.invite -> {
|
||||
R.id.invite -> {
|
||||
navigator.openInviteUsersToRoom(requireActivity(), roomDetailArgs.roomId)
|
||||
true
|
||||
}
|
||||
@ -807,19 +821,19 @@ class RoomDetailFragment @Inject constructor(
|
||||
callActionsHandler.onVoiceCallClicked()
|
||||
true
|
||||
}
|
||||
R.id.video_call -> {
|
||||
R.id.video_call -> {
|
||||
callActionsHandler.onVideoCallClicked()
|
||||
true
|
||||
}
|
||||
R.id.hangup_call -> {
|
||||
R.id.hangup_call -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EndCall)
|
||||
true
|
||||
}
|
||||
R.id.search -> {
|
||||
R.id.search -> {
|
||||
handleSearchAction()
|
||||
true
|
||||
}
|
||||
R.id.dev_tools -> {
|
||||
R.id.dev_tools -> {
|
||||
navigator.openDevTools(requireContext(), roomDetailArgs.roomId)
|
||||
true
|
||||
}
|
||||
@ -921,9 +935,9 @@ class RoomDetailFragment @Inject constructor(
|
||||
when (roomDetailPendingAction) {
|
||||
is RoomDetailPendingAction.JumpToReadReceipt ->
|
||||
roomDetailViewModel.handle(RoomDetailAction.JumpToReadReceipt(roomDetailPendingAction.userId))
|
||||
is RoomDetailPendingAction.MentionUser ->
|
||||
is RoomDetailPendingAction.MentionUser ->
|
||||
insertUserDisplayNameInTextEditor(roomDetailPendingAction.userId)
|
||||
is RoomDetailPendingAction.OpenOrCreateDm ->
|
||||
is RoomDetailPendingAction.OpenOrCreateDm ->
|
||||
roomDetailViewModel.handle(RoomDetailAction.OpenOrCreateDm(roomDetailPendingAction.userId))
|
||||
}.exhaustive
|
||||
}
|
||||
@ -1078,9 +1092,9 @@ class RoomDetailFragment @Inject constructor(
|
||||
withState(roomDetailViewModel) {
|
||||
val showJumpToUnreadBanner = when (it.unreadState) {
|
||||
UnreadState.Unknown,
|
||||
UnreadState.HasNoUnread -> false
|
||||
UnreadState.HasNoUnread -> false
|
||||
is UnreadState.ReadMarkerNotLoaded -> true
|
||||
is UnreadState.HasUnread -> {
|
||||
is UnreadState.HasUnread -> {
|
||||
if (it.canShowJumpToReadMarker) {
|
||||
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
|
||||
val positionOfReadMarker = timelineEventController.getPositionOfReadMarker()
|
||||
@ -1268,7 +1282,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
navigator.openRoom(vectorBaseActivity, async())
|
||||
vectorBaseActivity.finish()
|
||||
}
|
||||
is Fail -> {
|
||||
is Fail -> {
|
||||
vectorBaseActivity.hideWaitingView()
|
||||
vectorBaseActivity.toast(errorFormatter.toHumanReadable(async.error))
|
||||
}
|
||||
@ -1277,19 +1291,19 @@ class RoomDetailFragment @Inject constructor(
|
||||
|
||||
private fun renderSendMessageResult(sendMessageResult: RoomDetailViewEvents.SendMessageResult) {
|
||||
when (sendMessageResult) {
|
||||
is RoomDetailViewEvents.SlashCommandHandled -> {
|
||||
is RoomDetailViewEvents.SlashCommandHandled -> {
|
||||
sendMessageResult.messageRes?.let { showSnackWithMessage(getString(it)) }
|
||||
}
|
||||
is RoomDetailViewEvents.SlashCommandError -> {
|
||||
is RoomDetailViewEvents.SlashCommandError -> {
|
||||
displayCommandError(getString(R.string.command_problem_with_parameters, sendMessageResult.command.command))
|
||||
}
|
||||
is RoomDetailViewEvents.SlashCommandUnknown -> {
|
||||
is RoomDetailViewEvents.SlashCommandUnknown -> {
|
||||
displayCommandError(getString(R.string.unrecognized_command, sendMessageResult.command))
|
||||
}
|
||||
is RoomDetailViewEvents.SlashCommandResultOk -> {
|
||||
is RoomDetailViewEvents.SlashCommandResultOk -> {
|
||||
updateComposerText("")
|
||||
}
|
||||
is RoomDetailViewEvents.SlashCommandResultError -> {
|
||||
is RoomDetailViewEvents.SlashCommandResultError -> {
|
||||
displayCommandError(errorFormatter.toHumanReadable(sendMessageResult.throwable))
|
||||
}
|
||||
is RoomDetailViewEvents.SlashCommandNotImplemented -> {
|
||||
@ -1311,7 +1325,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
private fun displayE2eError(withHeldCode: WithHeldCode?) {
|
||||
val msgId = when (withHeldCode) {
|
||||
WithHeldCode.BLACKLISTED -> R.string.crypto_error_withheld_blacklisted
|
||||
WithHeldCode.UNVERIFIED -> R.string.crypto_error_withheld_unverified
|
||||
WithHeldCode.UNVERIFIED -> R.string.crypto_error_withheld_unverified
|
||||
WithHeldCode.UNAUTHORISED,
|
||||
WithHeldCode.UNAVAILABLE -> R.string.crypto_error_withheld_generic
|
||||
else -> R.string.notice_crypto_unable_to_decrypt_friendly_desc
|
||||
@ -1362,7 +1376,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
|
||||
private fun displayRoomDetailActionSuccess(result: RoomDetailViewEvents.ActionSuccess) {
|
||||
when (val data = result.action) {
|
||||
is RoomDetailAction.ReportContent -> {
|
||||
is RoomDetailAction.ReportContent -> {
|
||||
when {
|
||||
data.spam -> {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
@ -1399,7 +1413,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
is RoomDetailAction.RequestVerification -> {
|
||||
is RoomDetailAction.RequestVerification -> {
|
||||
Timber.v("## SAS RequestVerification action")
|
||||
VerificationBottomSheet.withArgs(
|
||||
roomDetailArgs.roomId,
|
||||
@ -1414,7 +1428,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
data.transactionId
|
||||
).show(parentFragmentManager, "REQ")
|
||||
}
|
||||
is RoomDetailAction.ResumeVerification -> {
|
||||
is RoomDetailAction.ResumeVerification -> {
|
||||
val otherUserId = data.otherUserId ?: return
|
||||
VerificationBottomSheet().apply {
|
||||
arguments = Bundle().apply {
|
||||
@ -1557,11 +1571,11 @@ class RoomDetailFragment @Inject constructor(
|
||||
is MessageVerificationRequestContent -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.ResumeVerification(informationData.eventId, null))
|
||||
}
|
||||
is MessageWithAttachmentContent -> {
|
||||
is MessageWithAttachmentContent -> {
|
||||
val action = RoomDetailAction.DownloadOrOpen(informationData.eventId, informationData.senderId, messageContent)
|
||||
roomDetailViewModel.handle(action)
|
||||
}
|
||||
is EncryptedEventContent -> {
|
||||
is EncryptedEventContent -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.TapOnFailedToDecrypt(informationData.eventId))
|
||||
}
|
||||
}
|
||||
@ -1724,75 +1738,75 @@ class RoomDetailFragment @Inject constructor(
|
||||
|
||||
private fun handleActions(action: EventSharedAction) {
|
||||
when (action) {
|
||||
is EventSharedAction.OpenUserProfile -> {
|
||||
is EventSharedAction.OpenUserProfile -> {
|
||||
openRoomMemberProfile(action.userId)
|
||||
}
|
||||
is EventSharedAction.AddReaction -> {
|
||||
is EventSharedAction.AddReaction -> {
|
||||
emojiActivityResultLauncher.launch(EmojiReactionPickerActivity.intent(requireContext(), action.eventId))
|
||||
}
|
||||
is EventSharedAction.ViewReactions -> {
|
||||
is EventSharedAction.ViewReactions -> {
|
||||
ViewReactionsBottomSheet.newInstance(roomDetailArgs.roomId, action.messageInformationData)
|
||||
.show(requireActivity().supportFragmentManager, "DISPLAY_REACTIONS")
|
||||
}
|
||||
is EventSharedAction.Copy -> {
|
||||
is EventSharedAction.Copy -> {
|
||||
// I need info about the current selected message :/
|
||||
copyToClipboard(requireContext(), action.content, false)
|
||||
showSnackWithMessage(getString(R.string.copied_to_clipboard))
|
||||
}
|
||||
is EventSharedAction.Redact -> {
|
||||
is EventSharedAction.Redact -> {
|
||||
promptConfirmationToRedactEvent(action)
|
||||
}
|
||||
is EventSharedAction.Share -> {
|
||||
is EventSharedAction.Share -> {
|
||||
onShareActionClicked(action)
|
||||
}
|
||||
is EventSharedAction.Save -> {
|
||||
is EventSharedAction.Save -> {
|
||||
onSaveActionClicked(action)
|
||||
}
|
||||
is EventSharedAction.ViewEditHistory -> {
|
||||
is EventSharedAction.ViewEditHistory -> {
|
||||
onEditedDecorationClicked(action.messageInformationData)
|
||||
}
|
||||
is EventSharedAction.ViewSource -> {
|
||||
is EventSharedAction.ViewSource -> {
|
||||
JSonViewerDialog.newInstance(
|
||||
action.content,
|
||||
-1,
|
||||
createJSonViewerStyleProvider(colorProvider)
|
||||
).show(childFragmentManager, "JSON_VIEWER")
|
||||
}
|
||||
is EventSharedAction.ViewDecryptedSource -> {
|
||||
is EventSharedAction.ViewDecryptedSource -> {
|
||||
JSonViewerDialog.newInstance(
|
||||
action.content,
|
||||
-1,
|
||||
createJSonViewerStyleProvider(colorProvider)
|
||||
).show(childFragmentManager, "JSON_VIEWER")
|
||||
}
|
||||
is EventSharedAction.QuickReact -> {
|
||||
is EventSharedAction.QuickReact -> {
|
||||
// eventId,ClickedOn,Add
|
||||
roomDetailViewModel.handle(RoomDetailAction.UpdateQuickReactAction(action.eventId, action.clickedOn, action.add))
|
||||
}
|
||||
is EventSharedAction.Edit -> {
|
||||
is EventSharedAction.Edit -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterEditMode(action.eventId, views.composerLayout.text.toString()))
|
||||
}
|
||||
is EventSharedAction.Quote -> {
|
||||
is EventSharedAction.Quote -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterQuoteMode(action.eventId, views.composerLayout.text.toString()))
|
||||
}
|
||||
is EventSharedAction.Reply -> {
|
||||
is EventSharedAction.Reply -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterReplyMode(action.eventId, views.composerLayout.text.toString()))
|
||||
}
|
||||
is EventSharedAction.CopyPermalink -> {
|
||||
is EventSharedAction.CopyPermalink -> {
|
||||
val permalink = session.permalinkService().createPermalink(roomDetailArgs.roomId, action.eventId)
|
||||
copyToClipboard(requireContext(), permalink, false)
|
||||
showSnackWithMessage(getString(R.string.copied_to_clipboard))
|
||||
}
|
||||
is EventSharedAction.Resend -> {
|
||||
is EventSharedAction.Resend -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.ResendMessage(action.eventId))
|
||||
}
|
||||
is EventSharedAction.Remove -> {
|
||||
is EventSharedAction.Remove -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.RemoveFailedEcho(action.eventId))
|
||||
}
|
||||
is EventSharedAction.Cancel -> {
|
||||
handleCancelSend(action)
|
||||
}
|
||||
is EventSharedAction.ReportContentSpam -> {
|
||||
is EventSharedAction.ReportContentSpam -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.ReportContent(
|
||||
action.eventId, action.senderId, "This message is spam", spam = true))
|
||||
}
|
||||
@ -1800,22 +1814,22 @@ class RoomDetailFragment @Inject constructor(
|
||||
roomDetailViewModel.handle(RoomDetailAction.ReportContent(
|
||||
action.eventId, action.senderId, "This message is inappropriate", inappropriate = true))
|
||||
}
|
||||
is EventSharedAction.ReportContentCustom -> {
|
||||
is EventSharedAction.ReportContentCustom -> {
|
||||
promptReasonToReportContent(action)
|
||||
}
|
||||
is EventSharedAction.IgnoreUser -> {
|
||||
is EventSharedAction.IgnoreUser -> {
|
||||
action.senderId?.let { askConfirmationToIgnoreUser(it) }
|
||||
}
|
||||
is EventSharedAction.OnUrlClicked -> {
|
||||
is EventSharedAction.OnUrlClicked -> {
|
||||
onUrlClicked(action.url, action.title)
|
||||
}
|
||||
is EventSharedAction.OnUrlLongClicked -> {
|
||||
is EventSharedAction.OnUrlLongClicked -> {
|
||||
onUrlLongClicked(action.url)
|
||||
}
|
||||
is EventSharedAction.ReRequestKey -> {
|
||||
is EventSharedAction.ReRequestKey -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.ReRequestKeys(action.eventId))
|
||||
}
|
||||
is EventSharedAction.UseKeyBackup -> {
|
||||
is EventSharedAction.UseKeyBackup -> {
|
||||
context?.let {
|
||||
startActivity(KeysBackupRestoreActivity.intent(it))
|
||||
}
|
||||
@ -1955,10 +1969,10 @@ class RoomDetailFragment @Inject constructor(
|
||||
|
||||
private fun launchAttachmentProcess(type: AttachmentTypeSelectorView.Type) {
|
||||
when (type) {
|
||||
AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera(requireContext(), attachmentPhotoActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile(attachmentFileActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera(requireContext(), attachmentPhotoActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile(attachmentFileActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery(attachmentImageActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio(attachmentAudioActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio(attachmentAudioActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.CONTACT -> attachmentsHelper.selectContact(attachmentContactActivityResultLauncher)
|
||||
AttachmentTypeSelectorView.Type.STICKER -> roomDetailViewModel.handle(RoomDetailAction.SelectStickerAttachment)
|
||||
}.exhaustive
|
||||
|
@ -70,6 +70,7 @@ import im.vector.app.features.roomprofile.RoomProfileActivity
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.app.features.settings.VectorSettingsActivity
|
||||
import im.vector.app.features.share.SharedData
|
||||
import im.vector.app.features.spaces.SpacePreviewActivity
|
||||
import im.vector.app.features.terms.ReviewTermsActivity
|
||||
import im.vector.app.features.widgets.WidgetActivity
|
||||
import im.vector.app.features.widgets.WidgetArgsBuilder
|
||||
@ -102,7 +103,7 @@ class DefaultNavigator @Inject constructor(
|
||||
startActivity(context, intent, buildTask)
|
||||
}
|
||||
|
||||
override fun switchToSpace(context: Context, spaceId: String, roomId: String?) {
|
||||
override fun switchToSpace(context: Context, spaceId: String, roomId: String?, openShareSheet: Boolean) {
|
||||
if (sessionHolder.getSafeActiveSession()?.spaceService()?.getSpace(spaceId) == null) {
|
||||
fatalError("Trying to open an unknown space $spaceId", vectorPreferences.failFast())
|
||||
return
|
||||
@ -115,10 +116,16 @@ class DefaultNavigator @Inject constructor(
|
||||
Timber.d("## Nav: Failed to switch to space $spaceId")
|
||||
}
|
||||
if (roomId != null) {
|
||||
openRoom(context, roomId)
|
||||
val args = RoomDetailArgs(roomId, eventId = null, openShareSpaceForId = spaceId.takeIf { openShareSheet })
|
||||
val intent = RoomDetailActivity.newIntent(context, args)
|
||||
startActivity(context, intent, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun openSpacePreview(context: Context, spaceId: String) {
|
||||
startActivity(context, SpacePreviewActivity.newIntent(context, spaceId), false)
|
||||
}
|
||||
|
||||
override fun performDeviceVerification(context: Context, otherUserId: String, sasTransactionId: String) {
|
||||
val session = sessionHolder.getSafeActiveSession() ?: return
|
||||
val tx = session.cryptoService().verificationService().getExistingTransaction(otherUserId, sasTransactionId)
|
||||
|
@ -38,7 +38,9 @@ interface Navigator {
|
||||
|
||||
fun openRoom(context: Context, roomId: String, eventId: String? = null, buildTask: Boolean = false)
|
||||
|
||||
fun switchToSpace(context: Context, spaceId: String, roomId: String?)
|
||||
fun switchToSpace(context: Context, spaceId: String, roomId: String?, openShareSheet: Boolean)
|
||||
|
||||
fun openSpacePreview(context: Context, spaceId: String)
|
||||
|
||||
fun performDeviceVerification(context: Context, otherUserId: String, sasTransactionId: String)
|
||||
|
||||
|
@ -30,6 +30,7 @@ import org.matrix.android.sdk.api.extensions.orFalse
|
||||
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.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
import org.matrix.android.sdk.api.util.toOptional
|
||||
import org.matrix.android.sdk.rx.rx
|
||||
@ -147,33 +148,43 @@ class PermalinkHandler @Inject constructor(private val activeSessionHolder: Acti
|
||||
val membership = roomSummary?.membership
|
||||
val eventId = permalinkData.eventId
|
||||
val roomAlias = permalinkData.getRoomAliasOrNull()
|
||||
val isSpace = roomSummary?.roomType == RoomType.SPACE
|
||||
return when {
|
||||
membership == Membership.BAN -> context.toast(R.string.error_opening_banned_room)
|
||||
membership?.isActive().orFalse() -> {
|
||||
navigator.openRoom(context, roomId, eventId, buildTask)
|
||||
if (isSpace) {
|
||||
// navigator.switchToSpace(context, roomId, null)
|
||||
navigator.openSpacePreview(context, roomId)
|
||||
} else {
|
||||
navigator.openRoom(context, roomId, eventId, buildTask)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (roomSummary == null) {
|
||||
// we don't know this room, try to peek
|
||||
val roomPreviewData = RoomPreviewData(
|
||||
roomId = roomId,
|
||||
roomAlias = roomAlias,
|
||||
peekFromServer = true,
|
||||
buildTask = buildTask,
|
||||
homeServers = permalinkData.viaParameters
|
||||
)
|
||||
navigator.openRoomPreview(context, roomPreviewData)
|
||||
if (isSpace) {
|
||||
navigator.openSpacePreview(context, roomId)
|
||||
} else {
|
||||
val roomPreviewData = RoomPreviewData(
|
||||
roomId = roomId,
|
||||
eventId = eventId,
|
||||
roomAlias = roomAlias ?: roomSummary.canonicalAlias,
|
||||
roomName = roomSummary.displayName,
|
||||
avatarUrl = roomSummary.avatarUrl,
|
||||
buildTask = buildTask,
|
||||
homeServers = permalinkData.viaParameters
|
||||
)
|
||||
navigator.openRoomPreview(context, roomPreviewData)
|
||||
if (roomSummary == null) {
|
||||
// we don't know this room, try to peek
|
||||
val roomPreviewData = RoomPreviewData(
|
||||
roomId = roomId,
|
||||
roomAlias = roomAlias,
|
||||
peekFromServer = true,
|
||||
buildTask = buildTask,
|
||||
homeServers = permalinkData.viaParameters
|
||||
)
|
||||
navigator.openRoomPreview(context, roomPreviewData)
|
||||
} else {
|
||||
val roomPreviewData = RoomPreviewData(
|
||||
roomId = roomId,
|
||||
eventId = eventId,
|
||||
roomAlias = roomAlias ?: roomSummary.canonicalAlias,
|
||||
roomName = roomSummary.displayName,
|
||||
avatarUrl = roomSummary.avatarUrl,
|
||||
buildTask = buildTask,
|
||||
homeServers = permalinkData.viaParameters
|
||||
)
|
||||
navigator.openRoomPreview(context, roomPreviewData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.spaces
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.di.ScreenComponent
|
||||
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
||||
import im.vector.app.core.utils.startSharePlainTextIntent
|
||||
import im.vector.app.databinding.BottomSheetSpaceInviteBinding
|
||||
import im.vector.app.features.invite.InviteUsersToRoomActivity
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import javax.inject.Inject
|
||||
|
||||
class ShareSpaceBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetSpaceInviteBinding>() {
|
||||
|
||||
@Parcelize
|
||||
data class Args(
|
||||
val spaceId: String
|
||||
) : Parcelable
|
||||
|
||||
override val showExpanded = true
|
||||
|
||||
@Inject
|
||||
lateinit var activeSessionHolder: ActiveSessionHolder
|
||||
|
||||
override fun injectWith(injector: ScreenComponent) {
|
||||
injector.inject(this)
|
||||
}
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetSpaceInviteBinding {
|
||||
return BottomSheetSpaceInviteBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// Not going for full view model for now, as it may change
|
||||
|
||||
val args: Args = arguments?.getParcelable(EXTRA_ARGS)
|
||||
?: return Unit.also { dismiss() }
|
||||
val summary = activeSessionHolder.getSafeActiveSession()?.spaceService()?.getSpace(args.spaceId)?.spaceSummary()
|
||||
|
||||
val spaceName = summary?.roomSummary?.name
|
||||
views.descriptionText.text = getString(R.string.invite_people_to_your_space_desc, spaceName)
|
||||
|
||||
views.inviteByMailButton.debouncedClicks {
|
||||
}
|
||||
|
||||
views.inviteByMxidButton.debouncedClicks {
|
||||
val intent = InviteUsersToRoomActivity.getIntent(requireContext(), args.spaceId)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
views.inviteByLinkButton.debouncedClicks {
|
||||
activeSessionHolder.getSafeActiveSession()?.permalinkService()?.createRoomPermalink(args.spaceId)?.let { permalink ->
|
||||
startSharePlainTextIntent(
|
||||
fragment = this,
|
||||
activityResultLauncher = null,
|
||||
chooserTitle = getString(R.string.share_by_text),
|
||||
text = getString(R.string.share_space_link_message, spaceName, permalink),
|
||||
extraTitle = getString(R.string.share_space_link_message, spaceName, permalink)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
views.skipButton.debouncedClicks {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val EXTRA_ARGS = "EXTRA_ARGS"
|
||||
|
||||
fun show(fragmentManager: FragmentManager, spaceId: String): ShareSpaceBottomSheet {
|
||||
return ShareSpaceBottomSheet().apply {
|
||||
isCancelable = true
|
||||
arguments = Bundle().apply {
|
||||
this.putParcelable(EXTRA_ARGS, ShareSpaceBottomSheet.Args(spaceId = spaceId))
|
||||
}
|
||||
}.also {
|
||||
it.show(fragmentManager, ShareSpaceBottomSheet::class.java.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -80,6 +80,10 @@ class SpaceListFragment @Inject constructor(
|
||||
viewModel.handle(SpaceListAction.SelectSpace(spaceSummary))
|
||||
}
|
||||
|
||||
override fun onLeaveSpace(spaceSummary: SpaceSummary) {
|
||||
viewModel.handle(SpaceListAction.LeaveSpace(spaceSummary))
|
||||
}
|
||||
|
||||
override fun onAddSpaceSelected() {
|
||||
viewModel.handle(SpaceListAction.AddSpace)
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ class SpaceSummaryController @Inject constructor(
|
||||
matrixItem(it.toMatrixItem())
|
||||
selected(false)
|
||||
listener { callback?.onSpaceSelected(it) }
|
||||
// lea { callback?.onSpaceSelected(it) }
|
||||
}
|
||||
}
|
||||
genericFooterItem {
|
||||
@ -101,6 +102,7 @@ class SpaceSummaryController @Inject constructor(
|
||||
id(groupSummary.spaceId)
|
||||
matrixItem(groupSummary.toMatrixItem())
|
||||
selected(isSelected)
|
||||
onLeave { callback?.onLeaveSpace(groupSummary) }
|
||||
listener { callback?.onSpaceSelected(groupSummary) }
|
||||
}
|
||||
}
|
||||
@ -118,6 +120,7 @@ class SpaceSummaryController @Inject constructor(
|
||||
|
||||
interface Callback {
|
||||
fun onSpaceSelected(spaceSummary: SpaceSummary)
|
||||
fun onLeaveSpace(spaceSummary: SpaceSummary)
|
||||
fun onAddSpaceSelected()
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,14 @@ package im.vector.app.features.spaces
|
||||
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
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.core.platform.CheckableConstraintLayout
|
||||
import im.vector.app.core.utils.DebouncedClickListener
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
|
||||
@ -34,12 +36,22 @@ abstract class SpaceSummaryItem : VectorEpoxyModel<SpaceSummaryItem.Holder>() {
|
||||
@EpoxyAttribute lateinit var matrixItem: MatrixItem
|
||||
@EpoxyAttribute var selected: Boolean = false
|
||||
@EpoxyAttribute var listener: (() -> Unit)? = null
|
||||
@EpoxyAttribute var onLeave: (() -> Unit)? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.rootView.setOnClickListener { listener?.invoke() }
|
||||
holder.groupNameView.text = matrixItem.displayName
|
||||
holder.rootView.isChecked = selected
|
||||
if (onLeave != null) {
|
||||
holder.leaveView.setOnClickListener(
|
||||
DebouncedClickListener({ _ ->
|
||||
onLeave?.invoke()
|
||||
})
|
||||
)
|
||||
} else {
|
||||
holder.leaveView.isVisible = false
|
||||
}
|
||||
avatarRenderer.renderSpace(matrixItem, holder.avatarImageView)
|
||||
}
|
||||
|
||||
@ -52,5 +64,6 @@ abstract class SpaceSummaryItem : VectorEpoxyModel<SpaceSummaryItem.Holder>() {
|
||||
val avatarImageView by bind<ImageView>(R.id.groupAvatarImageView)
|
||||
val groupNameView by bind<TextView>(R.id.groupNameView)
|
||||
val rootView by bind<CheckableConstraintLayout>(R.id.itemGroupLayout)
|
||||
val leaveView by bind<ImageView>(R.id.groupTmpLeave)
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package im.vector.app.features.spaces
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import arrow.core.Option
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
@ -34,18 +35,22 @@ import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.grouplist.SelectedSpaceDataSource
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.functions.BiFunction
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||
import org.matrix.android.sdk.api.session.space.SpaceSummary
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import org.matrix.android.sdk.rx.rx
|
||||
|
||||
const val ALL_COMMUNITIES_GROUP_ID = "+ALL_COMMUNITIES_GROUP_ID"
|
||||
|
||||
sealed class SpaceListAction : VectorViewModelAction {
|
||||
data class SelectSpace(val spaceSummary: SpaceSummary) : SpaceListAction()
|
||||
data class LeaveSpace(val spaceSummary: SpaceSummary) : SpaceListAction()
|
||||
object AddSpace : SpaceListAction()
|
||||
}
|
||||
|
||||
@ -88,13 +93,18 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
|
||||
init {
|
||||
observeSpaceSummaries()
|
||||
observeSelectionState()
|
||||
selectedSpaceDataSource.observe().execute {
|
||||
if (this.selectedSpace != it.invoke()?.orNull()) {
|
||||
copy(
|
||||
selectedSpace = it.invoke()?.orNull()
|
||||
)
|
||||
} else this
|
||||
}
|
||||
selectedSpaceDataSource
|
||||
.observe()
|
||||
.subscribe {
|
||||
if (currentGroupId != it.orNull()?.spaceId) {
|
||||
setState {
|
||||
copy(
|
||||
selectedSpace = it.orNull()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.disposeOnClear()
|
||||
}
|
||||
|
||||
private fun observeSelectionState() {
|
||||
@ -119,11 +129,12 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
|
||||
override fun handle(action: SpaceListAction) {
|
||||
when (action) {
|
||||
is SpaceListAction.SelectSpace -> handleSelectSpace(action)
|
||||
else -> handleAddSpace()
|
||||
is SpaceListAction.LeaveSpace -> handleLeaveSpace(action)
|
||||
SpaceListAction.AddSpace -> handleAddSpace()
|
||||
}
|
||||
}
|
||||
|
||||
// PRIVATE METHODS *****************************************************************************
|
||||
// PRIVATE METHODS *****************************************************************************
|
||||
|
||||
private fun handleSelectSpace(action: SpaceListAction.SelectSpace) = withState { state ->
|
||||
// get uptodate version of the space
|
||||
@ -146,6 +157,16 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleLeaveSpace(action: SpaceListAction.LeaveSpace) {
|
||||
viewModelScope.launch {
|
||||
awaitCallback {
|
||||
tryOrNull("Failed to leave space ${action.spaceSummary.spaceId}") {
|
||||
session.spaceService().getSpace(action.spaceSummary.spaceId)?.asRoom()?.leave(null, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleAddSpace() {
|
||||
_viewEvents.post(SpaceListViewEvents.AddSpace)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package im.vector.app.features.spaces.create
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
@ -25,6 +26,7 @@ import androidx.appcompat.content.res.AppCompatResources.getDrawable
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.withStyledAttributes
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
import im.vector.app.databinding.ViewSpaceTypeButtonBinding
|
||||
|
||||
class WizardButtonView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
|
||||
@ -36,7 +38,7 @@ class WizardButtonView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
set(value) {
|
||||
if (value != title) {
|
||||
field = value
|
||||
views.title.text = value
|
||||
views.title.setTextOrHide(value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +46,7 @@ class WizardButtonView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
set(value) {
|
||||
if (value != subTitle) {
|
||||
field = value
|
||||
views.subTitle.text = value
|
||||
views.subTitle.setTextOrHide(value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,15 +58,13 @@ class WizardButtonView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
}
|
||||
}
|
||||
|
||||
// private var tint: Int? = null
|
||||
// set(value) {
|
||||
// field = value
|
||||
// if (value != null) {
|
||||
// views.buttonImageView.imageTintList = ColorStateList.valueOf(value)
|
||||
// } else {
|
||||
// views.buttonImageView.clearColorFilter()
|
||||
// }
|
||||
// }
|
||||
private var tint: Int? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (value != null) {
|
||||
views.buttonImageView.imageTintList = ColorStateList.valueOf(value)
|
||||
}
|
||||
}
|
||||
|
||||
// var action: (() -> Unit)? = null
|
||||
|
||||
@ -72,16 +72,19 @@ class WizardButtonView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
inflate(context, R.layout.view_space_type_button, this)
|
||||
views = ViewSpaceTypeButtonBinding.bind(this)
|
||||
|
||||
views.subTitle.setTextOrHide(null)
|
||||
|
||||
if (isInEditMode) {
|
||||
title = "Title"
|
||||
subTitle = "This is doing something"
|
||||
}
|
||||
|
||||
context.withStyledAttributes(attrs, R.styleable.WizardButtonView) {
|
||||
title = getString(R.styleable.WizardButtonView_title) ?: ""
|
||||
subTitle = getString(R.styleable.WizardButtonView_subTitle) ?: ""
|
||||
title = getString(R.styleable.WizardButtonView_title)
|
||||
subTitle = getString(R.styleable.WizardButtonView_subTitle)
|
||||
icon = getDrawable(R.styleable.WizardButtonView_icon)
|
||||
// tint = getColor(R.styleable.WizardButtonView_iconTint, ThemeUtils.getColor(context, R.attr.riotx_text_primary))
|
||||
tint = getColor(R.styleable.WizardButtonView_iconTint, -1)
|
||||
.takeIf { it != -1 }
|
||||
}
|
||||
|
||||
val outValue = TypedValue()
|
||||
|
21
vector/src/main/res/drawable/ic_mail.xml
Normal file
21
vector/src/main/res/drawable/ic_mail.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M4,4H20C21.1,4 22,4.9 22,6V18C22,19.1 21.1,20 20,20H4C2.9,20 2,19.1 2,18V6C2,4.9 2.9,4 4,4Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#737D8C"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M22,6L12,13L2,6"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#737D8C"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
12
vector/src/main/res/drawable/ic_share_link.xml
Normal file
12
vector/src/main/res/drawable/ic_share_link.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12.5285,6.5409L13.0273,6.0421C14.4052,4.6643 16.6259,4.651 17.9874,6.0125C19.349,7.374 19.3357,9.5947 17.9579,10.9725L15.5878,13.3425C14.21,14.7203 11.9893,14.7335 10.6277,13.372M11.4717,17.4589L10.9727,17.9579C9.5948,19.3357 7.3741,19.349 6.0126,17.9875C4.651,16.626 4.6643,14.4053 6.0421,13.0275L8.412,10.6577C9.7899,9.2799 12.0106,9.2667 13.3721,10.6281"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#737D8C"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
79
vector/src/main/res/layout/bottom_sheet_space_invite.xml
Normal file
79
vector/src/main/res/layout/bottom_sheet_space_invite.xml
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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:id="@+id/callControlsWrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?riotx_bottom_sheet_background"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headerText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/invite_people_to_your_space"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/descriptionText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/joinInfoHelpText"
|
||||
app:layout_constraintTop_toBottomOf="@id/headerText"
|
||||
app:layout_constraintVertical_bias="1"
|
||||
tools:text="@string/invite_people_to_your_space_desc" />
|
||||
|
||||
|
||||
<im.vector.app.features.spaces.create.WizardButtonView
|
||||
android:id="@+id/inviteByMailButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:icon="@drawable/ic_mail"
|
||||
app:iconTint="?riotx_text_secondary"
|
||||
app:title="@string/invite_by_email" />
|
||||
|
||||
<im.vector.app.features.spaces.create.WizardButtonView
|
||||
android:id="@+id/inviteByMxidButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:icon="@drawable/ic_add_people"
|
||||
app:iconTint="?riotx_text_secondary"
|
||||
app:title="@string/invite_by_mxid" />
|
||||
|
||||
|
||||
<im.vector.app.features.spaces.create.WizardButtonView
|
||||
android:id="@+id/inviteByLinkButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:icon="@drawable/ic_share_link"
|
||||
app:iconTint="?riotx_text_secondary"
|
||||
app:title="@string/invite_by_link">
|
||||
|
||||
</im.vector.app.features.spaces.create.WizardButtonView>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/skipButton"
|
||||
style="@style/VectorButtonStyleOutlined"
|
||||
android:textAllCaps="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/layout_vertical_margin"
|
||||
android:textColor="?colorAccent"
|
||||
android:text="@string/skip_for_now"/>
|
||||
|
||||
</LinearLayout>
|
@ -35,11 +35,26 @@
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/groupBottomSeparator"
|
||||
app:layout_constraintEnd_toStartOf="@+id/groupAvatarChevron"
|
||||
app:layout_constraintEnd_toStartOf="@+id/groupTmpLeave"
|
||||
app:layout_constraintStart_toEndOf="@+id/groupAvatarImageView"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/groupTmpLeave"
|
||||
android:clickable="true"
|
||||
android:background="?selectableItemBackground"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:padding="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/ic_room_actions_leave"
|
||||
android:tint="@color/riotx_destructive_accent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/groupAvatarChevron"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/groupAvatarChevron"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -2,10 +2,10 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/rounded_rect_shape_8"
|
||||
android:id="@+id/content"
|
||||
android:padding="4dp">
|
||||
|
||||
<ImageView
|
||||
@ -34,6 +34,7 @@
|
||||
app:layout_constraintEnd_toStartOf="@id/rightChevron"
|
||||
app:layout_constraintStart_toEndOf="@id/buttonImageView"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginBottom="0dp"
|
||||
tools:text="Public" />
|
||||
|
||||
|
||||
@ -53,7 +54,8 @@
|
||||
app:layout_constraintStart_toEndOf="@id/buttonImageView"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_goneMarginBottom="8dp"
|
||||
tools:text="Open to anyone, best for communities" />
|
||||
tools:text="Open to anyone, best for communities"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/rightChevron"
|
||||
|
@ -3277,6 +3277,14 @@
|
||||
<string name="create_spaces_room_public_header_desc">We’ll create rooms for them, and auto-join everyone. You can add more later too.</string>
|
||||
<string name="create_spaces_default_public_room_name">General</string>
|
||||
<string name="create_spaces_loading_message">Creating Space…</string>
|
||||
<string name="invite_people_to_your_space">Invite people to your space</string>
|
||||
<string name="invite_people_to_your_space_desc">It’s just you at the moment. %s will be even better with others.</string>
|
||||
<string name="invite_by_email">Invite by email</string>
|
||||
<string name="invite_by_mxid">Invite by username</string>
|
||||
<string name="invite_by_link">Share link</string>
|
||||
<!-- First one is the space name, and the second one is the matrix.to link -->
|
||||
<string name="share_space_link_message">Join my space %1$s %2$s</string>
|
||||
<string name="skip_for_now">Skip for now</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user