Reorganize app source code

This commit is contained in:
topjohnwu
2020-08-18 06:31:15 -07:00
parent d7a26dbf27
commit 846bbb4da1
77 changed files with 158 additions and 191 deletions
@@ -0,0 +1,117 @@
package com.topjohnwu.magisk.arch
import android.Manifest
import androidx.annotation.CallSuper
import androidx.core.graphics.Insets
import androidx.databinding.Bindable
import androidx.databinding.Observable
import androidx.databinding.PropertyChangeRegistry
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavDirections
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.model.events.BackPressEvent
import com.topjohnwu.magisk.model.events.PermissionEvent
import com.topjohnwu.magisk.model.events.SnackbarEvent
import com.topjohnwu.magisk.model.events.ViewActionEvent
import com.topjohnwu.magisk.model.navigation.NavigationWrapper
import com.topjohnwu.magisk.utils.ObservableHost
import com.topjohnwu.magisk.utils.set
import kotlinx.coroutines.Job
import org.koin.core.KoinComponent
abstract class BaseViewModel(
initialState: State = State.LOADING
) : ViewModel(), ObservableHost, KoinComponent {
override var callbacks: PropertyChangeRegistry? = null
enum class State {
LOADED, LOADING, LOADING_FAILED
}
@get:Bindable
val loading get() = state == State.LOADING
@get:Bindable
val loaded get() = state == State.LOADED
@get:Bindable
val loadFailed get() = state == State.LOADING_FAILED
val isConnected get() = Info.isConnected
val viewEvents: LiveData<ViewEvent> get() = _viewEvents
@get:Bindable
var insets = Insets.NONE
set(value) = set(value, field, { field = it }, BR.insets)
var state= initialState
set(value) = set(value, field, { field = it }, BR.loading, BR.loaded, BR.loadFailed)
private val _viewEvents = MutableLiveData<ViewEvent>()
private var runningJob: Job? = null
private val refreshCallback = object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
requestRefresh()
}
}
init {
isConnected.addOnPropertyChangedCallback(refreshCallback)
}
/** This should probably never be called manually, it's called manually via delegate. */
@Synchronized
fun requestRefresh() {
if (runningJob?.isActive == true) {
return
}
runningJob = refresh()
}
protected open fun refresh(): Job? = null
@CallSuper
override fun onCleared() {
isConnected.removeOnPropertyChangedCallback(refreshCallback)
super.onCleared()
}
fun withView(action: BaseActivity.() -> Unit) {
ViewActionEvent(action).publish()
}
fun withPermissions(vararg permissions: String, callback: (Boolean) -> Unit) {
PermissionEvent(permissions.toList(), callback).publish()
}
fun withExternalRW(callback: () -> Unit) {
withPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE) {
if (!it) {
SnackbarEvent(R.string.external_rw_permission_denied).publish()
} else {
callback()
}
}
}
fun back() = BackPressEvent().publish()
fun <Event : ViewEvent> Event.publish() {
_viewEvents.postValue(this)
}
fun <Event : ViewEventWithScope> Event.publish() {
scope = viewModelScope
_viewEvents.postValue(this)
}
fun NavDirections.publish() {
_viewEvents.postValue(NavigationWrapper(this))
}
}