From 234dfa18d3f7ed7e126de34c90d5863687701f2d Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 19 Jun 2020 20:38:30 +0200 Subject: [PATCH] Widgets: fix some issues with navigation --- .../session/widgets/WidgetPostAPIMediator.kt | 2 +- .../api/session/widgets/WidgetService.kt | 3 +- .../api/session/widgets/model/WidgetType.kt | 32 +++--- .../widgets/DefaultWidgetPostAPIMediator.kt | 2 +- .../session/widgets/DefaultWidgetService.kt | 5 +- .../widgets/token/GetScalarTokenTask.kt | 3 +- .../home/room/detail/RoomDetailAction.kt | 1 + .../home/room/detail/RoomDetailFragment.kt | 62 ++++++++---- .../home/room/detail/RoomDetailViewEvents.kt | 4 + .../home/room/detail/RoomDetailViewModel.kt | 20 +++- .../sticker/StickerPickerActionHandler.kt | 4 + .../WidgetRequestCodes.kt} | 5 +- .../features/navigation/DefaultNavigator.kt | 11 ++- .../riotx/features/navigation/Navigator.kt | 6 +- .../settings/VectorSettingsActivity.kt | 3 + .../riotx/features/widgets/WidgetFragment.kt | 27 +++-- .../features/widgets/WidgetPostAPIHandler.kt | 99 +++++++++---------- .../features/widgets/WidgetViewEvents.kt | 2 +- .../riotx/features/widgets/WidgetViewModel.kt | 25 +++-- .../features/widgets/webview/WidgetWebView.kt | 12 --- vector/src/main/res/values/strings.xml | 3 + 21 files changed, 198 insertions(+), 133 deletions(-) rename vector/src/main/java/im/vector/riotx/features/home/room/detail/{sticker/StickerPickerConstants.kt => widget/WidgetRequestCodes.kt} (82%) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetPostAPIMediator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetPostAPIMediator.kt index ac3ed8df09..bc39afda8f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetPostAPIMediator.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetPostAPIMediator.kt @@ -90,6 +90,6 @@ interface WidgetPostAPIMediator { /** * Triggered when a widget is posting */ - fun handleWidgetRequest(eventData: JsonDict): Boolean + fun handleWidgetRequest(mediator: WidgetPostAPIMediator, eventData: JsonDict): Boolean } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetService.kt index 2585d0a968..1f62a335a9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetService.kt @@ -34,7 +34,8 @@ interface WidgetService { fun getWidgetURLFormatter(): WidgetURLFormatter /** - * Returns an instance of [WidgetPostAPIMediator]. + * Returns a new instance of [WidgetPostAPIMediator]. + * Be careful to call clearWebView method and setHandler to null to avoid memory leaks. * This is to be used for "admin" widgets so you can interact through JS. */ fun getWidgetPostAPIMediator(): WidgetPostAPIMediator diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/WidgetType.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/WidgetType.kt index 4a265d71b7..d930a335d3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/WidgetType.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/WidgetType.kt @@ -16,6 +16,22 @@ package im.vector.matrix.android.api.session.widgets.model +private val DEFINED_TYPES by lazy { + listOf( + WidgetType.Jitsi, + WidgetType.TradingView, + WidgetType.Spotify, + WidgetType.Video, + WidgetType.GoogleDoc, + WidgetType.GoogleCalendar, + WidgetType.Etherpad, + WidgetType.StickerPicker, + WidgetType.Grafana, + WidgetType.Custom, + WidgetType.IntegrationManager + ) +} + sealed class WidgetType(open val preferred: String, open val legacy: String = preferred) { object Jitsi : WidgetType("m.jitsi", "jitsi") object TradingView : WidgetType("m.tradingview") @@ -30,7 +46,7 @@ sealed class WidgetType(open val preferred: String, open val legacy: String = pr object IntegrationManager : WidgetType("m.integration_manager") data class Fallback(override val preferred: String) : WidgetType(preferred) - fun matches(type: String?): Boolean { + fun matches(type: String): Boolean { return type == preferred || type == legacy } @@ -40,20 +56,6 @@ sealed class WidgetType(open val preferred: String, open val legacy: String = pr companion object { - private val DEFINED_TYPES = listOf( - Jitsi, - TradingView, - Spotify, - Video, - GoogleDoc, - GoogleCalendar, - Etherpad, - StickerPicker, - Grafana, - Custom, - IntegrationManager - ) - fun fromString(type: String): WidgetType { val matchingType = DEFINED_TYPES.firstOrNull { it.matches(type) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetPostAPIMediator.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetPostAPIMediator.kt index 345ef39edd..5bf2d02e3c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetPostAPIMediator.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetPostAPIMediator.kt @@ -78,7 +78,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(private val mosh private fun onWidgetMessage(eventData: JsonDict) { try { - if (handler?.handleWidgetRequest(eventData) == false) { + if (handler?.handleWidgetRequest(this, eventData) == false) { sendError("", eventData) } } catch (e: Exception) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetService.kt index 424168bc62..ab5f1e8858 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetService.kt @@ -26,10 +26,11 @@ import im.vector.matrix.android.api.session.widgets.WidgetURLFormatter import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.matrix.android.api.util.Cancelable import javax.inject.Inject +import javax.inject.Provider internal class DefaultWidgetService @Inject constructor(private val widgetManager: WidgetManager, private val widgetURLFormatter: WidgetURLFormatter, - private val widgetPostAPIMediator: WidgetPostAPIMediator) + private val widgetPostAPIMediator: Provider) : WidgetService { override fun getWidgetURLFormatter(): WidgetURLFormatter { @@ -37,7 +38,7 @@ internal class DefaultWidgetService @Inject constructor(private val widgetManage } override fun getWidgetPostAPIMediator(): WidgetPostAPIMediator { - return widgetPostAPIMediator + return widgetPostAPIMediator.get() } override fun getRoomWidgets( diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/token/GetScalarTokenTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/token/GetScalarTokenTask.kt index b1532df4f1..7afff00d64 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/token/GetScalarTokenTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/token/GetScalarTokenTask.kt @@ -25,7 +25,6 @@ import im.vector.matrix.android.api.session.widgets.WidgetManagementFailure import im.vector.matrix.android.internal.session.widgets.WidgetsAPI import im.vector.matrix.android.internal.session.widgets.WidgetsAPIProvider import im.vector.matrix.android.internal.task.Task -import timber.log.Timber import javax.inject.Inject import javax.net.ssl.HttpsURLConnection @@ -68,7 +67,7 @@ internal class DefaultGetScalarTokenTask @Inject constructor(private val widgets throw IllegalStateException("Scalar token is null") } scalarTokenStore.setToken(serverUrl, registerWidgetResponse.scalarToken) - return validateToken(widgetsAPI,serverUrl, registerWidgetResponse.scalarToken) + return validateToken(widgetsAPI, serverUrl, registerWidgetResponse.scalarToken) } private suspend fun validateToken(widgetsAPI: WidgetsAPI, serverUrl: String, scalarToken: String): String { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailAction.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailAction.kt index fba4f9e79e..a980ee4915 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailAction.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailAction.kt @@ -76,4 +76,5 @@ sealed class RoomDetailAction : VectorViewModelAction { data class ReRequestKeys(val eventId: String) : RoomDetailAction() object SelectStickerAttachment : RoomDetailAction() + object OpenIntegrationManager: RoomDetailAction() } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index dbb26377f6..e402433cef 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -134,7 +134,6 @@ import im.vector.riotx.features.crypto.verification.VerificationBottomSheet import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.composer.TextComposerView import im.vector.riotx.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet -import im.vector.riotx.features.home.room.detail.sticker.StickerPickerConstants import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.home.room.detail.timeline.action.EventSharedAction import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet @@ -149,6 +148,7 @@ import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData import im.vector.riotx.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet import im.vector.riotx.features.home.room.detail.widget.RoomWidgetsBannerView import im.vector.riotx.features.home.room.detail.widget.RoomWidgetsBottomSheet +import im.vector.riotx.features.home.room.detail.widget.WidgetRequestCodes import im.vector.riotx.features.html.EventHtmlRenderer import im.vector.riotx.features.html.PillImageSpan import im.vector.riotx.features.invite.VectorInviteView @@ -159,6 +159,7 @@ import im.vector.riotx.features.permalink.NavigationInterceptor import im.vector.riotx.features.permalink.PermalinkHandler import im.vector.riotx.features.reactions.EmojiReactionPickerActivity import im.vector.riotx.features.settings.VectorPreferences +import im.vector.riotx.features.settings.VectorSettingsActivity import im.vector.riotx.features.share.SharedData import im.vector.riotx.features.themes.ThemeUtils import im.vector.riotx.features.widgets.WidgetActivity @@ -302,22 +303,33 @@ class RoomDetailFragment @Inject constructor( roomDetailViewModel.observeViewEvents { when (it) { - is RoomDetailViewEvents.Failure -> showErrorInSnackbar(it.throwable) - is RoomDetailViewEvents.OnNewTimelineEvents -> scrollOnNewMessageCallback.addNewTimelineEventIds(it.eventIds) - is RoomDetailViewEvents.ActionSuccess -> displayRoomDetailActionSuccess(it) - is RoomDetailViewEvents.ActionFailure -> displayRoomDetailActionFailure(it) - is RoomDetailViewEvents.ShowMessage -> showSnackWithMessage(it.message, Snackbar.LENGTH_LONG) - is RoomDetailViewEvents.NavigateToEvent -> navigateToEvent(it) - is RoomDetailViewEvents.FileTooBigError -> displayFileTooBigError(it) - is RoomDetailViewEvents.DownloadFileState -> handleDownloadFileState(it) - is RoomDetailViewEvents.JoinRoomCommandSuccess -> handleJoinedToAnotherRoom(it) - is RoomDetailViewEvents.SendMessageResult -> renderSendMessageResult(it) - RoomDetailViewEvents.DisplayPromptForIntegrationManager -> displayPromptForIntegrationManager() - is RoomDetailViewEvents.OpenStickerPicker -> openStickerPicker(it) + is RoomDetailViewEvents.Failure -> showErrorInSnackbar(it.throwable) + is RoomDetailViewEvents.OnNewTimelineEvents -> scrollOnNewMessageCallback.addNewTimelineEventIds(it.eventIds) + is RoomDetailViewEvents.ActionSuccess -> displayRoomDetailActionSuccess(it) + is RoomDetailViewEvents.ActionFailure -> displayRoomDetailActionFailure(it) + is RoomDetailViewEvents.ShowMessage -> showSnackWithMessage(it.message, Snackbar.LENGTH_LONG) + is RoomDetailViewEvents.NavigateToEvent -> navigateToEvent(it) + is RoomDetailViewEvents.FileTooBigError -> displayFileTooBigError(it) + is RoomDetailViewEvents.DownloadFileState -> handleDownloadFileState(it) + is RoomDetailViewEvents.JoinRoomCommandSuccess -> handleJoinedToAnotherRoom(it) + is RoomDetailViewEvents.SendMessageResult -> renderSendMessageResult(it) + RoomDetailViewEvents.DisplayPromptForIntegrationManager -> displayPromptForIntegrationManager() + is RoomDetailViewEvents.OpenStickerPicker -> openStickerPicker(it) + is RoomDetailViewEvents.DisplayEnableIntegrationsWarning -> displayEnableIntegrationsWarning() + is RoomDetailViewEvents.OpenIntegrationManager -> openIntegrationManager() }.exhaustive } } + private fun openIntegrationManager(screen: String? = null) { + navigator.openIntegrationManager( + fragment = this, + roomId = roomDetailArgs.roomId, + integId = null, + screen = screen + ) + } + private fun setupWidgetsBannerView() { roomWidgetsBannerView.callback = this } @@ -334,10 +346,7 @@ class RoomDetailFragment @Inject constructor( .setView(v) .setPositiveButton(R.string.yes) { _, _ -> // Open integration manager, to the sticker installation page - navigator.openIntegrationManager( - context = requireContext(), - roomId = roomDetailArgs.roomId, - integId = null, + openIntegrationManager( screen = WidgetType.StickerPicker.preferred ) } @@ -345,6 +354,17 @@ class RoomDetailFragment @Inject constructor( .show() } + private fun displayEnableIntegrationsWarning() { + AlertDialog.Builder(requireContext()) + .setTitle(R.string.integration_manager_not_enabled_title) + .setMessage(R.string.integration_manager_not_enabled_msg) + .setPositiveButton(R.string.open_settings) { _, _ -> + navigator.openSettings(requireContext(), VectorSettingsActivity.EXTRA_DIRECT_ACCESS_GENERAL) + } + .setNegativeButton(R.string.cancel, null) + .show() + } + private fun handleJoinedToAnotherRoom(action: RoomDetailViewEvents.JoinRoomCommandSuccess) { updateComposerText("") lockSendButton = false @@ -469,7 +489,7 @@ class RoomDetailFragment @Inject constructor( true } R.id.open_matrix_apps -> { - navigator.openIntegrationManager(requireContext(), roomDetailArgs.roomId, null, null) + roomDetailViewModel.handle(RoomDetailAction.OpenIntegrationManager) true } else -> super.onOptionsItemSelected(item) @@ -548,16 +568,16 @@ class RoomDetailFragment @Inject constructor( val hasBeenHandled = attachmentsHelper.onActivityResult(requestCode, resultCode, data) if (!hasBeenHandled && resultCode == RESULT_OK && data != null) { when (requestCode) { - AttachmentsPreviewActivity.REQUEST_CODE -> { + AttachmentsPreviewActivity.REQUEST_CODE -> { val sendData = AttachmentsPreviewActivity.getOutput(data) val keepOriginalSize = AttachmentsPreviewActivity.getKeepOriginalSize(data) roomDetailViewModel.handle(RoomDetailAction.SendMedia(sendData, !keepOriginalSize)) } - REACTION_SELECT_REQUEST_CODE -> { + REACTION_SELECT_REQUEST_CODE -> { val (eventId, reaction) = EmojiReactionPickerActivity.getOutput(data) ?: return roomDetailViewModel.handle(RoomDetailAction.SendReaction(eventId, reaction)) } - StickerPickerConstants.STICKER_PICKER_REQUEST_CODE -> { + WidgetRequestCodes.STICKER_PICKER_REQUEST_CODE -> { val content = WidgetActivity.getOutput(data).toModel() ?: return roomDetailViewModel.handle(RoomDetailAction.SendSticker(content)) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt index 73ce95eda2..560da2e116 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt @@ -52,8 +52,12 @@ sealed class RoomDetailViewEvents : VectorViewEvents { object DisplayPromptForIntegrationManager: RoomDetailViewEvents() + object DisplayEnableIntegrationsWarning: RoomDetailViewEvents() + data class OpenStickerPicker(val widget: Widget): RoomDetailViewEvents() + object OpenIntegrationManager: RoomDetailViewEvents() + object MessageSent : SendMessageResult() data class JoinRoomCommandSuccess(val roomId: String) : SendMessageResult() class SlashCommandError(val command: Command) : SendMessageResult() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index 69a6429efb..8641549e68 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -79,7 +79,9 @@ import io.reactivex.Observable import io.reactivex.functions.BiFunction import io.reactivex.rxkotlin.subscribeBy import io.reactivex.schedulers.Schedulers +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.commonmark.parser.Parser import org.commonmark.renderer.html.HtmlRenderer import timber.log.Timber @@ -252,6 +254,7 @@ class RoomDetailViewModel @AssistedInject constructor( is RoomDetailAction.ResumeVerification -> handleResumeRequestVerification(action) is RoomDetailAction.ReRequestKeys -> handleReRequestKeys(action) is RoomDetailAction.SelectStickerAttachment -> handleSelectStickerAttachment() + is RoomDetailAction.OpenIntegrationManager -> handleOpenIntegrationManager() } } @@ -266,6 +269,19 @@ class RoomDetailViewModel @AssistedInject constructor( } } + private fun handleOpenIntegrationManager() { + viewModelScope.launch { + val viewEvent = withContext(Dispatchers.Default) { + if (isIntegrationEnabled()) { + RoomDetailViewEvents.OpenIntegrationManager + } else { + RoomDetailViewEvents.DisplayEnableIntegrationsWarning + } + } + _viewEvents.post(viewEvent) + } + } + private fun startTrackingUnreadMessages() { trackUnreadMessages.set(true) setState { copy(canShowJumpToReadMarker = false) } @@ -365,13 +381,15 @@ class RoomDetailViewModel @AssistedInject constructor( } } + private fun isIntegrationEnabled() = session.integrationManagerService().isIntegrationEnabled() + fun isMenuItemVisible(@IdRes itemId: Int) = when (itemId) { R.id.clear_message_queue -> /* For now always disable on production, worker cancellation is not working properly */ timeline.pendingEventCount() > 0 && vectorPreferences.developerMode() R.id.resend_all -> timeline.failedToDeliverEventCount() > 0 R.id.clear_all -> timeline.failedToDeliverEventCount() > 0 - R.id.open_matrix_apps -> session.integrationManagerService().isIntegrationEnabled() + R.id.open_matrix_apps -> true else -> false } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerActionHandler.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerActionHandler.kt index 3b939892b5..ebae583d8c 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerActionHandler.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerActionHandler.kt @@ -27,6 +27,10 @@ class StickerPickerActionHandler @Inject constructor(private val session: Sessio suspend fun handle(): RoomDetailViewEvents = withContext(Dispatchers.Default) { // Search for the sticker picker widget in the user account + val integrationsEnabled = session.integrationManagerService().isIntegrationEnabled() + if (!integrationsEnabled) { + return@withContext RoomDetailViewEvents.DisplayEnableIntegrationsWarning + } val stickerWidget = session.widgetService().getUserWidgets(WidgetType.StickerPicker.values()).firstOrNull { it.isActive } if (stickerWidget == null || stickerWidget.computedUrl.isNullOrBlank()) { RoomDetailViewEvents.DisplayPromptForIntegrationManager diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerConstants.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/WidgetRequestCodes.kt similarity index 82% rename from vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerConstants.kt rename to vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/WidgetRequestCodes.kt index 8068eafc85..6fdfa598e4 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerConstants.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/WidgetRequestCodes.kt @@ -14,8 +14,9 @@ * limitations under the License. */ -package im.vector.riotx.features.home.room.detail.sticker +package im.vector.riotx.features.home.room.detail.widget -object StickerPickerConstants { +object WidgetRequestCodes { const val STICKER_PICKER_REQUEST_CODE = 16000 + const val INTEGRATION_MANAGER_REQUEST_CODE = 16001 } diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt index 6a0094520a..a909e5becf 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt @@ -30,8 +30,8 @@ import androidx.fragment.app.Fragment import im.vector.matrix.android.api.session.crypto.verification.IncomingSasVerificationTransaction import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom import im.vector.matrix.android.api.session.terms.TermsService -import im.vector.matrix.android.api.util.MatrixItem import im.vector.matrix.android.api.session.widgets.model.Widget +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.error.fatalError @@ -46,7 +46,7 @@ import im.vector.riotx.features.crypto.verification.VerificationBottomSheet import im.vector.riotx.features.debug.DebugMenuActivity import im.vector.riotx.features.home.room.detail.RoomDetailActivity import im.vector.riotx.features.home.room.detail.RoomDetailArgs -import im.vector.riotx.features.home.room.detail.sticker.StickerPickerConstants +import im.vector.riotx.features.home.room.detail.widget.WidgetRequestCodes import im.vector.riotx.features.home.room.filtered.FilteredRoomsActivity import im.vector.riotx.features.invite.InviteUsersToRoomActivity import im.vector.riotx.features.media.BigImageViewerActivity @@ -230,12 +230,13 @@ class DefaultNavigator @Inject constructor( override fun openStickerPicker(fragment: Fragment, roomId: String, widget: Widget, requestCode: Int) { val widgetArgs = widgetArgsBuilder.buildStickerPickerArgs(roomId, widget) val intent = WidgetActivity.newIntent(fragment.requireContext(), widgetArgs) - fragment.startActivityForResult(intent, StickerPickerConstants.STICKER_PICKER_REQUEST_CODE) + fragment.startActivityForResult(intent, WidgetRequestCodes.STICKER_PICKER_REQUEST_CODE) } - override fun openIntegrationManager(context: Context, roomId: String, integId: String?, screen: String?) { + override fun openIntegrationManager(fragment: Fragment, roomId: String, integId: String?, screen: String?) { val widgetArgs = widgetArgsBuilder.buildIntegrationManagerArgs(roomId, integId, screen) - context.startActivity(WidgetActivity.newIntent(context, widgetArgs)) + val intent = WidgetActivity.newIntent(fragment.requireContext(), widgetArgs) + fragment.startActivityForResult(intent, WidgetRequestCodes.INTEGRATION_MANAGER_REQUEST_CODE) } override fun openRoomWidget(context: Context, roomId: String, widget: Widget) { diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt index 35ace87b6b..916a46c041 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt @@ -25,7 +25,7 @@ import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom import im.vector.matrix.android.api.session.terms.TermsService import im.vector.matrix.android.api.util.MatrixItem import im.vector.matrix.android.api.session.widgets.model.Widget -import im.vector.riotx.features.home.room.detail.sticker.StickerPickerConstants +import im.vector.riotx.features.home.room.detail.widget.WidgetRequestCodes import im.vector.riotx.features.media.ImageContentRenderer import im.vector.riotx.features.media.VideoContentRenderer import im.vector.riotx.features.settings.VectorSettingsActivity @@ -85,9 +85,9 @@ interface Navigator { fun openStickerPicker(fragment: Fragment, roomId: String, widget: Widget, - requestCode: Int = StickerPickerConstants.STICKER_PICKER_REQUEST_CODE) + requestCode: Int = WidgetRequestCodes.STICKER_PICKER_REQUEST_CODE) - fun openIntegrationManager(context: Context, roomId: String, integId: String?, screen: String?) + fun openIntegrationManager(fragment: Fragment, roomId: String, integId: String?, screen: String?) fun openRoomWidget(context: Context, roomId: String, widget: Widget) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsActivity.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsActivity.kt index 0c73c0f5d3..3a41318619 100755 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsActivity.kt @@ -59,6 +59,8 @@ class VectorSettingsActivity : VectorBaseActivity(), if (isFirstCreation()) { // display the fragment when (intent.getIntExtra(EXTRA_DIRECT_ACCESS, EXTRA_DIRECT_ACCESS_ROOT)) { + EXTRA_DIRECT_ACCESS_GENERAL -> + replaceFragment(R.id.vector_settings_page, VectorSettingsGeneralFragment::class.java, null, FRAGMENT_TAG) EXTRA_DIRECT_ACCESS_ADVANCED_SETTINGS -> replaceFragment(R.id.vector_settings_page, VectorSettingsAdvancedSettingsFragment::class.java, null, FRAGMENT_TAG) EXTRA_DIRECT_ACCESS_SECURITY_PRIVACY -> @@ -137,6 +139,7 @@ class VectorSettingsActivity : VectorBaseActivity(), const val EXTRA_DIRECT_ACCESS_ADVANCED_SETTINGS = 1 const val EXTRA_DIRECT_ACCESS_SECURITY_PRIVACY = 2 const val EXTRA_DIRECT_ACCESS_SECURITY_PRIVACY_MANAGE_SESSIONS = 3 + const val EXTRA_DIRECT_ACCESS_GENERAL = 4 private const val FRAGMENT_TAG = "VectorSettingsPreferencesFragment" } diff --git a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetFragment.kt b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetFragment.kt index 14b25d0439..b162149ffe 100644 --- a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetFragment.kt @@ -40,6 +40,7 @@ import im.vector.riotx.R import im.vector.riotx.core.platform.OnBackPressed import im.vector.riotx.core.platform.VectorBaseFragment import im.vector.riotx.core.utils.openUrlInExternalBrowser +import im.vector.riotx.features.home.room.detail.widget.WidgetRequestCodes import im.vector.riotx.features.terms.ReviewTermsActivity import im.vector.riotx.features.webview.WebViewEventListener import im.vector.riotx.features.widgets.webview.clearAfterWidget @@ -77,7 +78,7 @@ class WidgetFragment @Inject constructor() : VectorBaseFragment(), WebViewEventL Timber.v("Observed view events: $it") when (it) { is WidgetViewEvents.DisplayTerms -> displayTerms(it) - is WidgetViewEvents.LoadFormattedURL -> loadFormattedUrl(it) + is WidgetViewEvents.OnURLFormatted -> loadFormattedUrl(it) is WidgetViewEvents.DisplayIntegrationManager -> displayIntegrationManager(it) is WidgetViewEvents.Failure -> displayErrorDialog(it.throwable) } @@ -86,11 +87,17 @@ class WidgetFragment @Inject constructor() : VectorBaseFragment(), WebViewEventL } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (requestCode == ReviewTermsActivity.TERMS_REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - viewModel.handle(WidgetAction.OnTermsReviewed) - } else { - vectorBaseActivity.finish() + when (requestCode) { + ReviewTermsActivity.TERMS_REQUEST_CODE -> { + Timber.v("On terms results") + if (resultCode == Activity.RESULT_OK) { + viewModel.handle(WidgetAction.OnTermsReviewed) + } else { + vectorBaseActivity.finish() + } + } + WidgetRequestCodes.INTEGRATION_MANAGER_REQUEST_CODE -> { + viewModel.handle(WidgetAction.LoadFormattedUrl) } } } @@ -139,7 +146,7 @@ class WidgetFragment @Inject constructor() : VectorBaseFragment(), WebViewEventL override fun onOptionsItemSelected(item: MenuItem): Boolean = withState(viewModel) { state -> when (item.itemId) { R.id.action_edit -> { - navigator.openIntegrationManager(requireContext(), state.roomId, state.widgetId, state.widgetKind.screenId) + navigator.openIntegrationManager(this, state.roomId, state.widgetId, state.widgetKind.screenId) return@withState true } R.id.action_delete -> { @@ -261,9 +268,9 @@ class WidgetFragment @Inject constructor() : VectorBaseFragment(), WebViewEventL ) } - private fun loadFormattedUrl(loadFormattedUrl: WidgetViewEvents.LoadFormattedURL) { + private fun loadFormattedUrl(event: WidgetViewEvents.OnURLFormatted) { widgetWebView.clearHistory() - widgetWebView.loadUrl(loadFormattedUrl.formattedURL) + widgetWebView.loadUrl(event.formattedURL) } private fun setStateError(message: String?) { @@ -280,7 +287,7 @@ class WidgetFragment @Inject constructor() : VectorBaseFragment(), WebViewEventL private fun displayIntegrationManager(event: WidgetViewEvents.DisplayIntegrationManager) { navigator.openIntegrationManager( - context = vectorBaseActivity, + fragment = this, roomId = fragmentArgs.roomId, integId = event.integId, screen = event.integType diff --git a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetPostAPIHandler.kt b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetPostAPIHandler.kt index 351a15aad1..7115a2ea62 100644 --- a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetPostAPIHandler.kt +++ b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetPostAPIHandler.kt @@ -39,13 +39,12 @@ import java.util.ArrayList import java.util.HashMap class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roomId: String, - @Assisted private val navigationCallback: NavigationCallback, private val stringProvider: StringProvider, private val session: Session) : WidgetPostAPIMediator.Handler { @AssistedInject.Factory interface Factory { - fun create(roomId: String, navigationCallback: NavigationCallback): WidgetPostAPIHandler + fun create(roomId: String): WidgetPostAPIHandler } interface NavigationCallback { @@ -54,31 +53,31 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo fun openIntegrationManager(integId: String?, integType: String?) } - private val widgetPostAPIMediator = session.widgetService().getWidgetPostAPIMediator() private val room = session.getRoom(roomId)!! + var navigationCallback: NavigationCallback? = null - override fun handleWidgetRequest(eventData: JsonDict): Boolean { + override fun handleWidgetRequest(mediator: WidgetPostAPIMediator, eventData: JsonDict): Boolean { return when (eventData["action"] as String?) { "integration_manager_open" -> handleIntegrationManagerOpenAction(eventData).run { true } - "bot_options" -> getBotOptions(eventData).run { true } - "can_send_event" -> canSendEvent(eventData).run { true } + "bot_options" -> getBotOptions(mediator, eventData).run { true } + "can_send_event" -> canSendEvent(mediator, eventData).run { true } "close_scalar" -> handleCloseScalar().run { true } - "get_membership_count" -> getMembershipCount(eventData).run { true } - "get_widgets" -> getWidgets(eventData).run { true } - "invite" -> inviteUser(eventData).run { true } - "join_rules_state" -> getJoinRules(eventData).run { true } - "membership_state" -> getMembershipState(eventData).run { true } - "set_bot_options" -> setBotOptions(eventData).run { true } - "set_bot_power" -> setBotPower(eventData).run { true } - "set_plumbing_state" -> setPlumbingState(eventData).run { true } - "set_widget" -> setWidget(eventData).run { true } - "m.sticker" -> pickStickerData(eventData).run { true } + "get_membership_count" -> getMembershipCount(mediator, eventData).run { true } + "get_widgets" -> getWidgets(mediator, eventData).run { true } + "invite" -> inviteUser(mediator, eventData).run { true } + "join_rules_state" -> getJoinRules(mediator, eventData).run { true } + "membership_state" -> getMembershipState(mediator, eventData).run { true } + "set_bot_options" -> setBotOptions(mediator, eventData).run { true } + "set_bot_power" -> setBotPower(mediator, eventData).run { true } + "set_plumbing_state" -> setPlumbingState(mediator, eventData).run { true } + "set_widget" -> setWidget(mediator, eventData).run { true } + "m.sticker" -> pickStickerData(mediator, eventData).run { true } else -> false } } private fun handleCloseScalar() { - navigationCallback.close() + navigationCallback?.close() } private fun handleIntegrationManagerOpenAction(eventData: JsonDict) { @@ -101,7 +100,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo // Add "type_" as a prefix integType?.let { integType = "type_$integType" } } - navigationCallback.openIntegrationManager(integId, integType) + navigationCallback?.openIntegrationManager(integId, integType) } /** @@ -109,8 +108,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @param eventData the modular data */ - private fun getBotOptions(eventData: JsonDict) { - if (checkRoomId(eventData) || checkUserId(eventData)) { + private fun getBotOptions(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { + if (checkRoomId(widgetPostAPIMediator, eventData) || checkUserId(widgetPostAPIMediator, eventData)) { return } val userId = eventData["user_id"] as String @@ -134,8 +133,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo } } - private fun canSendEvent(eventData: JsonDict) { - if (checkRoomId(eventData)) { + private fun canSendEvent(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { + if (checkRoomId(widgetPostAPIMediator, eventData)) { return } Timber.d("Received request canSendEvent in room $roomId") @@ -170,8 +169,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @param eventData the modular data */ - private fun getMembershipState(eventData: JsonDict) { - if (checkRoomId(eventData) || checkUserId(eventData)) { + private fun getMembershipState(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { + if (checkRoomId(widgetPostAPIMediator, eventData) || checkUserId(widgetPostAPIMediator, eventData)) { return } val userId = eventData["user_id"] as String @@ -189,8 +188,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @param eventData the modular data */ - private fun getJoinRules(eventData: JsonDict) { - if (checkRoomId(eventData)) { + private fun getJoinRules(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { + if (checkRoomId(widgetPostAPIMediator, eventData)) { return } Timber.d("Received request join rules in room $roomId") @@ -207,8 +206,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @param eventData the modular data */ - private fun getWidgets(eventData: JsonDict) { - if (checkRoomId(eventData)) { + private fun getWidgets(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { + if (checkRoomId(widgetPostAPIMediator, eventData)) { return } Timber.d("Received request to get widget in room $roomId") @@ -227,12 +226,12 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @param eventData the modular data */ - private fun setWidget(eventData: JsonDict) { + private fun setWidget(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { val userWidget = eventData["userWidget"] as Boolean? if (userWidget == true) { Timber.d("Received request to set widget for user") } else { - if (checkRoomId(eventData)) { + if (checkRoomId(widgetPostAPIMediator, eventData)) { return } Timber.d("Received request to set widget in room $roomId") @@ -283,14 +282,14 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo session.updateAccountData( type = UserAccountData.TYPE_WIDGETS, content = addUserWidgetBody, - callback = createWidgetAPICallback(eventData) + callback = createWidgetAPICallback(widgetPostAPIMediator, eventData) ) } else { session.widgetService().createRoomWidget( roomId = roomId, widgetId = widgetId, content = widgetEventContent, - callback = createWidgetAPICallback(eventData) + callback = createWidgetAPICallback(widgetPostAPIMediator, eventData) ) } } @@ -300,8 +299,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @param eventData the modular data */ - private fun setPlumbingState(eventData: JsonDict) { - if (checkRoomId(eventData)) { + private fun setPlumbingState(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { + if (checkRoomId(widgetPostAPIMediator, eventData)) { return } val description = "Received request to set plumbing state to status " + eventData["status"] + " in room " + roomId + " requested" @@ -315,7 +314,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo eventType = EventType.PLUMBING, stateKey = null, body = params, - callback = createWidgetAPICallback(eventData) + callback = createWidgetAPICallback(widgetPostAPIMediator, eventData) ) } @@ -325,8 +324,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * @param eventData the modular data */ @Suppress("UNCHECKED_CAST") - private fun setBotOptions(eventData: JsonDict) { - if (checkRoomId(eventData) || checkUserId(eventData)) { + private fun setBotOptions(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { + if (checkRoomId(widgetPostAPIMediator, eventData) || checkUserId(widgetPostAPIMediator, eventData)) { return } val userId = eventData["user_id"] as String @@ -338,7 +337,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo eventType = EventType.BOT_OPTIONS, stateKey = stateKey, body = content, - callback = createWidgetAPICallback(eventData) + callback = createWidgetAPICallback(widgetPostAPIMediator, eventData) ) } @@ -347,8 +346,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @param eventData the modular data */ - private fun setBotPower(eventData: JsonDict) { - if (checkRoomId(eventData) || checkUserId(eventData)) { + private fun setBotPower(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { + if (checkRoomId(widgetPostAPIMediator, eventData) || checkUserId(widgetPostAPIMediator, eventData)) { return } val userId = eventData["user_id"] as String @@ -369,8 +368,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @param eventData the modular data */ - private fun inviteUser(eventData: JsonDict) { - if (checkRoomId(eventData) || checkUserId(eventData)) { + private fun inviteUser(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { + if (checkRoomId(widgetPostAPIMediator, eventData) || checkUserId(widgetPostAPIMediator, eventData)) { return } val userId = eventData["user_id"] as String @@ -380,7 +379,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo if (member != null && member.membership == Membership.JOIN) { widgetPostAPIMediator.sendSuccess(eventData) } else { - room.invite(userId = userId, callback = createWidgetAPICallback(eventData)) + room.invite(userId = userId, callback = createWidgetAPICallback(widgetPostAPIMediator, eventData)) } } @@ -389,8 +388,8 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @param eventData the modular data */ - private fun getMembershipCount(eventData: JsonDict) { - if (checkRoomId(eventData)) { + private fun getMembershipCount(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { + if (checkRoomId(widgetPostAPIMediator, eventData)) { return } val numberOfJoinedMembers = room.getNumberOfJoinedMembers() @@ -398,7 +397,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo } @Suppress("UNCHECKED_CAST") - private fun pickStickerData(eventData: JsonDict) { + private fun pickStickerData(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict) { Timber.d("Received request send sticker") val data = eventData["data"] if (data == null) { @@ -411,7 +410,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo return } widgetPostAPIMediator.sendSuccess(eventData) - navigationCallback.closeWithResult(content) + navigationCallback?.closeWithResult(content) } /** @@ -420,7 +419,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @return true in case of error */ - private fun checkRoomId(eventData: JsonDict): Boolean { + private fun checkRoomId(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict): Boolean { val roomIdInEvent = eventData["room_id"] as String? // Check if param is present if (null == roomIdInEvent) { @@ -443,7 +442,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo * * @return true in case of error */ - private fun checkUserId(eventData: JsonDict): Boolean { + private fun checkUserId(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict): Boolean { val userIdInEvent = eventData["user_id"] as String? // Check if param is present if (null == userIdInEvent) { @@ -454,7 +453,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo return false } - private fun createWidgetAPICallback(eventData: JsonDict): WidgetAPICallback { + private fun createWidgetAPICallback(widgetPostAPIMediator: WidgetPostAPIMediator, eventData: JsonDict): WidgetAPICallback { return WidgetAPICallback(widgetPostAPIMediator, eventData, stringProvider) } } diff --git a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewEvents.kt index 7750f2dd68..5b40e0441d 100644 --- a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewEvents.kt @@ -23,6 +23,6 @@ sealed class WidgetViewEvents : VectorViewEvents { data class Failure(val throwable: Throwable): WidgetViewEvents() data class Close(val content: Content? = null) : WidgetViewEvents() data class DisplayIntegrationManager(val integId: String?, val integType: String?) : WidgetViewEvents() - data class LoadFormattedURL(val formattedURL: String) : WidgetViewEvents() + data class OnURLFormatted(val formattedURL: String) : WidgetViewEvents() data class DisplayTerms(val url: String, val token: String) : WidgetViewEvents() } diff --git a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewModel.kt b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewModel.kt index 9b3b5d59c9..d516137bc5 100644 --- a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewModel.kt @@ -76,6 +76,7 @@ class WidgetViewModel @AssistedInject constructor(@Assisted val initialState: Wi private val integrationManagerService = session.integrationManagerService() private val widgetURLFormatter = widgetService.getWidgetURLFormatter() private val postAPIMediator = widgetService.getWidgetPostAPIMediator() + private var widgetPostAPIHandler: WidgetPostAPIHandler? = null // Flag to avoid infinite loop private var canRefreshToken = true @@ -83,9 +84,14 @@ class WidgetViewModel @AssistedInject constructor(@Assisted val initialState: Wi init { integrationManagerService.addListener(this) if (initialState.widgetKind.isAdmin()) { - val widgetPostAPIHandler = widgetPostAPIHandlerFactory.create(initialState.roomId, this) + widgetPostAPIHandler = widgetPostAPIHandlerFactory.create(initialState.roomId).apply { + navigationCallback = this@WidgetViewModel + } postAPIMediator.setHandler(widgetPostAPIHandler) } + if (!integrationManagerService.isIntegrationEnabled()) { + _viewEvents.post(WidgetViewEvents.Close(null)) + } setupName() refreshPermissionStatus() observePowerLevel() @@ -142,10 +148,10 @@ class WidgetViewModel @AssistedInject constructor(@Assisted val initialState: Wi is WidgetAction.OnWebViewLoadingError -> handleWebViewLoadingError(action) is WidgetAction.OnWebViewLoadingSuccess -> handleWebViewLoadingSuccess(action) is WidgetAction.OnWebViewStartedToLoad -> handleWebViewStartLoading() - WidgetAction.LoadFormattedUrl -> loadFormattedUrl() + WidgetAction.LoadFormattedUrl -> loadFormattedUrl(forceFetchToken = false) WidgetAction.DeleteWidget -> handleDeleteWidget() WidgetAction.RevokeWidget -> handleRevokeWidget() - WidgetAction.OnTermsReviewed -> refreshPermissionStatus() + WidgetAction.OnTermsReviewed -> loadFormattedUrl(forceFetchToken = false) } } @@ -227,7 +233,7 @@ class WidgetViewModel @AssistedInject constructor(@Assisted val initialState: Wi ) setState { copy(formattedURL = Success(formattedUrl)) } Timber.v("Post load formatted url event: $formattedUrl") - _viewEvents.post(WidgetViewEvents.LoadFormattedURL(formattedUrl)) + _viewEvents.post(WidgetViewEvents.OnURLFormatted(formattedUrl)) } catch (failure: Throwable) { if (failure is WidgetManagementFailure.TermsNotSignedException) { _viewEvents.post(WidgetViewEvents.DisplayTerms(initialState.baseUrl, failure.token)) @@ -265,17 +271,24 @@ class WidgetViewModel @AssistedInject constructor(@Assisted val initialState: Wi override fun onCleared() { integrationManagerService.removeListener(this) + widgetPostAPIHandler?.navigationCallback = null postAPIMediator.setHandler(null) super.onCleared() } -// IntegrationManagerService.Listener + // IntegrationManagerService.Listener override fun onWidgetPermissionsChanged(widgets: Map) { refreshPermissionStatus() } -// WidgetPostAPIHandler.NavigationCallback + override fun onIsEnabledChanged(enabled: Boolean) { + if (!enabled) { + _viewEvents.post(WidgetViewEvents.Close(null)) + } + } + + // WidgetPostAPIHandler.NavigationCallback override fun close() { _viewEvents.post(WidgetViewEvents.Close(null)) diff --git a/vector/src/main/java/im/vector/riotx/features/widgets/webview/WidgetWebView.kt b/vector/src/main/java/im/vector/riotx/features/widgets/webview/WidgetWebView.kt index 68cbe76531..995ae67fae 100644 --- a/vector/src/main/java/im/vector/riotx/features/widgets/webview/WidgetWebView.kt +++ b/vector/src/main/java/im/vector/riotx/features/widgets/webview/WidgetWebView.kt @@ -81,22 +81,10 @@ fun WebView.clearAfterWidget() { webChromeClient = null webViewClient = null clearHistory() - // NOTE: clears RAM cache, if you pass true, it will also clear the disk cache. clearCache(true) - // Loading a blank page is optional, but will ensure that the WebView isn't doing anything when you destroy it. loadUrl("about:blank") - - onPause() removeAllViews() - - // NOTE: This pauses JavaScript execution for ALL WebViews, - // do not use if you have other WebViews still alive. - // If you create another WebView after calling this, - // make sure to call mWebView.resumeTimers(). - pauseTimers() - - // NOTE: This can occasionally cause a segfault below API 17 (4.2) destroy() } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 19afc120cb..8b5f996f37 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1162,6 +1162,9 @@ Read DRM protected Media + Integrations are disabled + Enable integrations in settings to allow this action. + Unable to create widget. Failed to send request. Power level must be positive integer.