Use RV to show Magisk logs

This commit is contained in:
LoveSy 2023-03-19 23:45:45 -07:00 committed by John Wu
parent 03cee0b8d4
commit 4de93cfd4b
7 changed files with 134 additions and 57 deletions

View File

@ -1,30 +1,29 @@
package com.topjohnwu.magisk.ui.log
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.textview.MaterialTextView
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.model.su.SuLog
import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
import com.topjohnwu.magisk.databinding.RvContainer
import com.topjohnwu.magisk.databinding.set
import com.topjohnwu.magisk.ktx.timeDateFormat
import com.topjohnwu.magisk.ktx.toTime
import com.topjohnwu.magisk.databinding.ViewAwareRvItem
class LogRvItem(
override val item: SuLog
) : ObservableDiffRvItem<LogRvItem>(), RvContainer<SuLog> {
override val item: String
) : ObservableDiffRvItem<LogRvItem>(), RvContainer<String>, ViewAwareRvItem {
override val layoutRes = R.layout.item_log_access_md2
override val layoutRes = R.layout.item_log_textview
val date = item.time.toTime(timeDateFormat)
override fun itemSameAs(other: LogRvItem) = item == other.item
@get:Bindable
var isTop = false
set(value) = set(value, field, { field = it }, BR.top)
@get:Bindable
var isBottom = false
set(value) = set(value, field, { field = it }, BR.bottom)
override fun itemSameAs(other: LogRvItem) = item.appName == other.item.appName
override fun onBind(binding: ViewDataBinding, recyclerView: RecyclerView) {
val view = binding.root as MaterialTextView
view.measure(0, 0)
val desiredWidth = view.measuredWidth
val layoutParams = view.layoutParams
layoutParams.width = desiredWidth
if (recyclerView.width < desiredWidth) {
recyclerView.requestLayout()
}
}
}

View File

@ -26,6 +26,9 @@ import java.io.FileInputStream
class LogViewModel(
private val repo: LogRepository
) : AsyncLoadViewModel() {
@get:Bindable
var loading = true
private set(value) = set(value, field, { field = it }, BR.loading)
// --- empty view
@ -34,27 +37,34 @@ class LogViewModel(
// --- su log
val items = DiffRvItemList<LogRvItem>()
val items = DiffRvItemList<SuLogRvItem>()
val extraBindings = bindExtra {
it.put(BR.viewModel, this)
}
// --- magisk log
@get:Bindable
var consoleText = " "
set(value) = set(value, field, { field = it }, BR.consoleText)
val logs = DiffRvItemList<LogRvItem>()
var magiskLogRaw = " "
override suspend fun doLoadWork() {
consoleText = repo.fetchMagiskLogs()
val (suLogs, diff) = withContext(Dispatchers.Default) {
val suLogs = repo.fetchSuLogs().map { LogRvItem(it) }
loading = true
val (logs, logDiff) = withContext(Dispatchers.Default) {
magiskLogRaw = repo.fetchMagiskLogs()
val logs = magiskLogRaw.split('\n').map { LogRvItem(it) }
logs to this@LogViewModel.logs.calculateDiff(logs)
}
this.logs.update(logs, logDiff)
val (suLogs, suDiff) = withContext(Dispatchers.Default) {
val suLogs = repo.fetchSuLogs().map { SuLogRvItem(it) }
suLogs to items.calculateDiff(suLogs)
}
items.firstOrNull()?.isTop = false
items.lastOrNull()?.isBottom = false
items.update(suLogs, diff)
items.update(suLogs, suDiff)
items.firstOrNull()?.isTop = true
items.lastOrNull()?.isBottom = true
loading = false
}
fun saveMagiskLog() = withExternalRW {
@ -82,7 +92,7 @@ class LogViewModel(
file.write("\n---Magisk Logs---\n")
file.write("${Info.env.versionString} (${Info.env.versionCode})\n\n")
if (Info.env.isActive) file.write(consoleText)
if (Info.env.isActive) file.write(magiskLogRaw)
file.write("\n---Manager Logs---\n")
file.write("${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})\n\n")

View File

@ -0,0 +1,30 @@
package com.topjohnwu.magisk.ui.log
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.model.su.SuLog
import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
import com.topjohnwu.magisk.databinding.RvContainer
import com.topjohnwu.magisk.databinding.set
import com.topjohnwu.magisk.ktx.timeDateFormat
import com.topjohnwu.magisk.ktx.toTime
class SuLogRvItem(
override val item: SuLog
) : ObservableDiffRvItem<SuLogRvItem>(), RvContainer<SuLog> {
override val layoutRes = R.layout.item_log_access_md2
val date = item.time.toTime(timeDateFormat)
@get:Bindable
var isTop = false
set(value) = set(value, field, { field = it }, BR.top)
@get:Bindable
var isBottom = false
set(value) = set(value, field, { field = it }, BR.bottom)
override fun itemSameAs(other: SuLogRvItem) = item.appName == other.item.appName
}

View File

@ -23,6 +23,7 @@
android:layout_height="match_parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
gone="@{viewModel.loading}"
android:id="@+id/log_filter_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@ -15,46 +15,63 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
gone="@{viewModel.consoleText.empty}"
<HorizontalScrollView
gone="@{viewModel.loading}"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:fillViewport="true">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/log_magisk"
app:items="@{viewModel.logs}"
app:extraBindings="@{viewModel.extraBindings}"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingTop="@dimen/internal_action_bar_size"
android:paddingBottom="@dimen/internal_action_bar_size"
app:fitsSystemWindowsInsets="top|bottom"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_log_textview"
tools:paddingTop="24dp" />
</HorizontalScrollView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:paddingTop="@dimen/internal_action_bar_size"
android:paddingBottom="128dp"
android:text="@{viewModel.consoleText}"
android:textAppearance="@style/AppearanceFoundation.Caption"
app:layout_fitsSystemWindowsInsets="top|bottom"
tools:text="@tools:sample/lorem/random" />
</HorizontalScrollView>
</androidx.core.widget.NestedScrollView>
<FrameLayout
gone="@{!viewModel.consoleText.empty}"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical">
<include
item="@{viewModel.itemMagiskEmpty}"
layout="@layout/item_text"
<TextView
goneUnless="@{viewModel.loading}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/loading"
android:textAppearance="@style/AppearanceFoundation.Title"
android:textStyle="bold" />
<ProgressBar
style="@style/WidgetFoundation.ProgressBar.Indeterminate"
goneUnless="@{viewModel.loading}"
android:layout_marginTop="@dimen/l1" />
<FrameLayout
gone="@{viewModel.loading || !viewModel.magiskLogRaw.empty}"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:layout_gravity="center">
</FrameLayout>
<include
item="@{viewModel.itemMagiskEmpty}"
layout="@layout/item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
</LinearLayout>
</FrameLayout>
</layout>

View File

@ -9,7 +9,7 @@
<variable
name="item"
type="com.topjohnwu.magisk.ui.log.LogRvItem" />
type="com.topjohnwu.magisk.ui.log.SuLogRvItem" />
<variable
name="viewModel"

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="item"
type="com.topjohnwu.magisk.ui.log.LogRvItem" />
</data>
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:textAppearance="@style/AppearanceFoundation.Caption"
android:text="@{item.item}" />
</layout>