diff --git a/app/build.gradle b/app/build.gradle index 92d7b50c..d54e1eaf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,7 +13,7 @@ jacoco.toolVersion = "0.8.7" android { - compileSdkVersion 31 + compileSdkVersion 32 buildToolsVersion '31.0.0' compileOptions { coreLibraryDesugaringEnabled true @@ -27,7 +27,7 @@ android { defaultConfig { applicationId "org.pixeldroid.app" minSdkVersion 23 - targetSdkVersion 31 + targetSdkVersion 32 versionCode 10 versionName "1.0.beta" + versionCode @@ -106,17 +106,17 @@ dependencies { /** * AndroidX dependencies: */ - implementation 'androidx.appcompat:appcompat:1.4.1' - implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.2' + implementation 'androidx.core:core-ktx:1.8.0' implementation 'androidx.preference:preference-ktx:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.3' - implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1' - implementation 'androidx.navigation:navigation-ui-ktx:2.4.1' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.navigation:navigation-fragment-ktx:2.4.2' + implementation 'androidx.navigation:navigation-ui-ktx:2.4.2' implementation "androidx.browser:browser:1.4.0" implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" - implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1' - implementation 'androidx.navigation:navigation-ui-ktx:2.4.1' + implementation 'androidx.navigation:navigation-fragment-ktx:2.4.2' + implementation 'androidx.navigation:navigation-ui-ktx:2.4.2' implementation 'androidx.paging:paging-runtime-ktx:3.1.1' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1' @@ -133,7 +133,7 @@ dependencies { // Use the most recent version of CameraX - def cameraX_version = '1.1.0-beta02' + def cameraX_version = '1.1.0-rc01' implementation "androidx.camera:camera-core:$cameraX_version" implementation "androidx.camera:camera-camera2:$cameraX_version" // CameraX Lifecycle library @@ -142,6 +142,8 @@ dependencies { // CameraX View class implementation "androidx.camera:camera-view:$cameraX_version" + implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0' + def room_version = "2.4.2" implementation "androidx.room:room-runtime:$room_version" kapt "androidx.room:room-compiler:$room_version" @@ -154,7 +156,7 @@ dependencies { */ - implementation 'com.google.android.material:material:1.5.0' + implementation 'com.google.android.material:material:1.6.1' //Dagger (dependency injection) implementation 'com.google.dagger:dagger-android:2.40.5' @@ -163,7 +165,7 @@ dependencies { kapt 'com.google.dagger:dagger-android-processor:2.40.5' kapt 'com.google.dagger:dagger-compiler:2.40.5' - implementation 'com.squareup.okhttp3:okhttp:4.9.1' + implementation 'com.squareup.okhttp3:okhttp:4.9.2' implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0' @@ -227,7 +229,7 @@ dependencies { androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0' androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.0.2' - androidTestImplementation 'com.squareup.okhttp3:mockwebserver:4.9.0' + androidTestImplementation 'com.squareup.okhttp3:mockwebserver:4.9.2' } diff --git a/app/src/androidTest/java/org/pixeldroid/app/HomeFeedTest.kt b/app/src/androidTest/java/org/pixeldroid/app/HomeFeedTest.kt index 84c9e735..8d6cefb1 100644 --- a/app/src/androidTest/java/org/pixeldroid/app/HomeFeedTest.kt +++ b/app/src/androidTest/java/org/pixeldroid/app/HomeFeedTest.kt @@ -6,7 +6,6 @@ import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ApplicationProvider import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions -import androidx.test.espresso.action.ViewActions.openLinkWithText import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition @@ -24,9 +23,6 @@ import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test -import org.junit.rules.TestRule -import org.junit.rules.Timeout -import org.junit.runner.Description import org.junit.runner.RunWith import org.junit.runners.model.Statement @@ -68,22 +64,22 @@ class HomeFeedTest { @RepeatTest fun clickingTabOnAlbumShowsNextPhoto() { //Wait for the feed to load - waitForView(R.id.postPager) + waitForView(R.id.albumPager) activityScenario.onActivity { a -> run { //Pick the second photo - a.findViewById(R.id.postPager).currentItem = 2 + a.findViewById(R.id.albumPager).currentItem = 2 } } - onView(first(withId(R.id.postPager))).check(matches(isDisplayed())) + onView(first(withId(R.id.albumPager))).check(matches(isDisplayed())) } @Test @RepeatTest fun tabReClickScrollUp() { //Wait for the feed to load - waitForView(R.id.postPager) + waitForView(R.id.albumPager) onView(withId(R.id.list)).perform(scrollToPosition(4)) @@ -97,7 +93,7 @@ class HomeFeedTest { @RepeatTest fun hashtag() { //Wait for the feed to load - waitForView(R.id.postPager) + waitForView(R.id.albumPager) onView(allOf(withClassName(endsWith("RecyclerView")), not(withId(R.id.material_drawer_recycler_view)))) .perform( diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cfcdb8c7..4a3bdf48 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,9 +23,13 @@ android:theme="@style/AppTheme" tools:replace="android:allowBackup"> + + val index = intent.getIntExtra("index", 0) + binding.albumPager.adapter = AlbumViewPagerAdapter(mediaAttachments, + sensitive = false, + opened = true + ) + binding.albumPager.currentItem = index + + if(mediaAttachments.size == 1){ + binding.albumPager.isUserInputEnabled = false + } + else if((mediaAttachments.size) > 1) { + binding.postIndicator.setViewPager(binding.albumPager) + binding.postIndicator.visibility = View.VISIBLE + } else { + binding.postIndicator.visibility = View.GONE + } + + + + supportActionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.setDisplayShowTitleEnabled(false) + supportActionBar?.setBackgroundDrawable(null) + window.statusBarColor = ContextCompat.getColor(this,android.R.color.transparent); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/pixeldroid/app/posts/MediaViewerActivity.kt b/app/src/main/java/org/pixeldroid/app/posts/MediaViewerActivity.kt index 39c91472..aa414d57 100644 --- a/app/src/main/java/org/pixeldroid/app/posts/MediaViewerActivity.kt +++ b/app/src/main/java/org/pixeldroid/app/posts/MediaViewerActivity.kt @@ -7,6 +7,7 @@ import android.media.AudioManager.STREAM_MUSIC import android.os.Bundle import androidx.core.net.toUri import androidx.core.view.ViewCompat +import androidx.core.view.WindowCompat.getInsetsController import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import androidx.media.AudioAttributesCompat @@ -50,19 +51,19 @@ class MediaViewerActivity : BaseActivity() { mediaPlayer.setMediaItem(mediaItem) binding.videoView.mediaControlView?.setOnFullScreenListener{ view, fullscreen -> - val windowInsetsController = ViewCompat.getWindowInsetsController(window.decorView) + val windowInsetsController = getInsetsController(window, window.decorView) if (!fullscreen) { // Configure the behavior of the hidden system bars - windowInsetsController?.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // Hide both the status bar and the navigation bar - windowInsetsController?.show(WindowInsetsCompat.Type.systemBars()) + windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) supportActionBar?.show() requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED } else { // Configure the behavior of the hidden system bars - windowInsetsController?.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // Hide both the status bar and the navigation bar - windowInsetsController?.hide(WindowInsetsCompat.Type.systemBars()) + windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) requestedOrientation = if (mediaPlayer.videoSize.height < mediaPlayer.videoSize.width) { diff --git a/app/src/main/java/org/pixeldroid/app/posts/NestedScrollableHost.kt b/app/src/main/java/org/pixeldroid/app/posts/NestedScrollableHost.kt index fa0157d7..9a4d74a1 100644 --- a/app/src/main/java/org/pixeldroid/app/posts/NestedScrollableHost.kt +++ b/app/src/main/java/org/pixeldroid/app/posts/NestedScrollableHost.kt @@ -1,29 +1,17 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * 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 org.pixeldroid.app.posts import android.content.Context +import android.content.Intent import android.util.AttributeSet +import android.view.GestureDetector import android.view.MotionEvent import android.view.View import android.view.ViewConfiguration import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.GestureDetectorCompat import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL +import org.pixeldroid.app.utils.api.objects.Attachment import kotlin.math.absoluteValue import kotlin.math.sign @@ -35,13 +23,11 @@ import kotlin.math.sign * This solution has limitations when using multiple levels of nested scrollable elements * (e.g. a horizontal RecyclerView in a vertical RecyclerView in a horizontal ViewPager2). */ -class NestedScrollableHost : ConstraintLayout { - constructor(context: Context) : super(context) - constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) +class NestedScrollableHost(context: Context, attrs: AttributeSet? = null) : + ConstraintLayout(context, attrs) { + private var mDetector: GestureDetectorCompat private var touchSlop = 0 - private var initialX = 0f - private var initialY = 0f private val parentViewPager: ViewPager2? get() { var v: View? = parent as? View @@ -51,12 +37,15 @@ class NestedScrollableHost : ConstraintLayout { return v as? ViewPager2 } - var doubleTapCallback: ((Boolean) -> Unit)? = null + + var images: ArrayList = ArrayList(); + var doubleTapCallback: (() -> Unit)? = null private val child: View? get() = if (childCount > 0) getChildAt(0) else null init { touchSlop = ViewConfiguration.get(context).scaledTouchSlop + mDetector = GestureDetectorCompat(context, MyGestureListener()) } private fun canChildScroll(orientation: Int, delta: Float): Boolean { @@ -69,35 +58,58 @@ class NestedScrollableHost : ConstraintLayout { } override fun onInterceptTouchEvent(e: MotionEvent): Boolean { - handleInterceptTouchEvent(e) + mDetector.onTouchEvent(e) return super.onInterceptTouchEvent(e) } - private fun handleInterceptTouchEvent(e: MotionEvent) { - val orientation = parentViewPager?.orientation ?: return + private inner class MyGestureListener : GestureDetector.SimpleOnGestureListener() { - if (e.action == MotionEvent.ACTION_DOWN) { - initialX = e.x - initialY = e.y - doubleTapCallback?.invoke(true) - } - // Early return if child can't scroll in same direction as parent - if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) { - return - } + override fun onDown(e: MotionEvent): Boolean { + val orientation = parentViewPager?.orientation ?: return true + + if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) { + return true + } - if (e.action == MotionEvent.ACTION_DOWN) { parent.requestDisallowInterceptTouchEvent(true) - } else if (e.action == MotionEvent.ACTION_MOVE) { - val dx = e.x - initialX - val dy = e.y - initialY + + return true + } + + override fun onDoubleTap(e: MotionEvent?): Boolean { + doubleTapCallback?.invoke() + return super.onDoubleTap(e) + } + + override fun onSingleTapConfirmed(e: MotionEvent?): Boolean { + // Disable opening AlbumActivity if the only image is a video (let the video open directly) + if(images.size == 1 && images.first().type == Attachment.AttachmentType.video){ + return super.onSingleTapConfirmed(e) + } + val intent = Intent(context, AlbumActivity::class.java) + + intent.putExtra("images", images) + intent.putExtra("index", (child as ViewPager2).currentItem) + + context.startActivity(intent) + + return super.onSingleTapConfirmed(e) + } + override fun onScroll( + e1: MotionEvent, + e2: MotionEvent, + distanceX: Float, + distanceY: Float + ): Boolean { + val orientation = parentViewPager?.orientation ?: return true + + val dx = e2.x - e1.x + val dy = e2.y - e1.y val isVpHorizontal = orientation == ORIENTATION_HORIZONTAL // assuming ViewPager2 touch-slop is 2x touch-slop of child - val scaledDx = dx.absoluteValue * if (isVpHorizontal) .5f/ touchSlopModifier else 1f - val scaledDy = dy.absoluteValue * if (isVpHorizontal) 1f else .5f/touchSlopModifier - - if(dx.absoluteValue * .5f > touchSlop || scaledDy > touchSlop) doubleTapCallback?.invoke(false) + val scaledDx = dx.absoluteValue * if (isVpHorizontal) .5f / touchSlopModifier else 1f + val scaledDy = dy.absoluteValue * if (isVpHorizontal) 1f else .5f / touchSlopModifier if (scaledDx > touchSlop || scaledDy > touchSlop) { @@ -115,6 +127,7 @@ class NestedScrollableHost : ConstraintLayout { } } } + return super.onScroll(e1, e2, distanceX, distanceY) } } diff --git a/app/src/main/java/org/pixeldroid/app/posts/StatusViewHolder.kt b/app/src/main/java/org/pixeldroid/app/posts/StatusViewHolder.kt index a1127538..2d01e948 100644 --- a/app/src/main/java/org/pixeldroid/app/posts/StatusViewHolder.kt +++ b/app/src/main/java/org/pixeldroid/app/posts/StatusViewHolder.kt @@ -1,27 +1,46 @@ package org.pixeldroid.app.posts import android.Manifest +import android.app.Activity import android.app.AlertDialog import android.content.Intent import android.graphics.Typeface import android.graphics.drawable.AnimatedVectorDrawable import android.graphics.drawable.Drawable +import android.net.Uri import android.text.method.LinkMovementMethod import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.* +import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat import androidx.lifecycle.LifecycleCoroutineScope import androidx.recyclerview.widget.RecyclerView import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat +import androidx.viewbinding.ViewBinding import com.bumptech.glide.Glide import com.bumptech.glide.RequestBuilder +import com.bumptech.glide.load.model.GlideUrl +import com.bumptech.glide.request.target.CustomViewTarget +import com.bumptech.glide.request.transition.Transition +import com.davemorrissey.labs.subscaleview.ImageSource +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.google.android.material.snackbar.Snackbar +import com.karumi.dexter.Dexter +import com.karumi.dexter.listener.PermissionDeniedResponse +import com.karumi.dexter.listener.PermissionGrantedResponse +import com.karumi.dexter.listener.single.BasePermissionListener +import kotlinx.coroutines.launch import org.pixeldroid.app.R import org.pixeldroid.app.databinding.AlbumImageViewBinding +import org.pixeldroid.app.databinding.OpenedAlbumBinding import org.pixeldroid.app.databinding.PostFragmentBinding +import org.pixeldroid.app.posts.MediaViewerActivity.Companion.openActivity import org.pixeldroid.app.utils.BlurHashDecoder import org.pixeldroid.app.utils.ImageConverter import org.pixeldroid.app.utils.api.PixelfedAPI @@ -32,15 +51,8 @@ import org.pixeldroid.app.utils.api.objects.Status.Companion.POST_TAG import org.pixeldroid.app.utils.api.objects.Status.Companion.VIEW_COMMENTS_TAG import org.pixeldroid.app.utils.db.AppDatabase import org.pixeldroid.app.utils.di.PixelfedAPIHolder -import com.karumi.dexter.Dexter -import com.karumi.dexter.listener.PermissionDeniedResponse -import com.karumi.dexter.listener.PermissionGrantedResponse -import com.karumi.dexter.listener.single.BasePermissionListener -import kotlinx.coroutines.launch -import org.pixeldroid.app.posts.MediaViewerActivity.Companion.VIDEO_DESCRIPTION_TAG -import org.pixeldroid.app.posts.MediaViewerActivity.Companion.VIDEO_URL_TAG -import org.pixeldroid.app.posts.MediaViewerActivity.Companion.openActivity import retrofit2.HttpException +import java.io.File import java.io.IOException import kotlin.math.roundToInt @@ -88,7 +100,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold private fun setupPost( request: RequestBuilder, domain: String, - isActivity: Boolean + isActivity: Boolean, ) { //Setup username as a button that opens the profile binding.username.apply { @@ -148,9 +160,9 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold binding.postPager.visibility = View.VISIBLE //Attach the given tabs to the view pager - binding.postPager.adapter = AlbumViewPagerAdapter(status?.media_attachments ?: emptyList(), status?.sensitive) + binding.postPager.adapter = AlbumViewPagerAdapter(status?.media_attachments ?: emptyList(), status?.sensitive, false) - if(status?.media_attachments?.size ?: 0 > 1) { + if((status?.media_attachments?.size ?: 0) > 1) { binding.postIndicator.setViewPager(binding.postPager) binding.postIndicator.visibility = View.VISIBLE } else { @@ -206,7 +218,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold apiHolder: PixelfedAPIHolder, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope, - isActivity: Boolean + isActivity: Boolean, ){ //Set the special HTML text setDescription(apiHolder, lifecycleScope) @@ -459,36 +471,28 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold } } - //Activate double tap liking - var clicked = false + //Activate tap interactions (double and single) binding.postPagerHost.doubleTapCallback = { - if(!it) clicked = false - else lifecycleScope.launchWhenCreated { + lifecycleScope.launchWhenCreated { //Check that the post isn't hidden - if(binding.sensitiveWarning.visibility == View.GONE) { - //Check for double click - if(clicked) { - val api: PixelfedAPI = apiHolder.api ?: apiHolder.setToCurrentUser() - if (binding.liker.isChecked) { - // Button is active, unlike - binding.liker.isChecked = false - unLikePostCall(api) - } else { - // Button is inactive, like - binding.liker.playAnimation() - binding.liker.isChecked = true - binding.likeAnimation.animateView() - likePostCall(api) - } + if (binding.sensitiveWarning.visibility == View.GONE) { + val api: PixelfedAPI = apiHolder.api ?: apiHolder.setToCurrentUser() + if (binding.liker.isChecked) { + // Button is active, unlike + binding.liker.isChecked = false + unLikePostCall(api) } else { - clicked = true - - //Reset clicked to false after 500ms - binding.postPager.handler.postDelayed(fun() { clicked = false }, 500) + // Button is inactive, like + binding.liker.playAnimation() + binding.liker.isChecked = true + binding.likeAnimation.animateView() + likePostCall(api) } } } } + status?.media_attachments?.let { binding.postPagerHost.images = ArrayList(it) } + } private fun ImageView.animateView() { visibility = View.VISIBLE @@ -544,8 +548,8 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold //endregion private fun showComments( - lifecycleScope: LifecycleCoroutineScope, - isActivity: Boolean + lifecycleScope: LifecycleCoroutineScope, + isActivity: Boolean, ) { //Show number of comments on the post if (status?.replies_count == 0) { @@ -584,14 +588,20 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold } } -private class AlbumViewPagerAdapter(private val media_attachments: List, private var sensitive: Boolean?) : +class AlbumViewPagerAdapter( + private val media_attachments: List, private var sensitive: Boolean?, + private val opened: Boolean, //TODO if opened don't open again, and use PhotoView instead of shite +) : RecyclerView.Adapter() { + private var isActionBarHidden: Boolean = false + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val itemBinding = AlbumImageViewBinding.inflate( + return if(!opened) ViewHolderClosed(AlbumImageViewBinding.inflate( LayoutInflater.from(parent.context), parent, false - ) - return ViewHolder(itemBinding) + )) else ViewHolderOpen(OpenedAlbumBinding.inflate( + LayoutInflater.from(parent.context), parent, false + )) } override fun getItemCount() = media_attachments.size @@ -608,19 +618,52 @@ private class AlbumViewPagerAdapter(private val media_attachments: List((holder.image as SubsamplingScaleImageView)) { + override fun onResourceReady(resource: File, t: Transition?) = + view.setImage(ImageSource.uri(Uri.fromFile(resource))) + override fun onLoadFailed(errorDrawable: Drawable?) {} + override fun onResourceCleared(placeholder: Drawable?) {} + }) + (holder.image as SubsamplingScaleImageView).apply { + setMinimumDpi(80) + setDoubleTapZoomDpi(240) + resetScaleAndCenter() + } + holder.image.setOnClickListener { + val windowInsetsController = WindowCompat.getInsetsController((it.context as Activity).window, it) + // Configure the behavior of the hidden system bars + if (isActionBarHidden) { + windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + // Hide both the status bar and the navigation bar + (it.context as AppCompatActivity).supportActionBar?.show() + windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) + isActionBarHidden = false + } else { + // Configure the behavior of the hidden system bars + windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + // Hide both the status bar and the navigation bar + (it.context as AppCompatActivity).supportActionBar?.hide() + windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) + isActionBarHidden = true + } + } + } + else Glide.with(holder.binding.root) .asDrawable().fitCenter() .placeholder(blurhashBitMap) - .load(imageUrl).into(holder.image) - } else { + .load(imageUrl).into(holder.image as ImageView) + } else if(!opened){ Glide.with(holder.binding.root) .asDrawable().fitCenter() - .load(blurhashBitMap).into(holder.image) + .load(blurhashBitMap).into(holder.image as ImageView) } holder.videoPlayButton.visibility = if(video) View.VISIBLE else View.GONE - if(video){ + if(video && (opened || media_attachments.size == 1)){ holder.videoPlayButton.setOnClickListener { openActivity(holder.binding.root.context, url, description) } @@ -646,9 +689,17 @@ private class AlbumViewPagerAdapter(private val media_attachments: List + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/opened_album.xml b/app/src/main/res/layout/opened_album.xml new file mode 100644 index 00000000..5f2dcc9f --- /dev/null +++ b/app/src/main/res/layout/opened_album.xml @@ -0,0 +1,26 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 2b32ba41..20fc5dc0 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -21,6 +21,19 @@ @android:style/TextAppearance.Large + +