diff --git a/app/src/main/java/com/topjohnwu/magisk/redesign/MainActivity.kt b/app/src/main/java/com/topjohnwu/magisk/redesign/MainActivity.kt index c938aaeb5..8d0e43c2e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/redesign/MainActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/redesign/MainActivity.kt @@ -164,4 +164,9 @@ open class MainActivity : CompatActivity( .start() } + fun invalidateToolbar() { + //binding.mainToolbar.startAnimations() + binding.mainToolbar.invalidate() + } + } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/redesign/log/LogFragment.kt b/app/src/main/java/com/topjohnwu/magisk/redesign/log/LogFragment.kt index 2a4537fd3..9af2d842c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/redesign/log/LogFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/redesign/log/LogFragment.kt @@ -1,9 +1,17 @@ package com.topjohnwu.magisk.redesign.log 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.databinding.FragmentLogMd2Binding +import com.topjohnwu.magisk.redesign.MainActivity import com.topjohnwu.magisk.redesign.compat.CompatFragment +import com.topjohnwu.magisk.redesign.hide.MotionRevealHelper import org.koin.androidx.viewmodel.ext.android.viewModel class LogFragment : CompatFragment() { @@ -11,14 +19,58 @@ class LogFragment : CompatFragment() { override val layoutRes = R.layout.fragment_log_md2 override val viewModel by viewModel() + 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 onStart() { super.onStart() - + setHasOptionsMenu(true) 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 onBackPressed(): Boolean { + if (binding.logFilter.isVisible) { + isMagiskLogVisible = false + return true + } + return super.onBackPressed() + } + } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/redesign/log/LogViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/redesign/log/LogViewModel.kt index dadbd3684..b8e94c177 100644 --- a/app/src/main/java/com/topjohnwu/magisk/redesign/log/LogViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/redesign/log/LogViewModel.kt @@ -1,33 +1,107 @@ package com.topjohnwu.magisk.redesign.log 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.databinding.ComparableRvItem 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.events.SnackbarEvent import com.topjohnwu.magisk.redesign.compat.CompatViewModel import com.topjohnwu.magisk.redesign.home.itemBindingOf 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( private val repo: LogRepository ) : CompatViewModel() { + // --- main view + val items = diffListOf() val itemBinding = itemBindingOf { it.bindExtra(BR.viewModel, this) } - override fun refresh() = repo.fetchLogsNowrap() - .map { it.map { LogItem(it) } } - .map { it to items.calculateDiff(it) } - .subscribeK { - items.firstOrNull()?.isTop = false - items.lastOrNull()?.isBottom = false + // --- console - items.update(it.first, it.second) + val consoleAdapter = BindingAdapter() + val itemsConsole = diffListOf>() + val itemConsoleBinding = itemBindingOf> {} - items.firstOrNull()?.isTop = true - items.lastOrNull()?.isBottom = true + 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() + } + + 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) + ) + + val logFile = File(Config.downloadDirectory, filename) + 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 diff --git a/app/src/main/res/drawable/ic_folder_list.xml b/app/src/main/res/drawable/ic_folder_list.xml new file mode 100644 index 000000000..7c13a421c --- /dev/null +++ b/app/src/main/res/drawable/ic_folder_list.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_save_md2.xml b/app/src/main/res/drawable/ic_save_md2.xml new file mode 100644 index 000000000..81d0e3b04 --- /dev/null +++ b/app/src/main/res/drawable/ic_save_md2.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_log_md2.xml b/app/src/main/res/layout/fragment_log_md2.xml index 4fb807940..13e333407 100644 --- a/app/src/main/res/layout/fragment_log_md2.xml +++ b/app/src/main/res/layout/fragment_log_md2.xml @@ -11,19 +11,56 @@ - + android:layout_height="match_parent"> + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_log_magisk.xml b/app/src/main/res/layout/include_log_magisk.xml new file mode 100644 index 000000000..5995f80bc --- /dev/null +++ b/app/src/main/res/layout/include_log_magisk.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_log_md2.xml b/app/src/main/res/menu/menu_log_md2.xml new file mode 100644 index 000000000..0356092b2 --- /dev/null +++ b/app/src/main/res/menu/menu_log_md2.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file