Show additional bug report info in AboutActivity (#3802)
Make it easier for people to find information we need for a bug report, and show it on AboutActivity. New info is: - Device manufacturer (e.g., "Google") and model (e.g., "Pixel 4a (5G)") - Android version (e.g., "13") - SDK version (e.g., "33") - Active account (e.g., "@Tusky@mastodon.social") - Server's version (e.g., "4.1.2+nightly-20230627") All info is copyable to make it easy to include in a bug report. A button to copy the information is also shown.
This commit is contained in:
parent
561af5f105
commit
9cda091d03
|
@ -1,6 +1,10 @@
|
|||
package com.keylesspalace.tusky
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableString
|
||||
import android.text.SpannableStringBuilder
|
||||
|
@ -8,13 +12,21 @@ import android.text.method.LinkMovementMethod
|
|||
import android.text.style.URLSpan
|
||||
import android.text.util.Linkify
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.keylesspalace.tusky.components.instanceinfo.InstanceInfoRepository
|
||||
import com.keylesspalace.tusky.databinding.ActivityAboutBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.util.NoUnderlineURLSpan
|
||||
import com.keylesspalace.tusky.util.hide
|
||||
import com.keylesspalace.tusky.util.show
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class AboutActivity : BottomSheetActivity(), Injectable {
|
||||
@Inject
|
||||
lateinit var instanceInfoRepository: InstanceInfoRepository
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -32,6 +44,28 @@ class AboutActivity : BottomSheetActivity(), Injectable {
|
|||
|
||||
binding.versionTextView.text = getString(R.string.about_app_version, getString(R.string.app_name), BuildConfig.VERSION_NAME)
|
||||
|
||||
binding.deviceInfo.text = getString(
|
||||
R.string.about_device_info,
|
||||
Build.MANUFACTURER,
|
||||
Build.MODEL,
|
||||
Build.VERSION.RELEASE,
|
||||
Build.VERSION.SDK_INT
|
||||
)
|
||||
|
||||
lifecycleScope.launch {
|
||||
accountManager.activeAccount?.let { account ->
|
||||
val instanceInfo = instanceInfoRepository.getInstanceInfo()
|
||||
binding.accountInfo.text = getString(
|
||||
R.string.about_account_info,
|
||||
account.username,
|
||||
account.domain,
|
||||
instanceInfo.version
|
||||
)
|
||||
binding.accountInfoTitle.show()
|
||||
binding.accountInfo.show()
|
||||
}
|
||||
}
|
||||
|
||||
if (BuildConfig.CUSTOM_INSTANCE.isBlank()) {
|
||||
binding.aboutPoweredByTusky.hide()
|
||||
}
|
||||
|
@ -47,6 +81,16 @@ class AboutActivity : BottomSheetActivity(), Injectable {
|
|||
binding.aboutLicensesButton.setOnClickListener {
|
||||
startActivityWithSlideInAnimation(Intent(this, LicenseActivity::class.java))
|
||||
}
|
||||
|
||||
binding.copyDeviceInfo.setOnClickListener {
|
||||
val text = "${binding.versionTextView.text}\n\nDevice:\n\n${binding.deviceInfo.text}\n\nAccount:\n\n${binding.accountInfo.text}"
|
||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("Tusky version information", text)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
|
||||
Toast.makeText(this, getString(R.string.about_copied), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,5 +28,6 @@ data class InstanceInfo(
|
|||
val maxMediaAttachments: Int,
|
||||
val maxFields: Int,
|
||||
val maxFieldNameLength: Int?,
|
||||
val maxFieldValueLength: Int?
|
||||
val maxFieldValueLength: Int?,
|
||||
val version: String?
|
||||
)
|
||||
|
|
|
@ -99,7 +99,8 @@ class InstanceInfoRepository @Inject constructor(
|
|||
maxMediaAttachments = instanceInfo?.maxMediaAttachments ?: DEFAULT_MAX_MEDIA_ATTACHMENTS,
|
||||
maxFields = instanceInfo?.maxFields ?: DEFAULT_MAX_ACCOUNT_FIELDS,
|
||||
maxFieldNameLength = instanceInfo?.maxFieldNameLength,
|
||||
maxFieldValueLength = instanceInfo?.maxFieldValueLength
|
||||
maxFieldValueLength = instanceInfo?.maxFieldValueLength,
|
||||
version = instanceInfo?.version
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
|
||||
</vector>
|
|
@ -21,104 +21,190 @@
|
|||
android:layout_gravity="center"
|
||||
android:textDirection="anyRtl">
|
||||
|
||||
<LinearLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/logo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/versionTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:drawableStart="@mipmap/ic_launcher"
|
||||
android:drawablePadding="16dp"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginTop="12dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Large"
|
||||
android:textIsSelectable="true"
|
||||
android:textStyle="normal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/logo"
|
||||
tools:text="Tusky Test" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/deviceInfoTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginStart="@dimen/text_content_margin"
|
||||
android:layout_marginEnd="@dimen/text_content_margin"
|
||||
android:lineSpacingMultiplier="1.1"
|
||||
android:text="@string/about_device_info_title"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold" />
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/versionTextView"
|
||||
tools:text="Your device" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/deviceInfo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:lineSpacingMultiplier="1.1"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textIsSelectable="true"
|
||||
app:layout_constraintEnd_toEndOf="@+id/deviceInfoTitle"
|
||||
app:layout_constraintStart_toStartOf="@+id/deviceInfoTitle"
|
||||
app:layout_constraintTop_toBottomOf="@id/deviceInfoTitle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/accountInfoTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:lineSpacingMultiplier="1.1"
|
||||
android:text="@string/about_account_info_title"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toStartOf="@+id/copyDeviceInfo"
|
||||
app:layout_constraintStart_toStartOf="@+id/deviceInfo"
|
||||
app:layout_constraintTop_toBottomOf="@id/deviceInfo"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/accountInfo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:lineSpacingMultiplier="1.1"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textIsSelectable="true"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="@+id/accountInfoTitle"
|
||||
app:layout_constraintStart_toStartOf="@+id/accountInfoTitle"
|
||||
app:layout_constraintTop_toBottomOf="@id/accountInfoTitle"
|
||||
tools:text="\@Tusky@mastodon.social\nVersion: xxx"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/copyDeviceInfo"
|
||||
style="@style/TuskyImageButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:contentDescription="@string/about_copy"
|
||||
android:layout_marginEnd="@dimen/text_content_margin"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/accountInfo"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:srcCompat="@drawable/ic_content_copy_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/aboutPoweredByTusky"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:drawablePadding="16dp"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="18sp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/about_powered_by_tusky"
|
||||
android:textStyle="bold" />
|
||||
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||
app:layout_constraintEnd_toEndOf="@+id/copyDeviceInfo"
|
||||
app:layout_constraintStart_toStartOf="@+id/deviceInfo"
|
||||
app:layout_constraintTop_toBottomOf="@+id/accountInfo" />
|
||||
|
||||
<com.keylesspalace.tusky.view.ClickableSpanTextView
|
||||
android:id="@+id/aboutLicenseInfoTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:hyphenationFrequency="full"
|
||||
android:lineSpacingMultiplier="1.2"
|
||||
android:paddingStart="@dimen/text_content_margin"
|
||||
android:paddingEnd="@dimen/text_content_margin"
|
||||
android:textAlignment="center"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="@+id/copyDeviceInfo"
|
||||
app:layout_constraintStart_toStartOf="@+id/accountInfo"
|
||||
app:layout_constraintTop_toBottomOf="@id/aboutPoweredByTusky"
|
||||
tools:text="@string/about_tusky_license" />
|
||||
|
||||
<com.keylesspalace.tusky.view.ClickableSpanTextView
|
||||
android:id="@+id/aboutWebsiteInfoTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:lineSpacingMultiplier="1.2"
|
||||
android:paddingStart="@dimen/text_content_margin"
|
||||
android:paddingEnd="@dimen/text_content_margin"
|
||||
android:textAlignment="center"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="@+id/aboutLicenseInfoTextView"
|
||||
app:layout_constraintStart_toStartOf="@+id/aboutLicenseInfoTextView"
|
||||
app:layout_constraintTop_toBottomOf="@id/aboutLicenseInfoTextView"
|
||||
tools:text="@string/about_project_site" />
|
||||
|
||||
<com.keylesspalace.tusky.view.ClickableSpanTextView
|
||||
android:id="@+id/aboutBugsFeaturesInfoTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:lineSpacingMultiplier="1.2"
|
||||
android:paddingStart="@dimen/text_content_margin"
|
||||
android:paddingEnd="@dimen/text_content_margin"
|
||||
android:text="@string/about_bug_feature_request_site"
|
||||
android:textAlignment="center"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="16sp" />
|
||||
app:layout_constraintEnd_toEndOf="@+id/aboutWebsiteInfoTextView"
|
||||
app:layout_constraintStart_toStartOf="@+id/aboutWebsiteInfoTextView"
|
||||
app:layout_constraintTop_toBottomOf="@id/aboutWebsiteInfoTextView" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/tuskyProfileButton"
|
||||
style="@style/TuskyButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:lineSpacingMultiplier="1.2"
|
||||
android:maxWidth="320dp"
|
||||
android:text="@string/about_tusky_account"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="16sp" />
|
||||
android:textSize="16sp"
|
||||
android:layout_marginEnd="@dimen/text_content_margin"
|
||||
app:layout_constraintEnd_toStartOf="@+id/aboutLicensesButton"
|
||||
app:layout_constraintStart_toStartOf="@+id/aboutBugsFeaturesInfoTextView"
|
||||
app:layout_constraintTop_toBottomOf="@id/aboutBugsFeaturesInfoTextView" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/aboutLicensesButton"
|
||||
style="@style/TuskyButton.Outlined"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:lineSpacingMultiplier="1.2"
|
||||
android:maxWidth="320dp"
|
||||
android:text="@string/title_licenses"
|
||||
android:textAlignment="center"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="16sp" />
|
||||
android:textSize="16sp"
|
||||
android:layout_marginEnd="@dimen/text_content_margin"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/tuskyProfileButton"
|
||||
app:layout_constraintTop_toTopOf="@+id/tuskyProfileButton" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</FrameLayout>
|
||||
|
|
|
@ -391,6 +391,10 @@
|
|||
|
||||
<string name="about_title_activity">About</string>
|
||||
<string name="about_tusky_version">Tusky %s</string>
|
||||
<string name="about_device_info_title">Your device</string>
|
||||
<string name="about_device_info">%s %s\nAndroid version: %s\nSDK version: %d</string>
|
||||
<string name="about_account_info_title">Your account</string>
|
||||
<string name="about_account_info">\@%s\@%s\nVersion: %s</string>
|
||||
<string name="about_powered_by_tusky">Powered by Tusky</string>
|
||||
<string name="about_tusky_license">Tusky is free and open-source software.
|
||||
It is licensed under the GNU General Public License Version 3.
|
||||
|
@ -401,14 +405,8 @@
|
|||
to show we do not mean the software is gratis. Source: https://www.gnu.org/philosophy/free-sw.html
|
||||
* the url can be changed to link to the localized version of the license.
|
||||
-->
|
||||
<string name="about_project_site">
|
||||
Project website:\n
|
||||
https://tusky.app
|
||||
</string>
|
||||
<string name="about_bug_feature_request_site">
|
||||
Bug reports & feature requests:\n
|
||||
https://github.com/tuskyapp/Tusky/issues
|
||||
</string>
|
||||
<string name="about_project_site">Project website: https://tusky.app</string>
|
||||
<string name="about_bug_feature_request_site">Bug reports & feature requests:\nhttps://github.com/tuskyapp/Tusky/issues</string>
|
||||
<string name="about_tusky_account">Tusky\'s Profile</string>
|
||||
|
||||
<string name="post_share_content">Share content of post</string>
|
||||
|
@ -817,4 +815,6 @@
|
|||
For example the local timeline of your instance [iconics gmd_group]. Or you can search them
|
||||
by name [iconics gmd_search]; for example search for Tusky to find our Mastodon account.</string>
|
||||
<string name="load_newest_notifications">Load newest notifications</string>
|
||||
<string name="about_copy">Copy version and device information</string>
|
||||
<string name="about_copied">Copied version and device information</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue