diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
index 4347afbca..087bf4223 100644
--- a/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
@@ -43,6 +43,8 @@ class LogViewModel(
private val logItem get() = items[0] as LogRvItem
private val magiskLogItem get() = items[1] as MagiskLogRvItem
+ val scrollPosition = KObservableField(0)
+
init {
currentPage.addOnPropertyChangedCallback {
it ?: return@addOnPropertyChangedCallback
@@ -59,6 +61,10 @@ class LogViewModel(
else -> ""
}
+ fun scrollDownPressed() {
+ scrollPosition.value = magiskLogItem.items.size - 1
+ }
+
fun refresh() {
fetchLogs().subscribeK { logItem.update(it) }
fetchMagiskLog().subscribeK { magiskLogItem.update(it) }
diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt b/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt
index d468c5217..5c102442f 100644
--- a/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt
+++ b/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt
@@ -11,8 +11,10 @@ import androidx.databinding.InverseBindingAdapter
import androidx.databinding.InverseBindingListener
import androidx.drawerlayout.widget.DrawerLayout
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
+import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
+import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.navigation.NavigationView
import com.skoumal.teanity.extensions.subscribeK
import com.topjohnwu.magisk.R
@@ -176,4 +178,32 @@ fun setScrollToLast(view: RecyclerView, shouldScrollToLast: Boolean) {
} else {
view.adapter?.removeListener()
}
-}
\ No newline at end of file
+}
+
+@BindingAdapter("hide")
+fun setHidden(view: FloatingActionButton, hide: Boolean) {
+ if (hide) view.hide() else view.show()
+}
+
+@BindingAdapter("scrollPosition", "scrollPositionSmooth", requireAll = false)
+fun setScrollPosition(view: RecyclerView, position: Int, smoothScroll: Boolean) = when {
+ smoothScroll -> view.smoothScrollToPosition(position)
+ else -> view.scrollToPosition(position)
+}
+
+@BindingAdapter("recyclerScrollEvent")
+fun setScrollListener(view: RecyclerView, listener: InverseBindingListener) {
+ view.addOnScrollListener(object : RecyclerView.OnScrollListener() {
+ override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
+ // don't change this or the recycler will stop at every line, effectively disabling smooth scroll
+ if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+ listener.onChange()
+ }
+ }
+ })
+}
+
+@InverseBindingAdapter(attribute = "scrollPosition", event = "recyclerScrollEvent")
+fun getScrollPosition(view: RecyclerView) = (view.layoutManager as? LinearLayoutManager)
+ ?.findLastCompletelyVisibleItemPosition()
+ ?: -1
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_arrow_down.xml b/app/src/main/res/drawable/ic_arrow_down.xml
new file mode 100644
index 000000000..569d3a745
--- /dev/null
+++ b/app/src/main/res/drawable/ic_arrow_down.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_page_magisk_log.xml b/app/src/main/res/layout/item_page_magisk_log.xml
index 252a47983..5bc134ba7 100644
--- a/app/src/main/res/layout/item_page_magisk_log.xml
+++ b/app/src/main/res/layout/item_page_magisk_log.xml
@@ -15,20 +15,39 @@
-
-
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file