mirror of
https://github.com/bitfireAT/davx5-ose
synced 2024-10-15 15:59:18 +00:00
Migrate DebugInfoActivity
to Compose (#509)
* Gave more flexibility Signed-off-by: Arnau Mora <arnyminerz@proton.me> * Migrated to Compose Signed-off-by: Arnau Mora <arnyminerz@proton.me> * Adjusted paddings Signed-off-by: Arnau Mora <arnyminerz@proton.me> * Added missing observer Signed-off-by: Arnau Mora <arnyminerz@proton.me> * CardWithImagE: add another preview with subtitle, icon and content * Made buttons uppercase Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me> * Adjusted spacings Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me> * Changed snackbar host state Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me> * Changed nullable expression Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me> * Using shareFile for zip Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me> * Minor changes (comments/formatting) * Switched to view instead of sharing files Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me> * Adapted image height for landscape Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me> * CardView: allow to pass image alignment; use card_theme_max_height * DebugInfoActivity: paddings, images --------- Signed-off-by: Arnau Mora <arnyminerz@proton.me> Signed-off-by: Arnau Mora Gras <arnyminerz@proton.me> Co-authored-by: Ricki Hirner <hirner@bitfire.at>
This commit is contained in:
parent
3c4601f7a1
commit
b8f4b9af30
|
@ -3,31 +3,72 @@
|
|||
**************************************************************************************************/
|
||||
|
||||
package at.bitfire.davdroid.ui
|
||||
|
||||
import android.accounts.Account
|
||||
import android.accounts.AccountManager
|
||||
import android.app.Application
|
||||
import android.app.usage.UsageStatsManager
|
||||
import android.content.*
|
||||
import android.content.ContentProviderClient
|
||||
import android.content.ContentResolver
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Uri
|
||||
import android.os.*
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.os.LocaleList
|
||||
import android.os.PowerManager
|
||||
import android.os.StatFs
|
||||
import android.provider.CalendarContract
|
||||
import android.provider.ContactsContract
|
||||
import android.text.format.DateUtils
|
||||
import android.view.View
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material.FloatingActionButton
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.LinearProgressIndicator
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.SnackbarDuration
|
||||
import androidx.compose.material.SnackbarHost
|
||||
import androidx.compose.material.SnackbarHostState
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Adb
|
||||
import androidx.compose.material.icons.rounded.BugReport
|
||||
import androidx.compose.material.icons.rounded.Info
|
||||
import androidx.compose.material.icons.rounded.Share
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.BiasAlignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.app.ShareCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.content.pm.PackageInfoCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.*
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkQuery
|
||||
import at.bitfire.dav4jvm.exception.DavException
|
||||
|
@ -36,7 +77,6 @@ import at.bitfire.davdroid.BuildConfig
|
|||
import at.bitfire.davdroid.InvalidAccountException
|
||||
import at.bitfire.davdroid.R
|
||||
import at.bitfire.davdroid.TextTable
|
||||
import at.bitfire.davdroid.databinding.ActivityDebugInfoBinding
|
||||
import at.bitfire.davdroid.db.AppDatabase
|
||||
import at.bitfire.davdroid.log.Logger
|
||||
import at.bitfire.davdroid.resource.LocalAddressBook
|
||||
|
@ -44,10 +84,11 @@ import at.bitfire.davdroid.settings.AccountSettings
|
|||
import at.bitfire.davdroid.settings.SettingsManager
|
||||
import at.bitfire.davdroid.syncadapter.PeriodicSyncWorker
|
||||
import at.bitfire.davdroid.syncadapter.SyncWorker
|
||||
import at.bitfire.davdroid.ui.widget.CardWithImage
|
||||
import at.bitfire.ical4android.TaskProvider
|
||||
import at.bitfire.ical4android.TaskProvider.ProviderName
|
||||
import at.techbee.jtx.JtxContract
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.accompanist.themeadapter.material.MdcTheme
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
@ -61,7 +102,11 @@ import org.apache.commons.io.IOUtils
|
|||
import org.apache.commons.lang3.StringUtils
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils
|
||||
import org.dmfs.tasks.contract.TaskContract
|
||||
import java.io.*
|
||||
import java.io.File
|
||||
import java.io.IOError
|
||||
import java.io.IOException
|
||||
import java.io.StringReader
|
||||
import java.io.Writer
|
||||
import java.util.TimeZone
|
||||
import java.util.logging.Level
|
||||
import java.util.zip.ZipEntry
|
||||
|
@ -120,22 +165,109 @@ class DebugInfoActivity : AppCompatActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val binding = DataBindingUtil.setContentView<ActivityDebugInfoBinding>(this, R.layout.activity_debug_info)
|
||||
binding.model = model
|
||||
binding.lifecycleOwner = this
|
||||
model.zipFile.observe(this) { zipFile ->
|
||||
if (zipFile == null) return@observe
|
||||
|
||||
model.cause.observe(this) { cause ->
|
||||
if (cause == null)
|
||||
return@observe
|
||||
// ZIP file is ready
|
||||
shareFile(
|
||||
zipFile,
|
||||
subject = "${getString(R.string.app_name)} ${BuildConfig.VERSION_NAME} debug info",
|
||||
text = getString(R.string.debug_info_attached),
|
||||
type = "*/*", // application/zip won't show all apps that can manage binary files, like ShareViaHttp
|
||||
)
|
||||
|
||||
binding.causeCaption.text = when (cause) {
|
||||
is HttpException -> getString(if (cause.code / 100 == 5) R.string.debug_info_server_error else R.string.debug_info_http_error)
|
||||
is DavException -> getString(R.string.debug_info_webdav_error)
|
||||
is IOException, is IOError -> getString(R.string.debug_info_io_error)
|
||||
else -> cause::class.java.simpleName
|
||||
// only share ZIP file once
|
||||
model.zipFile.value = null
|
||||
}
|
||||
|
||||
binding.causeText.text = getString(
|
||||
setContent {
|
||||
MdcTheme {
|
||||
val debugInfo by model.debugInfo.observeAsState()
|
||||
val zipProgress by model.zipProgress.observeAsState(false)
|
||||
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
|
||||
Scaffold(
|
||||
floatingActionButton = {
|
||||
if (debugInfo != null && !zipProgress) {
|
||||
FloatingActionButton(
|
||||
onClick = model::generateZip
|
||||
) {
|
||||
Icon(Icons.Rounded.Share, stringResource(R.string.share))
|
||||
}
|
||||
}
|
||||
},
|
||||
snackbarHost = {
|
||||
SnackbarHost(hostState = snackbarHostState)
|
||||
}
|
||||
) { paddingValues ->
|
||||
val error by model.error.observeAsState()
|
||||
LaunchedEffect(error) {
|
||||
error?.let {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = it,
|
||||
duration = SnackbarDuration.Long
|
||||
)
|
||||
|
||||
model.error.value = null
|
||||
}
|
||||
}
|
||||
|
||||
Content(paddingValues)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Content(paddingValues: PaddingValues) {
|
||||
val debugInfo by model.debugInfo.observeAsState()
|
||||
val zipProgress by model.zipProgress.observeAsState(false)
|
||||
val modelCause by model.cause.observeAsState()
|
||||
val localResource by model.localResource.observeAsState()
|
||||
val remoteResource by model.remoteResource.observeAsState()
|
||||
val logFile by model.logFile.observeAsState()
|
||||
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
) {
|
||||
if (debugInfo == null) item { LinearProgressIndicator() }
|
||||
if (debugInfo != null) {
|
||||
if (zipProgress) item { LinearProgressIndicator() }
|
||||
item {
|
||||
CardWithImage(
|
||||
image = painterResource(R.drawable.undraw_server_down),
|
||||
imageAlignment = BiasAlignment(0f, .7f),
|
||||
title = stringResource(R.string.debug_info_archive_caption),
|
||||
subtitle = stringResource(R.string.debug_info_archive_subtitle),
|
||||
message = stringResource(R.string.debug_info_archive_text),
|
||||
icon = Icons.Rounded.Share,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||
) {
|
||||
TextButton(
|
||||
onClick = model::generateZip,
|
||||
enabled = !zipProgress
|
||||
) {
|
||||
Text(
|
||||
stringResource(R.string.debug_info_archive_share).uppercase()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
modelCause?.let { cause ->
|
||||
item {
|
||||
CardWithImage(
|
||||
title = when (cause) {
|
||||
is HttpException -> stringResource(if (cause.code / 100 == 5) R.string.debug_info_server_error else R.string.debug_info_http_error)
|
||||
is DavException -> stringResource(R.string.debug_info_webdav_error)
|
||||
is IOException, is IOError -> stringResource(R.string.debug_info_io_error)
|
||||
else -> cause::class.java.simpleName
|
||||
},
|
||||
subtitle = cause.localizedMessage,
|
||||
message = stringResource(
|
||||
if (cause is HttpException)
|
||||
when {
|
||||
cause.code == 403 -> R.string.debug_info_http_403_description
|
||||
|
@ -145,76 +277,124 @@ class DebugInfoActivity : AppCompatActivity() {
|
|||
}
|
||||
else
|
||||
R.string.debug_info_unexpected_error
|
||||
),
|
||||
icon = Icons.Rounded.Info,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||
) {
|
||||
TextButton(
|
||||
enabled = debugInfo != null,
|
||||
onClick = { viewFile(debugInfo!!) }
|
||||
) {
|
||||
Text(
|
||||
stringResource(R.string.debug_info_view_details).uppercase()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debugInfo?.let { info ->
|
||||
item {
|
||||
CardWithImage(
|
||||
title = stringResource(R.string.debug_info_title),
|
||||
subtitle = stringResource(R.string.debug_info_subtitle),
|
||||
icon = Icons.Rounded.BugReport,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||
) {
|
||||
TextButton(
|
||||
onClick = { viewFile(info) }
|
||||
) {
|
||||
Text(
|
||||
stringResource(R.string.debug_info_view_details).uppercase()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (localResource != null || remoteResource != null) item {
|
||||
CardWithImage(
|
||||
title = stringResource(R.string.debug_info_involved_caption),
|
||||
subtitle = stringResource(R.string.debug_info_involved_subtitle),
|
||||
icon = Icons.Rounded.Adb,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||
) {
|
||||
remoteResource?.let {
|
||||
Text(
|
||||
text = stringResource(R.string.debug_info_involved_remote),
|
||||
style = MaterialTheme.typography.body1
|
||||
)
|
||||
Text(
|
||||
text = it,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
)
|
||||
}
|
||||
localResource?.let {
|
||||
Text(
|
||||
text = stringResource(R.string.debug_info_involved_local),
|
||||
style = MaterialTheme.typography.body1
|
||||
)
|
||||
Text(
|
||||
text = it,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
logFile?.let { logs ->
|
||||
item {
|
||||
CardWithImage(
|
||||
title = stringResource(R.string.debug_info_logs_caption),
|
||||
subtitle = stringResource(R.string.debug_info_logs_subtitle),
|
||||
icon = Icons.Rounded.BugReport,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||
) {
|
||||
TextButton(
|
||||
onClick = { shareFile(logs) }
|
||||
) {
|
||||
Text(
|
||||
stringResource(R.string.debug_info_logs_view).uppercase()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model.debugInfo.observe(this) { debugInfo ->
|
||||
val showDebugInfo = View.OnClickListener {
|
||||
private fun shareFile(
|
||||
file: File,
|
||||
subject: String? = null,
|
||||
text: String? = null,
|
||||
type: String = "text/plain"
|
||||
) {
|
||||
val uri = FileProvider.getUriForFile(
|
||||
this,
|
||||
getString(R.string.authority_debug_provider),
|
||||
debugInfo
|
||||
file
|
||||
)
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.setDataAndType(uri, "text/plain")
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
startActivity(Intent.createChooser(intent, null))
|
||||
}
|
||||
binding.causeView.setOnClickListener(showDebugInfo)
|
||||
binding.debugInfoView.setOnClickListener(showDebugInfo)
|
||||
|
||||
binding.fab.apply {
|
||||
setOnClickListener { shareArchive() }
|
||||
isEnabled = true
|
||||
}
|
||||
binding.zipShare.setOnClickListener { shareArchive() }
|
||||
ShareCompat.IntentBuilder(this)
|
||||
.setSubject(subject)
|
||||
.setText(text)
|
||||
.setType(type)
|
||||
.setStream(uri)
|
||||
.startChooser()
|
||||
}
|
||||
|
||||
model.logFile.observe(this) { logs ->
|
||||
binding.logsView.setOnClickListener {
|
||||
val uri = FileProvider.getUriForFile(this, getString(R.string.authority_debug_provider), logs)
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.setDataAndType(uri, "text/plain")
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
startActivity(Intent.createChooser(intent, null))
|
||||
}
|
||||
}
|
||||
|
||||
model.zipFile.observe(this) { zipFile ->
|
||||
if (zipFile != null) {
|
||||
// ZIP file is ready
|
||||
val builder = ShareCompat.IntentBuilder(this)
|
||||
.setSubject("${getString(R.string.app_name)} ${BuildConfig.VERSION_NAME} debug info")
|
||||
.setText(getString(R.string.debug_info_attached))
|
||||
.setType("*/*") // application/zip won't show all apps that can manage binary files, like ShareViaHttp
|
||||
.setStream(
|
||||
FileProvider.getUriForFile(
|
||||
private fun viewFile(
|
||||
file: File,
|
||||
title: String? = null
|
||||
) {
|
||||
val uri = FileProvider.getUriForFile(
|
||||
this,
|
||||
getString(R.string.authority_debug_provider),
|
||||
zipFile
|
||||
file
|
||||
)
|
||||
)
|
||||
builder.intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
builder.startChooser()
|
||||
|
||||
// Not beautiful, because it changes model data from the view.
|
||||
// See https://github.com/android/architecture-components-samples/issues/63
|
||||
model.zipFile.value = null
|
||||
val intent = Intent(Intent.ACTION_VIEW).apply {
|
||||
setDataAndType(uri, "text/plain")
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
}
|
||||
|
||||
model.error.observe(this) { message ->
|
||||
if (message != null) {
|
||||
Snackbar.make(binding.fab, message, Snackbar.LENGTH_LONG).show()
|
||||
|
||||
// Reset error message so that it won't be shown when activity is re-created
|
||||
model.error.value = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun shareArchive() {
|
||||
model.generateZip()
|
||||
startActivity(Intent.createChooser(intent, title))
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.BiasAlignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
|
@ -209,6 +210,7 @@ fun TasksCard(
|
|||
) {
|
||||
CardWithImage(
|
||||
image = painterResource(R.drawable.intro_tasks),
|
||||
imageAlignment = BiasAlignment(0f, .1f),
|
||||
title = stringResource(R.string.intro_tasks_title),
|
||||
message = stringResource(R.string.intro_tasks_text1),
|
||||
modifier = Modifier
|
||||
|
|
|
@ -4,60 +4,113 @@
|
|||
|
||||
package at.bitfire.davdroid.ui.widget
|
||||
|
||||
import android.content.res.Configuration.ORIENTATION_PORTRAIT
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.TabletAndroid
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.BiasAlignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import at.bitfire.davdroid.R
|
||||
|
||||
@Composable
|
||||
fun CardWithImage(
|
||||
image: Painter,
|
||||
title: String,
|
||||
message: String,
|
||||
modifier: Modifier = Modifier,
|
||||
image: Painter? = null,
|
||||
imageContentDescription: String? = null,
|
||||
imageAlignment: Alignment = Alignment.Center,
|
||||
message: String? = null,
|
||||
subtitle: String? = null,
|
||||
icon: ImageVector? = null,
|
||||
iconContentDescription: String? = null,
|
||||
content: @Composable ColumnScope.() -> Unit = {}
|
||||
) {
|
||||
val configuration = LocalConfiguration.current
|
||||
|
||||
Card(modifier) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
image?.let {
|
||||
Image(
|
||||
painter = image,
|
||||
painter = it,
|
||||
contentDescription = imageContentDescription,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(max = dimensionResource(R.dimen.card_theme_max_height)),
|
||||
contentScale = ContentScale.Crop,
|
||||
alignment = imageAlignment
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
icon?.let {
|
||||
Icon(
|
||||
imageVector = it,
|
||||
contentDescription = iconContentDescription,
|
||||
modifier = Modifier
|
||||
.size(44.dp)
|
||||
.padding(end = 12.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Column(Modifier.fillMaxWidth()) {
|
||||
Text(
|
||||
text = title,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
style = MaterialTheme.typography.h6
|
||||
)
|
||||
subtitle?.let {
|
||||
Text(
|
||||
text = message,
|
||||
text = it,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
style = MaterialTheme.typography.subtitle1
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
message?.let {
|
||||
Text(
|
||||
text = it,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 12.dp),
|
||||
.padding(top = 12.dp),
|
||||
style = MaterialTheme.typography.body1
|
||||
)
|
||||
}
|
||||
|
||||
content()
|
||||
}
|
||||
|
@ -67,10 +120,34 @@ fun CardWithImage(
|
|||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CardWithImagePreview() {
|
||||
fun CardWithImage_Preview() {
|
||||
CardWithImage(
|
||||
image = painterResource(R.drawable.intro_tasks),
|
||||
title = "Demo card",
|
||||
message = "This is the message to be displayed under the title, but before the content."
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CardWithImage_Preview_WithIconAndSubtitleAndContent() {
|
||||
CardWithImage(
|
||||
title = "Demo card",
|
||||
icon = Icons.Default.TabletAndroid,
|
||||
subtitle = "Subtitle",
|
||||
message = "This is the message to be displayed under the title, but before the content."
|
||||
) {
|
||||
Text("Content")
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CardWithImage_Preview_WithIconAndContentNoMessage() {
|
||||
CardWithImage(
|
||||
title = "Demo card",
|
||||
icon = Icons.Default.TabletAndroid
|
||||
) {
|
||||
Text("Content")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,489 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".ui.DebugInfoActivity">
|
||||
<data>
|
||||
<import type="android.view.View"/>
|
||||
<variable
|
||||
name="model"
|
||||
type="at.bitfire.davdroid.ui.DebugInfoActivity.ReportModel"/>
|
||||
</data>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/activity_margin"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||
android:visibility="@{model.debugInfo == null ? View.VISIBLE : View.GONE}"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="@{model.debugInfo != null ? View.VISIBLE : View.GONE}">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/card_padding">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/zipStart"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_begin="@dimen/card_padding" />
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/zipEnd"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_end="@dimen/card_padding" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/zipProgress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:indeterminate="true"
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||
android:visibility="@{model.zipProgress ? View.VISIBLE : View.GONE}"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/zipIcon"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="0dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginTop="@dimen/card_margin_title_text"
|
||||
app:layout_constraintTop_toBottomOf="@id/zipProgress"
|
||||
app:layout_constraintLeft_toLeftOf="@id/zipStart"
|
||||
app:layout_constraintRight_toLeftOf="@id/zipCaption"
|
||||
app:layout_constraintBottom_toBottomOf="@id/zipSubtitle"
|
||||
android:src="@drawable/ic_share" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/zipCaption"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@id/zipIcon"
|
||||
app:layout_constraintTop_toTopOf="@id/zipIcon"
|
||||
app:layout_constraintRight_toRightOf="@id/zipEnd"
|
||||
app:layout_constraintBottom_toTopOf="@id/zipSubtitle"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline6"
|
||||
android:text="@string/debug_info_archive_caption" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/zipSubtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@id/zipIcon"
|
||||
app:layout_constraintTop_toBottomOf="@id/zipCaption"
|
||||
app:layout_constraintRight_toRightOf="@id/zipEnd"
|
||||
app:layout_constraintBottom_toTopOf="@id/zipText"
|
||||
style="@style/TextAppearance.MaterialComponents.Subtitle1"
|
||||
android:text="@string/debug_info_archive_subtitle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/zipText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/zipSubtitle"
|
||||
app:layout_constraintLeft_toLeftOf="@id/zipStart"
|
||||
app:layout_constraintRight_toRightOf="@id/zipEnd"
|
||||
android:layout_marginTop="@dimen/card_margin_title_text"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:text="@string/debug_info_archive_text"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/zipShare"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/card_margin_title_text"
|
||||
app:layout_constraintTop_toBottomOf="@id/zipText"
|
||||
app:layout_constraintLeft_toLeftOf="@id/zipStart"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:enabled="@{model.debugInfo != null && !model.zipProgress}"
|
||||
android:text="@string/debug_info_archive_share" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="@{model.cause == null ? View.GONE : View.VISIBLE}">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/card_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/causeStart"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_begin="@dimen/card_padding" />
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/causeEnd"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_end="@dimen/card_padding" />
|
||||
|
||||
<at.bitfire.davdroid.ui.widget.CropImageView
|
||||
android:id="@+id/causeTheme"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxHeight="@dimen/card_theme_max_height"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/causeIcon"
|
||||
android:adjustViewBounds="true"
|
||||
app:verticalOffsetPercent=".85"
|
||||
app:srcCompat="@drawable/undraw_server_down" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/causeIcon"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="0dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginTop="@dimen/card_margin_title_text"
|
||||
app:layout_constraintTop_toBottomOf="@id/causeTheme"
|
||||
app:layout_constraintLeft_toLeftOf="@id/causeStart"
|
||||
app:layout_constraintRight_toLeftOf="@id/causeCaption"
|
||||
app:layout_constraintBottom_toBottomOf="@id/causeSubtitle"
|
||||
android:src="@drawable/ic_info" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/causeCaption"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@id/causeIcon"
|
||||
app:layout_constraintTop_toTopOf="@id/causeIcon"
|
||||
app:layout_constraintRight_toRightOf="@id/causeEnd"
|
||||
app:layout_constraintBottom_toTopOf="@id/causeSubtitle"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline6"
|
||||
tools:text="SampleException" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/causeSubtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@id/causeIcon"
|
||||
app:layout_constraintTop_toBottomOf="@id/causeCaption"
|
||||
app:layout_constraintRight_toRightOf="@id/causeEnd"
|
||||
app:layout_constraintBottom_toTopOf="@id/causeText"
|
||||
style="@style/TextAppearance.MaterialComponents.Subtitle1"
|
||||
tools:text="Couldn't find …"
|
||||
android:text="@{model.cause.localizedMessage}" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/causeText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/causeSubtitle"
|
||||
app:layout_constraintLeft_toLeftOf="@id/causeStart"
|
||||
app:layout_constraintRight_toRightOf="@id/causeEnd"
|
||||
android:layout_marginTop="@dimen/card_margin_title_text"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
tools:text="Error explanation"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/causeView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/card_margin_title_text"
|
||||
app:layout_constraintTop_toBottomOf="@id/causeText"
|
||||
app:layout_constraintLeft_toLeftOf="@id/causeStart"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:text="@string/debug_info_view_details"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="@{(model.debugInfo != null && model.cause == null) ? View.VISIBLE : View.GONE}">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/card_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/debugInfoStart"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_begin="@dimen/card_padding" />
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/debugInfoEnd"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_end="@dimen/card_padding" />
|
||||
|
||||
<at.bitfire.davdroid.ui.widget.CropImageView
|
||||
android:id="@+id/debugInfoTheme"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxHeight="@dimen/card_theme_max_height"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/debugInfoIcon"
|
||||
android:adjustViewBounds="true"
|
||||
app:verticalOffsetPercent=".85"
|
||||
app:srcCompat="@drawable/undraw_server_down" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/debugInfoIcon"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="0dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_marginTop="@dimen/card_margin_title_text"
|
||||
app:layout_constraintTop_toBottomOf="@id/debugInfoTheme"
|
||||
app:layout_constraintLeft_toLeftOf="@id/debugInfoStart"
|
||||
app:layout_constraintRight_toLeftOf="@id/debugInfoCaption"
|
||||
app:layout_constraintBottom_toBottomOf="@id/debugInfoSubtitle"
|
||||
android:src="@drawable/ic_bug_report"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/debugInfoCaption"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@id/debugInfoIcon"
|
||||
app:layout_constraintTop_toTopOf="@id/debugInfoIcon"
|
||||
app:layout_constraintRight_toRightOf="@id/debugInfoEnd"
|
||||
app:layout_constraintBottom_toTopOf="@id/debugInfoSubtitle"
|
||||
android:text="@string/debug_info_title"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline6"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/debugInfoSubtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@id/debugInfoIcon"
|
||||
app:layout_constraintTop_toBottomOf="@id/debugInfoCaption"
|
||||
app:layout_constraintRight_toRightOf="@id/debugInfoEnd"
|
||||
app:layout_constraintBottom_toTopOf="@id/debugInfoView"
|
||||
android:text="@string/debug_info_subtitle"
|
||||
style="@style/TextAppearance.MaterialComponents.Subtitle1"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/debugInfoView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/card_margin_title_text"
|
||||
app:layout_constraintTop_toBottomOf="@id/debugInfoSubtitle"
|
||||
app:layout_constraintLeft_toLeftOf="@id/debugInfoStart"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:text="@string/debug_info_view_details"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="@{(model.localResource != null || model.remoteResource != null) ? View.VISIBLE : View.GONE}">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/card_padding">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/resIcon"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="0dp"
|
||||
android:paddingEnd="12dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@id/resCaption"
|
||||
app:layout_constraintBottom_toBottomOf="@id/resSubtitle"
|
||||
android:src="@drawable/ic_adb"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/resCaption"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@id/resIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/resSubtitle"
|
||||
android:text="@string/debug_info_involved_caption"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline6"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/resSubtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/card_margin_title_text"
|
||||
app:layout_constraintLeft_toRightOf="@id/resIcon"
|
||||
app:layout_constraintTop_toBottomOf="@id/resCaption"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/resRemoteTitle"
|
||||
android:text="@string/debug_info_involved_subtitle"
|
||||
style="@style/TextAppearance.MaterialComponents.Subtitle1"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/resRemoteTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="@{model.remoteResource != null ? View.VISIBLE : View.GONE}"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
app:layout_constraintTop_toBottomOf="@id/resSubtitle"
|
||||
app:layout_constraintBottom_toTopOf="@id/resRemote"
|
||||
android:text="@string/debug_info_involved_remote"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/resRemote"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/resRemoteTitle"
|
||||
app:layout_constraintBottom_toTopOf="@id/resLocalTitle"
|
||||
android:visibility="@{model.remoteResource != null ? View.VISIBLE : View.GONE}"
|
||||
android:fontFamily="monospace"
|
||||
android:textIsSelectable="true"
|
||||
android:text="@{model.remoteResource}"
|
||||
tools:text="https://example.com"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/resLocalTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="@{model.localResource != null ? View.VISIBLE : View.GONE}"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
app:layout_constraintTop_toBottomOf="@id/resRemote"
|
||||
app:layout_constraintBottom_toTopOf="@id/resLocal"
|
||||
android:text="@string/debug_info_involved_local"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/resLocal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/resLocalTitle"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:visibility="@{model.localResource != null ? View.VISIBLE : View.GONE}"
|
||||
android:fontFamily="monospace"
|
||||
android:textIsSelectable="true"
|
||||
android:text="@{model.localResource}"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="@{model.logFile == null ? View.GONE : View.VISIBLE}">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/card_padding">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/logsIcon"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="0dp"
|
||||
android:paddingEnd="12dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@id/logsCaption"
|
||||
app:layout_constraintBottom_toBottomOf="@id/logsSubtitle"
|
||||
android:src="@drawable/ic_adb"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/logsCaption"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@id/logsIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/logsSubtitle"
|
||||
android:text="@string/debug_info_logs_caption"
|
||||
style="@style/TextAppearance.MaterialComponents.Headline6"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/logsSubtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toRightOf="@id/logsIcon"
|
||||
app:layout_constraintTop_toBottomOf="@id/logsCaption"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/logsView"
|
||||
android:text="@string/debug_info_logs_subtitle"
|
||||
style="@style/TextAppearance.MaterialComponents.Subtitle1"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/logsView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/card_margin_title_text"
|
||||
app:layout_constraintTop_toBottomOf="@id/logsSubtitle"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:text="@string/debug_info_logs_view"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
android:contentDescription="@string/share"
|
||||
android:enabled="@{model.debugInfo != null && !model.zipProgress}"
|
||||
android:src="@drawable/ic_share"/>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</layout>
|
Loading…
Reference in a new issue