From e3155b6c980b7792a38529fdd65793dcf13df30f Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Fri, 3 Dec 2021 15:47:45 +0000 Subject: [PATCH 01/37] removing notifications v1, v2 is live --- vector/build.gradle | 1 - .../settings/SettingsNotificationsRobot.kt | 24 ++----- .../im/vector/app/features/VectorFeatures.kt | 2 - .../RoomListQuickActionsEpoxyController.kt | 70 +++++++------------ .../roomprofile/RoomProfileFragment.kt | 17 +---- .../features/settings/VectorPreferences.kt | 4 -- ...rSettingsNotificationPreferenceFragment.kt | 14 +--- .../res/xml/vector_settings_notifications.xml | 8 --- 8 files changed, 36 insertions(+), 104 deletions(-) diff --git a/vector/build.gradle b/vector/build.gradle index d29f36c877..9664d85bf2 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -141,7 +141,6 @@ android { resValue "string", "build_number", "\"${buildNumber}\"" buildConfigField "im.vector.app.features.VectorFeatures.LoginVersion", "LOGIN_VERSION", "im.vector.app.features.VectorFeatures.LoginVersion.V1" - buildConfigField "im.vector.app.features.VectorFeatures.NotificationSettingsVersion", "NOTIFICATION_SETTINGS_VERSION", "im.vector.app.features.VectorFeatures.NotificationSettingsVersion.V2" buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping" diff --git a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt index 4dddc4c9cc..433a70b5e3 100644 --- a/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt +++ b/vector/src/androidTest/java/im/vector/app/ui/robot/settings/SettingsNotificationsRobot.kt @@ -18,29 +18,19 @@ package im.vector.app.ui.robot.settings import androidx.test.espresso.Espresso.pressBack import com.adevinta.android.barista.interaction.BaristaClickInteractions.clickOn -import im.vector.app.BuildConfig import im.vector.app.R import im.vector.app.espresso.tools.clickOnPreference -import im.vector.app.features.VectorFeatures class SettingsNotificationsRobot { fun crawl() { - when (BuildConfig.NOTIFICATION_SETTINGS_VERSION!!) { - VectorFeatures.NotificationSettingsVersion.V1 -> { - clickOn(R.string.settings_notification_advanced) - pressBack() - } - VectorFeatures.NotificationSettingsVersion.V2 -> { - clickOn(R.string.settings_notification_default) - pressBack() - clickOn(R.string.settings_notification_mentions_and_keywords) - // TODO Test adding a keyword? - pressBack() - clickOn(R.string.settings_notification_other) - pressBack() - } - } + clickOn(R.string.settings_notification_default) + pressBack() + clickOn(R.string.settings_notification_mentions_and_keywords) + // TODO Test adding a keyword? + pressBack() + clickOn(R.string.settings_notification_other) + pressBack() /* clickOn(R.string.settings_noisy_notifications_preferences) diff --git a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt index b40d2d02f2..e106f7f75f 100644 --- a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt +++ b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt @@ -21,7 +21,6 @@ import im.vector.app.BuildConfig interface VectorFeatures { fun loginVersion(): LoginVersion - fun notificationSettingsVersion(): NotificationSettingsVersion enum class LoginVersion { V1, @@ -36,5 +35,4 @@ interface VectorFeatures { class DefaultVectorFeatures : VectorFeatures { override fun loginVersion(): VectorFeatures.LoginVersion = BuildConfig.LOGIN_VERSION - override fun notificationSettingsVersion(): VectorFeatures.NotificationSettingsVersion = BuildConfig.NOTIFICATION_SETTINGS_VERSION } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt index a2d10cf818..433fca5430 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt @@ -24,7 +24,6 @@ import im.vector.app.core.epoxy.bottomsheet.bottomSheetRoomPreviewItem import im.vector.app.core.epoxy.profiles.notifications.radioButtonItem import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider -import im.vector.app.features.VectorFeatures import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.notifications.notificationOptions import im.vector.app.features.roomprofile.notifications.notificationStateMapped @@ -39,7 +38,6 @@ class RoomListQuickActionsEpoxyController @Inject constructor( private val avatarRenderer: AvatarRenderer, private val colorProvider: ColorProvider, private val stringProvider: StringProvider, - private val features: VectorFeatures ) : TypedEpoxyController() { var listener: Listener? = null @@ -48,54 +46,38 @@ class RoomListQuickActionsEpoxyController @Inject constructor( val notificationViewState = state.notificationSettingsViewState val roomSummary = notificationViewState.roomSummary() ?: return val host = this - val isV2 = features.notificationSettingsVersion() == VectorFeatures.NotificationSettingsVersion.V2 - // V2 always shows full details as we no longer display the sheet from RoomProfile > Notifications - val showFull = state.roomListActionsArgs.mode == RoomListActionsArgs.Mode.FULL || isV2 - - if (showFull) { - // Preview, favorite, settings - bottomSheetRoomPreviewItem { - id("room_preview") - avatarRenderer(host.avatarRenderer) - matrixItem(roomSummary.toMatrixItem()) - stringProvider(host.stringProvider) - colorProvider(host.colorProvider) - izLowPriority(roomSummary.isLowPriority) - izFavorite(roomSummary.isFavorite) - settingsClickListener { host.listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Settings(roomSummary.roomId)) } - favoriteClickListener { host.listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Favorite(roomSummary.roomId)) } - lowPriorityClickListener { host.listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.LowPriority(roomSummary.roomId)) } - } - - // Notifications - bottomSheetDividerItem { - id("notifications_separator") - } + // Preview, favorite, settings + bottomSheetRoomPreviewItem { + id("room_preview") + avatarRenderer(host.avatarRenderer) + matrixItem(roomSummary.toMatrixItem()) + stringProvider(host.stringProvider) + colorProvider(host.colorProvider) + izLowPriority(roomSummary.isLowPriority) + izFavorite(roomSummary.isFavorite) + settingsClickListener { host.listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Settings(roomSummary.roomId)) } + favoriteClickListener { host.listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Favorite(roomSummary.roomId)) } + lowPriorityClickListener { host.listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.LowPriority(roomSummary.roomId)) } } - if (isV2) { - notificationViewState.notificationOptions.forEach { notificationState -> - val title = titleForNotificationState(notificationState) - radioButtonItem { - id(notificationState.name) - titleRes(title) - selected(notificationViewState.notificationStateMapped() == notificationState) - listener { - host.listener?.didSelectRoomNotificationState(notificationState) - } + // Notifications + bottomSheetDividerItem { + id("notifications_separator") + } + + notificationViewState.notificationOptions.forEach { notificationState -> + val title = titleForNotificationState(notificationState) + radioButtonItem { + id(notificationState.name) + titleRes(title) + selected(notificationViewState.notificationStateMapped() == notificationState) + listener { + host.listener?.didSelectRoomNotificationState(notificationState) } } - } else { - val selectedRoomState = notificationViewState.notificationState() - RoomListQuickActionsSharedAction.NotificationsAllNoisy(roomSummary.roomId).toBottomSheetItem(0, selectedRoomState) - RoomListQuickActionsSharedAction.NotificationsAll(roomSummary.roomId).toBottomSheetItem(1, selectedRoomState) - RoomListQuickActionsSharedAction.NotificationsMentionsOnly(roomSummary.roomId).toBottomSheetItem(2, selectedRoomState) - RoomListQuickActionsSharedAction.NotificationsMute(roomSummary.roomId).toBottomSheetItem(3, selectedRoomState) } - if (showFull) { - RoomListQuickActionsSharedAction.Leave(roomSummary.roomId, showIcon = !isV2).toBottomSheetItem(5) - } + RoomListQuickActionsSharedAction.Leave(roomSummary.roomId, showIcon = !true).toBottomSheetItem(5) } @StringRes diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt index 4dac4be489..35088b6e07 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt @@ -44,13 +44,10 @@ import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.startSharePlainTextIntent import im.vector.app.databinding.FragmentMatrixProfileBinding import im.vector.app.databinding.ViewStubRoomProfileHeaderBinding -import im.vector.app.features.VectorFeatures import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.RoomDetailPendingAction import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet -import im.vector.app.features.home.room.list.actions.RoomListActionsArgs -import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel import kotlinx.coroutines.flow.launchIn @@ -69,8 +66,7 @@ data class RoomProfileArgs( class RoomProfileFragment @Inject constructor( private val roomProfileController: RoomProfileController, private val avatarRenderer: AvatarRenderer, - private val roomDetailPendingActionStore: RoomDetailPendingActionStore, - private val features: VectorFeatures + private val roomDetailPendingActionStore: RoomDetailPendingActionStore ) : VectorBaseFragment(), RoomProfileController.Callback { @@ -259,16 +255,7 @@ class RoomProfileFragment @Inject constructor( } override fun onNotificationsClicked() { - when (features.notificationSettingsVersion()) { - VectorFeatures.NotificationSettingsVersion.V1 -> { - RoomListQuickActionsBottomSheet - .newInstance(roomProfileArgs.roomId, RoomListActionsArgs.Mode.NOTIFICATIONS) - .show(childFragmentManager, "ROOM_PROFILE_NOTIFICATIONS") - } - VectorFeatures.NotificationSettingsVersion.V2 -> { - roomProfileSharedActionViewModel.post(RoomProfileSharedAction.OpenRoomNotificationSettings) - } - } + roomProfileSharedActionViewModel.post(RoomProfileSharedAction.OpenRoomNotificationSettings) } override fun onUploadsClicked() { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 6eb8d7c195..47c9af3168 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -46,10 +46,6 @@ class VectorPreferences @Inject constructor(private val context: Context) { const val SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY = "SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY" const val SETTINGS_DISCOVERY_PREFERENCE_KEY = "SETTINGS_DISCOVERY_PREFERENCE_KEY" - const val SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY" - const val SETTINGS_NOTIFICATION_DEFAULT_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_DEFAULT_PREFERENCE_KEY" - const val SETTINGS_NOTIFICATION_KEYWORD_AND_MENTIONS_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_KEYWORD_AND_MENTIONS_PREFERENCE_KEY" - const val SETTINGS_NOTIFICATION_OTHER_PREFERENCE_KEY = "SETTINGS_NOTIFICATION_OTHER_PREFERENCE_KEY" const val SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY" const val SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY" const val SETTINGS_COPYRIGHT_PREFERENCE_KEY = "SETTINGS_COPYRIGHT_PREFERENCE_KEY" diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt index 3004d30913..4199bd1753 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt @@ -40,7 +40,6 @@ import im.vector.app.core.pushers.PushersManager import im.vector.app.core.services.GuardServiceStarter import im.vector.app.core.utils.isIgnoringBatteryOptimizations import im.vector.app.core.utils.requestDisablingBatteryOptimization -import im.vector.app.features.VectorFeatures import im.vector.app.features.notifications.NotificationUtils import im.vector.app.features.settings.BackgroundSyncMode import im.vector.app.features.settings.BackgroundSyncModeChooserDialog @@ -64,8 +63,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( private val pushManager: PushersManager, private val activeSessionHolder: ActiveSessionHolder, private val vectorPreferences: VectorPreferences, - private val guardServiceStarter: GuardServiceStarter, - private val features: VectorFeatures + private val guardServiceStarter: GuardServiceStarter ) : VectorSettingsBaseFragment(), BackgroundSyncModeChooserDialog.InteractionListener { @@ -147,7 +145,6 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( refreshBackgroundSyncPrefs() handleSystemPreference() - handleVersionedSettings() } private fun bindEmailNotifications() { @@ -312,15 +309,6 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( } } - private fun handleVersionedSettings() { - val isNotificationSettingsV2Enabled = features.notificationSettingsVersion() == VectorFeatures.NotificationSettingsVersion.V2 - - findPreference(VectorPreferences.SETTINGS_NOTIFICATION_ADVANCED_PREFERENCE_KEY)?.isVisible = !isNotificationSettingsV2Enabled - findPreference(VectorPreferences.SETTINGS_NOTIFICATION_DEFAULT_PREFERENCE_KEY)?.isVisible = isNotificationSettingsV2Enabled - findPreference(VectorPreferences.SETTINGS_NOTIFICATION_KEYWORD_AND_MENTIONS_PREFERENCE_KEY)?.isVisible = isNotificationSettingsV2Enabled - findPreference(VectorPreferences.SETTINGS_NOTIFICATION_OTHER_PREFERENCE_KEY)?.isVisible = isNotificationSettingsV2Enabled - } - override fun onResume() { super.onResume() activeSessionHolder.getSafeActiveSession()?.refreshPushers() diff --git a/vector/src/main/res/xml/vector_settings_notifications.xml b/vector/src/main/res/xml/vector_settings_notifications.xml index 154e7cca0d..66ac93a4f9 100644 --- a/vector/src/main/res/xml/vector_settings_notifications.xml +++ b/vector/src/main/res/xml/vector_settings_notifications.xml @@ -20,14 +20,6 @@ - - Date: Mon, 6 Dec 2021 10:14:20 +0000 Subject: [PATCH 02/37] removing now longer needed Mode argument --- .../features/home/room/list/RoomListFragment.kt | 3 +-- .../actions/RoomListQuickActionsBottomSheet.kt | 15 ++++----------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt index 6543cc8795..f67abfbc88 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt @@ -44,7 +44,6 @@ import im.vector.app.core.resources.UserPreferencesProvider import im.vector.app.databinding.FragmentRoomListBinding import im.vector.app.features.home.RoomListDisplayMode import im.vector.app.features.home.room.filtered.FilteredRoomFooterItem -import im.vector.app.features.home.room.list.actions.RoomListActionsArgs import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel @@ -476,7 +475,7 @@ class RoomListFragment @Inject constructor( footerController.setData(it) } RoomListQuickActionsBottomSheet - .newInstance(room.roomId, RoomListActionsArgs.Mode.FULL) + .newInstance(room.roomId) .show(childFragmentManager, "ROOM_LIST_QUICK_ACTIONS") return true } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt index 014ce14c95..5d8cda94ae 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsBottomSheet.kt @@ -43,15 +43,8 @@ import javax.inject.Inject @Parcelize data class RoomListActionsArgs( - val roomId: String, - val mode: Mode -) : Parcelable { - - enum class Mode { - FULL, - NOTIFICATIONS - } -} + val roomId: String +) : Parcelable /** * Bottom sheet fragment that shows room information with list of contextual actions @@ -124,9 +117,9 @@ class RoomListQuickActionsBottomSheet : } companion object { - fun newInstance(roomId: String, mode: RoomListActionsArgs.Mode): RoomListQuickActionsBottomSheet { + fun newInstance(roomId: String): RoomListQuickActionsBottomSheet { return RoomListQuickActionsBottomSheet().apply { - setArguments(RoomListActionsArgs(roomId, mode)) + setArguments(RoomListActionsArgs(roomId)) } } } From 952ceced05c3f055806f326b51827503bec94314 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 1 Dec 2021 17:17:11 +0000 Subject: [PATCH 03/37] updating url preview to match new designs --- .../drawable/ic_close_with_circular_bg.xml | 23 +++ .../src/main/res/layout/view_url_preview.xml | 142 +++++++++--------- 2 files changed, 92 insertions(+), 73 deletions(-) create mode 100644 vector/src/main/res/drawable/ic_close_with_circular_bg.xml diff --git a/vector/src/main/res/drawable/ic_close_with_circular_bg.xml b/vector/src/main/res/drawable/ic_close_with_circular_bg.xml new file mode 100644 index 0000000000..a38416674a --- /dev/null +++ b/vector/src/main/res/drawable/ic_close_with_circular_bg.xml @@ -0,0 +1,23 @@ + + + + + diff --git a/vector/src/main/res/layout/view_url_preview.xml b/vector/src/main/res/layout/view_url_preview.xml index 45c35279c8..772bd7d48b 100644 --- a/vector/src/main/res/layout/view_url_preview.xml +++ b/vector/src/main/res/layout/view_url_preview.xml @@ -7,83 +7,79 @@ android:layout_height="wrap_content" tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> - + - + - + - + - + - + + + + + + + \ No newline at end of file From 6a749f106da71bdb7b7fa17355f264701e0af101 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 1 Dec 2021 17:27:59 +0000 Subject: [PATCH 04/37] adding changelog entry --- changelog.d/4278.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4278.feature diff --git a/changelog.d/4278.feature b/changelog.d/4278.feature new file mode 100644 index 0000000000..fe82755186 --- /dev/null +++ b/changelog.d/4278.feature @@ -0,0 +1 @@ +Updates URL previews to match latest designs \ No newline at end of file From 0150d830d4a28d90d708ef9a35103cbe92e8aada Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 2 Dec 2021 09:46:36 +0000 Subject: [PATCH 05/37] flattening preview url view layout with custom view to reduce view hierarchy --- .../ui-styles/src/main/res/values/dimens.xml | 3 + .../detail/timeline/url/PreviewUrlView.kt | 8 +- .../src/main/res/layout/view_url_preview.xml | 136 +++++++++--------- 3 files changed, 73 insertions(+), 74 deletions(-) diff --git a/library/ui-styles/src/main/res/values/dimens.xml b/library/ui-styles/src/main/res/values/dimens.xml index 519920786c..864f3d3d7f 100644 --- a/library/ui-styles/src/main/res/values/dimens.xml +++ b/library/ui-styles/src/main/res/values/dimens.xml @@ -39,4 +39,7 @@ 320dp + + + 8dp \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt index 3e08ce5589..1a81362618 100755 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt @@ -19,13 +19,14 @@ package im.vector.app.features.home.room.detail.timeline.url import android.content.Context import android.util.AttributeSet import android.view.View -import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible +import com.google.android.material.card.MaterialCardView import im.vector.app.R import im.vector.app.core.extensions.setTextOrHide import im.vector.app.databinding.ViewUrlPreviewBinding import im.vector.app.features.home.room.detail.timeline.TimelineEventController import im.vector.app.features.media.ImageContentRenderer +import im.vector.app.features.themes.ThemeUtils import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.media.PreviewUrlData @@ -36,7 +37,7 @@ class PreviewUrlView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : ConstraintLayout(context, attrs, defStyleAttr), View.OnClickListener { +) : MaterialCardView(context, attrs, defStyleAttr), View.OnClickListener { private lateinit var views: ViewUrlPreviewBinding @@ -44,6 +45,9 @@ class PreviewUrlView @JvmOverloads constructor( init { setupView() + radius = resources.getDimensionPixelSize(R.dimen.preview_url_view_corner_radius).toFloat() + cardElevation = 0f + setCardBackgroundColor(ThemeUtils.getColor(context, R.attr.vctr_system)) } private var state: PreviewUrlUiState = PreviewUrlUiState.Unknown diff --git a/vector/src/main/res/layout/view_url_preview.xml b/vector/src/main/res/layout/view_url_preview.xml index 772bd7d48b..f40316b77b 100644 --- a/vector/src/main/res/layout/view_url_preview.xml +++ b/vector/src/main/res/layout/view_url_preview.xml @@ -1,85 +1,77 @@ + tools:parentTag="com.google.android.material.card.MaterialCardView"> - - - - - - - - - - - - - + android:layout_height="wrap_content" + android:orientation="vertical"> + android:id="@+id/url_preview_image" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:adjustViewBounds="true" + android:importantForAccessibility="no" + android:scaleType="fitXY" + tools:src="@tools:sample/backgrounds/scenic" /> - + + + + + + + + + \ No newline at end of file From f3f28f3989c4b946213b1c9f868e2a2a0191bbae Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 2 Dec 2021 10:09:31 +0000 Subject: [PATCH 06/37] limiting title to avoid overlapping with close icon --- vector/src/main/res/layout/view_url_preview.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/layout/view_url_preview.xml b/vector/src/main/res/layout/view_url_preview.xml index f40316b77b..5636068fdb 100644 --- a/vector/src/main/res/layout/view_url_preview.xml +++ b/vector/src/main/res/layout/view_url_preview.xml @@ -41,7 +41,7 @@ android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="4dp" - android:layout_marginEnd="8dp" + android:layout_marginEnd="@dimen/layout_touch_size" android:ellipsize="end" android:maxLines="2" android:textColor="?vctr_content_primary" From 170f34639bdcc758388e698fdc03add2c8ba2ca0 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 2 Dec 2021 10:19:14 +0000 Subject: [PATCH 07/37] using themed colours for the close button --- vector/src/main/res/drawable/ic_close_with_circular_bg.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vector/src/main/res/drawable/ic_close_with_circular_bg.xml b/vector/src/main/res/drawable/ic_close_with_circular_bg.xml index a38416674a..5e54b638a0 100644 --- a/vector/src/main/res/drawable/ic_close_with_circular_bg.xml +++ b/vector/src/main/res/drawable/ic_close_with_circular_bg.xml @@ -5,19 +5,19 @@ android:viewportHeight="24"> From 9094173b52ddd6728e4d39008330826b6449520f Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 2 Dec 2021 11:01:03 +0000 Subject: [PATCH 08/37] matching iOS max line rules for the preview description --- .../home/room/detail/timeline/url/PreviewUrlView.kt | 6 ++++++ vector/src/main/res/layout/view_url_preview.xml | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt index 1a81362618..631f00819c 100755 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt @@ -125,9 +125,15 @@ class PreviewUrlView @JvmOverloads constructor( private fun renderData(previewUrlData: PreviewUrlData, imageContentRenderer: ImageContentRenderer) { isVisible = true + views.urlPreviewTitle.setTextOrHide(previewUrlData.title) views.urlPreviewImage.isVisible = previewUrlData.mxcUrl?.let { imageContentRenderer.render(it, views.urlPreviewImage) }.orFalse() views.urlPreviewDescription.setTextOrHide(previewUrlData.description) + views.urlPreviewDescription.maxLines = when { + previewUrlData.mxcUrl != null -> 2 + previewUrlData.title != null -> 3 + else -> 5 + } views.urlPreviewSite.setTextOrHide(previewUrlData.siteName.takeIf { it != previewUrlData.title }) } diff --git a/vector/src/main/res/layout/view_url_preview.xml b/vector/src/main/res/layout/view_url_preview.xml index 5636068fdb..530a8da476 100644 --- a/vector/src/main/res/layout/view_url_preview.xml +++ b/vector/src/main/res/layout/view_url_preview.xml @@ -58,7 +58,6 @@ android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:ellipsize="end" - android:maxLines="2" android:textColor="?vctr_content_secondary" tools:text="The British perfumer says removing actor John Boyega from his own advert was “utterly despicable”." /> From 5cfebb764c3b93b75c17f6684a31f99280028b59 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 2 Dec 2021 11:46:26 +0000 Subject: [PATCH 09/37] capping the preview image url based on the height - stops large screens eg tablets from attempting to fill the screen --- .../res/layout/item_timeline_event_text_message_stub.xml | 2 +- vector/src/main/res/layout/view_url_preview.xml | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/vector/src/main/res/layout/item_timeline_event_text_message_stub.xml b/vector/src/main/res/layout/item_timeline_event_text_message_stub.xml index 39df45989c..8d4bfcf14e 100644 --- a/vector/src/main/res/layout/item_timeline_event_text_message_stub.xml +++ b/vector/src/main/res/layout/item_timeline_event_text_message_stub.xml @@ -16,7 +16,7 @@ From 3ff3507fa1a9627e13a39a6ce5edfb4e572470e5 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Thu, 2 Dec 2021 11:50:28 +0000 Subject: [PATCH 10/37] forcing the send spacing to always be taking into account - ensures all message lengths are consistent --- .../vector/app/core/ui/views/SendStateImageView.kt | 12 ++++++------ .../src/main/res/layout/item_timeline_event_base.xml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt index cb1d08d2e5..3d710e2b24 100644 --- a/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt +++ b/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt @@ -20,7 +20,7 @@ import android.content.Context import android.content.res.ColorStateList import android.util.AttributeSet import androidx.appcompat.widget.AppCompatImageView -import androidx.core.view.isVisible +import androidx.core.view.isInvisible import im.vector.app.R import im.vector.app.features.home.room.detail.timeline.item.SendStateDecoration import im.vector.app.features.themes.ThemeUtils @@ -38,28 +38,28 @@ class SendStateImageView @JvmOverloads constructor( } fun render(sendState: SendStateDecoration) { - isVisible = when (sendState) { + isInvisible = when (sendState) { SendStateDecoration.SENDING_NON_MEDIA -> { setImageResource(R.drawable.ic_sending_message) imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.vctr_content_tertiary)) contentDescription = context.getString(R.string.event_status_a11y_sending) - true + false } SendStateDecoration.SENT -> { setImageResource(R.drawable.ic_message_sent) imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(context, R.attr.vctr_content_tertiary)) contentDescription = context.getString(R.string.event_status_a11y_sent) - true + false } SendStateDecoration.FAILED -> { setImageResource(R.drawable.ic_sending_message_failed) imageTintList = null contentDescription = context.getString(R.string.event_status_a11y_failed) - true + false } SendStateDecoration.SENDING_MEDIA, SendStateDecoration.NONE -> { - false + true } } } diff --git a/vector/src/main/res/layout/item_timeline_event_base.xml b/vector/src/main/res/layout/item_timeline_event_base.xml index ed6e501d49..d85dc5cd0d 100644 --- a/vector/src/main/res/layout/item_timeline_event_base.xml +++ b/vector/src/main/res/layout/item_timeline_event_base.xml @@ -152,7 +152,7 @@ android:layout_marginBottom="4dp" android:contentDescription="@string/event_status_a11y_sending" android:src="@drawable/ic_sending_message" - android:visibility="gone" + android:visibility="invisible" tools:tint="?vctr_content_tertiary" tools:visibility="visible" /> From 9ed72fd1eb37b4e5df0489f3de8c038c34e49ede Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 7 Dec 2021 12:58:46 +0000 Subject: [PATCH 11/37] removing manual end alignment for voice messages as send status gutter is now always present --- .../home/room/detail/timeline/item/BaseEventItem.kt | 10 ---------- .../home/room/detail/timeline/item/MessageVoiceItem.kt | 4 ---- 2 files changed, 14 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/BaseEventItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/BaseEventItem.kt index 6aeb1519a9..5dfbf5d8f6 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/BaseEventItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/BaseEventItem.kt @@ -43,22 +43,12 @@ abstract class BaseEventItem : VectorEpoxyModel @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) lateinit var dimensionConverter: DimensionConverter - protected var ignoreSendStatusVisibility = false - @CallSuper override fun bind(holder: H) { super.bind(holder) holder.leftGuideline.updateLayoutParams { this.marginStart = leftGuideline } - // Ignore visibility of the send status icon? - holder.contentContainer.updateLayoutParams { - if (ignoreSendStatusVisibility) { - addRule(RelativeLayout.ALIGN_PARENT_END) - } else { - removeRule(RelativeLayout.ALIGN_PARENT_END) - } - } holder.checkableBackground.isChecked = highlighted } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt index fb7d0cabd5..f006c2aa35 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt @@ -33,10 +33,6 @@ import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlayb @EpoxyModelClass(layout = R.layout.item_timeline_event_base) abstract class MessageVoiceItem : AbsMessageItem() { - init { - ignoreSendStatusVisibility = true - } - @EpoxyAttribute var mxcUrl: String = "" From 23bc867b95d7f96e3dc551a2a5374bcb7ba1cfb7 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 7 Dec 2021 13:47:29 +0000 Subject: [PATCH 12/37] removing manual send status spacing - it's no longer needed as the send status is always present (but invisible) --- vector/src/main/res/layout/item_timeline_event_base.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/vector/src/main/res/layout/item_timeline_event_base.xml b/vector/src/main/res/layout/item_timeline_event_base.xml index d85dc5cd0d..6d778e85a4 100644 --- a/vector/src/main/res/layout/item_timeline_event_base.xml +++ b/vector/src/main/res/layout/item_timeline_event_base.xml @@ -115,27 +115,23 @@ android:id="@+id/messageContentRedactedStub" style="@style/TimelineContentStubBaseParams" android:layout_height="wrap_content" - android:layout_marginEnd="56dp" android:layout="@layout/item_timeline_event_redacted_stub" /> From 7e6a5f944feea75d377dcfc497d153315d4edb12 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 7 Dec 2021 15:14:39 +0000 Subject: [PATCH 13/37] adding a consistent padding to allow message types to avoid touching the side gutter --- vector/src/main/res/layout/item_timeline_event_base.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/vector/src/main/res/layout/item_timeline_event_base.xml b/vector/src/main/res/layout/item_timeline_event_base.xml index 6d778e85a4..6d3d3e8cd5 100644 --- a/vector/src/main/res/layout/item_timeline_event_base.xml +++ b/vector/src/main/res/layout/item_timeline_event_base.xml @@ -80,6 +80,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/messageMemberNameView" + android:layout_marginEnd="8dp" android:layout_toStartOf="@id/messageSendStateImageView" android:layout_toEndOf="@id/messageStartGuideline" android:addStatesFromChildren="true"> From 96295f61028934650dc3e546bdd6ccb73d377ff8 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 7 Dec 2021 10:42:02 +0000 Subject: [PATCH 14/37] removing no longer possible branches --- .../RoomListQuickActionsEpoxyController.kt | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt index 433fca5430..b343013408 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt @@ -77,7 +77,7 @@ class RoomListQuickActionsEpoxyController @Inject constructor( } } - RoomListQuickActionsSharedAction.Leave(roomSummary.roomId, showIcon = !true).toBottomSheetItem(5) + RoomListQuickActionsSharedAction.Leave(roomSummary.roomId, showIcon = !true).toBottomSheetItem() } @StringRes @@ -88,18 +88,11 @@ class RoomListQuickActionsEpoxyController @Inject constructor( else -> null } - private fun RoomListQuickActionsSharedAction.toBottomSheetItem(index: Int, roomNotificationState: RoomNotificationState? = null) { + private fun RoomListQuickActionsSharedAction.Leave.toBottomSheetItem() { val host = this@RoomListQuickActionsEpoxyController - val selected = when (this) { - is RoomListQuickActionsSharedAction.NotificationsAllNoisy -> roomNotificationState == RoomNotificationState.ALL_MESSAGES_NOISY - is RoomListQuickActionsSharedAction.NotificationsAll -> roomNotificationState == RoomNotificationState.ALL_MESSAGES - is RoomListQuickActionsSharedAction.NotificationsMentionsOnly -> roomNotificationState == RoomNotificationState.MENTIONS_ONLY - is RoomListQuickActionsSharedAction.NotificationsMute -> roomNotificationState == RoomNotificationState.MUTE - else -> false - } return bottomSheetActionItem { - id("action_$index") - selected(selected) + id("action_leave") + selected(false) if (iconResId != null) { iconRes(iconResId) } else { From d13a3eaad5ad8a8ed965c1e015a3501940341bc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Dec 2021 00:40:35 +0000 Subject: [PATCH 15/37] Bump mavericks from 2.4.0 to 2.5.0 Bumps `mavericks` from 2.4.0 to 2.5.0. Updates `mavericks` from 2.4.0 to 2.5.0 - [Release notes](https://github.com/airbnb/mavericks/releases) - [Changelog](https://github.com/airbnb/mavericks/blob/main/CHANGELOG.md) - [Commits](https://github.com/airbnb/mavericks/compare/2.4.0...2.5.0) Updates `mavericks-testing` from 2.4.0 to 2.5.0 - [Release notes](https://github.com/airbnb/mavericks/releases) - [Changelog](https://github.com/airbnb/mavericks/blob/main/CHANGELOG.md) - [Commits](https://github.com/airbnb/mavericks/compare/2.4.0...2.5.0) --- updated-dependencies: - dependency-name: com.airbnb.android:mavericks dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.airbnb.android:mavericks-testing dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index aa57546de0..5bf1a2f5ac 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -19,7 +19,7 @@ def moshi = "1.12.0" def lifecycle = "2.4.0" def flowBinding = "1.2.0" def epoxy = "4.6.2" -def mavericks = "2.4.0" +def mavericks = "2.5.0" def glide = "4.12.0" def bigImageViewer = "1.8.1" def jjwt = "0.11.2" From d2969766cab718eb40dec5f1e241499e8556bd8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Dec 2021 00:42:33 +0000 Subject: [PATCH 16/37] Bump libphonenumber from 8.12.38 to 8.12.39 Bumps [libphonenumber](https://github.com/google/libphonenumber) from 8.12.38 to 8.12.39. - [Release notes](https://github.com/google/libphonenumber/releases) - [Changelog](https://github.com/google/libphonenumber/blob/master/making-metadata-changes.md) - [Commits](https://github.com/google/libphonenumber/compare/v8.12.38...v8.12.39) --- updated-dependencies: - dependency-name: com.googlecode.libphonenumber:libphonenumber dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- matrix-sdk-android/build.gradle | 2 +- vector/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index cec5982658..55d4e232be 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -158,7 +158,7 @@ dependencies { implementation libs.apache.commonsImaging // Phone number https://github.com/google/libphonenumber - implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.38' + implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.39' testImplementation libs.tests.junit testImplementation 'org.robolectric:robolectric:4.7.3' diff --git a/vector/build.gradle b/vector/build.gradle index d29f36c877..a957e41d50 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -365,7 +365,7 @@ dependencies { implementation 'com.facebook.stetho:stetho:1.6.0' // Phone number https://github.com/google/libphonenumber - implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.38' + implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.39' // FlowBinding implementation libs.github.flowBinding From f675dcdefdd6bba1643fe57b6737e4e0db1cef66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Dec 2021 23:06:34 +0000 Subject: [PATCH 17/37] Bump realm-gradle-plugin from 10.8.1 to 10.9.0 Bumps [realm-gradle-plugin](https://github.com/realm/realm-java) from 10.8.1 to 10.9.0. - [Release notes](https://github.com/realm/realm-java/releases) - [Changelog](https://github.com/realm/realm-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/realm/realm-java/compare/v10.8.1...v10.9.0) --- updated-dependencies: - dependency-name: io.realm:realm-gradle-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- matrix-sdk-android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 55d4e232be..477f971e04 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -9,7 +9,7 @@ buildscript { mavenCentral() } dependencies { - classpath "io.realm:realm-gradle-plugin:10.8.1" + classpath "io.realm:realm-gradle-plugin:10.9.0" } } From f97753fdc16d1ae566dc484458cc2de55557f59b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Dec 2021 23:07:58 +0000 Subject: [PATCH 18/37] Bump gradle from 7.0.3 to 7.0.4 Bumps gradle from 7.0.3 to 7.0.4. --- updated-dependencies: - dependency-name: com.android.tools.build:gradle dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 5bf1a2f5ac..4a076a23bd 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,7 +7,7 @@ ext.versions = [ 'targetCompat' : JavaVersion.VERSION_11, ] -def gradle = "7.0.3" +def gradle = "7.0.4" // Ref: https://kotlinlang.org/releases.html def kotlin = "1.5.31" def kotlinCoroutines = "1.5.2" From ad1fbab956b74bccabb0c67a9976e219b32a2293 Mon Sep 17 00:00:00 2001 From: Ekaterina Gerasimova Date: Thu, 9 Dec 2021 09:09:12 +0000 Subject: [PATCH 19/37] Remove automation for old Delight board Covered by 4617.misc changelog entry --- .github/workflows/triage-move-labelled.yml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.github/workflows/triage-move-labelled.yml b/.github/workflows/triage-move-labelled.yml index 39f7a5de09..876491aa35 100644 --- a/.github/workflows/triage-move-labelled.yml +++ b/.github/workflows/triage-move-labelled.yml @@ -47,21 +47,6 @@ jobs: PROJECT_ID: "PN_kwDOAM0swc0sUA" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} - spaces_issues_to_old_board: - name: Spaces issues to old Delight project board - runs-on: ubuntu-latest - if: > - contains(github.event.issue.labels.*.name, 'A-Spaces') || - contains(github.event.issue.labels.*.name, 'A-Space-Settings') || - contains(github.event.issue.labels.*.name, 'A-Subspaces') - steps: - - uses: konradpabjan/move-labeled-or-milestoned-issue@219d384e03fa4b6460cd24f9f37d19eb033a4338 - with: - action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}" - project-url: "https://github.com/orgs/vector-im/projects/6" - column-name: "📥 Inbox" - label-name: "A-Spaces" - spaces_issues_to_new_board: name: Spaces issues to new Delight project board runs-on: ubuntu-latest From ed6e7a12adf17a9b7c87e29ed14d4ed686334c8e Mon Sep 17 00:00:00 2001 From: Ekaterina Gerasimova Date: Thu, 9 Dec 2021 09:15:32 +0000 Subject: [PATCH 20/37] Remove automation for new Delight board There's no Android developer on the Delight team right now, so it makes sense to redirect Spaces issues to the Android team. Covered by the 4617.misc changelog entry. --- .github/workflows/triage-move-labelled.yml | 48 +++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/triage-move-labelled.yml b/.github/workflows/triage-move-labelled.yml index 876491aa35..124233c5e3 100644 --- a/.github/workflows/triage-move-labelled.yml +++ b/.github/workflows/triage-move-labelled.yml @@ -47,30 +47,30 @@ jobs: PROJECT_ID: "PN_kwDOAM0swc0sUA" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} - spaces_issues_to_new_board: - name: Spaces issues to new Delight project board - runs-on: ubuntu-latest - if: > - contains(github.event.issue.labels.*.name, 'A-Spaces') || - contains(github.event.issue.labels.*.name, 'A-Space-Settings') || - contains(github.event.issue.labels.*.name, 'A-Subspaces') - steps: - - uses: octokit/graphql-action@v2.x - with: - headers: '{"GraphQL-Features": "projects_next_graphql"}' - query: | - mutation add_to_project($projectid:String!,$contentid:String!) { - addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { - projectNextItem { - id - } - } - } - projectid: ${{ env.PROJECT_ID }} - contentid: ${{ github.event.issue.node_id }} - env: - PROJECT_ID: "PN_kwDOAM0swc1HvQ" - GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} +# delight_issues_to_board: +# name: Spaces issues to new Delight project board +# runs-on: ubuntu-latest +# if: > +# contains(github.event.issue.labels.*.name, 'A-Spaces') || +# contains(github.event.issue.labels.*.name, 'A-Space-Settings') || +# contains(github.event.issue.labels.*.name, 'A-Subspaces') +# steps: +# - uses: octokit/graphql-action@v2.x +# with: +# headers: '{"GraphQL-Features": "projects_next_graphql"}' +# query: | +# mutation add_to_project($projectid:String!,$contentid:String!) { +# addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { +# projectNextItem { +# id +# } +# } +# } +# projectid: ${{ env.PROJECT_ID }} +# contentid: ${{ github.event.issue.node_id }} +# env: +# PROJECT_ID: "PN_kwDOAM0swc1HvQ" +# GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} move_voice-message_issues: name: A-Voice Messages to voice message board From 2c8cc3e16d3bc38aed2f54a6a8c08ab26a3bc539 Mon Sep 17 00:00:00 2001 From: daniellekirkwood <89144281+daniellekirkwood@users.noreply.github.com> Date: Thu, 9 Dec 2021 15:20:10 +0000 Subject: [PATCH 21/37] Add automation to move messages bubbles issues to the message bubbles board (#4667) * Add automation to move message bubbles issues to bubbles board * Add changelog entry Changelog entry to note new automation to move message bubbles issues to message bubbles board --- .github/workflows/triage-move-labelled.yml | 23 ++++++++++++++++++++++ changelog.d/4666.misc | 1 + 2 files changed, 24 insertions(+) create mode 100644 changelog.d/4666.misc diff --git a/.github/workflows/triage-move-labelled.yml b/.github/workflows/triage-move-labelled.yml index 124233c5e3..ef3a0ab688 100644 --- a/.github/workflows/triage-move-labelled.yml +++ b/.github/workflows/triage-move-labelled.yml @@ -117,3 +117,26 @@ jobs: env: PROJECT_ID: "PN_kwDOAM0swc0rRA" GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + + move_message_bubbles_issues: + name: A-Message-Bubbles to Message bubbles board + runs-on: ubuntu-latest + if: > + contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') + steps: + - uses: octokit/graphql-action@v2.x + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + mutation add_to_project($projectid:String!,$contentid:String!) { + addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { + projectNextItem { + id + } + } + } + projectid: ${{ env.PROJECT_ID }} + contentid: ${{ github.event.issue.node_id }} + env: + PROJECT_ID: "PN_kwDOAM0swc3m-g" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} diff --git a/changelog.d/4666.misc b/changelog.d/4666.misc new file mode 100644 index 0000000000..9401963de5 --- /dev/null +++ b/changelog.d/4666.misc @@ -0,0 +1 @@ +Add automation to move message bubbles issues to message bubbles board. From 8fefee9b02d43669d376e67458a938466342148c Mon Sep 17 00:00:00 2001 From: Ekaterina Gerasimova Date: Thu, 9 Dec 2021 22:49:46 +0000 Subject: [PATCH 22/37] Fix graphql warning in issue automation workflow Fixes #4671 --- .github/workflows/triage-move-labelled.yml | 10 +++++----- changelog.d/4671.misc | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 changelog.d/4671.misc diff --git a/.github/workflows/triage-move-labelled.yml b/.github/workflows/triage-move-labelled.yml index ef3a0ab688..67c4e9dbab 100644 --- a/.github/workflows/triage-move-labelled.yml +++ b/.github/workflows/triage-move-labelled.yml @@ -34,7 +34,7 @@ jobs: with: headers: '{"GraphQL-Features": "projects_next_graphql"}' query: | - mutation add_to_project($projectid:String!,$contentid:String!) { + mutation add_to_project($projectid:ID!,$contentid:ID!) { addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { projectNextItem { id @@ -59,7 +59,7 @@ jobs: # with: # headers: '{"GraphQL-Features": "projects_next_graphql"}' # query: | -# mutation add_to_project($projectid:String!,$contentid:String!) { +# mutation add_to_project($projectid:ID!,$contentid:ID!) { # addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { # projectNextItem { # id @@ -82,7 +82,7 @@ jobs: with: headers: '{"GraphQL-Features": "projects_next_graphql"}' query: | - mutation add_to_project($projectid:String!,$contentid:String!) { + mutation add_to_project($projectid:ID!,$contentid:ID!) { addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { projectNextItem { id @@ -105,7 +105,7 @@ jobs: with: headers: '{"GraphQL-Features": "projects_next_graphql"}' query: | - mutation add_to_project($projectid:String!,$contentid:String!) { + mutation add_to_project($projectid:ID!,$contentid:ID!) { addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { projectNextItem { id @@ -128,7 +128,7 @@ jobs: with: headers: '{"GraphQL-Features": "projects_next_graphql"}' query: | - mutation add_to_project($projectid:String!,$contentid:String!) { + mutation add_to_project($projectid:ID!,$contentid:ID!) { addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { projectNextItem { id diff --git a/changelog.d/4671.misc b/changelog.d/4671.misc new file mode 100644 index 0000000000..1d2282038e --- /dev/null +++ b/changelog.d/4671.misc @@ -0,0 +1 @@ +Fix graphql warning in issue workflow automation From f340a19c8e36fd4e22b428f6b95838e28f9bcd2d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 16:30:45 +0100 Subject: [PATCH 23/37] Fix issue in disconnect identity server confirmation dialog content --- .../app/features/discovery/DiscoverySettingsFragment.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt index 9c46fc2089..e1e1c9a537 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt @@ -167,10 +167,11 @@ class DiscoverySettingsFragment @Inject constructor( val pidList = state.emailList().orEmpty() + state.phoneNumbersList().orEmpty() val hasBoundIds = pidList.any { it.isShared() == SharedState.SHARED } + val serverUrl = state.identityServer()?.serverUrl.orEmpty() val message = if (hasBoundIds) { - getString(R.string.settings_discovery_disconnect_with_bound_pid, state.identityServer(), state.identityServer()) + getString(R.string.settings_discovery_disconnect_with_bound_pid, serverUrl, serverUrl) } else { - getString(R.string.disconnect_identity_server_dialog_content, state.identityServer()) + getString(R.string.disconnect_identity_server_dialog_content, serverUrl) } MaterialAlertDialogBuilder(requireActivity()) From d49a0dde6ec79e1782d4a667b78101d64082ee0d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 18:55:43 +0100 Subject: [PATCH 24/37] Legals: Add the screen (WIP) --- .../im/vector/app/core/di/FragmentModule.kt | 6 + .../app/core/di/MavericksViewModelModule.kt | 6 + .../app/features/discovery/Extensions.kt | 37 ++++-- .../discovery/IdentityServerWithTerms.kt | 1 + .../features/settings/legals/LegalsAction.kt | 23 ++++ .../settings/legals/LegalsController.kt | 118 ++++++++++++++++++ .../settings/legals/LegalsFragment.kt | 84 +++++++++++++ .../features/settings/legals/LegalsState.kt | 28 +++++ .../settings/legals/LegalsViewEvents.kt | 23 ++++ .../settings/legals/LegalsViewModel.kt | 91 ++++++++++++++ vector/src/main/res/values/strings.xml | 7 +- .../src/main/res/xml/vector_settings_root.xml | 5 + 12 files changed, 415 insertions(+), 14 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/settings/legals/LegalsAction.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/legals/LegalsState.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewEvents.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index b8d00fac5a..43bb505a5e 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -133,6 +133,7 @@ import im.vector.app.features.settings.devtools.KeyRequestsFragment import im.vector.app.features.settings.devtools.OutgoingKeyRequestListFragment import im.vector.app.features.settings.homeserver.HomeserverSettingsFragment import im.vector.app.features.settings.ignored.VectorSettingsIgnoredUsersFragment +import im.vector.app.features.settings.legals.LegalsFragment import im.vector.app.features.settings.locale.LocalePickerFragment import im.vector.app.features.settings.notifications.VectorSettingsAdvancedNotificationPreferenceFragment import im.vector.app.features.settings.notifications.VectorSettingsNotificationPreferenceFragment @@ -699,6 +700,11 @@ interface FragmentModule { @FragmentKey(DiscoverySettingsFragment::class) fun bindDiscoverySettingsFragment(fragment: DiscoverySettingsFragment): Fragment + @Binds + @IntoMap + @FragmentKey(LegalsFragment::class) + fun bindLegalsFragment(fragment: LegalsFragment): Fragment + @Binds @IntoMap @FragmentKey(ReviewTermsFragment::class) diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt index cac694e84e..37721ca9f9 100644 --- a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt @@ -85,6 +85,7 @@ import im.vector.app.features.settings.devtools.KeyRequestListViewModel import im.vector.app.features.settings.devtools.KeyRequestViewModel import im.vector.app.features.settings.homeserver.HomeserverSettingsViewModel import im.vector.app.features.settings.ignored.IgnoredUsersViewModel +import im.vector.app.features.settings.legals.LegalsViewModel import im.vector.app.features.settings.locale.LocalePickerViewModel import im.vector.app.features.settings.push.PushGatewaysViewModel import im.vector.app.features.settings.threepids.ThreePidsSettingsViewModel @@ -504,6 +505,11 @@ interface MavericksViewModelModule { @MavericksViewModelKey(DiscoverySettingsViewModel::class) fun discoverySettingsViewModelFactory(factory: DiscoverySettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *> + @Binds + @IntoMap + @MavericksViewModelKey(LegalsViewModel::class) + fun legalsViewModelFactory(factory: LegalsViewModel.Factory): MavericksAssistedViewModelFactory<*, *> + @Binds @IntoMap @MavericksViewModelKey(RoomDetailViewModel::class) diff --git a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt index bf6bd89938..119e544414 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt @@ -23,18 +23,29 @@ import org.matrix.android.sdk.api.session.terms.TermsService suspend fun Session.fetchIdentityServerWithTerms(userLanguage: String): IdentityServerWithTerms? { val identityServerUrl = identityService().getCurrentIdentityServerUrl() return identityServerUrl?.let { - val terms = getTerms(TermsService.ServiceType.IdentityService, identityServerUrl.ensureProtocol()) - .serverResponse - .getLocalizedTerms(userLanguage) - val policyUrls = terms.mapNotNull { - val name = it.localizedName ?: it.policyName - val url = it.localizedUrl - if (name == null || url == null) { - null - } else { - IdentityServerPolicy(name = name, url = url) - } - } - IdentityServerWithTerms(identityServerUrl, policyUrls) + fetchTerms(it, TermsService.ServiceType.IdentityService, userLanguage) } } + +suspend fun Session.fetchHomeserverWithTerms(userLanguage: String): IdentityServerWithTerms { + val homeserverUrl = sessionParams.homeServerUrl + return fetchTerms(homeserverUrl, TermsService.ServiceType.IdentityService, userLanguage) +} + +private suspend fun Session.fetchTerms(serviceUrl: String, + serviceType: TermsService.ServiceType, + userLanguage: String): IdentityServerWithTerms { + val terms = getTerms(serviceType, serviceUrl.ensureProtocol()) + .serverResponse + .getLocalizedTerms(userLanguage) + val policyUrls = terms.mapNotNull { + val name = it.localizedName ?: it.policyName + val url = it.localizedUrl + if (name == null || url == null) { + null + } else { + IdentityServerPolicy(name = name, url = url) + } + } + return IdentityServerWithTerms(serviceUrl, policyUrls) +} diff --git a/vector/src/main/java/im/vector/app/features/discovery/IdentityServerWithTerms.kt b/vector/src/main/java/im/vector/app/features/discovery/IdentityServerWithTerms.kt index 36bae0d0c5..0454de70d7 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/IdentityServerWithTerms.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/IdentityServerWithTerms.kt @@ -16,6 +16,7 @@ package im.vector.app.features.discovery +// TODO Rename for more generic name data class IdentityServerWithTerms( val serverUrl: String, val policies: List diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsAction.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsAction.kt new file mode 100644 index 0000000000..424c6bb78b --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsAction.kt @@ -0,0 +1,23 @@ +/* + * 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.settings.legals + +import im.vector.app.core.platform.VectorViewModelAction + +sealed interface LegalsAction : VectorViewModelAction { + object Refresh : LegalsAction +} diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt new file mode 100644 index 0000000000..29ad27b4a9 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt @@ -0,0 +1,118 @@ +/* + * 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.settings.legals + +import com.airbnb.epoxy.TypedEpoxyController +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.Uninitialized +import im.vector.app.R +import im.vector.app.core.epoxy.errorWithRetryItem +import im.vector.app.core.epoxy.loadingItem +import im.vector.app.core.error.ErrorFormatter +import im.vector.app.core.resources.StringProvider +import im.vector.app.features.discovery.IdentityServerPolicy +import im.vector.app.features.discovery.IdentityServerWithTerms +import im.vector.app.features.discovery.discoveryPolicyItem +import im.vector.app.features.discovery.settingsInfoItem +import im.vector.app.features.discovery.settingsSectionTitleItem +import javax.inject.Inject + +class LegalsController @Inject constructor( + private val stringProvider: StringProvider, + private val errorFormatter: ErrorFormatter +) : TypedEpoxyController() { + + var listener: Listener? = null + + override fun buildModels(data: LegalsState) { + buildAppSection() + buildHomeserverSection(data) + buildIdentityServerSection(data) + } + + private fun buildAppSection() { + settingsSectionTitleItem { + id("appTitle") + titleResId(R.string.legals_application_title) + } + + // TODO + } + + private fun buildHomeserverSection(data: LegalsState) { + settingsSectionTitleItem { + id("hsServerTitle") + titleResId(R.string.legals_home_server_title) + } + + buildPolicy("hs", data.homeServer) + } + + private fun buildIdentityServerSection(data: LegalsState) { + if (data.hasIdentityServer) { + settingsSectionTitleItem { + id("idServerTitle") + titleResId(R.string.legals_identity_server_title) + } + + buildPolicy("is", data.identityServer) + } + } + + private fun buildPolicy(tag: String, serverWithTerms: Async) { + val host = this + + when (serverWithTerms) { + Uninitialized, + is Loading -> loadingItem { + id("loading_$tag") + } + is Success -> { + val policies = serverWithTerms()?.policies + if (policies.isNullOrEmpty()) { + settingsInfoItem { + id("emptyPolicy") + helperText(host.stringProvider.getString(R.string.legals_no_policy_provided)) + } + } else { + policies.forEach { policy -> + discoveryPolicyItem { + id(policy.url) + name(policy.name) + url(policy.url) + clickListener { host.listener?.openPolicy(policy) } + } + } + } + } + is Fail -> { + errorWithRetryItem { + id("errorRetry_$tag") + text(host.errorFormatter.toHumanReadable(serverWithTerms.error)) + listener { host.listener?.onTapRetry() } + } + } + } + } + + interface Listener { + fun onTapRetry() + fun openPolicy(policy: IdentityServerPolicy) + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt new file mode 100644 index 0000000000..9aa7633e84 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt @@ -0,0 +1,84 @@ +/* + * 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.settings.legals + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity +import com.airbnb.mvrx.fragmentViewModel +import com.airbnb.mvrx.withState +import im.vector.app.R +import im.vector.app.core.extensions.cleanup +import im.vector.app.core.extensions.configureWith +import im.vector.app.core.extensions.exhaustive +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.utils.openUrlInChromeCustomTab +import im.vector.app.databinding.FragmentGenericRecyclerBinding +import im.vector.app.features.discovery.IdentityServerPolicy +import javax.inject.Inject + +class LegalsFragment @Inject constructor( + private val controller: LegalsController +) : VectorBaseFragment(), + LegalsController.Listener { + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentGenericRecyclerBinding { + return FragmentGenericRecyclerBinding.inflate(inflater, container, false) + } + + private val viewModel by fragmentViewModel(LegalsViewModel::class) + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + controller.listener = this + views.genericRecyclerView.configureWith(controller) + + viewModel.observeViewEvents { + when (it) { + is LegalsViewEvents.Failure -> { + displayErrorDialog(it.throwable) + } + }.exhaustive + } + } + + override fun onDestroyView() { + views.genericRecyclerView.cleanup() + controller.listener = null + super.onDestroyView() + } + + override fun invalidate() = withState(viewModel) { state -> + controller.setData(state) + } + + override fun onResume() { + super.onResume() + (activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.preference_root_legals) + viewModel.handle(LegalsAction.Refresh) + } + + override fun onTapRetry() { + viewModel.handle(LegalsAction.Refresh) + } + + override fun openPolicy(policy: IdentityServerPolicy) { + openUrlInChromeCustomTab(requireContext(), null, policy.url) + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsState.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsState.kt new file mode 100644 index 0000000000..fea9a06c11 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsState.kt @@ -0,0 +1,28 @@ +/* + * 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.settings.legals + +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.MavericksState +import com.airbnb.mvrx.Uninitialized +import im.vector.app.features.discovery.IdentityServerWithTerms + +data class LegalsState( + val homeServer: Async = Uninitialized, + val hasIdentityServer: Boolean = false, + val identityServer: Async = Uninitialized +) : MavericksState diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewEvents.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewEvents.kt new file mode 100644 index 0000000000..40741a4d62 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewEvents.kt @@ -0,0 +1,23 @@ +/* + * 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.settings.legals + +import im.vector.app.core.platform.VectorViewEvents + +sealed interface LegalsViewEvents : VectorViewEvents { + data class Failure(val throwable: Throwable) : LegalsViewEvents +} diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt new file mode 100644 index 0000000000..7947bcc570 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt @@ -0,0 +1,91 @@ +/* + * 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.settings.legals + +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Loading +import com.airbnb.mvrx.MavericksViewModelFactory +import com.airbnb.mvrx.Success +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import im.vector.app.R +import im.vector.app.core.di.MavericksAssistedViewModelFactory +import im.vector.app.core.di.hiltMavericksViewModelFactory +import im.vector.app.core.extensions.exhaustive +import im.vector.app.core.platform.VectorViewModel +import im.vector.app.core.resources.StringProvider +import im.vector.app.features.discovery.fetchHomeserverWithTerms +import im.vector.app.features.discovery.fetchIdentityServerWithTerms +import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.session.Session + +class LegalsViewModel @AssistedInject constructor( + @Assisted initialState: LegalsState, + private val session: Session, + private val stringProvider: StringProvider +) : VectorViewModel(initialState) { + + @AssistedFactory + interface Factory : MavericksAssistedViewModelFactory { + override fun create(initialState: LegalsState): LegalsViewModel + } + + companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() + + override fun handle(action: LegalsAction) { + when (action) { + LegalsAction.Refresh -> loadData() + }.exhaustive + } + + private fun loadData() = withState { state -> + loadHomeserver(state) + val url = session.identityService().getCurrentIdentityServerUrl() + if (url.isNullOrEmpty()) { + setState { copy(hasIdentityServer = false) } + } else { + setState { copy(hasIdentityServer = true) } + loadIdentityServer(state) + } + } + + private fun loadHomeserver(state: LegalsState) { + if (state.homeServer !is Success) { + setState { copy(homeServer = Loading()) } + viewModelScope.launch { + runCatching { session.fetchHomeserverWithTerms(stringProvider.getString(R.string.resources_language)) } + .fold( + onSuccess = { setState { copy(homeServer = Success(it)) } }, + onFailure = { setState { copy(homeServer = Fail(it)) } } + ) + } + } + } + + private fun loadIdentityServer(state: LegalsState) { + if (state.identityServer !is Success) { + setState { copy(identityServer = Loading()) } + viewModelScope.launch { + runCatching { session.fetchIdentityServerWithTerms(stringProvider.getString(R.string.resources_language)) } + .fold( + onSuccess = { setState { copy(identityServer = Success(it)) } }, + onFailure = { setState { copy(identityServer = Fail(it)) } } + ) + } + } + } +} diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index ddb731a5e0..e23cc02235 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1397,6 +1397,11 @@ Allow integrations Integration manager + ${app_name} policy + Your homeserver policy + Your identity server policy + This server does not provide any policy. + Integrations are disabled "Enable 'Allow integrations' in Settings to do this." @@ -2270,6 +2275,7 @@ Voice & Video Help & About + Legals Register token @@ -3566,7 +3572,6 @@ Manage rooms and spaces - Show all rooms in Home All rooms you’re in will be shown in Home. diff --git a/vector/src/main/res/xml/vector_settings_root.xml b/vector/src/main/res/xml/vector_settings_root.xml index 32e21b3391..712c1e7a4c 100644 --- a/vector/src/main/res/xml/vector_settings_root.xml +++ b/vector/src/main/res/xml/vector_settings_root.xml @@ -53,4 +53,9 @@ android:title="@string/preference_root_help_about" app:fragment="im.vector.app.features.settings.VectorSettingsHelpAboutFragment" /> + + \ No newline at end of file From 411fd31d4cb1051e854ec3f86a27a3f8eb4ca98f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 19:58:50 +0100 Subject: [PATCH 25/37] Legals: Trick to get the homeserver policy --- .../sdk/api/session/terms/TermsService.kt | 7 ++- .../session/terms/DefaultTermsService.kt | 53 +++++++++++++++++-- .../sdk/internal/session/terms/TermsAPI.kt | 10 ++++ .../app/features/discovery/Extensions.kt | 2 +- .../app/features/terms/ReviewTermsFragment.kt | 1 + 5 files changed, 66 insertions(+), 7 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt index 10ce0829d0..9898923003 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt @@ -19,7 +19,12 @@ package org.matrix.android.sdk.api.session.terms interface TermsService { enum class ServiceType { IntegrationManager, - IdentityService + IdentityService, + + /** + * It's only possible to use this value for [getTerms] + */ + Homeserver } suspend fun getTerms(serviceType: ServiceType, baseUrl: String): GetTermsResponse diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt index d40fd8d076..5cdef3db0a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt @@ -18,10 +18,13 @@ package org.matrix.android.sdk.internal.session.terms import dagger.Lazy import okhttp3.OkHttpClient +import org.matrix.android.sdk.api.auth.data.LoginFlowTypes +import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.terms.GetTermsResponse import org.matrix.android.sdk.api.session.terms.TermsService +import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate import org.matrix.android.sdk.internal.network.NetworkConstants import org.matrix.android.sdk.internal.network.RetrofitFactory @@ -48,11 +51,49 @@ internal class DefaultTermsService @Inject constructor( override suspend fun getTerms(serviceType: TermsService.ServiceType, baseUrl: String): GetTermsResponse { - val url = buildUrl(baseUrl, serviceType) - val termsResponse = executeRequest(null) { - termsAPI.getTerms("${url}terms") + return if (serviceType == TermsService.ServiceType.Homeserver) { + getHomeserverTerms(baseUrl) + } else { + val url = buildUrl(baseUrl, serviceType) + val termsResponse = executeRequest(null) { + termsAPI.getTerms("${url}terms") + } + GetTermsResponse(termsResponse, getAlreadyAcceptedTermUrlsFromAccountData()) } - return GetTermsResponse(termsResponse, getAlreadyAcceptedTermUrlsFromAccountData()) + } + + /** + * We use a trick here to get the homeserver T&C, we use the register API + */ + private suspend fun getHomeserverTerms(baseUrl: String): GetTermsResponse { + return try { + executeRequest(null) { + termsAPI.register(baseUrl + NetworkConstants.URI_API_PREFIX_PATH_R0 + "register") + } + // Return empty result if it succeed, but it should never happen + buildEmptyGetTermsResponse() + } catch (throwable: Throwable) { + @Suppress("UNCHECKED_CAST") + ((throwable.toRegistrationFlowResponse() + ?.params?.get(LoginFlowTypes.TERMS) as? JsonDict) + ?.get("policies") as? JsonDict) + ?.let { dict -> + GetTermsResponse( + serverResponse = TermsResponse( + policies = dict + ), + alreadyAcceptedTermUrls = emptySet() + ) + } + ?: buildEmptyGetTermsResponse() + } + } + + private fun buildEmptyGetTermsResponse(): GetTermsResponse { + return GetTermsResponse( + serverResponse = TermsResponse(), + alreadyAcceptedTermUrls = emptySet() + ) } override suspend fun agreeToTerms(serviceType: TermsService.ServiceType, @@ -91,7 +132,9 @@ internal class DefaultTermsService @Inject constructor( private fun buildUrl(baseUrl: String, serviceType: TermsService.ServiceType): String { val servicePath = when (serviceType) { TermsService.ServiceType.IntegrationManager -> NetworkConstants.URI_INTEGRATION_MANAGER_PATH - TermsService.ServiceType.IdentityService -> NetworkConstants.URI_IDENTITY_PATH_V2 + TermsService.ServiceType.IdentityService -> NetworkConstants.URI_IDENTITY_PATH_V2 + TermsService.ServiceType.Homeserver -> + error("You cannot use this API with parameter TermsService.ServiceType.Homeserver") } return "${baseUrl.ensureTrailingSlash()}$servicePath" } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt index 91d27030de..fb6aff5a9e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.internal.session.terms +import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.api.util.emptyJsonDict import org.matrix.android.sdk.internal.network.HttpHeaders import retrofit2.http.Body import retrofit2.http.GET @@ -37,4 +39,12 @@ internal interface TermsAPI { suspend fun agreeToTerms(@Url url: String, @Body params: AcceptTermsBody, @Header(HttpHeaders.Authorization) token: String) + + /** + * API to retrieve the terms for a homeserver. The API /terms does not exist yet, so retrieve the terms from the login flow. + * We do not care about the result (Credentials) + */ + @POST + suspend fun register(@Url url: String, + @Body body: JsonDict = emptyJsonDict) } diff --git a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt index 119e544414..08712f6e68 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt @@ -29,7 +29,7 @@ suspend fun Session.fetchIdentityServerWithTerms(userLanguage: String): Identity suspend fun Session.fetchHomeserverWithTerms(userLanguage: String): IdentityServerWithTerms { val homeserverUrl = sessionParams.homeServerUrl - return fetchTerms(homeserverUrl, TermsService.ServiceType.IdentityService, userLanguage) + return fetchTerms(homeserverUrl, TermsService.ServiceType.Homeserver, userLanguage) } private suspend fun Session.fetchTerms(serviceUrl: String, diff --git a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt index cb76e5b31f..6381854433 100644 --- a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt @@ -53,6 +53,7 @@ class ReviewTermsFragment @Inject constructor( termsController.description = when (reviewTermsViewModel.termsArgs.type) { TermsService.ServiceType.IdentityService -> getString(R.string.terms_description_for_identity_server) TermsService.ServiceType.IntegrationManager -> getString(R.string.terms_description_for_integration_manager) + TermsService.ServiceType.Homeserver -> error("Homeserver is not supported here") } termsController.listener = this From e1fc7cfaba947fb0178573cc0701eb8433144492 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 21:57:45 +0100 Subject: [PATCH 26/37] Rename some classes --- .../main/java/im/vector/app/core/utils/Dialogs.kt | 4 ++-- .../contactsbook/ContactsBookViewEvents.kt | 4 ++-- .../discovery/DiscoverySettingsController.kt | 2 +- .../discovery/DiscoverySettingsFragment.kt | 2 +- .../features/discovery/DiscoverySettingsState.kt | 2 +- .../discovery/DiscoverySettingsViewModel.kt | 6 +++--- .../im/vector/app/features/discovery/Extensions.kt | 10 +++++----- ...tityServerWithTerms.kt => ServerAndPolicies.kt} | 7 +++---- .../features/settings/legals/LegalsController.kt | 14 +++++++------- .../app/features/settings/legals/LegalsFragment.kt | 4 ++-- .../app/features/settings/legals/LegalsState.kt | 6 +++--- .../features/userdirectory/UserListViewEvents.kt | 4 ++-- 12 files changed, 32 insertions(+), 33 deletions(-) rename vector/src/main/java/im/vector/app/features/discovery/{IdentityServerWithTerms.kt => ServerAndPolicies.kt} (82%) diff --git a/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt b/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt index ad01546782..11b9a693da 100644 --- a/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt +++ b/vector/src/main/java/im/vector/app/core/utils/Dialogs.kt @@ -23,7 +23,7 @@ import android.webkit.WebViewClient import android.widget.TextView import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R -import im.vector.app.features.discovery.IdentityServerWithTerms +import im.vector.app.features.discovery.ServerAndPolicies import me.gujun.android.span.link import me.gujun.android.span.span @@ -45,7 +45,7 @@ fun Context.displayInWebView(url: String) { .show() } -fun Context.showIdentityServerConsentDialog(identityServerWithTerms: IdentityServerWithTerms?, +fun Context.showIdentityServerConsentDialog(identityServerWithTerms: ServerAndPolicies?, consentCallBack: (() -> Unit)) { // Build the message val content = span { diff --git a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewEvents.kt b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewEvents.kt index c7fd13a62c..cb8d137c05 100644 --- a/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/contactsbook/ContactsBookViewEvents.kt @@ -17,9 +17,9 @@ package im.vector.app.features.contactsbook import im.vector.app.core.platform.VectorViewEvents -import im.vector.app.features.discovery.IdentityServerWithTerms +import im.vector.app.features.discovery.ServerAndPolicies sealed class ContactsBookViewEvents : VectorViewEvents { data class Failure(val throwable: Throwable) : ContactsBookViewEvents() - data class OnPoliciesRetrieved(val identityServerWithTerms: IdentityServerWithTerms?) : ContactsBookViewEvents() + data class OnPoliciesRetrieved(val identityServerWithTerms: ServerAndPolicies?) : ContactsBookViewEvents() } diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt index 03c5d981cb..551b72dd82 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsController.kt @@ -433,6 +433,6 @@ class DiscoverySettingsController @Inject constructor( fun onTapUpdateUserConsent(newValue: Boolean) fun onTapRetryToRetrieveBindings() fun onPolicyUrlsExpandedStateToggled(newExpandedState: Boolean) - fun onPolicyTapped(policy: IdentityServerPolicy) + fun onPolicyTapped(policy: ServerPolicy) } } diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt index e1e1c9a537..2c37a19e7d 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsFragment.kt @@ -204,7 +204,7 @@ class DiscoverySettingsFragment @Inject constructor( viewModel.handle(DiscoverySettingsAction.SetPoliciesExpandState(expanded = newExpandedState)) } - override fun onPolicyTapped(policy: IdentityServerPolicy) { + override fun onPolicyTapped(policy: ServerPolicy) { openUrlInChromeCustomTab(requireContext(), null, policy.url) } diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsState.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsState.kt index da8603a437..e44caa4121 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsState.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsState.kt @@ -21,7 +21,7 @@ import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized data class DiscoverySettingsState( - val identityServer: Async = Uninitialized, + val identityServer: Async = Uninitialized, val emailList: Async> = Uninitialized, val phoneNumbersList: Async> = Uninitialized, // Can be true if terms are updated diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt index 4eb3fada28..19f233fe98 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoverySettingsViewModel.kt @@ -78,7 +78,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor( init { setState { copy( - identityServer = Success(identityService.getCurrentIdentityServerUrl()?.let { IdentityServerWithTerms(it, emptyList()) }), + identityServer = Success(identityService.getCurrentIdentityServerUrl()?.let { ServerAndPolicies(it, emptyList()) }), userConsent = identityService.getUserConsent() ) } @@ -151,7 +151,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor( val data = session.identityService().setNewIdentityServer(action.url) setState { copy( - identityServer = Success(IdentityServerWithTerms(data, emptyList())), + identityServer = Success(ServerAndPolicies(data, emptyList())), userConsent = false ) } @@ -401,7 +401,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor( } } - private suspend fun fetchIdentityServerWithTerms(): IdentityServerWithTerms? { + private suspend fun fetchIdentityServerWithTerms(): ServerAndPolicies? { return session.fetchIdentityServerWithTerms(stringProvider.getString(R.string.resources_language)) } } diff --git a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt index 08712f6e68..1360c9e95d 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt @@ -20,21 +20,21 @@ import im.vector.app.core.utils.ensureProtocol import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.terms.TermsService -suspend fun Session.fetchIdentityServerWithTerms(userLanguage: String): IdentityServerWithTerms? { +suspend fun Session.fetchIdentityServerWithTerms(userLanguage: String): ServerAndPolicies? { val identityServerUrl = identityService().getCurrentIdentityServerUrl() return identityServerUrl?.let { fetchTerms(it, TermsService.ServiceType.IdentityService, userLanguage) } } -suspend fun Session.fetchHomeserverWithTerms(userLanguage: String): IdentityServerWithTerms { +suspend fun Session.fetchHomeserverWithTerms(userLanguage: String): ServerAndPolicies { val homeserverUrl = sessionParams.homeServerUrl return fetchTerms(homeserverUrl, TermsService.ServiceType.Homeserver, userLanguage) } private suspend fun Session.fetchTerms(serviceUrl: String, serviceType: TermsService.ServiceType, - userLanguage: String): IdentityServerWithTerms { + userLanguage: String): ServerAndPolicies { val terms = getTerms(serviceType, serviceUrl.ensureProtocol()) .serverResponse .getLocalizedTerms(userLanguage) @@ -44,8 +44,8 @@ private suspend fun Session.fetchTerms(serviceUrl: String, if (name == null || url == null) { null } else { - IdentityServerPolicy(name = name, url = url) + ServerPolicy(name = name, url = url) } } - return IdentityServerWithTerms(serviceUrl, policyUrls) + return ServerAndPolicies(serviceUrl, policyUrls) } diff --git a/vector/src/main/java/im/vector/app/features/discovery/IdentityServerWithTerms.kt b/vector/src/main/java/im/vector/app/features/discovery/ServerAndPolicies.kt similarity index 82% rename from vector/src/main/java/im/vector/app/features/discovery/IdentityServerWithTerms.kt rename to vector/src/main/java/im/vector/app/features/discovery/ServerAndPolicies.kt index 0454de70d7..17f1b0cff9 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/IdentityServerWithTerms.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/ServerAndPolicies.kt @@ -16,13 +16,12 @@ package im.vector.app.features.discovery -// TODO Rename for more generic name -data class IdentityServerWithTerms( +data class ServerAndPolicies( val serverUrl: String, - val policies: List + val policies: List ) -data class IdentityServerPolicy( +data class ServerPolicy( val name: String, val url: String ) diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt index 29ad27b4a9..9bfbea6a42 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt @@ -26,8 +26,8 @@ import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider -import im.vector.app.features.discovery.IdentityServerPolicy -import im.vector.app.features.discovery.IdentityServerWithTerms +import im.vector.app.features.discovery.ServerPolicy +import im.vector.app.features.discovery.ServerAndPolicies import im.vector.app.features.discovery.discoveryPolicyItem import im.vector.app.features.discovery.settingsInfoItem import im.vector.app.features.discovery.settingsSectionTitleItem @@ -75,16 +75,16 @@ class LegalsController @Inject constructor( } } - private fun buildPolicy(tag: String, serverWithTerms: Async) { + private fun buildPolicy(tag: String, serverAndPolicies: Async) { val host = this - when (serverWithTerms) { + when (serverAndPolicies) { Uninitialized, is Loading -> loadingItem { id("loading_$tag") } is Success -> { - val policies = serverWithTerms()?.policies + val policies = serverAndPolicies()?.policies if (policies.isNullOrEmpty()) { settingsInfoItem { id("emptyPolicy") @@ -104,7 +104,7 @@ class LegalsController @Inject constructor( is Fail -> { errorWithRetryItem { id("errorRetry_$tag") - text(host.errorFormatter.toHumanReadable(serverWithTerms.error)) + text(host.errorFormatter.toHumanReadable(serverAndPolicies.error)) listener { host.listener?.onTapRetry() } } } @@ -113,6 +113,6 @@ class LegalsController @Inject constructor( interface Listener { fun onTapRetry() - fun openPolicy(policy: IdentityServerPolicy) + fun openPolicy(policy: ServerPolicy) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt index 9aa7633e84..c6b5c2bf1c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt @@ -29,7 +29,7 @@ import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.databinding.FragmentGenericRecyclerBinding -import im.vector.app.features.discovery.IdentityServerPolicy +import im.vector.app.features.discovery.ServerPolicy import javax.inject.Inject class LegalsFragment @Inject constructor( @@ -78,7 +78,7 @@ class LegalsFragment @Inject constructor( viewModel.handle(LegalsAction.Refresh) } - override fun openPolicy(policy: IdentityServerPolicy) { + override fun openPolicy(policy: ServerPolicy) { openUrlInChromeCustomTab(requireContext(), null, policy.url) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsState.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsState.kt index fea9a06c11..ad01f85338 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsState.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsState.kt @@ -19,10 +19,10 @@ package im.vector.app.features.settings.legals import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized -import im.vector.app.features.discovery.IdentityServerWithTerms +import im.vector.app.features.discovery.ServerAndPolicies data class LegalsState( - val homeServer: Async = Uninitialized, + val homeServer: Async = Uninitialized, val hasIdentityServer: Boolean = false, - val identityServer: Async = Uninitialized + val identityServer: Async = Uninitialized ) : MavericksState diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewEvents.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewEvents.kt index ffda0dd505..ef29e8015a 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewEvents.kt @@ -17,13 +17,13 @@ package im.vector.app.features.userdirectory import im.vector.app.core.platform.VectorViewEvents -import im.vector.app.features.discovery.IdentityServerWithTerms +import im.vector.app.features.discovery.ServerAndPolicies /** * Transient events for invite users to room screen */ sealed class UserListViewEvents : VectorViewEvents { data class Failure(val throwable: Throwable) : UserListViewEvents() - data class OnPoliciesRetrieved(val identityServerWithTerms: IdentityServerWithTerms?) : UserListViewEvents() + data class OnPoliciesRetrieved(val identityServerWithTerms: ServerAndPolicies?) : UserListViewEvents() data class OpenShareMatrixToLink(val link: String) : UserListViewEvents() } From e91e26ebfb5ee645acc2913909f26efd24aac9ba Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 22:17:51 +0100 Subject: [PATCH 27/37] Legals: Move the 3 element links to the new legal screen --- .../features/settings/VectorPreferences.kt | 3 -- .../VectorSettingsHelpAboutFragment.kt | 22 ----------- .../features/settings/VectorSettingsUrls.kt | 1 - .../features/settings/legals/ElementLegals.kt | 38 +++++++++++++++++++ .../settings/legals/LegalsController.kt | 33 +++++++++------- .../res/xml/vector_settings_help_about.xml | 12 ------ 6 files changed, 58 insertions(+), 51 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/settings/legals/ElementLegals.kt diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 47c9af3168..5bdd961277 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -42,13 +42,10 @@ class VectorPreferences @Inject constructor(private val context: Context) { const val SETTINGS_LOGGED_IN_PREFERENCE_KEY = "SETTINGS_LOGGED_IN_PREFERENCE_KEY" const val SETTINGS_HOME_SERVER_PREFERENCE_KEY = "SETTINGS_HOME_SERVER_PREFERENCE_KEY" const val SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY = "SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY" - const val SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY = "SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY" - const val SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY = "SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY" const val SETTINGS_DISCOVERY_PREFERENCE_KEY = "SETTINGS_DISCOVERY_PREFERENCE_KEY" const val SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY" const val SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY" - const val SETTINGS_COPYRIGHT_PREFERENCE_KEY = "SETTINGS_COPYRIGHT_PREFERENCE_KEY" const val SETTINGS_CLEAR_CACHE_PREFERENCE_KEY = "SETTINGS_CLEAR_CACHE_PREFERENCE_KEY" const val SETTINGS_CLEAR_MEDIA_CACHE_PREFERENCE_KEY = "SETTINGS_CLEAR_MEDIA_CACHE_PREFERENCE_KEY" const val SETTINGS_USER_SETTINGS_PREFERENCE_KEY = "SETTINGS_USER_SETTINGS_PREFERENCE_KEY" diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt index 03b7c16274..43325b6623 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt @@ -24,7 +24,6 @@ import im.vector.app.core.utils.FirstThrottler import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.displayInWebView import im.vector.app.core.utils.openAppSettingsPage -import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.features.version.VersionProvider import im.vector.app.openOssLicensesMenuActivity import org.matrix.android.sdk.api.Matrix @@ -77,27 +76,6 @@ class VectorSettingsHelpAboutFragment @Inject constructor( findPreference(VectorPreferences.SETTINGS_OLM_VERSION_PREFERENCE_KEY)!! .summary = session.cryptoService().getCryptoVersion(requireContext(), false) - // copyright - findPreference(VectorPreferences.SETTINGS_COPYRIGHT_PREFERENCE_KEY)!! - .onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrlInChromeCustomTab(requireContext(), null, VectorSettingsUrls.COPYRIGHT) - false - } - - // terms & conditions - findPreference(VectorPreferences.SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY)!! - .onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrlInChromeCustomTab(requireContext(), null, VectorSettingsUrls.TAC) - false - } - - // privacy policy - findPreference(VectorPreferences.SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY)!! - .onPreferenceClickListener = Preference.OnPreferenceClickListener { - openUrlInChromeCustomTab(requireContext(), null, VectorSettingsUrls.PRIVACY_POLICY) - false - } - // third party notice findPreference(VectorPreferences.SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY)!! .onPreferenceClickListener = Preference.OnPreferenceClickListener { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsUrls.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsUrls.kt index c5088aac6d..b3925c32dc 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsUrls.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsUrls.kt @@ -17,7 +17,6 @@ package im.vector.app.features.settings object VectorSettingsUrls { - const val COPYRIGHT = "https://element.io/copyright" const val TAC = "https://element.io/terms-of-service" const val PRIVACY_POLICY = "https://element.io/privacy" diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/ElementLegals.kt b/vector/src/main/java/im/vector/app/features/settings/legals/ElementLegals.kt new file mode 100644 index 0000000000..de59f36604 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/legals/ElementLegals.kt @@ -0,0 +1,38 @@ +/* + * 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.settings.legals + +import im.vector.app.R +import im.vector.app.core.resources.StringProvider +import im.vector.app.features.discovery.ServerPolicy +import im.vector.app.features.settings.VectorSettingsUrls +import javax.inject.Inject + +class ElementLegals @Inject constructor( + private val stringProvider: StringProvider +) { + /** + * Use ServerPolicy model + */ + fun getData(): List { + return listOf( + ServerPolicy(stringProvider.getString(R.string.settings_copyright), VectorSettingsUrls.COPYRIGHT), + ServerPolicy(stringProvider.getString(R.string.settings_app_term_conditions), VectorSettingsUrls.TAC), + ServerPolicy(stringProvider.getString(R.string.settings_privacy_policy), VectorSettingsUrls.PRIVACY_POLICY) + ) + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt index 9bfbea6a42..5470bb3ace 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt @@ -26,8 +26,8 @@ import im.vector.app.core.epoxy.errorWithRetryItem import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.resources.StringProvider -import im.vector.app.features.discovery.ServerPolicy import im.vector.app.features.discovery.ServerAndPolicies +import im.vector.app.features.discovery.ServerPolicy import im.vector.app.features.discovery.discoveryPolicyItem import im.vector.app.features.discovery.settingsInfoItem import im.vector.app.features.discovery.settingsSectionTitleItem @@ -35,6 +35,7 @@ import javax.inject.Inject class LegalsController @Inject constructor( private val stringProvider: StringProvider, + private val elementLegals: ElementLegals, private val errorFormatter: ErrorFormatter ) : TypedEpoxyController() { @@ -52,7 +53,7 @@ class LegalsController @Inject constructor( titleResId(R.string.legals_application_title) } - // TODO + buildPolicies("el", elementLegals.getData()) } private fun buildHomeserverSection(data: LegalsState) { @@ -61,7 +62,7 @@ class LegalsController @Inject constructor( titleResId(R.string.legals_home_server_title) } - buildPolicy("hs", data.homeServer) + buildPolicyAsync("hs", data.homeServer) } private fun buildIdentityServerSection(data: LegalsState) { @@ -71,11 +72,11 @@ class LegalsController @Inject constructor( titleResId(R.string.legals_identity_server_title) } - buildPolicy("is", data.identityServer) + buildPolicyAsync("is", data.identityServer) } } - private fun buildPolicy(tag: String, serverAndPolicies: Async) { + private fun buildPolicyAsync(tag: String, serverAndPolicies: Async) { val host = this when (serverAndPolicies) { @@ -91,14 +92,7 @@ class LegalsController @Inject constructor( helperText(host.stringProvider.getString(R.string.legals_no_policy_provided)) } } else { - policies.forEach { policy -> - discoveryPolicyItem { - id(policy.url) - name(policy.name) - url(policy.url) - clickListener { host.listener?.openPolicy(policy) } - } - } + buildPolicies(tag, policies) } } is Fail -> { @@ -111,6 +105,19 @@ class LegalsController @Inject constructor( } } + private fun buildPolicies(tag: String, policies: List) { + val host = this + + policies.forEach { policy -> + discoveryPolicyItem { + id(tag + policy.url) + name(policy.name) + url(policy.url) + clickListener { host.listener?.openPolicy(policy) } + } + } + } + interface Listener { fun onTapRetry() fun openPolicy(policy: ServerPolicy) diff --git a/vector/src/main/res/xml/vector_settings_help_about.xml b/vector/src/main/res/xml/vector_settings_help_about.xml index b36fba05c2..9171d1e6fe 100644 --- a/vector/src/main/res/xml/vector_settings_help_about.xml +++ b/vector/src/main/res/xml/vector_settings_help_about.xml @@ -23,18 +23,6 @@ android:title="@string/settings_olm_version" tools:summary="7.8.9" /> - - - - - - From a8c921ef031f7e7540808bf31e3d91cc7ec9d7bb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 22:21:18 +0100 Subject: [PATCH 28/37] Add some space between the 2 TextViews, and improve the layout --- .../main/res/layout/item_discovery_policy.xml | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/vector/src/main/res/layout/item_discovery_policy.xml b/vector/src/main/res/layout/item_discovery_policy.xml index 5d8c7159e9..d68b1e63a1 100644 --- a/vector/src/main/res/layout/item_discovery_policy.xml +++ b/vector/src/main/res/layout/item_discovery_policy.xml @@ -5,8 +5,20 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" + android:minHeight="64dp" android:padding="16dp"> + + + tools:text="Copyright" /> + tools:text="https://element.io/copyright" /> Date: Wed, 8 Dec 2021 22:46:25 +0100 Subject: [PATCH 29/37] Legals: Move the 2 copyrights items to the new legal screen --- .../features/discovery/DiscoveryPolicyItem.kt | 3 +- .../features/settings/VectorPreferences.kt | 2 -- .../VectorSettingsHelpAboutFragment.kt | 22 --------------- .../settings/legals/LegalsController.kt | 27 ++++++++++++++++++ .../settings/legals/LegalsFragment.kt | 28 ++++++++++++++++++- vector/src/main/res/values/strings.xml | 1 + .../res/xml/vector_settings_help_about.xml | 10 ------- 7 files changed, 57 insertions(+), 36 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/discovery/DiscoveryPolicyItem.kt b/vector/src/main/java/im/vector/app/features/discovery/DiscoveryPolicyItem.kt index c97a2286ae..4df4146d2f 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/DiscoveryPolicyItem.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/DiscoveryPolicyItem.kt @@ -24,6 +24,7 @@ import im.vector.app.R import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.onClick +import im.vector.app.core.extensions.setTextOrHide @EpoxyModelClass(layout = R.layout.item_discovery_policy) abstract class DiscoveryPolicyItem : EpoxyModelWithHolder() { @@ -40,7 +41,7 @@ abstract class DiscoveryPolicyItem : EpoxyModelWithHolder(APP_INFO_LINK_PREFERENCE_KEY)!! @@ -75,23 +70,6 @@ class VectorSettingsHelpAboutFragment @Inject constructor( // olm version findPreference(VectorPreferences.SETTINGS_OLM_VERSION_PREFERENCE_KEY)!! .summary = session.cryptoService().getCryptoVersion(requireContext(), false) - - // third party notice - findPreference(VectorPreferences.SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY)!! - .onPreferenceClickListener = Preference.OnPreferenceClickListener { - if (firstThrottler.canHandle() is FirstThrottler.CanHandlerResult.Yes) { - activity?.displayInWebView(VectorSettingsUrls.THIRD_PARTY_LICENSES) - } - false - } - - // Note: preference is not visible on F-Droid build - findPreference(VectorPreferences.SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY)!! - .onPreferenceClickListener = Preference.OnPreferenceClickListener { - // See https://developers.google.com/android/guides/opensource - openOssLicensesMenuActivity(requireActivity()) - false - } } companion object { diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt index 5470bb3ace..754a31be31 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt @@ -15,6 +15,7 @@ */ package im.vector.app.features.settings.legals +import android.content.res.Resources import com.airbnb.epoxy.TypedEpoxyController import com.airbnb.mvrx.Async import com.airbnb.mvrx.Fail @@ -35,6 +36,7 @@ import javax.inject.Inject class LegalsController @Inject constructor( private val stringProvider: StringProvider, + private val resources: Resources, private val elementLegals: ElementLegals, private val errorFormatter: ErrorFormatter ) : TypedEpoxyController() { @@ -45,6 +47,7 @@ class LegalsController @Inject constructor( buildAppSection() buildHomeserverSection(data) buildIdentityServerSection(data) + buildThirdPartyNotices() } private fun buildAppSection() { @@ -118,8 +121,32 @@ class LegalsController @Inject constructor( } } + private fun buildThirdPartyNotices() { + val host = this + settingsSectionTitleItem { + id("appTitle") + titleResId(R.string.legals_third_party_notices) + } + + discoveryPolicyItem { + id("elcp1") + name(host.stringProvider.getString(R.string.settings_third_party_notices)) + clickListener { host.listener?.openThirdPartyNotice() } + } + // Only on Gplay + if (resources.getBoolean(R.bool.isGplay)) { + discoveryPolicyItem { + id("elcp2") + name(host.stringProvider.getString(R.string.settings_other_third_party_notices)) + clickListener { host.listener?.openThirdPartyNoticeGplay() } + } + } + } + interface Listener { fun onTapRetry() fun openPolicy(policy: ServerPolicy) + fun openThirdPartyNotice() + fun openThirdPartyNoticeGplay() } } diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt index c6b5c2bf1c..6a3db28702 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt @@ -27,9 +27,13 @@ import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.utils.FirstThrottler +import im.vector.app.core.utils.displayInWebView import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.features.discovery.ServerPolicy +import im.vector.app.features.settings.VectorSettingsUrls +import im.vector.app.openOssLicensesMenuActivity import javax.inject.Inject class LegalsFragment @Inject constructor( @@ -42,6 +46,7 @@ class LegalsFragment @Inject constructor( } private val viewModel by fragmentViewModel(LegalsViewModel::class) + private val firstThrottler = FirstThrottler(1000) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -79,6 +84,27 @@ class LegalsFragment @Inject constructor( } override fun openPolicy(policy: ServerPolicy) { - openUrlInChromeCustomTab(requireContext(), null, policy.url) + openUrl(policy.url) + } + + override fun openThirdPartyNotice() { + openUrl(VectorSettingsUrls.THIRD_PARTY_LICENSES) + } + + private fun openUrl(url: String) { + if (firstThrottler.canHandle() is FirstThrottler.CanHandlerResult.Yes) { + if (url.startsWith("file://")) { + activity?.displayInWebView(url) + } else { + openUrlInChromeCustomTab(requireContext(), null, url) + } + } + } + + override fun openThirdPartyNoticeGplay() { + if (firstThrottler.canHandle() is FirstThrottler.CanHandlerResult.Yes) { + // See https://developers.google.com/android/guides/opensource + openOssLicensesMenuActivity(requireActivity()) + } } } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index e23cc02235..2759f0ebc5 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1400,6 +1400,7 @@ ${app_name} policy Your homeserver policy Your identity server policy + Third party libraries This server does not provide any policy. Integrations are disabled diff --git a/vector/src/main/res/xml/vector_settings_help_about.xml b/vector/src/main/res/xml/vector_settings_help_about.xml index 9171d1e6fe..c532536785 100644 --- a/vector/src/main/res/xml/vector_settings_help_about.xml +++ b/vector/src/main/res/xml/vector_settings_help_about.xml @@ -1,6 +1,5 @@ - - - - \ No newline at end of file From eed7d15b0e6c811337491af8b86ceb1ca31df938 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 22:54:15 +0100 Subject: [PATCH 30/37] Legals: only display external URLs. --- .../im/vector/app/features/settings/legals/LegalsController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt index 754a31be31..fa80bf2e9e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt @@ -115,7 +115,7 @@ class LegalsController @Inject constructor( discoveryPolicyItem { id(tag + policy.url) name(policy.name) - url(policy.url) + url(policy.url.takeIf { it.startsWith("http") }) clickListener { host.listener?.openPolicy(policy) } } } From 50a84a6c56b3df98e8766ad3a75b2d7073134aae Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 22:56:45 +0100 Subject: [PATCH 31/37] Use same height than the loading item to avoid dynamic resizing --- vector/src/main/res/layout/item_discovery_policy.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/layout/item_discovery_policy.xml b/vector/src/main/res/layout/item_discovery_policy.xml index d68b1e63a1..d1d003d1ef 100644 --- a/vector/src/main/res/layout/item_discovery_policy.xml +++ b/vector/src/main/res/layout/item_discovery_policy.xml @@ -5,7 +5,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" - android:minHeight="64dp" + android:minHeight="80dp" android:padding="16dp"> Date: Wed, 8 Dec 2021 22:59:01 +0100 Subject: [PATCH 32/37] Color for links --- vector/src/main/res/layout/item_discovery_policy.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/res/layout/item_discovery_policy.xml b/vector/src/main/res/layout/item_discovery_policy.xml index d1d003d1ef..86333bdee8 100644 --- a/vector/src/main/res/layout/item_discovery_policy.xml +++ b/vector/src/main/res/layout/item_discovery_policy.xml @@ -37,7 +37,7 @@ android:layout_height="wrap_content" android:paddingStart="0dp" android:paddingEnd="8dp" - android:textColor="?vctr_content_secondary" + android:textColor="?android:textColorLink" tools:text="https://element.io/copyright" /> From 17c4c1e9b8e6adbbed9491252253b3744a9931c4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 23:01:29 +0100 Subject: [PATCH 33/37] Changelog --- changelog.d/4660.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4660.feature diff --git a/changelog.d/4660.feature b/changelog.d/4660.feature new file mode 100644 index 0000000000..4eca82eaf5 --- /dev/null +++ b/changelog.d/4660.feature @@ -0,0 +1 @@ +Create a legal screen in the setting to group all the different policies. \ No newline at end of file From 7f7199abd4548936be07a6f4c816f6347123214a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 23:15:57 +0100 Subject: [PATCH 34/37] Add a help section in the settings. --- changelog.d/4638.feature | 1 + .../features/settings/VectorPreferences.kt | 1 + .../VectorSettingsHelpAboutFragment.kt | 13 +++++ .../features/settings/VectorSettingsUrls.kt | 1 + vector/src/main/res/values/strings.xml | 5 ++ .../res/xml/vector_settings_help_about.xml | 49 +++++++++++++------ 6 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 changelog.d/4638.feature diff --git a/changelog.d/4638.feature b/changelog.d/4638.feature new file mode 100644 index 0000000000..0f8bd36465 --- /dev/null +++ b/changelog.d/4638.feature @@ -0,0 +1 @@ +Add a help section in the settings. \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 8db2d777e1..c9464550ac 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -35,6 +35,7 @@ import javax.inject.Inject class VectorPreferences @Inject constructor(private val context: Context) { companion object { + const val SETTINGS_HELP_PREFERENCE_KEY = "SETTINGS_HELP_PREFERENCE_KEY" const val SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY = "SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY" const val SETTINGS_VERSION_PREFERENCE_KEY = "SETTINGS_VERSION_PREFERENCE_KEY" const val SETTINGS_SDK_VERSION_PREFERENCE_KEY = "SETTINGS_SDK_VERSION_PREFERENCE_KEY" diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt index 86b454a243..31d9cf0426 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt @@ -20,8 +20,10 @@ import androidx.preference.Preference import im.vector.app.BuildConfig import im.vector.app.R import im.vector.app.core.preference.VectorPreference +import im.vector.app.core.utils.FirstThrottler import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.openAppSettingsPage +import im.vector.app.core.utils.openUrlInChromeCustomTab import im.vector.app.features.version.VersionProvider import org.matrix.android.sdk.api.Matrix import javax.inject.Inject @@ -33,7 +35,18 @@ class VectorSettingsHelpAboutFragment @Inject constructor( override var titleRes = R.string.preference_root_help_about override val preferenceXmlRes = R.xml.vector_settings_help_about + private val firstThrottler = FirstThrottler(1000) + override fun bindPref() { + // Help + findPreference(VectorPreferences.SETTINGS_HELP_PREFERENCE_KEY)!! + .onPreferenceClickListener = Preference.OnPreferenceClickListener { + if (firstThrottler.canHandle() is FirstThrottler.CanHandlerResult.Yes) { + openUrlInChromeCustomTab(requireContext(), null, VectorSettingsUrls.HELP) + } + false + } + // preference to start the App info screen, to facilitate App permissions access findPreference(APP_INFO_LINK_PREFERENCE_KEY)!! .onPreferenceClickListener = Preference.OnPreferenceClickListener { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsUrls.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsUrls.kt index b3925c32dc..09249c4957 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsUrls.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsUrls.kt @@ -17,6 +17,7 @@ package im.vector.app.features.settings object VectorSettingsUrls { + const val HELP = "https://element.io/help" const val COPYRIGHT = "https://element.io/copyright" const val TAC = "https://element.io/terms-of-service" const val PRIVACY_POLICY = "https://element.io/privacy" diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 2759f0ebc5..97bf7a7d6a 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2278,6 +2278,11 @@ Help & About Legals + Help + Help and support + Get help with using Element + Versions + System settings Register token diff --git a/vector/src/main/res/xml/vector_settings_help_about.xml b/vector/src/main/res/xml/vector_settings_help_about.xml index c532536785..0388b545b7 100644 --- a/vector/src/main/res/xml/vector_settings_help_about.xml +++ b/vector/src/main/res/xml/vector_settings_help_about.xml @@ -2,24 +2,41 @@ - + - + - + - + + + + + + + + + + + + + + + \ No newline at end of file From 72bb58645b37615b10ea3a8e8de2eda7e2763850 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Dec 2021 23:41:58 +0100 Subject: [PATCH 35/37] Auto-review --- .../settings/legals/LegalsController.kt | 6 ++--- .../settings/legals/LegalsFragment.kt | 9 -------- .../settings/legals/LegalsViewEvents.kt | 23 ------------------- .../settings/legals/LegalsViewModel.kt | 3 ++- 4 files changed, 5 insertions(+), 36 deletions(-) delete mode 100644 vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewEvents.kt diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt index fa80bf2e9e..98e77ae7d5 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt @@ -124,19 +124,19 @@ class LegalsController @Inject constructor( private fun buildThirdPartyNotices() { val host = this settingsSectionTitleItem { - id("appTitle") + id("thirdTitle") titleResId(R.string.legals_third_party_notices) } discoveryPolicyItem { - id("elcp1") + id("eltpn1") name(host.stringProvider.getString(R.string.settings_third_party_notices)) clickListener { host.listener?.openThirdPartyNotice() } } // Only on Gplay if (resources.getBoolean(R.bool.isGplay)) { discoveryPolicyItem { - id("elcp2") + id("eltpn2") name(host.stringProvider.getString(R.string.settings_other_third_party_notices)) clickListener { host.listener?.openThirdPartyNoticeGplay() } } diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt index 6a3db28702..f9b50bdead 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt @@ -25,7 +25,6 @@ import com.airbnb.mvrx.withState import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith -import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.FirstThrottler import im.vector.app.core.utils.displayInWebView @@ -53,14 +52,6 @@ class LegalsFragment @Inject constructor( controller.listener = this views.genericRecyclerView.configureWith(controller) - - viewModel.observeViewEvents { - when (it) { - is LegalsViewEvents.Failure -> { - displayErrorDialog(it.throwable) - } - }.exhaustive - } } override fun onDestroyView() { diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewEvents.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewEvents.kt deleted file mode 100644 index 40741a4d62..0000000000 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewEvents.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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.settings.legals - -import im.vector.app.core.platform.VectorViewEvents - -sealed interface LegalsViewEvents : VectorViewEvents { - data class Failure(val throwable: Throwable) : LegalsViewEvents -} diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt index 7947bcc570..9d58535490 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsViewModel.kt @@ -26,6 +26,7 @@ import im.vector.app.R import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.extensions.exhaustive +import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.resources.StringProvider import im.vector.app.features.discovery.fetchHomeserverWithTerms @@ -37,7 +38,7 @@ class LegalsViewModel @AssistedInject constructor( @Assisted initialState: LegalsState, private val session: Session, private val stringProvider: StringProvider -) : VectorViewModel(initialState) { +) : VectorViewModel(initialState) { @AssistedFactory interface Factory : MavericksAssistedViewModelFactory { From 6ba5c7af27276ccb4e5d83baaed65a88c5cdeb70 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 9 Dec 2021 10:39:50 +0100 Subject: [PATCH 36/37] Legals: update setting icon --- .../src/main/res/drawable/ic_settings_root_legals.xml | 10 ++++++++++ vector/src/main/res/xml/vector_settings_root.xml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 vector/src/main/res/drawable/ic_settings_root_legals.xml diff --git a/vector/src/main/res/drawable/ic_settings_root_legals.xml b/vector/src/main/res/drawable/ic_settings_root_legals.xml new file mode 100644 index 0000000000..8c5049b36e --- /dev/null +++ b/vector/src/main/res/drawable/ic_settings_root_legals.xml @@ -0,0 +1,10 @@ + + + diff --git a/vector/src/main/res/xml/vector_settings_root.xml b/vector/src/main/res/xml/vector_settings_root.xml index 712c1e7a4c..520c4595ca 100644 --- a/vector/src/main/res/xml/vector_settings_root.xml +++ b/vector/src/main/res/xml/vector_settings_root.xml @@ -54,7 +54,7 @@ app:fragment="im.vector.app.features.settings.VectorSettingsHelpAboutFragment" /> From bf7907a119fd8abd4c18bbcd1f13ef4ab4305ebb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 9 Dec 2021 12:15:19 +0100 Subject: [PATCH 37/37] Legals: improve API to get homeserver terms --- .../sdk/api/session/terms/TermsService.kt | 15 ++++--- .../session/terms/DefaultTermsService.kt | 43 ++++++------------- .../app/features/discovery/Extensions.kt | 24 ++++++----- .../app/features/terms/ReviewTermsFragment.kt | 1 - 4 files changed, 34 insertions(+), 49 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt index 9898923003..e64cf1872e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt @@ -16,15 +16,12 @@ package org.matrix.android.sdk.api.session.terms +import org.matrix.android.sdk.internal.session.terms.TermsResponse + interface TermsService { enum class ServiceType { IntegrationManager, - IdentityService, - - /** - * It's only possible to use this value for [getTerms] - */ - Homeserver + IdentityService } suspend fun getTerms(serviceType: ServiceType, baseUrl: String): GetTermsResponse @@ -33,4 +30,10 @@ interface TermsService { baseUrl: String, agreedUrls: List, token: String?) + + /** + * Get the homeserver terms, from the register API. + * Will be updated once https://github.com/matrix-org/matrix-doc/pull/3012 will be implemented. + */ + suspend fun getHomeserverTerms(baseUrl: String): TermsResponse } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt index 5cdef3db0a..c52c6a404e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt @@ -51,51 +51,34 @@ internal class DefaultTermsService @Inject constructor( override suspend fun getTerms(serviceType: TermsService.ServiceType, baseUrl: String): GetTermsResponse { - return if (serviceType == TermsService.ServiceType.Homeserver) { - getHomeserverTerms(baseUrl) - } else { - val url = buildUrl(baseUrl, serviceType) - val termsResponse = executeRequest(null) { - termsAPI.getTerms("${url}terms") - } - GetTermsResponse(termsResponse, getAlreadyAcceptedTermUrlsFromAccountData()) + val url = buildUrl(baseUrl, serviceType) + val termsResponse = executeRequest(null) { + termsAPI.getTerms("${url}terms") } + return GetTermsResponse(termsResponse, getAlreadyAcceptedTermUrlsFromAccountData()) } /** * We use a trick here to get the homeserver T&C, we use the register API */ - private suspend fun getHomeserverTerms(baseUrl: String): GetTermsResponse { + override suspend fun getHomeserverTerms(baseUrl: String): TermsResponse { return try { executeRequest(null) { termsAPI.register(baseUrl + NetworkConstants.URI_API_PREFIX_PATH_R0 + "register") } // Return empty result if it succeed, but it should never happen - buildEmptyGetTermsResponse() + TermsResponse() } catch (throwable: Throwable) { @Suppress("UNCHECKED_CAST") - ((throwable.toRegistrationFlowResponse() - ?.params?.get(LoginFlowTypes.TERMS) as? JsonDict) - ?.get("policies") as? JsonDict) - ?.let { dict -> - GetTermsResponse( - serverResponse = TermsResponse( - policies = dict - ), - alreadyAcceptedTermUrls = emptySet() - ) - } - ?: buildEmptyGetTermsResponse() + TermsResponse( + policies = (throwable.toRegistrationFlowResponse() + ?.params + ?.get(LoginFlowTypes.TERMS) as? JsonDict) + ?.get("policies") as? JsonDict + ) } } - private fun buildEmptyGetTermsResponse(): GetTermsResponse { - return GetTermsResponse( - serverResponse = TermsResponse(), - alreadyAcceptedTermUrls = emptySet() - ) - } - override suspend fun agreeToTerms(serviceType: TermsService.ServiceType, baseUrl: String, agreedUrls: List, @@ -133,8 +116,6 @@ internal class DefaultTermsService @Inject constructor( val servicePath = when (serviceType) { TermsService.ServiceType.IntegrationManager -> NetworkConstants.URI_INTEGRATION_MANAGER_PATH TermsService.ServiceType.IdentityService -> NetworkConstants.URI_IDENTITY_PATH_V2 - TermsService.ServiceType.Homeserver -> - error("You cannot use this API with parameter TermsService.ServiceType.Homeserver") } return "${baseUrl.ensureTrailingSlash()}$servicePath" } diff --git a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt index 1360c9e95d..24d675695b 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt @@ -19,25 +19,27 @@ package im.vector.app.features.discovery import im.vector.app.core.utils.ensureProtocol import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.terms.TermsService +import org.matrix.android.sdk.internal.session.terms.TermsResponse suspend fun Session.fetchIdentityServerWithTerms(userLanguage: String): ServerAndPolicies? { - val identityServerUrl = identityService().getCurrentIdentityServerUrl() - return identityServerUrl?.let { - fetchTerms(it, TermsService.ServiceType.IdentityService, userLanguage) - } + return identityService().getCurrentIdentityServerUrl() + ?.let { identityServerUrl -> + val termsResponse = getTerms(TermsService.ServiceType.IdentityService, identityServerUrl.ensureProtocol()) + .serverResponse + buildServerAndPolicies(identityServerUrl, termsResponse, userLanguage) + } } suspend fun Session.fetchHomeserverWithTerms(userLanguage: String): ServerAndPolicies { val homeserverUrl = sessionParams.homeServerUrl - return fetchTerms(homeserverUrl, TermsService.ServiceType.Homeserver, userLanguage) + val terms = getHomeserverTerms(homeserverUrl.ensureProtocol()) + return buildServerAndPolicies(homeserverUrl, terms, userLanguage) } -private suspend fun Session.fetchTerms(serviceUrl: String, - serviceType: TermsService.ServiceType, - userLanguage: String): ServerAndPolicies { - val terms = getTerms(serviceType, serviceUrl.ensureProtocol()) - .serverResponse - .getLocalizedTerms(userLanguage) +private fun buildServerAndPolicies(serviceUrl: String, + termsResponse: TermsResponse, + userLanguage: String): ServerAndPolicies { + val terms = termsResponse.getLocalizedTerms(userLanguage) val policyUrls = terms.mapNotNull { val name = it.localizedName ?: it.policyName val url = it.localizedUrl diff --git a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt index 6381854433..cb76e5b31f 100644 --- a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt @@ -53,7 +53,6 @@ class ReviewTermsFragment @Inject constructor( termsController.description = when (reviewTermsViewModel.termsArgs.type) { TermsService.ServiceType.IdentityService -> getString(R.string.terms_description_for_identity_server) TermsService.ServiceType.IntegrationManager -> getString(R.string.terms_description_for_integration_manager) - TermsService.ServiceType.Homeserver -> error("Homeserver is not supported here") } termsController.listener = this