diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt b/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt index a20526e959..15374f96d1 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/AccountsInListFragment.kt @@ -1,4 +1,4 @@ -/* Copyright 2017 Andrew Dawson +/* Copyright 2023 Tusky contributors * * This file is a part of Tusky. * @@ -20,9 +20,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.LinearLayout import androidx.appcompat.widget.SearchView -import androidx.fragment.app.DialogFragment import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.preference.PreferenceManager @@ -43,6 +41,7 @@ import com.keylesspalace.tusky.util.loadAvatar import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.viewBinding +import com.keylesspalace.tusky.view.FullScreenDialogFragment import com.keylesspalace.tusky.viewmodel.AccountsInListViewModel import com.keylesspalace.tusky.viewmodel.State import kotlinx.coroutines.launch @@ -50,7 +49,7 @@ import javax.inject.Inject private typealias AccountInfo = Pair -class AccountsInListFragment : DialogFragment(), Injectable { +class AccountsInListFragment : FullScreenDialogFragment(), Injectable { @Inject lateinit var viewModelFactory: ViewModelFactory @@ -78,14 +77,6 @@ class AccountsInListFragment : DialogFragment(), Injectable { viewModel.load(listId) } - override fun onStart() { - super.onStart() - dialog?.apply { - // Stretch dialog to the window - window?.setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT) - } - } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_accounts_in_list, container, false) } @@ -257,3 +248,4 @@ class AccountsInListFragment : DialogFragment(), Injectable { } } } + diff --git a/app/src/main/java/com/keylesspalace/tusky/components/account/list/ListsForAccountFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/account/list/ListsForAccountFragment.kt index 08c93756b9..8fa54e4f6c 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/account/list/ListsForAccountFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/account/list/ListsForAccountFragment.kt @@ -20,8 +20,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.LinearLayout -import androidx.fragment.app.DialogFragment import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.DiffUtil @@ -38,11 +36,12 @@ import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.visible +import com.keylesspalace.tusky.view.FullScreenDialogFragment import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import javax.inject.Inject -class ListsForAccountFragment : DialogFragment(), Injectable { +class ListsForAccountFragment : FullScreenDialogFragment(), Injectable { @Inject lateinit var viewModelFactory: ViewModelFactory @@ -59,16 +58,6 @@ class ListsForAccountFragment : DialogFragment(), Injectable { viewModel.setup(requireArguments().getString(ARG_ACCOUNT_ID)!!) } - override fun onStart() { - super.onStart() - dialog?.apply { - window?.setLayout( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT - ) - } - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/dialog/CaptionDialog.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/dialog/CaptionDialog.kt index 3b6399d197..519044c48d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/compose/dialog/CaptionDialog.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/dialog/CaptionDialog.kt @@ -25,10 +25,8 @@ import android.view.View import android.view.ViewGroup import android.view.WindowManager import android.widget.EditText -import android.widget.LinearLayout import androidx.core.os.BundleCompat import androidx.core.os.bundleOf -import androidx.fragment.app.DialogFragment import com.bumptech.glide.Glide import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy import com.bumptech.glide.request.target.CustomTarget @@ -37,11 +35,12 @@ import com.keylesspalace.tusky.R import com.keylesspalace.tusky.databinding.DialogImageDescriptionBinding import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.viewBinding +import com.keylesspalace.tusky.view.FullScreenDialogFragment // https://github.com/tootsuite/mastodon/blob/c6904c0d3766a2ea8a81ab025c127169ecb51373/app/models/media_attachment.rb#L32 private const val MEDIA_DESCRIPTION_CHARACTER_LIMIT = 1500 -class CaptionDialog : DialogFragment() { +class CaptionDialog : FullScreenDialogFragment() { private lateinit var listener: Listener private lateinit var input: EditText @@ -116,10 +115,6 @@ class CaptionDialog : DialogFragment() { override fun onStart() { super.onStart() dialog?.apply { - window?.setLayout( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT - ) window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) } } diff --git a/app/src/main/java/com/keylesspalace/tusky/util/ViewExtensions.kt b/app/src/main/java/com/keylesspalace/tusky/util/ViewExtensions.kt index 392f65b770..e61137346a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/ViewExtensions.kt +++ b/app/src/main/java/com/keylesspalace/tusky/util/ViewExtensions.kt @@ -16,11 +16,14 @@ package com.keylesspalace.tusky.util +import android.content.res.Resources import android.util.Log +import android.util.TypedValue import android.view.View import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 +import kotlin.math.roundToInt fun View.show() { this.visibility = View.VISIBLE @@ -78,3 +81,15 @@ fun TextView.fixTextSelection() { setTextIsSelectable(false) post { setTextIsSelectable(true) } } + +fun Float.dpToPx(resource: Resources): Float { + return TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + this, + resource.displayMetrics + ) +} + +fun Int.dpToPx(resource: Resources): Int { + return this.toFloat().dpToPx(resource).roundToInt() +} diff --git a/app/src/main/java/com/keylesspalace/tusky/view/FullScreenDialogFragment.kt b/app/src/main/java/com/keylesspalace/tusky/view/FullScreenDialogFragment.kt new file mode 100644 index 0000000000..73536f9366 --- /dev/null +++ b/app/src/main/java/com/keylesspalace/tusky/view/FullScreenDialogFragment.kt @@ -0,0 +1,55 @@ +package com.keylesspalace.tusky.view + +import android.util.Size +import android.view.ViewGroup +import android.view.Window +import android.view.WindowInsets +import androidx.fragment.app.DialogFragment +import com.keylesspalace.tusky.R +import com.keylesspalace.tusky.util.dpToPx + +open class FullScreenDialogFragment : DialogFragment() { + /** + * Make sure the dialog window is full screen (minus normal insets like a device status bar). + * + * However the size is bounded to a maximum of `max_dialog_width_dp` and `max_dialog_height_dp` from the resources. + * So for example on tablet it does not fill the whole space. + */ + override fun onStart() { + super.onStart() + dialog?.apply { + window?.apply { + // On smaller devices this is -1 which is MATCH_PARENT + val maxWidthDp = resources.getInteger(R.integer.max_dialog_width_dp) + val maxHeightDp = resources.getInteger(R.integer.max_dialog_height_dp) + + if (maxWidthDp == ViewGroup.LayoutParams.MATCH_PARENT && maxHeightDp == ViewGroup.LayoutParams.MATCH_PARENT) { + this.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + } else { + val maxAvailablePixels = getAvailableScreenPixels(this) + + var maxWidthSpec = if (maxWidthDp == -1) maxWidthDp else maxWidthDp.dpToPx(this.context.resources) + if (maxWidthSpec > maxAvailablePixels.width) { + maxWidthSpec = maxAvailablePixels.width + } + var maxHeightSpec = if (maxHeightDp == -1) maxHeightDp else maxHeightDp.dpToPx(this.context.resources) + if (maxHeightSpec > maxAvailablePixels.height) { + maxHeightSpec = maxAvailablePixels.height + } + + this.setLayout(maxWidthSpec, maxHeightSpec) + } + } + } + } + + private fun getAvailableScreenPixels(window: Window): Size { + val windowInsets = window.windowManager.maximumWindowMetrics.windowInsets + val insets = windowInsets.getInsets(WindowInsets.Type.captionBar() or WindowInsets.Type.systemBars() or + WindowInsets.Type.navigationBars() or WindowInsets.Type.statusBars()) + val maxAvailableDeviceWidth = window.context.resources.displayMetrics.widthPixels - insets.left - insets.right + val maxAvailableDeviceHeight = window.context.resources.displayMetrics.heightPixels - insets.top - insets.bottom + + return Size(maxAvailableDeviceWidth, maxAvailableDeviceHeight) + } +} diff --git a/app/src/main/res/values-large-land/integers.xml b/app/src/main/res/values-large-land/integers.xml new file mode 100644 index 0000000000..35e8a5002f --- /dev/null +++ b/app/src/main/res/values-large-land/integers.xml @@ -0,0 +1,5 @@ + + + 800 + 1000 + diff --git a/app/src/main/res/values-large/integers.xml b/app/src/main/res/values-large/integers.xml new file mode 100644 index 0000000000..5e9c4e9883 --- /dev/null +++ b/app/src/main/res/values-large/integers.xml @@ -0,0 +1,5 @@ + + + 600 + 1200 + diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml index e85c561cf5..ae2cced5ac 100644 --- a/app/src/main/res/values/integers.xml +++ b/app/src/main/res/values/integers.xml @@ -1,6 +1,7 @@ + -1 + -1 3 - 1