Cleanup code

This commit is contained in:
vvb2060 2022-01-17 15:07:05 +08:00 committed by John Wu
parent 11600fc116
commit 2997258fd0
18 changed files with 8 additions and 452 deletions

View File

@ -84,9 +84,3 @@ abstract class BaseUIFragment<VM : BaseViewModel, Binding : ViewDataBinding> :
}
}
interface ReselectionTarget {
fun onReselected()
}

View File

@ -1,17 +0,0 @@
package com.topjohnwu.magisk.arch
import android.os.Handler
import androidx.core.os.postDelayed
import com.topjohnwu.superuser.internal.UiThreadHandler
interface Queryable {
val queryDelay: Long
val queryHandler: Handler get() = UiThreadHandler.handler
fun submitQuery() {
queryHandler.postDelayed(queryDelay) { query() }
}
fun query()
}

View File

@ -1,57 +0,0 @@
package com.topjohnwu.magisk.databinding
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.InsetDrawable
import androidx.databinding.BindingAdapter
import androidx.recyclerview.widget.RecyclerView
import com.topjohnwu.magisk.ktx.startEndToLeftRight
import com.topjohnwu.magisk.ktx.toPx
import com.topjohnwu.magisk.utils.KItemDecoration
import kotlin.math.roundToInt
@BindingAdapter(
"dividerColor",
"dividerHorizontal",
"dividerSize",
"dividerAfterLast",
"dividerMarginStart",
"dividerMarginEnd",
"dividerMarginTop",
"dividerMarginBottom",
requireAll = false
)
fun setDivider(
view: RecyclerView,
color: Int,
horizontal: Boolean,
_size: Float,
_afterLast: Boolean?,
marginStartF: Float,
marginEndF: Float,
marginTopF: Float,
marginBottomF: Float
) {
val orientation = if (horizontal) RecyclerView.HORIZONTAL else RecyclerView.VERTICAL
val size = if (_size > 0) _size.roundToInt() else 1.toPx()
val (width, height) = if (horizontal) size to 1 else 1 to size
val afterLast = _afterLast ?: true
val marginStart = marginStartF.roundToInt()
val marginEnd = marginEndF.roundToInt()
val marginTop = marginTopF.roundToInt()
val marginBottom = marginBottomF.roundToInt()
val (marginLeft, marginRight) = view.context.startEndToLeftRight(marginStart, marginEnd)
val drawable = GradientDrawable().apply {
setSize(width, height)
shape = GradientDrawable.RECTANGLE
setColor(color)
}.let {
InsetDrawable(it, marginLeft, marginTop, marginRight, marginBottom)
}
val decoration = KItemDecoration(view.context, orientation)
.setDeco(drawable)
.apply { showAfterLast = afterLast }
view.addItemDecoration(decoration)
}

View File

@ -30,7 +30,6 @@ import com.google.android.material.textfield.TextInputLayout
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.di.ServiceLocator
import com.topjohnwu.magisk.ktx.coroutineScope
import com.topjohnwu.magisk.ktx.replaceRandomWithSpecial
import com.topjohnwu.superuser.internal.UiThreadHandler
import com.topjohnwu.widget.IndeterminateCheckBox
import kotlinx.coroutines.*
@ -78,22 +77,6 @@ fun setImageResource(view: ImageView, drawable: Drawable) {
view.setImageDrawable(drawable)
}
@BindingAdapter("movieBehavior", "movieBehaviorText")
fun setMovieBehavior(view: TextView, isMovieBehavior: Boolean, text: String) {
(view.tag as? Job)?.cancel()
view.tag = null
if (isMovieBehavior) {
view.tag = GlobalScope.launch(Dispatchers.Main.immediate) {
while (true) {
delay(150)
view.text = text.replaceRandomWithSpecial()
}
}
} else {
view.text = text
}
}
@BindingAdapter("onTouch")
fun setOnTouchListener(view: View, listener: View.OnTouchListener) {
view.setOnTouchListener(listener)

View File

@ -10,22 +10,9 @@ import com.topjohnwu.magisk.MainDirections
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.*
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.model.module.OnlineModule
import com.topjohnwu.magisk.events.dialog.MarkDownDialog
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.magisk.view.Shortcuts
class OpenReadmeEvent(private val item: OnlineModule) : MarkDownDialog() {
override suspend fun getMarkdownText() = item.notes()
override fun build(dialog: MagiskDialog) {
super.build(dialog)
dialog.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
titleRes = android.R.string.cancel
}.cancellable(true)
}
}
class PermissionEvent(
private val permission: String,
private val callback: (Boolean) -> Unit

View File

@ -1,9 +0,0 @@
package com.topjohnwu.magisk.ktx
import android.content.res.Resources
import kotlin.math.ceil
import kotlin.math.roundToInt
fun Int.toDp(): Int = ceil(this / Resources.getSystem().displayMetrics.density).roundToInt()
fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).roundToInt()

View File

@ -1,11 +1,9 @@
package com.topjohnwu.magisk.ktx
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flow
@FlowPreview
inline fun <T, R> Flow<T>.concurrentMap(crossinline transform: suspend (T) -> R): Flow<R> {
return flatMapMerge { value ->
flow { emit(transform(value)) }

View File

@ -1,41 +0,0 @@
package com.topjohnwu.magisk.ktx
val specialChars = arrayOf('!', '@', '#', '$', '%', '&', '?')
val fullSpecialChars = arrayOf('', '', '', '', '', '', '')
fun String.isCJK(): Boolean {
for (i in 0 until length)
if (isCJK(codePointAt(i)))
return true
return false
}
fun isCJK(codepoint: Int) = Character.isIdeographic(codepoint)
fun String.replaceRandomWithSpecial(passes: Int): String {
var string = this
repeat(passes) {
string = string.replaceRandomWithSpecial()
}
return string
}
fun String.replaceRandomWithSpecial(): String {
val sp = if (isCJK()) fullSpecialChars else specialChars
var random: Char
do {
random = random()
} while (random == '.')
return replace(random, sp.random())
}
fun StringBuilder.appendIf(condition: Boolean, builder: StringBuilder.() -> Unit) =
if (condition) apply(builder) else this
fun String.trimEmptyToNull(): String? = if (isBlank()) null else this
fun String.legalFilename() = replace(" ", "_").replace("'", "").replace("\"", "")
.replace("$", "").replace("`", "").replace("*", "").replace("/", "_")
.replace("#", "").replace("@", "").replace("\\", "_")
fun String.isEmptyInternal() = isNullOrBlank()

View File

@ -20,7 +20,6 @@ import com.topjohnwu.magisk.MainDirections
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseMainActivity
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.arch.ReselectionTarget
import com.topjohnwu.magisk.core.*
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
import com.topjohnwu.magisk.di.viewModel
@ -82,9 +81,6 @@ class MainActivity : BaseMainActivity<MainViewModel, ActivityMainMd2Binding>() {
getScreen(it.itemId)?.navigate()
true
}
binding.mainNavigation.setOnItemReselectedListener {
(currentFragment as? ReselectionTarget)?.onReselected()
}
binding.mainNavigation.menu.apply {
findItem(R.id.superuserFragment)?.isEnabled = Utils.showSuperUser()
findItem(R.id.modulesFragment)?.isEnabled = Info.env.isActive

View File

@ -5,7 +5,6 @@ import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.arch.Queryable
import com.topjohnwu.magisk.databinding.filterableListOf
import com.topjohnwu.magisk.databinding.itemBindingOf
import com.topjohnwu.magisk.di.AppContext
@ -15,29 +14,25 @@ import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import java.util.*
import kotlin.collections.ArrayList
@FlowPreview
class DenyListViewModel : BaseViewModel(), Queryable {
override val queryDelay = 0L
class DenyListViewModel : BaseViewModel() {
var isShowSystem = false
set(value) {
field = value
submitQuery()
query()
}
var isShowOS = false
set(value) {
field = value
submitQuery()
query()
}
var query = ""
set(value) {
field = value
submitQuery()
query()
}
val items = filterableListOf<DenyListRvItem>()
@ -71,10 +66,10 @@ class DenyListViewModel : BaseViewModel(), Queryable {
apps to items.calculateDiff(apps)
}
items.update(apps, diff)
submitQuery()
query()
}
override fun query() {
fun query() {
items.filter {
fun filterSystem() = isShowSystem || !it.info.isSystemApp()

View File

@ -1,22 +0,0 @@
package com.topjohnwu.magisk.utils
class CachedValue<T>(private val factory: () -> T) : Lazy<T> {
private var _val : T? = null
override val value: T
get() {
val local = _val
return local ?: synchronized(this) {
_val ?: factory().also { _val = it }
}
}
override fun isInitialized() = _val != null
fun invalidate() {
synchronized(this) {
_val = null
}
}
}

View File

@ -1,116 +0,0 @@
package com.topjohnwu.magisk.utils
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.topjohnwu.magisk.arch.ViewEvent
class EndlessRecyclerScrollListener(
private val layoutManager: RecyclerView.LayoutManager,
private val loadMore: (page: Int, totalItemsCount: Int, view: RecyclerView?) -> Unit,
private val direction: Direction = Direction.BOTTOM,
visibleRowsThreshold: Int = VISIBLE_THRESHOLD
) : RecyclerView.OnScrollListener() {
constructor(
layoutManager: RecyclerView.LayoutManager,
loadMore: () -> Unit,
direction: Direction = Direction.BOTTOM,
visibleRowsThreshold: Int = VISIBLE_THRESHOLD
) : this(layoutManager, { _, _, _ -> loadMore() }, direction, visibleRowsThreshold)
enum class Direction {
TOP, BOTTOM
}
companion object {
private const val VISIBLE_THRESHOLD = 5
private const val STARTING_PAGE_INDEX = 0
}
// The minimum amount of items to have above/below your current scroll position
// before loading more.
private val visibleThreshold = when (layoutManager) {
is LinearLayoutManager -> visibleRowsThreshold
is GridLayoutManager -> visibleRowsThreshold * layoutManager.spanCount
is StaggeredGridLayoutManager -> visibleRowsThreshold * layoutManager.spanCount
else -> throw IllegalArgumentException("Only LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager are supported")
}
// The current offset index of data you have loaded
private var currentPage = 0
// The total number of items in the dataset after the last load
private var previousTotalItemCount = 0
// True if we are still waiting for the last set of data to load.
private var loading = true
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) {
if (dx == 0 && dy == 0) return
val totalItemCount = layoutManager.itemCount
val visibleItemPosition = if (direction == Direction.BOTTOM) {
when (layoutManager) {
is StaggeredGridLayoutManager ->
layoutManager.findLastVisibleItemPositions(null).maxOrNull() ?: 0
is GridLayoutManager -> layoutManager.findLastVisibleItemPosition()
is LinearLayoutManager -> layoutManager.findLastVisibleItemPosition()
else -> throw IllegalArgumentException("Only LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager are supported")
}
} else {
when (layoutManager) {
is StaggeredGridLayoutManager ->
layoutManager.findFirstVisibleItemPositions(null).minOrNull() ?: 0
is GridLayoutManager -> layoutManager.findFirstVisibleItemPosition()
is LinearLayoutManager -> layoutManager.findFirstVisibleItemPosition()
else -> throw IllegalArgumentException("Only LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager are supported")
}
}
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
currentPage =
STARTING_PAGE_INDEX
previousTotalItemCount = totalItemCount
if (totalItemCount == 0) {
loading = true
}
}
// If its still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && totalItemCount > previousTotalItemCount) {
loading = false
previousTotalItemCount = totalItemCount
}
// If it isnt currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
// threshold should reflect how many total columns there are too
if (!loading && shouldLoadMoreItems(visibleItemPosition, totalItemCount)) {
currentPage++
loadMore(currentPage, totalItemCount, view)
loading = true
}
}
private fun shouldLoadMoreItems(visibleItemPosition: Int, itemCount: Int) = when (direction) {
Direction.TOP -> visibleItemPosition < visibleThreshold
Direction.BOTTOM -> visibleItemPosition + visibleThreshold > itemCount
}
// Call this method whenever performing new searches
fun resetState() {
currentPage = STARTING_PAGE_INDEX
previousTotalItemCount = 0
loading = true
}
class ResetState : ViewEvent()
}

View File

@ -1,118 +0,0 @@
package com.topjohnwu.magisk.utils
import android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.view.View
import androidx.annotation.DrawableRes
import androidx.core.view.get
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView
import com.topjohnwu.magisk.ktx.drawableCompat
import kotlin.math.roundToInt
class KItemDecoration(
private val context: Context,
@RecyclerView.Orientation private val orientation: Int
) :
RecyclerView.ItemDecoration() {
private val bounds = Rect()
private var divider: Drawable? = null
var showAfterLast = true
fun setDeco(@DrawableRes drawable: Int) = apply {
setDeco(context.drawableCompat(drawable))
}
fun setDeco(drawable: Drawable?) = apply {
divider = drawable
}
override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
parent.layoutManager ?: return
divider?.let {
if (orientation == DividerItemDecoration.VERTICAL) {
drawVertical(canvas, parent, it)
} else {
drawHorizontal(canvas, parent, it)
}
}
}
private fun drawVertical(canvas: Canvas, parent: RecyclerView, drawable: Drawable) {
canvas.save()
val left: Int
val right: Int
if (parent.clipToPadding) {
left = parent.paddingLeft
right = parent.width - parent.paddingRight
canvas.clipRect(
left, parent.paddingTop, right,
parent.height - parent.paddingBottom
)
} else {
left = 0
right = parent.width
}
val to = if (showAfterLast) parent.childCount else parent.childCount - 1
(0 until to)
.map { parent[it] }
.forEach { child ->
parent.getDecoratedBoundsWithMargins(child, bounds)
val bottom = bounds.bottom + child.translationY.roundToInt()
val top = bottom - drawable.intrinsicHeight
drawable.setBounds(left, top, right, bottom)
drawable.draw(canvas)
}
canvas.restore()
}
private fun drawHorizontal(canvas: Canvas, parent: RecyclerView, drawable: Drawable) {
canvas.save()
val top: Int
val bottom: Int
if (parent.clipToPadding) {
top = parent.paddingTop
bottom = parent.height - parent.paddingBottom
canvas.clipRect(
parent.paddingLeft, top,
parent.width - parent.paddingRight, bottom
)
} else {
top = 0
bottom = parent.height
}
val to = if (showAfterLast) parent.childCount else parent.childCount - 1
(0 until to)
.map { parent[it] }
.forEach { child ->
parent.layoutManager!!.getDecoratedBoundsWithMargins(child, bounds)
val right = bounds.right + child.translationX.roundToInt()
val left = right - drawable.intrinsicWidth
drawable.setBounds(left, top, right, bottom)
drawable.draw(canvas)
}
canvas.restore()
}
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
if (parent.getChildAdapterPosition(view) == state.itemCount - 1) {
outRect.setEmpty()
return
}
if (orientation == RecyclerView.VERTICAL) {
outRect.set(0, 0, 0, divider?.intrinsicHeight ?: 0)
} else {
outRect.set(0, 0, divider?.intrinsicWidth ?: 0, 0)
}
}
}

View File

@ -30,11 +30,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="monospace"
precomputedText="@{viewModel.consoleText}"
android:textAppearance="@style/AppearanceFoundation.Caption"
android:textSize="10sp"
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" />

View File

@ -16,7 +16,6 @@
android:fontFamily="monospace"
android:text="@{item.item}"
android:textAppearance="@style/AppearanceFoundation.Caption"
android:textSize="10sp"
tools:text="@tools:sample/lorem/random" />
</layout>

View File

@ -66,7 +66,6 @@
android:layout_height="wrap_content"
android:text="@{item.date}"
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
android:textSize="10sp"
app:layout_constraintBottom_toTopOf="@+id/log_app_details"
app:layout_constraintTop_toBottomOf="@+id/log_app_name"
tools:text="06:00 PM, 10 Oct 2019" />
@ -77,7 +76,6 @@
android:layout_height="wrap_content"
android:text="@{String.format(`%s %s`, @string/pid(item.item.fromPid), @string/target_uid(item.item.toUid))}"
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/log_command"
app:layout_constraintStart_toStartOf="parent"
@ -91,7 +89,6 @@
android:fontFamily="monospace"
android:text="@{item.item.command}"
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/log_app_details"
app:layout_constraintTop_toTopOf="@+id/log_app_details"

View File

@ -1,10 +0,0 @@
<?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_refresh"
android:icon="@drawable/ic_refresh_data_md2"
android:title="@string/refresh"
app:showAsAction="ifRoom" />
</menu>

View File

@ -13,7 +13,5 @@
<dimen name="r1">8dp</dimen>
<!--l1 + fab size-->
<dimen name="internal_action_bar_size">56dp</dimen>
</resources>