Commit 67c50d75 authored by Viktor De Pasquale's avatar Viktor De Pasquale

Added magisk log screen

parent 94f0c616
...@@ -164,4 +164,9 @@ open class MainActivity : CompatActivity<MainViewModel, ActivityMainMd2Binding>( ...@@ -164,4 +164,9 @@ open class MainActivity : CompatActivity<MainViewModel, ActivityMainMd2Binding>(
.start() .start()
} }
fun invalidateToolbar() {
//binding.mainToolbar.startAnimations()
binding.mainToolbar.invalidate()
}
} }
\ No newline at end of file
package com.topjohnwu.magisk.redesign.log package com.topjohnwu.magisk.redesign.log
import android.graphics.Insets import android.graphics.Insets
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.core.view.isVisible
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding
import com.topjohnwu.magisk.redesign.MainActivity
import com.topjohnwu.magisk.redesign.compat.CompatFragment import com.topjohnwu.magisk.redesign.compat.CompatFragment
import com.topjohnwu.magisk.redesign.hide.MotionRevealHelper
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
class LogFragment : CompatFragment<LogViewModel, FragmentLogMd2Binding>() { class LogFragment : CompatFragment<LogViewModel, FragmentLogMd2Binding>() {
...@@ -11,14 +19,58 @@ class LogFragment : CompatFragment<LogViewModel, FragmentLogMd2Binding>() { ...@@ -11,14 +19,58 @@ class LogFragment : CompatFragment<LogViewModel, FragmentLogMd2Binding>() {
override val layoutRes = R.layout.fragment_log_md2 override val layoutRes = R.layout.fragment_log_md2
override val viewModel by viewModel<LogViewModel>() override val viewModel by viewModel<LogViewModel>()
private var actionSave: MenuItem? = null
private var isMagiskLogVisible
get() = binding.logFilter.isVisible
set(value) {
MotionRevealHelper.withViews(binding.logFilter, binding.logFilterToggle, value)
actionSave?.isVisible = value
(activity as MainActivity).invalidateToolbar()
}
override fun consumeSystemWindowInsets(insets: Insets) = insets override fun consumeSystemWindowInsets(insets: Insets) = insets
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
setHasOptionsMenu(true)
activity.title = resources.getString(R.string.section_log) activity.title = resources.getString(R.string.section_log)
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.logFilterToggle.setOnClickListener {
isMagiskLogVisible = true
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.menu_log_md2, menu)
actionSave = menu.findItem(R.id.action_save)?.also {
it.isVisible = isMagiskLogVisible
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_save -> viewModel.saveMagiskLog()
R.id.action_clear ->
if (isMagiskLogVisible) viewModel.clearMagiskLog()
else viewModel.clearLog()
}
return super.onOptionsItemSelected(item)
}
override fun onPreBind(binding: FragmentLogMd2Binding) = Unit override fun onPreBind(binding: FragmentLogMd2Binding) = Unit
override fun onBackPressed(): Boolean {
if (binding.logFilter.isVisible) {
isMagiskLogVisible = false
return true
}
return super.onBackPressed()
}
} }
\ No newline at end of file
package com.topjohnwu.magisk.redesign.log package com.topjohnwu.magisk.redesign.log
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.repository.LogRepository import com.topjohnwu.magisk.data.repository.LogRepository
import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.extensions.subscribeK import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.model.binding.BindingAdapter
import com.topjohnwu.magisk.model.entity.recycler.ConsoleRvItem
import com.topjohnwu.magisk.model.entity.recycler.LogItem import com.topjohnwu.magisk.model.entity.recycler.LogItem
import com.topjohnwu.magisk.model.events.SnackbarEvent
import com.topjohnwu.magisk.redesign.compat.CompatViewModel import com.topjohnwu.magisk.redesign.compat.CompatViewModel
import com.topjohnwu.magisk.redesign.home.itemBindingOf import com.topjohnwu.magisk.redesign.home.itemBindingOf
import com.topjohnwu.magisk.redesign.superuser.diffListOf import com.topjohnwu.magisk.redesign.superuser.diffListOf
import com.topjohnwu.superuser.Shell
import io.reactivex.Completable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
import java.io.File
import java.util.*
class LogViewModel( class LogViewModel(
private val repo: LogRepository private val repo: LogRepository
) : CompatViewModel() { ) : CompatViewModel() {
// --- main view
val items = diffListOf<LogItem>() val items = diffListOf<LogItem>()
val itemBinding = itemBindingOf<LogItem> { val itemBinding = itemBindingOf<LogItem> {
it.bindExtra(BR.viewModel, this) it.bindExtra(BR.viewModel, this)
} }
override fun refresh() = repo.fetchLogsNowrap() // --- console
.map { it.map { LogItem(it) } }
.map { it to items.calculateDiff(it) } val consoleAdapter = BindingAdapter()
.subscribeK { val itemsConsole = diffListOf<ComparableRvItem<*>>()
items.firstOrNull()?.isTop = false val itemConsoleBinding = itemBindingOf<ComparableRvItem<*>> {}
items.lastOrNull()?.isBottom = false
override fun refresh(): Disposable {
val logs = repo.fetchLogsNowrap()
.map { it.map { LogItem(it) } }
.observeOn(Schedulers.computation())
.map { it to items.calculateDiff(it) }
.observeOn(AndroidSchedulers.mainThread())
.doOnSuccess {
items.firstOrNull()?.isTop = false
items.lastOrNull()?.isBottom = false
items.update(it.first, it.second)
items.firstOrNull()?.isTop = true
items.lastOrNull()?.isBottom = true
}
.ignoreElement()
val console = repo.fetchMagiskLogs()
.map { it.map { ConsoleRvItem(it) } }
.observeOn(Schedulers.computation())
.map { it to itemsConsole.calculateDiff(it) }
.observeOn(AndroidSchedulers.mainThread())
.doOnSuccess { itemsConsole.update(it.first, it.second) }
.ignoreElement()
return Completable.merge(listOf(logs, console)).subscribeK()
}
items.update(it.first, it.second) fun saveMagiskLog() {
val now = Calendar.getInstance()
val filename = "magisk_log_%04d%02d%02d_%02d%02d%02d.log".format(
now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1,
now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY),
now.get(Calendar.MINUTE), now.get(Calendar.SECOND)
)
items.firstOrNull()?.isTop = true val logFile = File(Config.downloadDirectory, filename)
items.lastOrNull()?.isBottom = true runCatching {
logFile.createNewFile()
}.onFailure {
Timber.e(it)
return
}
Shell.su("cat ${Const.MAGISK_LOG} > $logFile").submit {
SnackbarEvent(logFile.path).publish()
}
}
fun clearMagiskLog() = repo.clearMagiskLogs()
.ignoreElement()
.subscribeK {
SnackbarEvent(R.string.logs_cleared).publish()
requestRefresh()
}
.add()
fun clearLog() = repo.clearLogs()
.subscribeK {
SnackbarEvent(R.string.logs_cleared).publish()
requestRefresh()
} }
.add()
} }
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?colorOnSurface"
android:pathData="M20,18H4V8H20M20,6H12L10,4H4A2,2 0 0,0 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8A2,2 0 0,0 20,6M15,16H6V14H15V16M18,12H6V10H18V12Z" />
</vector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?colorOnSurface"
android:pathData="M17 3H5C3.89 3 3 3.9 3 5V19C3 20.1 3.89 21 5 21H19C20.1 21 21 20.1 21 19V7L17 3M19 19H5V5H16.17L19 7.83V19M12 12C10.34 12 9 13.34 9 15S10.34 18 12 18 15 16.66 15 15 13.66 12 12 12M6 6H15V10H6V6Z" />
</vector>
\ No newline at end of file
...@@ -11,19 +11,56 @@ ...@@ -11,19 +11,56 @@
</data> </data>
<androidx.recyclerview.widget.RecyclerView <FrameLayout
itemBinding="@{viewModel.itemBinding}"
items="@{viewModel.items}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:clipToPadding="false"
android:orientation="vertical" <androidx.recyclerview.widget.RecyclerView
android:paddingStart="@dimen/l1" itemBinding="@{viewModel.itemBinding}"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}" items="@{viewModel.items}"
android:paddingEnd="@dimen/l1" android:layout_width="match_parent"
android:paddingBottom="@{viewModel.insets.bottom}" android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" android:clipToPadding="false"
tools:listitem="@layout/item_log_access_md2" android:orientation="vertical"
tools:paddingTop="40dp" /> android:paddingStart="@dimen/l1"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
android:paddingEnd="@dimen/l1"
android:paddingBottom="@{viewModel.insets.bottom}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_log_access_md2"
tools:paddingTop="24dp" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/log_filter_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginStart="@dimen/l1"
android:layout_marginEnd="@dimen/l1"
android:layout_marginBottom="@{viewModel.insets.bottom + (int) @dimen/l1}"
app:backgroundTint="?colorSurfaceSurfaceVariant"
app:srcCompat="@drawable/ic_folder_list"
app:tint="?colorPrimary"
tools:layout_marginBottom="64dp" />
<com.google.android.material.circularreveal.cardview.CircularRevealCardView
android:id="@+id/log_filter"
style="?styleCardVariant"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:visibility="invisible"
app:cardCornerRadius="0dp">
<include
android:id="@+id/log_filter_include"
layout="@layout/include_log_magisk"
viewModel="@{viewModel}"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.google.android.material.circularreveal.cardview.CircularRevealCardView>
</FrameLayout>
</layout> </layout>
\ No newline at end of file
<?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">
<data>
<variable
name="viewModel"
type="com.topjohnwu.magisk.redesign.log.LogViewModel" />
</data>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
adapter="@{viewModel.consoleAdapter}"
itemBinding="@{viewModel.itemConsoleBinding}"
items="@{viewModel.itemsConsole}"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
android:paddingBottom="@{viewModel.insets.bottom}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_console"
tools:paddingTop="24dp" />
</HorizontalScrollView>
</layout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_save"
android:icon="@drawable/ic_save_md2"
android:title="@string/menuSaveLog"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_clear"
android:icon="@drawable/ic_delete_md2"
android:title="@string/menuClearLog"
app:showAsAction="ifRoom" />
</menu>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment