diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt index 99849ef1d4..38992f25f5 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt @@ -22,27 +22,19 @@ interface BugReporter { /** * Send a bug report. * - * @param reportType The report type (bug, suggestion, feedback) * @param withDevicesLogs true to include the device log * @param withCrashLogs true to include the crash logs - * @param withKeyRequestHistory true to include the crash logs * @param withScreenshot true to include the screenshot * @param theBugDescription the bug description - * @param serverVersion version of the server * @param canContact true if the user opt in to be contacted directly - * @param customFields fields which will be sent with the report * @param listener the listener */ suspend fun sendBugReport( - reportType: ReportType, withDevicesLogs: Boolean, withCrashLogs: Boolean, - withKeyRequestHistory: Boolean, withScreenshot: Boolean, theBugDescription: String, - serverVersion: String, canContact: Boolean = false, - customFields: Map? = null, listener: BugReporterListener? ) diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporterListener.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporterListener.kt index 8f2ae90d1c..328a117ad1 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporterListener.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporterListener.kt @@ -42,5 +42,5 @@ interface BugReporterListener { /** * The bug report upload succeeded. */ - fun onUploadSucceed(reportUrl: String?) + fun onUploadSucceed() } diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/ReportType.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/ReportType.kt deleted file mode 100644 index 17b75ea1a7..0000000000 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/ReportType.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2022 New Vector Ltd - * - * 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 io.element.android.features.rageshake.api.reporter - -enum class ReportType { - BUG_REPORT, - SUGGESTION, - SPACE_BETA_FEEDBACK, - THREADS_BETA_FEEDBACK, - AUTO_UISI, - AUTO_UISI_SENDER, -} diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt index 9258909201..e90787ab5c 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt @@ -25,12 +25,11 @@ import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable +import io.element.android.features.rageshake.api.crash.CrashDataStore import io.element.android.features.rageshake.api.reporter.BugReporter import io.element.android.features.rageshake.api.reporter.BugReporterListener -import io.element.android.features.rageshake.api.reporter.ReportType -import io.element.android.features.rageshake.api.crash.CrashDataStore -import io.element.android.features.rageshake.impl.logs.VectorFileLogger import io.element.android.features.rageshake.api.screenshot.ScreenshotHolder +import io.element.android.features.rageshake.impl.logs.VectorFileLogger import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Presenter import kotlinx.coroutines.CoroutineScope @@ -64,7 +63,7 @@ class BugReportPresenter @Inject constructor( sendingAction.value = Async.Loading() } - override fun onUploadSucceed(reportUrl: String?) { + override fun onUploadSucceed() { sendingProgress.floatValue = 0f sendingAction.value = Async.Success(Unit) } @@ -135,15 +134,11 @@ class BugReportPresenter @Inject constructor( listener: BugReporterListener, ) = launch { bugReporter.sendBugReport( - reportType = ReportType.BUG_REPORT, withDevicesLogs = formState.sendLogs, withCrashLogs = hasCrashLogs && formState.sendLogs, - withKeyRequestHistory = false, withScreenshot = formState.sendScreenshot, theBugDescription = formState.description, - serverVersion = "", canContact = formState.canContact, - customFields = emptyMap(), listener = listener ) } diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt index a693189d3c..5d7a0160fc 100755 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt @@ -25,14 +25,12 @@ import com.squareup.anvil.annotations.ContributesBinding import io.element.android.features.rageshake.api.crash.CrashDataStore import io.element.android.features.rageshake.api.reporter.BugReporter import io.element.android.features.rageshake.api.reporter.BugReporterListener -import io.element.android.features.rageshake.api.reporter.ReportType import io.element.android.features.rageshake.api.screenshot.ScreenshotHolder import io.element.android.features.rageshake.impl.R import io.element.android.libraries.androidutils.file.compressFile import io.element.android.libraries.androidutils.file.safeDelete import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.data.tryOrNull -import io.element.android.libraries.core.extensions.toOnOff import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.di.AppScope @@ -77,26 +75,11 @@ class DefaultBugReporter @Inject constructor( private val userAgentProvider: UserAgentProvider, private val sessionStore: SessionStore, private val buildMeta: BuildMeta, - /* - private val versionProvider: VersionProvider, - private val vectorPreferences: VectorPreferences, - private val vectorFileLogger: VectorFileLogger, - private val systemLocaleProvider: SystemLocaleProvider, - private val matrix: Matrix, - private val processInfo: ProcessInfo, - private val sdkIntProvider: BuildVersionSdkIntProvider, - private val vectorLocale: VectorLocaleProvider, - */ ) : BugReporter { - var inMultiWindowMode = false - companion object { // filenames - private const val LOG_CAT_ERROR_FILENAME = "logcatError.log" private const val LOG_CAT_FILENAME = "logcat.log" private const val LOG_DIRECTORY_NAME = "logs" - // private const val KEY_REQUESTS_FILENAME = "keyRequests.log" - private const val BUFFER_SIZE = 1024 * 1024 * 50 } @@ -105,58 +88,20 @@ class DefaultBugReporter @Inject constructor( // boolean to cancel the bug report private val isCancelled = false - - /* - val adapter = MatrixJsonParser.getMoshi() - .adapter(Types.newParameterizedType(Map::class.java, String::class.java, Any::class.java)) - */ - - private val logcatCommandError = arrayOf( - "logcat", // /< Run 'logcat' command - "-d", // /< Dump the log rather than continue outputting it - "-v", // formatting - "threadtime", // include timestamps - "AndroidRuntime:E " + // /< Pick all AndroidRuntime errors (such as uncaught exceptions)"communicatorjni:V " + ///< All communicatorjni logging - "libcommunicator:V " + // /< All libcommunicator logging - "DEBUG:V " + // /< All DEBUG logging - which includes native land crashes (seg faults, etc) - "*:S" // /< Everything else silent, so don't pick it.. - ) - private val logcatCommandDebug = arrayOf("logcat", "-d", "-v", "threadtime", "*:*") - /** - * Send a bug report. - * - * @param reportType The report type (bug, suggestion, feedback) - * @param withDevicesLogs true to include the device log - * @param withCrashLogs true to include the crash logs - * @param withKeyRequestHistory true to include the crash logs - * @param withScreenshot true to include the screenshot - * @param theBugDescription the bug description - * @param serverVersion version of the server - * @param canContact true if the user opt in to be contacted directly - * @param customFields fields which will be sent with the report - * @param listener the listener - */ override suspend fun sendBugReport( - reportType: ReportType, withDevicesLogs: Boolean, withCrashLogs: Boolean, - withKeyRequestHistory: Boolean, withScreenshot: Boolean, theBugDescription: String, - serverVersion: String, canContact: Boolean, - customFields: Map?, listener: BugReporterListener? ) { // enumerate files to delete val bugReportFiles: MutableList = ArrayList() - try { - var serverError: String? = null - var reportURL: String? = null withContext(coroutineDispatchers.io) { var bugDescription = theBugDescription val crashCallStack = crashDataStore.crashInfo().first() @@ -181,7 +126,7 @@ class DefaultBugReporter @Inject constructor( } if (!isCancelled && (withCrashLogs || withDevicesLogs)) { - val gzippedLogcat = saveLogCat(false) + val gzippedLogcat = saveLogCat() if (null != gzippedLogcat) { if (gzippedFiles.size == 0) { @@ -192,68 +137,21 @@ class DefaultBugReporter @Inject constructor( } } - /* - activeSessionHolder.getSafeActiveSession() - ?.takeIf { !mIsCancelled && withKeyRequestHistory } - ?.cryptoService() - ?.getGossipingEvents() - ?.let { GossipingEventsSerializer().serialize(it) } - ?.toByteArray() - ?.let { rawByteArray -> - File(context.cacheDir.absolutePath, KEY_REQUESTS_FILENAME) - .also { - it.outputStream() - .use { os -> os.write(rawByteArray) } - } - } - ?.let { compressFile(it) } - ?.let { gzippedFiles.add(it) } - */ - val sessionData = sessionStore.getLatestSession() val deviceId = sessionData?.deviceId ?: "undefined" val userId = sessionData?.userId ?: "undefined" - var olmVersion = "undefined" if (!isCancelled) { - val text = when (reportType) { - ReportType.BUG_REPORT -> bugDescription - ReportType.SUGGESTION -> "[Suggestion] $bugDescription" - ReportType.SPACE_BETA_FEEDBACK -> "[spaces-feedback] $bugDescription" - ReportType.THREADS_BETA_FEEDBACK -> "[threads-feedback] $bugDescription" - ReportType.AUTO_UISI_SENDER, - ReportType.AUTO_UISI -> bugDescription - } - // build the multi part request val builder = BugReporterMultipartBody.Builder() - .addFormDataPart("text", text) - .addFormDataPart("app", rageShakeAppNameForReport(reportType)) + .addFormDataPart("text", bugDescription) + .addFormDataPart("app", context.getString(R.string.bug_report_app_name)) .addFormDataPart("user_agent", userAgentProvider.provide()) .addFormDataPart("user_id", userId) .addFormDataPart("can_contact", canContact.toString()) .addFormDataPart("device_id", deviceId) - // .addFormDataPart("version", versionProvider.getVersion(longFormat = true)) - // .addFormDataPart("branch_name", buildMeta.gitBranchName) - // .addFormDataPart("matrix_sdk_version", Matrix.getSdkVersion()) - .addFormDataPart("olm_version", olmVersion) .addFormDataPart("device", Build.MODEL.trim()) - // .addFormDataPart("verbose_log", vectorPreferences.labAllowedExtendedLogging().toOnOff()) - .addFormDataPart("multi_window", inMultiWindowMode.toOnOff()) - // .addFormDataPart( - // "os", Build.VERSION.RELEASE + " (API " + sdkIntProvider.get() + ") " + - // Build.VERSION.INCREMENTAL + "-" + Build.VERSION.CODENAME - // ) .addFormDataPart("locale", Locale.getDefault().toString()) - // .addFormDataPart("app_language", vectorLocale.applicationLocale.toString()) - // .addFormDataPart("default_app_language", systemLocaleProvider.getSystemLocale().toString()) - // .addFormDataPart("theme", ThemeUtils.getApplicationTheme(context)) - .addFormDataPart("server_version", serverVersion) - .apply { - customFields?.forEach { (name, value) -> - addFormDataPart(name, value) - } - } // add the gzipped files, don't cancel the whole upload if only some file failed to upload var uploadedSomeLogs = false @@ -293,31 +191,6 @@ class DefaultBugReporter @Inject constructor( // add some github labels builder.addFormDataPart("label", buildMeta.versionName) - // builder.addFormDataPart("label", buildMeta.flavorDescription) - // builder.addFormDataPart("label", buildMeta.gitBranchName) - - // Possible values for BuildConfig.BUILD_TYPE: "debug", "nightly", "release". - // builder.addFormDataPart("label", BuildConfig.BUILD_TYPE) - - when (reportType) { - ReportType.BUG_REPORT -> { - /* nop */ - } - ReportType.SUGGESTION -> builder.addFormDataPart("label", "[Suggestion]") - ReportType.SPACE_BETA_FEEDBACK -> builder.addFormDataPart("label", "spaces-feedback") - ReportType.THREADS_BETA_FEEDBACK -> builder.addFormDataPart("label", "threads-feedback") - ReportType.AUTO_UISI -> { - builder.addFormDataPart("label", "Z-UISI") - builder.addFormDataPart("label", "android") - builder.addFormDataPart("label", "uisi-recipient") - } - ReportType.AUTO_UISI_SENDER -> { - builder.addFormDataPart("label", "Z-UISI") - builder.addFormDataPart("label", "android") - builder.addFormDataPart("label", "uisi-sender") - } - } - if (crashCallStack.isNotEmpty() && withCrashLogs) { builder.addFormDataPart("label", "crash") } @@ -379,7 +252,6 @@ class DefaultBugReporter @Inject constructor( } else { try { val inputStream = response.body!!.byteStream() - serverError = inputStream.use { buildString { var ch = it.read() @@ -389,7 +261,6 @@ class DefaultBugReporter @Inject constructor( } } } - // check if the error message serverError?.let { try { @@ -401,7 +272,6 @@ class DefaultBugReporter @Inject constructor( Timber.e(e, "doInBackground ; Json conversion failed") } } - // should never happen if (null == serverError) { serverError = "Failed with error $responseCode" @@ -412,25 +282,17 @@ class DefaultBugReporter @Inject constructor( Timber.e(e, "## sendBugReport() : failed to parse error") } } - } else { - /* - reportURL = response?.body?.string()?.let { stringBody -> - adapter.fromJson(stringBody)?.get("report_url")?.toString() - } - */ } } } - withContext(coroutineDispatchers.main) { bugReportCall = null - if (null != listener) { try { if (isCancelled) { listener.onUploadCancelled() } else if (null == serverError) { - listener.onUploadSucceed(reportURL) + listener.onUploadSucceed() } else { listener.onUploadFailed(serverError) } @@ -449,47 +311,6 @@ class DefaultBugReporter @Inject constructor( } } - /** - * Send a bug report either with email or with Vector. - */ - /* TODO Remove - fun openBugReportScreen(activity: FragmentActivity, reportType: ReportType = ReportType.BUG_REPORT) { - screenshot = takeScreenshot(activity) - logDbInfo() - logProcessInfo() - logOtherInfo() - activity.startActivity(BugReportActivity.intent(activity, reportType)) - } - */ - - // private fun logOtherInfo() { - // Timber.i("SyncThread state: " + activeSessionHolder.getSafeActiveSession()?.syncService()?.getSyncState()) - // } - - // private fun logDbInfo() { - // val dbInfo = matrix.debugService().getDbUsageInfo() - // Timber.i(dbInfo) - // } - - // private fun logProcessInfo() { - // val pInfo = processInfo.getInfo() - // Timber.i(pInfo) - // } - - private fun rageShakeAppNameForReport(reportType: ReportType): String { - // As per https://github.com/matrix-org/rageshake - // app: Identifier for the application (eg 'riot-web'). - // Should correspond to a mapping configured in the configuration file for github issue reporting to work. - // (see R.string.bug_report_url for configured RS server) - return context.getString( - when (reportType) { - ReportType.AUTO_UISI_SENDER, - ReportType.AUTO_UISI -> R.string.bug_report_auto_uisi_app_name - else -> R.string.bug_report_app_name - } - ) - } - override fun logDirectory(): File { return File(context.cacheDir, LOG_DIRECTORY_NAME) } @@ -545,11 +366,10 @@ class DefaultBugReporter @Inject constructor( /** * Save the logcat. * - * @param isErrorLogcat true to save the error logcat * @return the file if the operation succeeds */ - private fun saveLogCat(isErrorLogcat: Boolean): File? { - val logCatErrFile = File(context.cacheDir.absolutePath, if (isErrorLogcat) LOG_CAT_ERROR_FILENAME else LOG_CAT_FILENAME) + private fun saveLogCat(): File? { + val logCatErrFile = File(context.cacheDir.absolutePath, LOG_CAT_FILENAME) if (logCatErrFile.exists()) { logCatErrFile.safeDelete() @@ -557,7 +377,7 @@ class DefaultBugReporter @Inject constructor( try { logCatErrFile.writer().use { - getLogCatError(it, isErrorLogcat) + getLogCatError(it) } return compressFile(logCatErrFile) @@ -578,13 +398,12 @@ class DefaultBugReporter @Inject constructor( * Retrieves the logs. * * @param streamWriter the stream writer - * @param isErrorLogCat true to save the error logs */ - private fun getLogCatError(streamWriter: OutputStreamWriter, isErrorLogCat: Boolean) { + private fun getLogCatError(streamWriter: OutputStreamWriter) { val logcatProc: Process try { - logcatProc = Runtime.getRuntime().exec(if (isErrorLogCat) logcatCommandError else logcatCommandDebug) + logcatProc = Runtime.getRuntime().exec(logcatCommandDebug) } catch (e1: IOException) { return } diff --git a/features/rageshake/impl/src/main/res/values/strings.xml b/features/rageshake/impl/src/main/res/values/strings.xml index 48eff44d57..dc1069570b 100644 --- a/features/rageshake/impl/src/main/res/values/strings.xml +++ b/features/rageshake/impl/src/main/res/values/strings.xml @@ -1,5 +1,4 @@ - - https://riot.im/bugreports/submit + element-x-android - element-auto-uisi + diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt index 82edaf563d..00343f8f6e 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt @@ -18,22 +18,17 @@ package io.element.android.features.rageshake.impl.bugreport import io.element.android.features.rageshake.api.reporter.BugReporter import io.element.android.features.rageshake.api.reporter.BugReporterListener -import io.element.android.features.rageshake.api.reporter.ReportType import io.element.android.libraries.matrix.test.A_FAILURE_REASON import kotlinx.coroutines.delay import java.io.File class FakeBugReporter(val mode: FakeBugReporterMode = FakeBugReporterMode.Success) : BugReporter { override suspend fun sendBugReport( - reportType: ReportType, withDevicesLogs: Boolean, withCrashLogs: Boolean, - withKeyRequestHistory: Boolean, withScreenshot: Boolean, theBugDescription: String, - serverVersion: String, canContact: Boolean, - customFields: Map?, listener: BugReporterListener?, ) { delay(100) @@ -54,7 +49,7 @@ class FakeBugReporter(val mode: FakeBugReporterMode = FakeBugReporterMode.Succes } listener?.onProgress(100) delay(100) - listener?.onUploadSucceed(null) + listener?.onUploadSucceed() } override fun cleanLogDirectoryIfNeeded() {