Kotlin: use orEmpty() for Maps

This commit is contained in:
Benoit Marty 2020-05-25 15:21:31 +02:00
parent e793a46576
commit 53c7ea2831
3 changed files with 59 additions and 25 deletions

View File

@ -16,6 +16,7 @@ Bugfix 🐛:
- Fix issues with FontScale switch (#69, #645) - Fix issues with FontScale switch (#69, #645)
- "Seen by" uses 12h time (#1378) - "Seen by" uses 12h time (#1378)
- Enable markdown (if active) when sending emote (#734) - Enable markdown (if active) when sending emote (#734)
- Screenshots for Rageshake now includes Dialogs such as BottomSheet (#1349)
Translations 🗣: Translations 🗣:
- -

View File

@ -80,5 +80,12 @@ fun <T : Fragment> VectorBaseFragment.addChildFragmentToBackstack(frameId: Int,
} }
} }
/**
* Return a list of all child Fragments, recursively
*/
fun Fragment.getAllChildFragments(): List<Fragment> {
return listOf(this) + childFragmentManager.fragments.map { it.getAllChildFragments() }.flatten()
}
// Define a missing constant // Define a missing constant
const val POP_BACK_STACK_EXCLUSIVE = 0 const val POP_BACK_STACK_EXCLUSIVE = 0

View File

@ -19,17 +19,20 @@
package im.vector.riotx.features.rageshake package im.vector.riotx.features.rageshake
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Canvas
import android.os.AsyncTask import android.os.AsyncTask
import android.os.Build import android.os.Build
import android.view.View import android.view.View
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentActivity
import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.Matrix
import im.vector.riotx.BuildConfig import im.vector.riotx.BuildConfig
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.di.ActiveSessionHolder
import im.vector.riotx.core.extensions.getAllChildFragments
import im.vector.riotx.core.extensions.toOnOff import im.vector.riotx.core.extensions.toOnOff
import im.vector.riotx.features.settings.VectorLocale import im.vector.riotx.features.settings.VectorLocale
import im.vector.riotx.features.settings.VectorPreferences import im.vector.riotx.features.settings.VectorPreferences
@ -423,7 +426,7 @@ class BugReporter @Inject constructor(
/** /**
* Send a bug report either with email or with Vector. * Send a bug report either with email or with Vector.
*/ */
fun openBugReportScreen(activity: Activity, forSuggestion: Boolean = false) { fun openBugReportScreen(activity: FragmentActivity, forSuggestion: Boolean = false) {
screenshot = takeScreenshot(activity) screenshot = takeScreenshot(activity)
val intent = Intent(activity, BugReportActivity::class.java) val intent = Intent(activity, BugReportActivity::class.java)
@ -512,41 +515,64 @@ class BugReporter @Inject constructor(
* *
* @return the screenshot * @return the screenshot
*/ */
private fun takeScreenshot(activity: Activity): Bitmap? { private fun takeScreenshot(activity: FragmentActivity): Bitmap? {
// get content view
val contentView = activity.findViewById<View>(android.R.id.content)
if (contentView == null) {
Timber.e("Cannot find content view on $activity. Cannot take screenshot.")
return null
}
// get the root view to snapshot // get the root view to snapshot
val rootView = contentView.rootView val rootView = activity.window?.decorView?.rootView
if (rootView == null) { if (rootView == null) {
Timber.e("Cannot find root view on $activity. Cannot take screenshot.") Timber.e("Cannot find root view on $activity. Cannot take screenshot.")
return null return null
} }
// refresh it
val mainBitmap = getBitmap(rootView)
if (mainBitmap == null) {
Timber.e("Cannot get main screenshot")
return null
}
try {
val cumulBitmap = Bitmap.createBitmap(mainBitmap.width, mainBitmap.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(cumulBitmap)
canvas.drawBitmap(mainBitmap, 0f, 0f, null)
// Add the dialogs if any
getDialogBitmaps(activity).forEach {
canvas.drawBitmap(it, 0f, 0f, null)
}
return cumulBitmap
} catch (e: Throwable) {
Timber.e(e, "Cannot get snapshot of screen: $e")
}
return null
}
private fun getDialogBitmaps(activity: FragmentActivity): List<Bitmap> {
return activity.supportFragmentManager.fragments
.map { it.getAllChildFragments() }
.flatten()
.filterIsInstance(DialogFragment::class.java)
.mapNotNull { fragment ->
fragment.dialog?.window?.decorView?.rootView?.let { rootView ->
getBitmap(rootView)
}
}
}
private fun getBitmap(rootView: View): Bitmap? {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
rootView.isDrawingCacheEnabled = false rootView.isDrawingCacheEnabled = false
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
rootView.isDrawingCacheEnabled = true rootView.isDrawingCacheEnabled = true
try { return try {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
var bitmap = rootView.drawingCache rootView.drawingCache
} catch (e: Throwable) {
// Make a copy, because if Activity is destroyed, the bitmap will be recycled Timber.e(e, "Cannot get snapshot of dialog: $e")
bitmap = Bitmap.createBitmap(bitmap) null
return bitmap
} catch (oom: OutOfMemoryError) {
Timber.e(oom, "Cannot get drawing cache for $activity OOM.")
} catch (e: Exception) {
Timber.e(e, "Cannot get snapshot of screen: $e")
} }
return null
} }
// ============================================================================================================== // ==============================================================================================================