Skip to content

Commit

Permalink
feat: new deploy user experience
Browse files Browse the repository at this point in the history
A notification will be created on deploy failure to guide user to view error logs.
  • Loading branch information
WhiredPlanck committed Dec 27, 2024
1 parent abfc41a commit 09d64a5
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 24 deletions.
66 changes: 66 additions & 0 deletions app/src/main/java/com/osfans/trime/daemon/RimeDaemon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,29 @@ package com.osfans.trime.daemon

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import com.osfans.trime.R
import com.osfans.trime.TrimeApplication
import com.osfans.trime.core.Rime
import com.osfans.trime.core.RimeApi
import com.osfans.trime.core.RimeLifecycle
import com.osfans.trime.core.RimeMessage
import com.osfans.trime.core.lifecycleScope
import com.osfans.trime.core.whenReady
import com.osfans.trime.ui.main.LogActivity
import com.osfans.trime.util.appContext
import com.osfans.trime.util.toast
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import splitties.systemservices.notificationManager
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
Expand Down Expand Up @@ -120,6 +130,7 @@ object RimeDaemon {
}

private const val CHANNEL_ID = "rime-daemon"
private const val MESSAGE_ID = 2331
private var restartId = 0

/**
Expand All @@ -140,11 +151,66 @@ object RimeDaemon {
.let { notificationManager.notify(id, it) }
realRime.finalize()
realRime.startup(fullCheck)
realRime.messageFlow
.onEach(::handleRimeMessage)
.launchIn(TrimeApplication.getInstance().coroutineScope)
TrimeApplication.getInstance().coroutineScope.launch {
// cancel notification on ready
realRime.lifecycle.whenReady {
notificationManager.cancel(id)
}
}
}

private suspend fun handleRimeMessage(it: RimeMessage<*>) {
if (it is RimeMessage.DeployMessage) {
when (it.data) {
RimeMessage.DeployMessage.State.Start -> {
withContext(Dispatchers.IO) {
Runtime.getRuntime().exec(arrayOf("logcat", "-c"))
}
}
RimeMessage.DeployMessage.State.Success -> {
ContextCompat.getMainExecutor(appContext).execute {
appContext.toast(R.string.deploy_finish)
}
}
RimeMessage.DeployMessage.State.Failure -> {
val intent =
Intent(appContext, LogActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val log =
withContext(Dispatchers.IO) {
Runtime
.getRuntime()
.exec(
arrayOf("logcat", "-d", "-v", "brief", "-s", "rime.trime:W"),
).inputStream
.bufferedReader()
.readText()
}
putExtra(LogActivity.FROM_DEPLOY, true)
putExtra(LogActivity.DEPLOY_FAILURE_TRACE, log)
}
NotificationCompat
.Builder(appContext, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_baseline_warning_24)
.setContentTitle(appContext.getString(R.string.rime_daemon))
.setContentText(appContext.getString(R.string.view_deploy_failure_log))
.setContentIntent(
PendingIntent.getActivity(
appContext,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT,
),
).setOngoing(false)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.build()
.let { notificationManager.notify(MESSAGE_ID, it) }
}
}
}
}
}
36 changes: 13 additions & 23 deletions app/src/main/java/com/osfans/trime/ui/components/log/LogView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,23 @@ package com.osfans.trime.ui.components.log

import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import android.widget.HorizontalScrollView
import androidx.core.content.ContextCompat
import androidx.core.text.buildSpannedString
import androidx.core.text.color
import androidx.lifecycle.findViewTreeLifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.osfans.trime.R
import com.osfans.trime.util.Logcat
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import splitties.resources.styledColor
import splitties.views.dsl.core.add
import splitties.views.dsl.core.lParams
import splitties.views.dsl.core.matchParent
import splitties.views.dsl.core.wrapContent
import splitties.views.dsl.recyclerview.recyclerView
import splitties.views.recyclerview.verticalLayoutManager

/**
* A scroll view to look up the app log.
Expand All @@ -39,21 +42,15 @@ class LogView
private val logAdapter = LogAdapter()

private val recyclerView =
RecyclerView(context).apply {
recyclerView {
adapter = logAdapter
layoutManager =
LinearLayoutManager(context).apply {
orientation = LinearLayoutManager.VERTICAL
}
layoutManager = verticalLayoutManager()
}

init {
addView(
add(
recyclerView,
LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT,
),
lParams(wrapContent, matchParent),
)
}

Expand All @@ -62,12 +59,6 @@ class LogView
super.onDetachedFromWindow()
}

fun fromCustomLogLines(lines: List<String>) {
lines.onEach {
dyeAndAppendString(it)
}
}

fun append(content: String) {
logAdapter.append(
buildSpannedString {
Expand All @@ -80,12 +71,11 @@ class LogView
this.logcat = logcat
logcat.initLogFlow()
logcat.logFlow
.onEach {
dyeAndAppendString(it)
}.launchIn(findViewTreeLifecycleOwner()!!.lifecycleScope)
.onEach(::buildColoredString)
.launchIn(findViewTreeLifecycleOwner()!!.lifecycleScope)
}

private fun dyeAndAppendString(str: String) {
private fun buildColoredString(str: String) {
val color =
ContextCompat.getColor(
context,
Expand Down
17 changes: 17 additions & 0 deletions app/src/main/java/com/osfans/trime/ui/main/LogActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package com.osfans.trime.ui.main

import android.content.ClipData
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
Expand All @@ -28,6 +29,7 @@ import com.osfans.trime.util.toast
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import splitties.systemservices.clipboardManager

/**
* The activity to show [LogView].
Expand All @@ -41,7 +43,9 @@ class LogActivity : AppCompatActivity() {

companion object {
const val FROM_CRASH = "from_crash"
const val FROM_DEPLOY = "from_deploy"
const val CRASH_STACK_TRACE = "crash_stack_trace"
const val DEPLOY_FAILURE_TRACE = "deploy_failure_trace"
}

private fun registerLauncher() {
Expand Down Expand Up @@ -88,6 +92,7 @@ class LogActivity : AppCompatActivity() {
if (intent.hasExtra(FROM_CRASH)) {
supportActionBar!!.setTitle(R.string.crash_logs)
clearButton.visibility = View.GONE
copyButton.visibility = View.GONE
AlertDialog
.Builder(this@LogActivity)
.setTitle(R.string.app_crash)
Expand All @@ -97,11 +102,16 @@ class LogActivity : AppCompatActivity() {
logView.append("--------- Crash stacktrace")
logView.append(intent.getStringExtra(CRASH_STACK_TRACE) ?: "<empty>")
logView.setLogcat(Logcat(TrimeApplication.getLastPid()))
} else if (intent.hasExtra(FROM_DEPLOY)) {
supportActionBar!!.setTitle(R.string.deploy_failure)
clearButton.visibility = View.GONE
logView.append(intent.getStringExtra(DEPLOY_FAILURE_TRACE) ?: "<empty>")
} else {
supportActionBar!!.apply {
setDisplayHomeAsUpEnabled(true)
setTitle(R.string.real_time_logs)
}
copyButton.visibility = View.GONE
logView.setLogcat(Logcat())
}
clearButton.setOnClickListener {
Expand All @@ -110,6 +120,13 @@ class LogActivity : AppCompatActivity() {
exportButton.setOnClickListener {
launcher.launch("$packageName-${iso8601UTCDateTime()}.txt")
}
copyButton.setOnClickListener {
val data = ClipData.newPlainText("log", logView.currentLog)
clipboardManager.setPrimaryClip(data)
if (clipboardManager.hasPrimaryClip()) {
toast(R.string.copy_done)
}
}
jumpToBottomButton.setOnClickListener {
logView.scrollToBottom()
}
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/ic_baseline_warning_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">

<path android:fillColor="@android:color/white" android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z"/>

</vector>
9 changes: 8 additions & 1 deletion app/src/main/res/layout/activity_log.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ SPDX-License-Identifier: GPL-3.0-or-later
android:layout_height="wrap_content"
android:text="@string/export" />

<Button
android:id="@+id/copyButton"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@android:string/copy" />

<Button
android:id="@+id/jumpToBottomButton"
style="?android:attr/buttonBarButtonStyle"
Expand All @@ -62,4 +69,4 @@ SPDX-License-Identifier: GPL-3.0-or-later
android:text="@string/scroll_to_bottom" />
</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
2 changes: 2 additions & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
<string name="top_left">左上</string>
<string name="top_right">右上</string>
<string name="display_position">显示位置</string>
<string name="deploy_failure">部署失败</string>
<string name="view_deploy_failure_log">部署失败。点此查看错误日志。</string>
</resources>
2 changes: 2 additions & 0 deletions app/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
<string name="top_left">左上</string>
<string name="top_right">右上</string>
<string name="display_position">顯示位置</string>
<string name="deploy_failure">部署失敗</string>
<string name="view_deploy_failure_log">部署失敗。點此檢視錯誤日誌。</string>
</resources>
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
<string name="top_left">Top left</string>
<string name="top_right">Top right</string>
<string name="display_position">Display position</string>
<string name="deploy_failure">Deploy failure</string>
<string name="view_deploy_failure_log">Deploy failure. Click here to view error log.</string>
</resources>

0 comments on commit 09d64a5

Please sign in to comment.