diff --git a/CHANGES.md b/CHANGES.md index 5524769469..c80337028e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Features ✨: Improvements 🙌: - Migrate to binary QR code verification (#994) - Share action is added to room profile and room member profile (#858) + - Display avatar in fullscreen (#861) - Fix some performance issues with crypto Bugfix 🐛: diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index ec6d5cfcf0..488f357c4b 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -40,6 +40,7 @@ android:name=".features.login.LoginActivity" android:windowSoftInputMode="adjustResize" /> + diff --git a/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt index b16248a5cc..04d4bd0f4c 100644 --- a/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt +++ b/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt @@ -41,6 +41,7 @@ import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsBotto import im.vector.riotx.features.invite.VectorInviteView import im.vector.riotx.features.link.LinkHandlerActivity import im.vector.riotx.features.login.LoginActivity +import im.vector.riotx.features.media.BigImageViewerActivity import im.vector.riotx.features.media.ImageMediaViewerActivity import im.vector.riotx.features.media.VideoMediaViewerActivity import im.vector.riotx.features.navigation.Navigator @@ -154,6 +155,8 @@ interface ScreenComponent { fun inject(activity: SharedSecureStorageActivity) + fun inject(bigImageViewerActivity: BigImageViewerActivity) + @Component.Factory interface Factory { fun create(vectorComponent: VectorComponent, diff --git a/vector/src/main/java/im/vector/riotx/features/media/BigImageViewerActivity.kt b/vector/src/main/java/im/vector/riotx/features/media/BigImageViewerActivity.kt new file mode 100644 index 0000000000..6c9817de3a --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/media/BigImageViewerActivity.kt @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.riotx.features.media + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.core.net.toUri +import im.vector.riotx.R +import im.vector.riotx.core.di.ActiveSessionHolder +import im.vector.riotx.core.di.ScreenComponent +import im.vector.riotx.core.platform.VectorBaseActivity +import kotlinx.android.synthetic.main.activity_big_image_viewer.* +import javax.inject.Inject + +class BigImageViewerActivity : VectorBaseActivity() { + + @Inject lateinit var sessionHolder: ActiveSessionHolder + + private val imageUrl by lazy { intent.getStringExtra(EXTRA_IMAGE_URL) } + + override fun injectWith(injector: ScreenComponent) { + injector.inject(this) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_big_image_viewer) + + setSupportActionBar(bigImageViewerToolbar) + supportActionBar?.apply { + title = intent.getStringExtra(EXTRA_TITLE) + setHomeButtonEnabled(true) + setDisplayHomeAsUpEnabled(true) + } + + val contentUrlResolver = sessionHolder.getActiveSession().contentUrlResolver() + val fullSize = contentUrlResolver.resolveFullSize(imageUrl) + bigImageViewerImageView.showImage(fullSize?.toUri()) + } + + companion object { + + private const val EXTRA_TITLE = "EXTRA_TITLE" + private const val EXTRA_IMAGE_URL = "EXTRA_IMAGE_URL" + + fun newIntent(context: Context, title: String?, imageUrl: String): Intent { + return Intent(context, BigImageViewerActivity::class.java).apply { + putExtra(EXTRA_TITLE, title) + putExtra(EXTRA_IMAGE_URL, imageUrl) + } + } + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt index 1bd30f0f25..b30932869e 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt @@ -19,7 +19,10 @@ package im.vector.riotx.features.navigation import android.app.Activity import android.content.Context import android.content.Intent +import android.view.View +import androidx.core.app.ActivityOptionsCompat import androidx.core.app.TaskStackBuilder +import androidx.core.view.ViewCompat import im.vector.matrix.android.api.session.crypto.sas.IncomingSasVerificationTransaction import im.vector.matrix.android.api.session.crypto.sas.VerificationMethod import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom @@ -36,6 +39,7 @@ import im.vector.riotx.features.debug.DebugMenuActivity import im.vector.riotx.features.home.room.detail.RoomDetailActivity import im.vector.riotx.features.home.room.detail.RoomDetailArgs import im.vector.riotx.features.home.room.filtered.FilteredRoomsActivity +import im.vector.riotx.features.media.BigImageViewerActivity import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity import im.vector.riotx.features.roomdirectory.createroom.CreateRoomActivity import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewActivity @@ -175,6 +179,14 @@ class DefaultNavigator @Inject constructor( context.startActivity(RoomProfileActivity.newIntent(context, roomId)) } + override fun openBigImageViewer(activity: Activity, sharedElement: View?, title: String, avatarUrl: String) { + val intent = BigImageViewerActivity.newIntent(activity, title, avatarUrl) + val options = sharedElement?.let { + ActivityOptionsCompat.makeSceneTransitionAnimation(activity, it, ViewCompat.getTransitionName(it) ?: "") + } + activity.startActivity(intent, options?.toBundle()) + } + private fun startActivity(context: Context, intent: Intent, buildTask: Boolean) { if (buildTask) { val stackBuilder = TaskStackBuilder.create(context) diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt index 89eab73af1..75591f5ff6 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.navigation import android.app.Activity import android.content.Context +import android.view.View import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom import im.vector.riotx.features.settings.VectorSettingsActivity import im.vector.riotx.features.share.SharedData @@ -59,4 +60,6 @@ interface Navigator { fun openRoomMemberProfile(userId: String, roomId: String?, context: Context, buildTask: Boolean = false) fun openRoomProfile(context: Context, roomId: String) + + fun openBigImageViewer(activity: Activity, sharedElement: View?, title: String, avatarUrl: String) } diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt index c62e8ce226..0b0dcca1cf 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -192,6 +192,10 @@ class RoomMemberProfileFragment @Inject constructor( } else { memberProfileDecorationImageView.isVisible = false } + + memberProfileAvatarView.setOnClickListener { view -> + onAvatarClicked(view, userMatrixItem) + } } } memberProfilePowerLevelView.setTextOrHide(state.userPowerLevelString()) @@ -227,4 +231,13 @@ class RoomMemberProfileFragment @Inject constructor( private fun handleShareRoomMemberProfile(permalink: String) { startSharePlainTextIntent(fragment = this, chooserTitle = null, text = permalink) } + + private fun onAvatarClicked(view: View, userMatrixItem: MatrixItem) { + userMatrixItem.avatarUrl + ?.takeIf { it.isNotBlank() } + ?.let { avatarUrl -> + val title = userMatrixItem.getBestName() + navigator.openBigImageViewer(requireActivity(), view, title, avatarUrl) + } + } } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt index 869810b08b..4ef0350a48 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/RoomProfileFragment.kt @@ -27,6 +27,7 @@ import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import im.vector.matrix.android.api.session.room.notification.RoomNotificationState +import im.vector.matrix.android.api.util.MatrixItem import im.vector.matrix.android.api.util.toMatrixItem import im.vector.riotx.R import im.vector.riotx.core.animations.AppBarStateChangeListener @@ -164,6 +165,10 @@ class RoomProfileFragment @Inject constructor( roomProfileDecorationImageView.isVisible = it.roomEncryptionTrustLevel != null roomProfileDecorationImageView.setImageResource(it.roomEncryptionTrustLevel.toImageRes()) matrixProfileDecorationToolbarAvatarImageView.setImageResource(it.roomEncryptionTrustLevel.toImageRes()) + + roomProfileAvatarView.setOnClickListener { view -> + onAvatarClicked(view, matrixItem) + } } } roomProfileController.setData(state) @@ -211,4 +216,13 @@ class RoomProfileFragment @Inject constructor( private fun onShareRoomProfile(permalink: String) { startSharePlainTextIntent(fragment = this, chooserTitle = null, text = permalink) } + + private fun onAvatarClicked(view: View, matrixItem: MatrixItem.RoomItem) { + matrixItem.avatarUrl + ?.takeIf { it.isNotBlank() } + ?.let { avatarUrl -> + val title = matrixItem.getBestName() + navigator.openBigImageViewer(requireActivity(), view, title, avatarUrl) + } + } } diff --git a/vector/src/main/res/layout/activity_big_image_viewer.xml b/vector/src/main/res/layout/activity_big_image_viewer.xml new file mode 100644 index 0000000000..124b76f64e --- /dev/null +++ b/vector/src/main/res/layout/activity_big_image_viewer.xml @@ -0,0 +1,27 @@ + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/layout/view_stub_room_profile_header.xml b/vector/src/main/res/layout/view_stub_room_profile_header.xml index 9b733b7fa6..f7ae1c77a5 100644 --- a/vector/src/main/res/layout/view_stub_room_profile_header.xml +++ b/vector/src/main/res/layout/view_stub_room_profile_header.xml @@ -12,6 +12,7 @@ android:layout_width="128dp" android:layout_height="128dp" android:layout_marginBottom="16dp" + android:transitionName="roomProfileAvatarView" app:layout_constraintBottom_toTopOf="@+id/roomProfileNameView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"