Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
fc886a5a
Commit
fc886a5a
authored
Sep 28, 2019
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge Teanity into sources
parent
0cb90e2e
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
67 changed files
with
1436 additions
and
570 deletions
+1436
-570
build.gradle
app/build.gradle
+15
-3
AdaptersGeneric.kt
.../java/com/topjohnwu/magisk/databinding/AdaptersGeneric.kt
+26
-0
AdaptersRecycler.kt
...java/com/topjohnwu/magisk/databinding/AdaptersRecycler.kt
+57
-0
BindingBoundAdapter.kt
...a/com/topjohnwu/magisk/databinding/BindingBoundAdapter.kt
+13
-0
RecyclerViewItems.kt
...ava/com/topjohnwu/magisk/databinding/RecyclerViewItems.kt
+48
-0
ApplicationModule.kt
...rc/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt
+1
-1
DataBinding.kt
.../main/java/com/topjohnwu/magisk/extensions/DataBinding.kt
+57
-0
Dimens.kt
app/src/main/java/com/topjohnwu/magisk/extensions/Dimens.kt
+9
-0
Misc.kt
app/src/main/java/com/topjohnwu/magisk/extensions/Misc.kt
+6
-0
RxJava.kt
app/src/main/java/com/topjohnwu/magisk/extensions/RxJava.kt
+201
-0
Snackbar.kt
...src/main/java/com/topjohnwu/magisk/extensions/Snackbar.kt
+126
-0
XAndroid.kt
...src/main/java/com/topjohnwu/magisk/extensions/XAndroid.kt
+33
-1
XBinding.kt
...src/main/java/com/topjohnwu/magisk/extensions/XBinding.kt
+1
-1
XList.kt
app/src/main/java/com/topjohnwu/magisk/extensions/XList.kt
+3
-4
XRx.kt
app/src/main/java/com/topjohnwu/magisk/extensions/XRx.kt
+0
-9
BindingAdapter.kt
...java/com/topjohnwu/magisk/model/binding/BindingAdapter.kt
+1
-1
RemoteFileService.kt
.../com/topjohnwu/magisk/model/download/RemoteFileService.kt
+1
-1
Version.kt
...rc/main/java/com/topjohnwu/magisk/model/entity/Version.kt
+0
-3
HideRvItem.kt
.../com/topjohnwu/magisk/model/entity/recycler/HideRvItem.kt
+5
-5
LenientRvItem.kt
...m/topjohnwu/magisk/model/entity/recycler/LenientRvItem.kt
+1
-1
LogRvItem.kt
...a/com/topjohnwu/magisk/model/entity/recycler/LogRvItem.kt
+3
-3
ModuleRvItem.kt
...om/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt
+3
-3
PolicyRvItem.kt
...om/topjohnwu/magisk/model/entity/recycler/PolicyRvItem.kt
+4
-4
SectionRvItem.kt
...m/topjohnwu/magisk/model/entity/recycler/SectionRvItem.kt
+1
-1
SpinnerRvItem.kt
...m/topjohnwu/magisk/model/entity/recycler/SpinnerRvItem.kt
+1
-1
EventHandler.kt
...in/java/com/topjohnwu/magisk/model/events/EventHandler.kt
+18
-0
RxEvents.kt
...c/main/java/com/topjohnwu/magisk/model/events/RxEvents.kt
+1
-1
SimpleViewEvent.kt
...java/com/topjohnwu/magisk/model/events/SimpleViewEvent.kt
+7
-0
SnackbarEvent.kt
...n/java/com/topjohnwu/magisk/model/events/SnackbarEvent.kt
+28
-0
ViewEventObserver.kt
...va/com/topjohnwu/magisk/model/events/ViewEventObserver.kt
+17
-0
ViewEvents.kt
...main/java/com/topjohnwu/magisk/model/events/ViewEvents.kt
+11
-2
MagiskNavigationEvent.kt
...opjohnwu/magisk/model/navigation/MagiskNavigationEvent.kt
+4
-2
FlashZip.kt
app/src/main/java/com/topjohnwu/magisk/tasks/FlashZip.kt
+1
-1
MagiskInstaller.kt
...c/main/java/com/topjohnwu/magisk/tasks/MagiskInstaller.kt
+0
-1
MainActivity.kt
app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.kt
+1
-5
MagiskActivity.kt
.../main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt
+33
-15
MagiskFragment.kt
.../main/java/com/topjohnwu/magisk/ui/base/MagiskFragment.kt
+40
-7
MagiskViewModel.kt
...main/java/com/topjohnwu/magisk/ui/base/MagiskViewModel.kt
+4
-4
FlashViewModel.kt
...main/java/com/topjohnwu/magisk/ui/flash/FlashViewModel.kt
+4
-5
HideViewModel.kt
...c/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt
+6
-6
HomeFragment.kt
...rc/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
+2
-2
HomeViewModel.kt
...c/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt
+2
-8
LogFragment.kt
app/src/main/java/com/topjohnwu/magisk/ui/log/LogFragment.kt
+1
-1
LogViewModel.kt
...src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
+7
-7
ModuleViewModel.kt
...in/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt
+4
-8
ModulesFragment.kt
...in/java/com/topjohnwu/magisk/ui/module/ModulesFragment.kt
+1
-1
ReposFragment.kt
...main/java/com/topjohnwu/magisk/ui/module/ReposFragment.kt
+1
-1
SettingsFragment.kt
...java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt
+1
-2
SuperuserViewModel.kt
...a/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt
+6
-6
SuRequestActivity.kt
...va/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt
+1
-1
SuRequestViewModel.kt
...a/com/topjohnwu/magisk/ui/surequest/SuRequestViewModel.kt
+4
-4
DataBindingAdapters.kt
...in/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt
+1
-1
DiffObservableList.kt
...ain/java/com/topjohnwu/magisk/utils/DiffObservableList.kt
+234
-0
KItemDecoration.kt
...c/main/java/com/topjohnwu/magisk/utils/KItemDecoration.kt
+117
-0
KObservableField.kt
.../main/java/com/topjohnwu/magisk/utils/KObservableField.kt
+49
-0
PatchAPK.kt
app/src/main/java/com/topjohnwu/magisk/utils/PatchAPK.kt
+1
-1
RxBus.kt
app/src/main/java/com/topjohnwu/magisk/utils/RxBus.kt
+36
-0
MagiskDialog.kt
app/src/main/java/com/topjohnwu/magisk/view/MagiskDialog.kt
+0
-155
MarkDownWindow.kt
...src/main/java/com/topjohnwu/magisk/view/MarkDownWindow.kt
+1
-1
EnvFixDialog.kt
...in/java/com/topjohnwu/magisk/view/dialogs/EnvFixDialog.kt
+1
-1
LoadingViewModel.kt
...n/java/com/topjohnwu/magisk/viewmodel/LoadingViewModel.kt
+78
-0
ObservableViewModel.kt
...ava/com/topjohnwu/magisk/viewmodel/ObservableViewModel.kt
+46
-0
StatefulViewModel.kt
.../java/com/topjohnwu/magisk/viewmodel/StatefulViewModel.kt
+15
-0
TeanityViewModel.kt
...n/java/com/topjohnwu/magisk/viewmodel/TeanityViewModel.kt
+33
-0
dialog_magisk_base.xml
app/src/main/res/layout/dialog_magisk_base.xml
+0
-276
fragment_magisk.xml
app/src/main/res/layout/fragment_magisk.xml
+1
-1
build.gradle
build.gradle
+2
-2
No files found.
app/build.gradle
View file @
fc886a5a
...
...
@@ -60,9 +60,19 @@ dependencies {
implementation
'com.github.topjohnwu:jtar:1.0.0'
implementation
'com.jakewharton.timber:timber:4.7.1'
implementation
'com.github.skoumalcz:teanity:0.3.3'
implementation
'com.ncapdevi:frag-nav:3.2.0'
implementation
'com.github.pwittchen:reactivenetwork-rx2:3.0.6'
implementation
'com.karumi:dexter:6.0.0'
implementation
"io.reactivex.rxjava2:rxjava:2.2.12"
implementation
"io.reactivex.rxjava2:rxkotlin:2.4.0"
implementation
"org.jetbrains.kotlin:kotlin-stdlib:${vKotlin}"
implementation
"org.jetbrains.kotlin:kotlin-stdlib-jdk7:${vKotlin}"
def
vBAdapt
=
'3.1.1'
implementation
"me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:${vBAdapt}"
implementation
"me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:${vBAdapt}"
def
vMarkwon
=
'3.1.0'
implementation
"ru.noties.markwon:core:${vMarkwon}"
...
...
@@ -104,8 +114,9 @@ dependencies {
implementation
"com.github.topjohnwu:room-runtime:${vRoom}"
kapt
"androidx.room:room-compiler:${vRoom}"
implementation
"org.jetbrains.kotlin:kotlin-stdlib:${kotlinVer}"
implementation
"org.jetbrains.kotlin:kotlin-stdlib-jdk7:${kotlinVer}"
def
vNav
=
"2.1.0"
implementation
"androidx.navigation:navigation-fragment-ktx:$vNav"
implementation
"androidx.navigation:navigation-ui-ktx:$vNav"
implementation
'androidx.constraintlayout:constraintlayout:1.1.3'
implementation
'androidx.browser:browser:1.0.0'
...
...
@@ -115,5 +126,6 @@ dependencies {
implementation
'androidx.work:work-runtime:2.2.0'
implementation
'androidx.transition:transition:1.2.0-rc01'
implementation
'androidx.multidex:multidex:2.0.1'
implementation
'androidx.core:core-ktx:1.1.0'
implementation
'com.google.android.material:material:1.1.0-alpha10'
}
app/src/main/java/com/topjohnwu/magisk/databinding/AdaptersGeneric.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.databinding
import
android.view.View
import
androidx.core.view.isGone
import
androidx.core.view.isInvisible
import
androidx.databinding.BindingAdapter
@BindingAdapter
(
"gone"
)
fun
setGone
(
view
:
View
,
gone
:
Boolean
)
{
view
.
isGone
=
gone
}
@BindingAdapter
(
"invisible"
)
fun
setInvisible
(
view
:
View
,
invisible
:
Boolean
)
{
view
.
isInvisible
=
invisible
}
@BindingAdapter
(
"goneUnless"
)
fun
setGoneUnless
(
view
:
View
,
goneUnless
:
Boolean
)
{
setGone
(
view
,
goneUnless
.
not
())
}
@BindingAdapter
(
"invisibleUnless"
)
fun
setInvisibleUnless
(
view
:
View
,
invisibleUnless
:
Boolean
)
{
setInvisible
(
view
,
invisibleUnless
.
not
())
}
app/src/main/java/com/topjohnwu/magisk/databinding/AdaptersRecycler.kt
0 → 100644
View file @
fc886a5a
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.extensions.startEndToLeftRight
import
com.topjohnwu.magisk.extensions.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
)
}
app/src/main/java/com/topjohnwu/magisk/databinding/BindingBoundAdapter.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.databinding
import
androidx.databinding.ViewDataBinding
import
me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter
open
class
BindingBoundAdapter
:
BindingRecyclerViewAdapter
<
RvItem
>()
{
override
fun
onBindBinding
(
binding
:
ViewDataBinding
,
variableId
:
Int
,
layoutRes
:
Int
,
position
:
Int
,
item
:
RvItem
)
{
super
.
onBindBinding
(
binding
,
variableId
,
layoutRes
,
position
,
item
)
item
.
onBindingBound
(
binding
)
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/databinding/RecyclerViewItems.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.databinding
import
androidx.annotation.CallSuper
import
androidx.databinding.ViewDataBinding
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.utils.DiffObservableList
import
me.tatarka.bindingcollectionadapter2.ItemBinding
abstract
class
RvItem
{
abstract
val
layoutRes
:
Int
@CallSuper
open
fun
bind
(
binding
:
ItemBinding
<
*
>)
{
binding
.
set
(
BR
.
item
,
layoutRes
)
}
/**
* This callback is useful if you want to manipulate your views directly.
* If you want to use this callback, you must set [me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter]
* on your RecyclerView and call it from there. You can use [BindingBoundAdapter] for your convenience.
*/
open
fun
onBindingBound
(
binding
:
ViewDataBinding
)
{}
}
abstract
class
ComparableRvItem
<
in
T
>
:
RvItem
()
{
abstract
fun
itemSameAs
(
other
:
T
):
Boolean
abstract
fun
contentSameAs
(
other
:
T
):
Boolean
@Suppress
(
"UNCHECKED_CAST"
)
open
fun
genericItemSameAs
(
other
:
Any
):
Boolean
=
other
::
class
==
this
::
class
&&
itemSameAs
(
other
as
T
)
@Suppress
(
"UNCHECKED_CAST"
)
open
fun
genericContentSameAs
(
other
:
Any
):
Boolean
=
other
::
class
==
this
::
class
&&
contentSameAs
(
other
as
T
)
companion
object
{
val
callback
=
object
:
DiffObservableList
.
Callback
<
ComparableRvItem
<*>>
{
override
fun
areItemsTheSame
(
oldItem
:
ComparableRvItem
<
*
>,
newItem
:
ComparableRvItem
<
*
>
)
=
oldItem
.
genericItemSameAs
(
newItem
)
override
fun
areContentsTheSame
(
oldItem
:
ComparableRvItem
<
*
>,
newItem
:
ComparableRvItem
<
*
>
)
=
oldItem
.
genericContentSameAs
(
newItem
)
}
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt
View file @
fc886a5a
...
...
@@ -7,7 +7,7 @@ import android.content.Context
import
android.os.Build
import
android.os.Bundle
import
androidx.preference.PreferenceManager
import
com.
skoumal.teanity.rxbu
s.RxBus
import
com.
topjohnwu.magisk.util
s.RxBus
import
org.koin.core.qualifier.named
import
org.koin.dsl.module
...
...
app/src/main/java/com/topjohnwu/magisk/extensions/DataBinding.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.extensions
import
androidx.databinding.Observable
import
androidx.databinding.ObservableBoolean
import
androidx.databinding.ObservableField
import
androidx.databinding.ObservableInt
fun
<
T
>
ObservableField
<
T
>.
addOnPropertyChangedCallback
(
removeAfterChanged
:
Boolean
=
false
,
callback
:
(
T
?)
->
Unit
)
{
addOnPropertyChangedCallback
(
object
:
Observable
.
OnPropertyChangedCallback
()
{
override
fun
onPropertyChanged
(
sender
:
Observable
?,
propertyId
:
Int
)
{
callback
(
get
())
if
(
removeAfterChanged
)
removeOnPropertyChangedCallback
(
this
)
}
})
}
fun
ObservableInt
.
addOnPropertyChangedCallback
(
removeAfterChanged
:
Boolean
=
false
,
callback
:
(
Int
)
->
Unit
)
{
addOnPropertyChangedCallback
(
object
:
Observable
.
OnPropertyChangedCallback
()
{
override
fun
onPropertyChanged
(
sender
:
Observable
?,
propertyId
:
Int
)
{
callback
(
get
())
if
(
removeAfterChanged
)
removeOnPropertyChangedCallback
(
this
)
}
})
}
fun
ObservableBoolean
.
addOnPropertyChangedCallback
(
removeAfterChanged
:
Boolean
=
false
,
callback
:
(
Boolean
)
->
Unit
)
{
addOnPropertyChangedCallback
(
object
:
Observable
.
OnPropertyChangedCallback
()
{
override
fun
onPropertyChanged
(
sender
:
Observable
?,
propertyId
:
Int
)
{
callback
(
get
())
if
(
removeAfterChanged
)
removeOnPropertyChangedCallback
(
this
)
}
})
}
inline
fun
<
T
>
ObservableField
<
T
>.
update
(
block
:
(
T
?)
->
Unit
)
{
set
(
get
().
apply
(
block
))
}
inline
fun
<
T
>
ObservableField
<
T
>.
updateNonNull
(
block
:
(
T
)
->
Unit
)
{
update
{
it
?:
return
@update
block
(
it
)
}
}
inline
fun
ObservableInt
.
update
(
block
:
(
Int
)
->
Unit
)
{
set
(
get
().
apply
(
block
))
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/extensions/Dimens.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.extensions
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
()
app/src/main/java/com/topjohnwu/magisk/extensions/Misc.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.extensions
import
android.os.Handler
import
android.os.Looper
fun
ui
(
body
:
()
->
Unit
)
=
Handler
(
Looper
.
getMainLooper
()).
post
(
body
)
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/extensions/RxJava.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.extensions
import
androidx.databinding.ObservableField
import
com.topjohnwu.magisk.utils.KObservableField
import
io.reactivex.*
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.disposables.Disposables
import
io.reactivex.functions.BiFunction
import
io.reactivex.schedulers.Schedulers
import
androidx.databinding.Observable
as
BindingObservable
fun
<
T
>
Observable
<
T
>.
applySchedulers
(
subscribeOn
:
Scheduler
=
Schedulers
.
io
(),
observeOn
:
Scheduler
=
AndroidSchedulers
.
mainThread
()
):
Observable
<
T
>
=
this
.
subscribeOn
(
subscribeOn
).
observeOn
(
observeOn
)
fun
<
T
>
Flowable
<
T
>.
applySchedulers
(
subscribeOn
:
Scheduler
=
Schedulers
.
io
(),
observeOn
:
Scheduler
=
AndroidSchedulers
.
mainThread
()
):
Flowable
<
T
>
=
this
.
subscribeOn
(
subscribeOn
).
observeOn
(
observeOn
)
fun
<
T
>
Single
<
T
>.
applySchedulers
(
subscribeOn
:
Scheduler
=
Schedulers
.
io
(),
observeOn
:
Scheduler
=
AndroidSchedulers
.
mainThread
()
):
Single
<
T
>
=
this
.
subscribeOn
(
subscribeOn
).
observeOn
(
observeOn
)
fun
<
T
>
Maybe
<
T
>.
applySchedulers
(
subscribeOn
:
Scheduler
=
Schedulers
.
io
(),
observeOn
:
Scheduler
=
AndroidSchedulers
.
mainThread
()
):
Maybe
<
T
>
=
this
.
subscribeOn
(
subscribeOn
).
observeOn
(
observeOn
)
fun
Completable
.
applySchedulers
(
subscribeOn
:
Scheduler
=
Schedulers
.
io
(),
observeOn
:
Scheduler
=
AndroidSchedulers
.
mainThread
()
):
Completable
=
this
.
subscribeOn
(
subscribeOn
).
observeOn
(
observeOn
)
/*=== ALIASES FOR OBSERVABLES ===*/
typealias
OnCompleteListener
=
()
->
Unit
typealias
OnSuccessListener
<
T
>
=
(
T
)
->
Unit
typealias
OnErrorListener
=
(
Throwable
)
->
Unit
/*=== ALIASES FOR OBSERVABLES ===*/
fun
<
T
>
Observable
<
T
>.
subscribeK
(
onError
:
OnErrorListener
=
{
it
.
printStackTrace
()
},
onComplete
:
OnCompleteListener
=
{},
onNext
:
OnSuccessListener
<
T
>
=
{}
)
=
applySchedulers
()
.
subscribe
(
onNext
,
onError
,
onComplete
)
fun
<
T
>
Single
<
T
>.
subscribeK
(
onError
:
OnErrorListener
=
{
it
.
printStackTrace
()
},
onNext
:
OnSuccessListener
<
T
>
=
{}
)
=
applySchedulers
()
.
subscribe
(
onNext
,
onError
)
fun
<
T
>
Maybe
<
T
>.
subscribeK
(
onError
:
OnErrorListener
=
{
it
.
printStackTrace
()
},
onComplete
:
OnCompleteListener
=
{},
onNext
:
OnSuccessListener
<
T
>
=
{}
)
=
applySchedulers
()
.
subscribe
(
onNext
,
onError
,
onComplete
)
fun
<
T
>
Flowable
<
T
>.
subscribeK
(
onError
:
OnErrorListener
=
{
it
.
printStackTrace
()
},
onComplete
:
OnCompleteListener
=
{},
onNext
:
OnSuccessListener
<
T
>
=
{}
)
=
applySchedulers
()
.
subscribe
(
onNext
,
onError
,
onComplete
)
fun
Completable
.
subscribeK
(
onError
:
OnErrorListener
=
{
it
.
printStackTrace
()
},
onComplete
:
OnCompleteListener
=
{}
)
=
applySchedulers
()
.
subscribe
(
onComplete
,
onError
)
fun
<
T
>
Observable
<
out
T
>.
updateBy
(
field
:
KObservableField
<
T
?
>
)
=
doOnNextUi
{
field
.
value
=
it
}
.
doOnErrorUi
{
field
.
value
=
null
}
fun
<
T
>
Single
<
out
T
>.
updateBy
(
field
:
KObservableField
<
T
?
>
)
=
doOnSuccessUi
{
field
.
value
=
it
}
.
doOnErrorUi
{
field
.
value
=
null
}
fun
<
T
>
Maybe
<
out
T
>.
updateBy
(
field
:
KObservableField
<
T
?
>
)
=
doOnSuccessUi
{
field
.
value
=
it
}
.
doOnErrorUi
{
field
.
value
=
null
}
.
doOnComplete
{
field
.
value
=
field
.
value
}
fun
<
T
>
Flowable
<
out
T
>.
updateBy
(
field
:
KObservableField
<
T
?
>
)
=
doOnNextUi
{
field
.
value
=
it
}
.
doOnErrorUi
{
field
.
value
=
null
}
fun
Completable
.
updateBy
(
field
:
KObservableField
<
Boolean
>
)
=
doOnCompleteUi
{
field
.
value
=
true
}
.
doOnErrorUi
{
field
.
value
=
false
}
fun
<
T
>
Observable
<
T
>.
doOnSubscribeUi
(
body
:
()
->
Unit
)
=
doOnSubscribe
{
ui
{
body
()
}
}
fun
<
T
>
Single
<
T
>.
doOnSubscribeUi
(
body
:
()
->
Unit
)
=
doOnSubscribe
{
ui
{
body
()
}
}
fun
<
T
>
Maybe
<
T
>.
doOnSubscribeUi
(
body
:
()
->
Unit
)
=
doOnSubscribe
{
ui
{
body
()
}
}
fun
<
T
>
Flowable
<
T
>.
doOnSubscribeUi
(
body
:
()
->
Unit
)
=
doOnSubscribe
{
ui
{
body
()
}
}
fun
Completable
.
doOnSubscribeUi
(
body
:
()
->
Unit
)
=
doOnSubscribe
{
ui
{
body
()
}
}
fun
<
T
>
Observable
<
T
>.
doOnErrorUi
(
body
:
(
Throwable
)
->
Unit
)
=
doOnError
{
ui
{
body
(
it
)
}
}
fun
<
T
>
Single
<
T
>.
doOnErrorUi
(
body
:
(
Throwable
)
->
Unit
)
=
doOnError
{
ui
{
body
(
it
)
}
}
fun
<
T
>
Maybe
<
T
>.
doOnErrorUi
(
body
:
(
Throwable
)
->
Unit
)
=
doOnError
{
ui
{
body
(
it
)
}
}
fun
<
T
>
Flowable
<
T
>.
doOnErrorUi
(
body
:
(
Throwable
)
->
Unit
)
=
doOnError
{
ui
{
body
(
it
)
}
}
fun
Completable
.
doOnErrorUi
(
body
:
(
Throwable
)
->
Unit
)
=
doOnError
{
ui
{
body
(
it
)
}
}
fun
<
T
>
Observable
<
T
>.
doOnNextUi
(
body
:
(
T
)
->
Unit
)
=
doOnNext
{
ui
{
body
(
it
)
}
}
fun
<
T
>
Flowable
<
T
>.
doOnNextUi
(
body
:
(
T
)
->
Unit
)
=
doOnNext
{
ui
{
body
(
it
)
}
}
fun
<
T
>
Single
<
T
>.
doOnSuccessUi
(
body
:
(
T
)
->
Unit
)
=
doOnSuccess
{
ui
{
body
(
it
)
}
}
fun
<
T
>
Maybe
<
T
>.
doOnSuccessUi
(
body
:
(
T
)
->
Unit
)
=
doOnSuccess
{
ui
{
body
(
it
)
}
}
fun
<
T
>
Maybe
<
T
>.
doOnCompleteUi
(
body
:
()
->
Unit
)
=
doOnComplete
{
ui
{
body
()
}
}
fun
Completable
.
doOnCompleteUi
(
body
:
()
->
Unit
)
=
doOnComplete
{
ui
{
body
()
}
}
fun
<
T
,
R
>
Observable
<
List
<
T
>>.
mapList
(
transformer
:
(
T
)
->
R
)
=
flatMapIterable
{
it
}
.
map
(
transformer
)
.
toList
()
fun
<
T
,
R
>
Single
<
List
<
T
>>.
mapList
(
transformer
:
(
T
)
->
R
)
=
flattenAsFlowable
{
it
}
.
map
(
transformer
)
.
toList
()
fun
<
T
,
R
>
Maybe
<
List
<
T
>>.
mapList
(
transformer
:
(
T
)
->
R
)
=
flattenAsFlowable
{
it
}
.
map
(
transformer
)
.
toList
()
fun
<
T
,
R
>
Flowable
<
List
<
T
>>.
mapList
(
transformer
:
(
T
)
->
R
)
=
flatMapIterable
{
it
}
.
map
(
transformer
)
.
toList
()
fun
<
T
>
ObservableField
<
T
>.
toObservable
():
Observable
<
T
>
{
val
observableField
=
this
return
Observable
.
create
{
emitter
->
observableField
.
get
()
?.
let
{
emitter
.
onNext
(
it
)
}
val
callback
=
object
:
BindingObservable
.
OnPropertyChangedCallback
()
{
override
fun
onPropertyChanged
(
sender
:
BindingObservable
?,
propertyId
:
Int
)
{
observableField
.
get
()
?.
let
{
emitter
.
onNext
(
it
)
}
}
}
observableField
.
addOnPropertyChangedCallback
(
callback
)
emitter
.
setDisposable
(
Disposables
.
fromAction
{
observableField
.
removeOnPropertyChangedCallback
(
callback
)
})
}
}
fun
<
T
:
Any
>
T
.
toSingle
()
=
Single
.
just
(
this
)
fun
<
T1
,
T2
,
R
>
zip
(
t1
:
Single
<
T1
>,
t2
:
Single
<
T2
>,
zipper
:
(
T1
,
T2
)
->
R
)
=
Single
.
zip
(
t1
,
t2
,
BiFunction
<
T1
,
T2
,
R
>
{
rt1
,
rt2
->
zipper
(
rt1
,
rt2
)
})
app/src/main/java/com/topjohnwu/magisk/extensions/Snackbar.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.extensions
import
android.content.Context
import
android.content.res.ColorStateList
import
android.view.View
import
android.widget.TextView
import
androidx.annotation.ColorInt
import
androidx.annotation.ColorRes
import
androidx.annotation.StringRes
import
androidx.appcompat.app.AppCompatActivity
import
androidx.core.content.ContextCompat
import
androidx.core.view.ViewCompat
import
androidx.fragment.app.Fragment
import
com.google.android.material.snackbar.Snackbar
fun
AppCompatActivity
.
snackbar
(
view
:
View
,
@StringRes
messageRes
:
Int
,
length
:
Int
=
Snackbar
.
LENGTH_SHORT
,
f
:
Snackbar
.()
->
Unit
=
{}
)
{
snackbar
(
view
,
getString
(
messageRes
),
length
,
f
)
}
fun
AppCompatActivity
.
snackbar
(
view
:
View
,
message
:
String
,
length
:
Int
=
Snackbar
.
LENGTH_SHORT
,
f
:
Snackbar
.()
->
Unit
=
{}
)
=
Snackbar
.
make
(
view
,
message
,
length
)
.
apply
(
f
)
.
show
()
fun
Fragment
.
snackbar
(
view
:
View
,
@StringRes
messageRes
:
Int
,
length
:
Int
=
Snackbar
.
LENGTH_SHORT
,
f
:
Snackbar
.()
->
Unit
=
{}
)
{
snackbar
(
view
,
getString
(
messageRes
),
length
,
f
)
}
fun
Fragment
.
snackbar
(
view
:
View
,
message
:
String
,
length
:
Int
=
Snackbar
.
LENGTH_SHORT
,
f
:
Snackbar
.()
->
Unit
=
{}
)
=
Snackbar
.
make
(
view
,
message
,
length
)
.
apply
(
f
)
.
show
()
fun
Snackbar
.
action
(
init
:
KSnackbar
.()
->
Unit
)
=
apply
{
val
config
=
KSnackbar
().
apply
(
init
)
setAction
(
config
.
title
(
context
),
config
.
onClickListener
)
when
{
config
.
hasValidColor
->
setActionTextColor
(
config
.
color
(
context
)
?:
return
@apply
)
config
.
hasValidColorStateList
->
setActionTextColor
(
config
.
colorStateList
(
context
)
?:
return
@apply
)
}
}
class
KSnackbar
{
var
colorRes
:
Int
=
-
1
var
colorStateListRes
:
Int
=
-
1
var
title
:
CharSequence
=
""
var
titleRes
:
Int
=
-
1
internal
var
onClickListener
:
(
View
)
->
Unit
=
{}
internal
val
hasValidColor
get
()
=
colorRes
!=
-
1
internal
val
hasValidColorStateList
get
()
=
colorStateListRes
!=
-
1
fun
onClicked
(
listener
:
(
View
)
->
Unit
)
{
onClickListener
=
listener
}
internal
fun
title
(
context
:
Context
)
=
if
(
title
.
isBlank
())
context
.
getString
(
titleRes
)
else
title
internal
fun
colorStateList
(
context
:
Context
)
=
context
.
colorStateListCompat
(
colorStateListRes
)
internal
fun
color
(
context
:
Context
)
=
context
.
colorCompat
(
colorRes
)
}
@Deprecated
(
"Kotlin DSL version is preferred"
,
ReplaceWith
(
"action {}"
))
fun
Snackbar
.
action
(
@StringRes
actionRes
:
Int
,
@ColorRes
colorRes
:
Int
?
=
null
,
listener
:
(
View
)
->
Unit
)
{
view
.
resources
.
getString
(
actionRes
)
colorRes
?.
let
{
ContextCompat
.
getColor
(
view
.
context
,
colorRes
)
}
action
{}
}
@Deprecated
(
"Kotlin DSL version is preferred"
,
ReplaceWith
(
"action {}"
))
fun
Snackbar
.
action
(
action
:
String
,
@ColorInt
color
:
Int
?
=
null
,
listener
:
(
View
)
->
Unit
)
{
setAction
(
action
,
listener
)
color
?.
let
{
setActionTextColor
(
color
)
}
}
fun
Snackbar
.
textColorRes
(
@ColorRes
colorRes
:
Int
)
{
textColor
(
context
.
colorCompat
(
colorRes
)
?:
return
)
}
fun
Snackbar
.
textColor
(
@ColorInt
color
:
Int
)
{
val
tv
=
view
.
findViewById
<
TextView
>(
com
.
google
.
android
.
material
.
R
.
id
.
snackbar_text
)
tv
.
setTextColor
(
color
)
}
fun
Snackbar
.
backgroundColorRes
(
@ColorRes
colorRes
:
Int
)
{
backgroundColor
(
context
.
colorCompat
(
colorRes
)
?:
return
)
}
fun
Snackbar
.
backgroundColor
(
@ColorInt
color
:
Int
)
{
ViewCompat
.
setBackgroundTintList
(
view
,
ColorStateList
.
valueOf
(
color
)
)
}
fun
Snackbar
.
alert
()
{
textColor
(
0
xF44336
)
}
fun
Snackbar
.
success
()
{
textColor
(
0
x4CAF50
)
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/extensions/XAndroid.kt
View file @
fc886a5a
...
...
@@ -8,9 +8,15 @@ import android.content.pm.PackageInfo
import
android.content.pm.PackageManager
import
android.content.pm.PackageManager.*
import
android.content.res.Configuration
import
android.content.res.Resources
import
android.database.Cursor
import
android.net.Uri
import
android.os.Build
import
android.provider.OpenableColumns
import
android.view.View
import
androidx.annotation.ColorRes
import
androidx.annotation.DrawableRes
import
androidx.core.content.ContextCompat
import
com.topjohnwu.magisk.utils.FileProvider
import
com.topjohnwu.magisk.utils.currentLocale
import
java.io.File
...
...
@@ -120,4 +126,30 @@ fun ApplicationInfo.getLabel(pm: PackageManager): String {
return
loadLabel
(
pm
).
toString
()
}
fun
Intent
.
exists
(
packageManager
:
PackageManager
)
=
resolveActivity
(
packageManager
)
!=
null
\ No newline at end of file
fun
Intent
.
exists
(
packageManager
:
PackageManager
)
=
resolveActivity
(
packageManager
)
!=
null
fun
Context
.
colorCompat
(
@ColorRes
id
:
Int
)
=
try
{
ContextCompat
.
getColor
(
this
,
id
)
}
catch
(
e
:
Resources
.
NotFoundException
)
{
null
}
fun
Context
.
colorStateListCompat
(
@ColorRes
id
:
Int
)
=
try
{
ContextCompat
.
getColorStateList
(
this
,
id
)
}
catch
(
e
:
Resources
.
NotFoundException
)
{
null
}
fun
Context
.
drawableCompat
(
@DrawableRes
id
:
Int
)
=
ContextCompat
.
getDrawable
(
this
,
id
)
/**
* Pass [start] and [end] dimensions, function will return left and right
* with respect to RTL layout direction
*/
fun
Context
.
startEndToLeftRight
(
start
:
Int
,
end
:
Int
):
Pair
<
Int
,
Int
>
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
JELLY_BEAN_MR1
&&
resources
.
configuration
.
layoutDirection
==
View
.
LAYOUT_DIRECTION_RTL
)
{
return
end
to
start
}
return
start
to
end
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/extensions/XBinding.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.extensions
import
com.
skoumal.teanity.util
.KObservableField
import
com.
topjohnwu.magisk.utils
.KObservableField
fun
KObservableField
<
Boolean
>.
toggle
()
{
...
...
app/src/main/java/com/topjohnwu/magisk/extensions/XList.kt
View file @
fc886a5a
...
...
@@ -2,8 +2,7 @@ package com.topjohnwu.magisk.extensions
import
androidx.collection.SparseArrayCompat
import
androidx.databinding.ObservableList
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.util.DiffObservableList
import
com.topjohnwu.magisk.utils.DiffObservableList
import
io.reactivex.disposables.Disposable
fun
<
T
>
MutableList
<
T
>.
update
(
newList
:
List
<
T
>)
{
...
...
@@ -26,8 +25,8 @@ fun List<String>.toShellCmd(): String {
}
fun
<
T1
,
T2
>
ObservableList
<
T1
>.
sendUpdatesTo
(
target
:
DiffObservableList
<
T2
>,
mapper
:
(
List
<
T1
>)
->
List
<
T2
>
target
:
DiffObservableList
<
T2
>,
mapper
:
(
List
<
T1
>)
->
List
<
T2
>
)
=
addOnListChangedCallback
(
object
:
ObservableList
.
OnListChangedCallback
<
ObservableList
<
T1
>>()
{
override
fun
onChanged
(
sender
:
ObservableList
<
T1
>?)
{
...
...
app/src/main/java/com/topjohnwu/magisk/extensions/XRx.kt
deleted
100644 → 0
View file @
0cb90e2e
package
com.topjohnwu.magisk.extensions
import
io.reactivex.Single
import
io.reactivex.functions.BiFunction
fun
<
T
:
Any
>
T
.
toSingle
()
=
Single
.
just
(
this
)
fun
<
T1
,
T2
,
R
>
zip
(
t1
:
Single
<
T1
>,
t2
:
Single
<
T2
>,
zipper
:
(
T1
,
T2
)
->
R
)
=
Single
.
zip
(
t1
,
t2
,
BiFunction
<
T1
,
T2
,
R
>
{
rt1
,
rt2
->
zipper
(
rt1
,
rt2
)
})
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/model/binding/BindingAdapter.kt
View file @
fc886a5a
...
...
@@ -2,7 +2,7 @@ package com.topjohnwu.magisk.model.binding
import
androidx.databinding.ViewDataBinding
import
androidx.recyclerview.widget.RecyclerView
import
com.
skoumal.teanity
.databinding.ComparableRvItem
import
com.
topjohnwu.magisk
.databinding.ComparableRvItem
import
com.topjohnwu.magisk.model.entity.recycler.LenientRvItem
import
me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter
...
...
app/src/main/java/com/topjohnwu/magisk/model/download/RemoteFileService.kt
View file @
fc886a5a
...
...
@@ -3,11 +3,11 @@ package com.topjohnwu.magisk.model.download
import
android.app.Activity
import
android.content.Intent
import
androidx.core.app.NotificationCompat
import
com.skoumal.teanity.extensions.subscribeK
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.network.GithubRawServices
import
com.topjohnwu.magisk.di.NullActivity
import
com.topjohnwu.magisk.extensions.get
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.writeTo
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject.*
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/Version.kt
deleted
100644 → 0
View file @
0cb90e2e
package
com.topjohnwu.magisk.model.entity
data class
Version
(
val
version
:
String
,
val
versionCode
:
Int
)
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/HideRvItem.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.model.entity.recycler
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import
com.skoumal.teanity.rxbus.RxBus
import
com.skoumal.teanity.util.DiffObservableList
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.utils.RxBus
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
import
com.topjohnwu.magisk.extensions.inject
import
com.topjohnwu.magisk.extensions.toggle
import
com.topjohnwu.magisk.model.entity.HideAppInfo
import
com.topjohnwu.magisk.model.entity.HideTarget
import
com.topjohnwu.magisk.model.entity.state.IndeterminateState
import
com.topjohnwu.magisk.model.events.HideProcessEvent
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.KObservableField
class
HideRvItem
(
val
item
:
HideAppInfo
,
targets
:
List
<
HideTarget
>)
:
ComparableRvItem
<
HideRvItem
>()
{
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/LenientRvItem.kt
View file @
fc886a5a
...
...
@@ -2,7 +2,7 @@ package com.topjohnwu.magisk.model.entity.recycler
import
androidx.databinding.ViewDataBinding
import
androidx.recyclerview.widget.RecyclerView
import
com.
skoumal.teanity
.databinding.ComparableRvItem
import
com.
topjohnwu.magisk
.databinding.ComparableRvItem
/**
* This item addresses issues where enclosing recycler has to be invalidated or generally
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/LogRvItem.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.model.entity.recycler
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.skoumal.teanity.util.DiffObservableList
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.timeFormatMedium
import
com.topjohnwu.magisk.extensions.toTime
import
com.topjohnwu.magisk.extensions.toggle
import
com.topjohnwu.magisk.model.entity.MagiskLog
import
com.topjohnwu.magisk.model.entity.WrappedMagiskLog
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.KObservableField
class
LogRvItem
:
ComparableRvItem
<
LogRvItem
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
item_page_log
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt
View file @
fc886a5a
...
...
@@ -2,14 +2,14 @@ package com.topjohnwu.magisk.model.entity.recycler
import
android.content.res.Resources
import
androidx.annotation.StringRes
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
import
com.topjohnwu.magisk.extensions.get
import
com.topjohnwu.magisk.extensions.toggle
import
com.topjohnwu.magisk.model.entity.module.Module
import
com.topjohnwu.magisk.model.entity.module.Repo
import
com.topjohnwu.magisk.utils.KObservableField
class
ModuleRvItem
(
val
item
:
Module
)
:
ComparableRvItem
<
ModuleRvItem
>()
{
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/PolicyRvItem.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.model.entity.recycler
import
android.graphics.drawable.Drawable
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import
com.skoumal.teanity.rxbus.RxBus
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.utils.RxBus
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
import
com.topjohnwu.magisk.extensions.inject
import
com.topjohnwu.magisk.extensions.toggle
import
com.topjohnwu.magisk.model.entity.MagiskPolicy
import
com.topjohnwu.magisk.model.events.PolicyEnableEvent
import
com.topjohnwu.magisk.model.events.PolicyUpdateEvent
import
com.topjohnwu.magisk.utils.KObservableField
class
PolicyRvItem
(
val
item
:
MagiskPolicy
,
val
icon
:
Drawable
)
:
ComparableRvItem
<
PolicyRvItem
>()
{
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/SectionRvItem.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.model.entity.recycler
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ComparableRvItem
class
SectionRvItem
(
val
text
:
String
)
:
ComparableRvItem
<
SectionRvItem
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
item_section
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/SpinnerRvItem.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.model.entity.recycler
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ComparableRvItem
class
SpinnerRvItem
(
val
item
:
String
)
:
ComparableRvItem
<
SpinnerRvItem
>()
{
...
...
app/src/main/java/com/topjohnwu/magisk/model/events/EventHandler.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.model.events
internal
interface
EventHandler
{
/**
* Called for all [ViewEvent]s published by associated viewModel.
* For [SimpleViewEvent]s, both this and [onSimpleEventDispatched]
* methods are called - you can choose the way how you handle them.
*/
fun
onEventDispatched
(
event
:
ViewEvent
)
{}
/**
* Called for all [SimpleViewEvent]s published by associated viewModel.
* Both this and [onEventDispatched] methods are called - you can choose
* the way how you handle them.
*/
fun
onSimpleEventDispatched
(
event
:
Int
)
{}
}
app/src/main/java/com/topjohnwu/magisk/model/events/RxEvents.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.model.events
import
com.
skoumal.teanity.rxbu
s.RxBus
import
com.
topjohnwu.magisk.util
s.RxBus
import
com.topjohnwu.magisk.model.entity.MagiskPolicy
import
com.topjohnwu.magisk.model.entity.recycler.HideProcessRvItem
import
com.topjohnwu.magisk.model.entity.recycler.ModuleRvItem
...
...
app/src/main/java/com/topjohnwu/magisk/model/events/SimpleViewEvent.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.model.events
import
com.topjohnwu.magisk.model.events.ViewEvent
class
SimpleViewEvent
(
val
event
:
Int
)
:
ViewEvent
()
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/model/events/SnackbarEvent.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.model.events
import
android.content.Context
import
androidx.annotation.StringRes
import
com.google.android.material.snackbar.Snackbar
import
com.topjohnwu.magisk.model.events.ViewEvent
class
SnackbarEvent
private
constructor
(
@StringRes
private
val
messageRes
:
Int
,
private
val
messageString
:
String
?,
val
length
:
Int
,
val
f
:
Snackbar
.()
->
Unit
)
:
ViewEvent
()
{
constructor
(
@StringRes
messageRes
:
Int
,
length
:
Int
=
Snackbar
.
LENGTH_SHORT
,
f
:
Snackbar
.()
->
Unit
=
{}
)
:
this
(
messageRes
,
null
,
length
,
f
)
constructor
(
message
:
String
,
length
:
Int
=
Snackbar
.
LENGTH_SHORT
,
f
:
Snackbar
.()
->
Unit
=
{}
)
:
this
(-
1
,
message
,
length
,
f
)
fun
message
(
context
:
Context
):
String
=
messageString
?:
context
.
getString
(
messageRes
)
}
app/src/main/java/com/topjohnwu/magisk/model/events/ViewEventObserver.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.model.events
import
androidx.lifecycle.Observer
/**
* Observer for [ViewEvent]s, which automatically checks if event was handled
*/
class
ViewEventObserver
(
private
val
onEventUnhandled
:
(
ViewEvent
)
->
Unit
)
:
Observer
<
ViewEvent
>
{
override
fun
onChanged
(
event
:
ViewEvent
?)
{
event
?.
let
{
if
(!
it
.
handled
)
{
it
.
handled
=
true
onEventUnhandled
(
it
)
}
}
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/model/events/ViewEvents.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.model.events
import
android.app.Activity
import
com.skoumal.teanity.viewevents.ViewEvent
import
com.topjohnwu.magisk.model.entity.module.Repo
import
io.reactivex.subjects.PublishSubject
/**
* Class for passing events from ViewModels to Activities/Fragments
* Variable [handled] used so each event is handled only once
* (see https://medium.com/google-developers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150)
* Use [ViewEventObserver] for observing these events
*/
abstract
class
ViewEvent
{
var
handled
=
false
}
data class
OpenLinkEvent
(
val
url
:
String
)
:
ViewEvent
()
...
...
@@ -35,4 +44,4 @@ class PermissionEvent(
class
BackPressEvent
:
ViewEvent
()
class
DieEvent
:
ViewEvent
()
\ No newline at end of file
class
DieEvent
:
ViewEvent
()
app/src/main/java/com/topjohnwu/magisk/model/navigation/MagiskNavigationEvent.kt
View file @
fc886a5a
...
...
@@ -4,10 +4,12 @@ import android.os.Bundle
import
androidx.annotation.AnimRes
import
androidx.annotation.AnimatorRes
import
androidx.fragment.app.Fragment
import
com.skoumal.teanity.viewevents.NavigationDslMarker
import
com.skoumal.teanity.viewevents.ViewEvent
import
com.topjohnwu.magisk.model.events.ViewEvent
import
kotlin.reflect.KClass
@DslMarker
annotation
class
NavigationDslMarker
class
MagiskNavigationEvent
(
val
navDirections
:
MagiskNavDirectionsBuilder
,
val
navOptions
:
MagiskNavOptions
,
...
...
app/src/main/java/com/topjohnwu/magisk/tasks/FlashZip.kt
View file @
fc886a5a
...
...
@@ -2,11 +2,11 @@ package com.topjohnwu.magisk.tasks
import
android.content.Context
import
android.net.Uri
import
com.skoumal.teanity.extensions.subscribeK
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.extensions.fileName
import
com.topjohnwu.magisk.extensions.inject
import
com.topjohnwu.magisk.extensions.readUri
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.utils.unzip
import
com.topjohnwu.superuser.Shell
import
io.reactivex.Single
...
...
app/src/main/java/com/topjohnwu/magisk/tasks/MagiskInstaller.kt
View file @
fc886a5a
...
...
@@ -6,7 +6,6 @@ import android.os.Build
import
android.text.TextUtils
import
androidx.annotation.MainThread
import
androidx.annotation.WorkerThread
import
com.skoumal.teanity.extensions.subscribeK
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Info
import
com.topjohnwu.magisk.data.network.GithubRawServices
...
...
app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.kt
View file @
fc886a5a
...
...
@@ -4,13 +4,13 @@ import android.content.Intent
import
android.os.Bundle
import
androidx.core.view.GravityCompat
import
androidx.fragment.app.Fragment
import
com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import
com.topjohnwu.magisk.ClassMap
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Const.Key.OPEN_SECTION
import
com.topjohnwu.magisk.Info
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ActivityMainBinding
import
com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
import
com.topjohnwu.magisk.model.navigation.Navigation
import
com.topjohnwu.magisk.ui.base.MagiskActivity
import
com.topjohnwu.magisk.ui.hide.MagiskHideFragment
...
...
@@ -43,10 +43,6 @@ open class MainActivity : MagiskActivity<MainViewModel, ActivityMainBinding>() {
SettingsFragment
::
class
)
/*
override
fun
getDarkTheme
():
Int
{
return
R
.
style
.
AppTheme_Dark
}*/
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
if
(!
SplashActivity
.
DONE
)
{
startActivity
(
Intent
(
this
,
ClassMap
[
SplashActivity
::
class
.
java
]))
...
...
app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskActivity.kt
View file @
fc886a5a
...
...
@@ -6,9 +6,11 @@ import android.content.Intent
import
android.content.res.Configuration
import
android.os.Bundle
import
androidx.annotation.CallSuper
import
androidx.appcompat.app.AppCompatActivity
import
androidx.appcompat.app.AppCompatDelegate
import
androidx.collection.SparseArrayCompat
import
androidx.core.net.toUri
import
androidx.databinding.DataBindingUtil
import
androidx.databinding.ViewDataBinding
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.FragmentTransaction
...
...
@@ -19,13 +21,12 @@ import com.karumi.dexter.listener.PermissionRequest
import
com.karumi.dexter.listener.multi.MultiplePermissionsListener
import
com.ncapdevi.fragnav.FragNavController
import
com.ncapdevi.fragnav.FragNavTransactionOptions
import
com.
skoumal.teanity.view.TeanityActivity
import
com.
skoumal.teanity.viewevents.ViewEvent
import
com.
topjohnwu.magisk.model.events.EventHandler
import
com.
topjohnwu.magisk.BR
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.extensions.set
import
com.topjohnwu.magisk.model.events.BackPressEvent
import
com.topjohnwu.magisk.model.events.PermissionEvent
import
com.topjohnwu.magisk.model.events.ViewActionEvent
import
com.topjohnwu.magisk.extensions.snackbar
import
com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.model.navigation.MagiskAnimBuilder
import
com.topjohnwu.magisk.model.navigation.MagiskNavigationEvent
import
com.topjohnwu.magisk.model.navigation.Navigator
...
...
@@ -39,17 +40,26 @@ import kotlin.reflect.KClass
typealias
RequestCallback
=
MagiskActivity
<*,
*>.(
Int
,
Intent
?)
->
Unit
abstract
class
MagiskActivity
<
ViewModel
:
MagiskViewModel
,
Binding
:
ViewDataBinding
>
:
TeanityActivity
<
ViewModel
,
Binding
>(),
FragNavController
.
RootFragmentListen
er
,
AppCompatActivity
(),
FragNavController
.
RootFragmentListener
,
EventHandl
er
,
Navigator
,
FragNavController
.
TransactionListener
{
override
val
numberOfRootFragments
:
Int
get
()
=
baseFragments
.
size
override
val
baseFragments
:
List
<
KClass
<
out
Fragment
>>
=
listOf
()
private
val
resultCallbacks
=
SparseArrayCompat
<
RequestCallback
>()
protected
lateinit
var
binding
:
Binding
protected
abstract
val
layoutRes
:
Int
protected
abstract
val
viewModel
:
ViewModel
protected
open
val
snackbarView
get
()
=
binding
.
root
protected
open
val
navHostId
:
Int
=
0
private
val
viewEventObserver
=
ViewEventObserver
{
onEventDispatched
(
it
)
if
(
it
is
SimpleViewEvent
)
{
onSimpleEventDispatched
(
it
.
event
)
}
}
private
val
resultCallbacks
=
SparseArrayCompat
<
RequestCallback
>()
protected
open
val
defaultPosition
:
Int
=
0
pr
otected
val
navigationController
get
()
=
if
(
navHostId
==
0
)
null
else
_navigationController
pr
ivate
val
navigationController
get
()
=
if
(
navHostId
==
0
)
null
else
_navigationController
private
val
_navigationController
by
lazy
{
if
(
navHostId
==
0
)
throw
IllegalStateException
(
"Did you forget to override \"navHostId\"?"
)
FragNavController
(
supportFragmentManager
,
navHostId
)
...
...
@@ -58,6 +68,9 @@ abstract class MagiskActivity<ViewModel : MagiskViewModel, Binding : ViewDataBin
private
val
isRootFragment
get
()
=
navigationController
?.
let
{
it
.
currentStackIndex
!=
defaultPosition
}
?:
false
override
val
numberOfRootFragments
:
Int
get
()
=
baseFragments
.
size
override
val
baseFragments
:
List
<
KClass
<
out
Fragment
>>
=
listOf
()
init
{
val
theme
=
if
(
Config
.
darkTheme
)
{
AppCompatDelegate
.
MODE_NIGHT_YES
...
...
@@ -79,6 +92,14 @@ abstract class MagiskActivity<ViewModel : MagiskViewModel, Binding : ViewDataBin
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
binding
=
DataBindingUtil
.
setContentView
<
Binding
>(
this
,
layoutRes
).
apply
{
setVariable
(
BR
.
viewModel
,
viewModel
)
lifecycleOwner
=
this
@MagiskActivity
}
viewModel
.
viewEvents
.
observe
(
this
,
viewEventObserver
)
navigationController
?.
apply
{
rootFragmentListener
=
this
@MagiskActivity
transactionListener
=
this
@MagiskActivity
...
...
@@ -95,6 +116,7 @@ abstract class MagiskActivity<ViewModel : MagiskViewModel, Binding : ViewDataBin
override
fun
onEventDispatched
(
event
:
ViewEvent
)
{
super
.
onEventDispatched
(
event
)
when
(
event
)
{
is
SnackbarEvent
->
snackbar
(
snackbarView
,
event
.
message
(
this
),
event
.
length
,
event
.
f
)
is
BackPressEvent
->
onBackPressed
()
is
MagiskNavigationEvent
->
navigateTo
(
event
)
is
ViewActionEvent
->
event
.
action
(
this
)
...
...
@@ -230,11 +252,7 @@ abstract class MagiskActivity<ViewModel : MagiskViewModel, Binding : ViewDataBin
}
}
fun
startActivityForResult
(
intent
:
Intent
,
requestCode
:
Int
,
listener
:
RequestCallback
)
{
fun
startActivityForResult
(
intent
:
Intent
,
requestCode
:
Int
,
listener
:
RequestCallback
)
{
resultCallbacks
[
requestCode
]
=
listener
startActivityForResult
(
intent
,
requestCode
)
}
...
...
app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskFragment.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.ui.base
import
android.os.Bundle
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
androidx.annotation.CallSuper
import
androidx.databinding.DataBindingUtil
import
androidx.databinding.ViewDataBinding
import
androidx.fragment.app.Fragment
import
com.skoumal.teanity.view.TeanityFragment
import
com.skoumal.teanity.viewevents.ViewEvent
import
com.topjohnwu.magisk.model.events.BackPressEvent
import
com.topjohnwu.magisk.model.events.PermissionEvent
import
com.topjohnwu.magisk.model.events.ViewActionEvent
import
androidx.navigation.findNavController
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.extensions.snackbar
import
com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.model.navigation.MagiskNavigationEvent
import
com.topjohnwu.magisk.model.navigation.Navigator
import
com.topjohnwu.magisk.model.permissions.PermissionRequestBuilder
import
kotlin.reflect.KClass
abstract
class
MagiskFragment
<
ViewModel
:
MagiskViewModel
,
Binding
:
ViewDataBinding
>
:
TeanityFragment
<
ViewModel
,
Binding
>(),
Navigato
r
{
Fragment
(),
Navigator
,
EventHandle
r
{
protected
val
activity
get
()
=
requireActivity
()
as
MagiskActivity
<*,
*>
protected
lateinit
var
binding
:
Binding
protected
abstract
val
layoutRes
:
Int
protected
abstract
val
viewModel
:
ViewModel
protected
open
val
snackbarView
get
()
=
binding
.
root
protected
val
navController
get
()
=
binding
.
root
.
findNavController
()
private
val
viewEventObserver
=
ViewEventObserver
{
onEventDispatched
(
it
)
if
(
it
is
SimpleViewEvent
)
{
onSimpleEventDispatched
(
it
.
event
)
}
}
// We don't need nested fragments
override
val
baseFragments
:
List
<
KClass
<
Fragment
>>
=
listOf
()
override
fun
navigateTo
(
event
:
MagiskNavigationEvent
)
=
activity
.
navigateTo
(
event
)
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
viewModel
.
viewEvents
.
observe
(
this
,
viewEventObserver
)
}
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?
):
View
?
{
binding
=
DataBindingUtil
.
inflate
<
Binding
>(
inflater
,
layoutRes
,
container
,
false
).
apply
{
setVariable
(
BR
.
viewModel
,
viewModel
)
lifecycleOwner
=
this
@MagiskFragment
}
return
binding
.
root
}
@CallSuper
override
fun
onEventDispatched
(
event
:
ViewEvent
)
{
super
.
onEventDispatched
(
event
)
when
(
event
)
{
is
SnackbarEvent
->
snackbar
(
snackbarView
,
event
.
message
(
requireContext
()),
event
.
length
,
event
.
f
)
is
BackPressEvent
->
activity
.
onBackPressed
()
is
MagiskNavigationEvent
->
navigateTo
(
event
)
is
ViewActionEvent
->
event
.
action
(
requireActivity
())
...
...
app/src/main/java/com/topjohnwu/magisk/ui/base/MagiskViewModel.kt
View file @
fc886a5a
...
...
@@ -2,14 +2,14 @@ package com.topjohnwu.magisk.ui.base
import
android.app.Activity
import
com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import
com.skoumal.teanity.extensions.doOnSubscribeUi
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.util.KObservableField
import
com.skoumal.teanity.viewmodel.LoadingViewModel
import
com.topjohnwu.magisk.extensions.doOnSubscribeUi
import
com.topjohnwu.magisk.extensions.get
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.model.events.BackPressEvent
import
com.topjohnwu.magisk.model.events.PermissionEvent
import
com.topjohnwu.magisk.model.events.ViewActionEvent
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.viewmodel.LoadingViewModel
import
io.reactivex.Observable
import
io.reactivex.subjects.PublishSubject
...
...
app/src/main/java/com/topjohnwu/magisk/ui/flash/FlashViewModel.kt
View file @
fc886a5a
...
...
@@ -7,21 +7,20 @@ import android.net.Uri
import
android.os.Handler
import
androidx.core.os.postDelayed
import
androidx.databinding.ObservableArrayList
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.util.DiffObservableList
import
com.skoumal.teanity.util.KObservableField
import
com.skoumal.teanity.viewevents.SnackbarEvent
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.*
import
com.topjohnwu.magisk.model.entity.recycler.ConsoleRvItem
import
com.topjohnwu.magisk.model.events.SnackbarEvent
import
com.topjohnwu.magisk.model.flash.FlashResultListener
import
com.topjohnwu.magisk.model.flash.Flashing
import
com.topjohnwu.magisk.model.flash.Patching
import
com.topjohnwu.magisk.ui.base.MagiskViewModel
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.superuser.Shell
import
me.tatarka.bindingcollectionadapter2.ItemBinding
import
java.io.File
...
...
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.ui.hide
import
android.content.pm.ApplicationInfo
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.rxbus.RxBus
import
com.skoumal.teanity.util.DiffObservableList
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.utils.RxBus
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.toSingle
import
com.topjohnwu.magisk.extensions.update
import
com.topjohnwu.magisk.model.entity.recycler.HideProcessRvItem
...
...
@@ -16,6 +14,8 @@ import com.topjohnwu.magisk.model.entity.recycler.HideRvItem
import
com.topjohnwu.magisk.model.entity.state.IndeterminateState
import
com.topjohnwu.magisk.model.events.HideProcessEvent
import
com.topjohnwu.magisk.ui.base.MagiskViewModel
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.KObservableField
import
me.tatarka.bindingcollectionadapter2.OnItemBind
import
timber.log.Timber
...
...
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.ui.home
import
android.content.Context
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.viewevents.ViewEvent
import
com.topjohnwu.magisk.model.events.ViewEvent
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.Info
...
...
@@ -10,6 +9,7 @@ import com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.databinding.FragmentMagiskBinding
import
com.topjohnwu.magisk.extensions.inject
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.writeTo
import
com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.ui.base.MagiskActivity
...
...
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.ui.home
import
android.content.pm.PackageManager
import
com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import
com.skoumal.teanity.extensions.doOnSubscribeUi
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.*
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.extensions.get
import
com.topjohnwu.magisk.extensions.packageName
import
com.topjohnwu.magisk.extensions.res
import
com.topjohnwu.magisk.extensions.toggle
import
com.topjohnwu.magisk.extensions.*
import
com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.model.observer.Observer
import
com.topjohnwu.magisk.ui.base.MagiskViewModel
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.SafetyNetHelper
import
com.topjohnwu.superuser.Shell
...
...
app/src/main/java/com/topjohnwu/magisk/ui/log/LogFragment.kt
View file @
fc886a5a
...
...
@@ -6,7 +6,7 @@ import android.view.Menu
import
android.view.MenuInflater
import
android.view.MenuItem
import
android.view.View
import
com.
skoumal.teanity.view
events.ViewEvent
import
com.
topjohnwu.magisk.model.
events.ViewEvent
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.FragmentLogBinding
import
com.topjohnwu.magisk.model.events.PageChangedEvent
...
...
app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.ui.log
import
android.content.res.Resources
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import
com.skoumal.teanity.extensions.doOnSubscribeUi
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.util.DiffObservableList
import
com.skoumal.teanity.util.KObservableField
import
com.skoumal.teanity.viewevents.SnackbarEvent
import
com.topjohnwu.magisk.model.events.SnackbarEvent
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.addOnPropertyChangedCallback
import
com.topjohnwu.magisk.extensions.doOnSubscribeUi
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.LogItemRvItem
...
...
@@ -20,6 +18,8 @@ import com.topjohnwu.magisk.model.entity.recycler.LogRvItem
import
com.topjohnwu.magisk.model.entity.recycler.MagiskLogRvItem
import
com.topjohnwu.magisk.model.events.PageChangedEvent
import
com.topjohnwu.magisk.ui.base.MagiskViewModel
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.superuser.Shell
import
me.tatarka.bindingcollectionadapter2.BindingViewPagerAdapter
import
me.tatarka.bindingcollectionadapter2.OnItemBind
...
...
app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt
View file @
fc886a5a
package
com.topjohnwu.magisk.ui.module
import
android.content.res.Resources
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import
com.skoumal.teanity.extensions.doOnSuccessUi
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.util.DiffObservableList
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.database.RepoDao
import
com.topjohnwu.magisk.
extensions.toSingle
import
com.topjohnwu.magisk.extensions.
update
import
com.topjohnwu.magisk.
databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.
*
import
com.topjohnwu.magisk.model.entity.module.Module
import
com.topjohnwu.magisk.model.entity.recycler.ModuleRvItem
import
com.topjohnwu.magisk.model.entity.recycler.RepoRvItem
...
...
@@ -21,6 +15,8 @@ import com.topjohnwu.magisk.model.events.OpenChangelogEvent
import
com.topjohnwu.magisk.model.events.OpenFilePickerEvent
import
com.topjohnwu.magisk.tasks.RepoUpdater
import
com.topjohnwu.magisk.ui.base.MagiskViewModel
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.KObservableField
import
io.reactivex.Single
import
io.reactivex.disposables.Disposable
import
me.tatarka.bindingcollectionadapter2.OnItemBind
...
...
app/src/main/java/com/topjohnwu/magisk/ui/module/ModulesFragment.kt
View file @
fc886a5a
...
...
@@ -8,7 +8,7 @@ import android.view.MenuInflater
import
android.view.MenuItem
import
android.view.View
import
androidx.recyclerview.widget.RecyclerView
import
com.
skoumal.teanity.view
events.ViewEvent
import
com.
topjohnwu.magisk.model.
events.ViewEvent
import
com.topjohnwu.magisk.ClassMap
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.R
...
...
app/src/main/java/com/topjohnwu/magisk/ui/module/ReposFragment.kt
View file @
fc886a5a
...
...
@@ -6,7 +6,7 @@ import android.view.Menu
import
android.view.MenuInflater
import
android.view.MenuItem
import
android.widget.SearchView
import
com.
skoumal.teanity.view
events.ViewEvent
import
com.
topjohnwu.magisk.model.
events.ViewEvent
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.FragmentReposBinding
...
...
app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt
View file @
fc886a5a
...
...
@@ -13,14 +13,13 @@ import androidx.preference.ListPreference
import
androidx.preference.Preference
import
androidx.preference.PreferenceCategory
import
androidx.preference.SwitchPreferenceCompat
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.database.RepoDao
import
com.topjohnwu.magisk.databinding.CustomDownloadDialogBinding
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.toLangTag
import
com.topjohnwu.magisk.model.download.DownloadService
import
com.topjohnwu.magisk.model.entity.internal.Configuration
...
...
app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt
View file @
fc886a5a
...
...
@@ -2,21 +2,21 @@ package com.topjohnwu.magisk.ui.superuser
import
android.content.pm.PackageManager
import
android.content.res.Resources
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.skoumal.teanity.extensions.applySchedulers
import
com.skoumal.teanity.extensions.subscribeK
import
com.skoumal.teanity.rxbus.RxBus
import
com.skoumal.teanity.util.DiffObservableList
import
com.skoumal.teanity.viewevents.SnackbarEvent
import
com.topjohnwu.magisk.utils.RxBus
import
com.topjohnwu.magisk.model.events.SnackbarEvent
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.database.PolicyDao
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.applySchedulers
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.toggle
import
com.topjohnwu.magisk.model.entity.MagiskPolicy
import
com.topjohnwu.magisk.model.entity.recycler.PolicyRvItem
import
com.topjohnwu.magisk.model.events.PolicyEnableEvent
import
com.topjohnwu.magisk.model.events.PolicyUpdateEvent
import
com.topjohnwu.magisk.ui.base.MagiskViewModel
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.FingerprintHelper
import
com.topjohnwu.magisk.view.dialogs.CustomAlertDialog
import
com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
...
...
app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt
View file @
fc886a5a
...
...
@@ -5,7 +5,7 @@ import android.os.Build
import
android.os.Bundle
import
android.text.TextUtils
import
android.view.Window
import
com.
skoumal.teanity.view
events.ViewEvent
import
com.
topjohnwu.magisk.model.
events.ViewEvent
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ActivityRequestBinding
import
com.topjohnwu.magisk.model.entity.MagiskPolicy
...
...
app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestViewModel.kt
View file @
fc886a5a
...
...
@@ -9,21 +9,21 @@ import android.graphics.drawable.Drawable
import
android.hardware.fingerprint.FingerprintManager
import
android.os.CountDownTimer
import
android.text.TextUtils
import
com.skoumal.teanity.databinding.ComparableRvItem
import
com.skoumal.teanity.extensions.addOnPropertyChangedCallback
import
com.skoumal.teanity.util.DiffObservableList
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.database.PolicyDao
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
import
com.topjohnwu.magisk.extensions.now
import
com.topjohnwu.magisk.model.entity.MagiskPolicy
import
com.topjohnwu.magisk.model.entity.recycler.SpinnerRvItem
import
com.topjohnwu.magisk.model.entity.toPolicy
import
com.topjohnwu.magisk.model.events.DieEvent
import
com.topjohnwu.magisk.ui.base.MagiskViewModel
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.FingerprintHelper
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.SuConnector
import
me.tatarka.bindingcollectionadapter2.BindingListViewAdapter
import
me.tatarka.bindingcollectionadapter2.ItemBinding
...
...
app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt
View file @
fc886a5a
...
...
@@ -16,9 +16,9 @@ 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
import
com.topjohnwu.magisk.extensions.replaceRandomWithSpecial
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.model.entity.state.IndeterminateState
import
io.reactivex.Observable
import
io.reactivex.disposables.Disposable
...
...
app/src/main/java/com/topjohnwu/magisk/utils/DiffObservableList.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.utils
import
androidx.annotation.MainThread
import
androidx.databinding.ListChangeRegistry
import
androidx.databinding.ObservableList
import
androidx.recyclerview.widget.DiffUtil
import
androidx.recyclerview.widget.ListUpdateCallback
import
java.util.*
import
kotlin.collections.ArrayList
/**
* @param callback The callback that controls the behavior of the DiffObservableList.
* @param detectMoves True if DiffUtil should try to detect moved items, false otherwise.
*/
open
class
DiffObservableList
<
T
>(
private
val
callback
:
Callback
<
T
>,
private
val
detectMoves
:
Boolean
=
true
)
:
AbstractList
<
T
>(),
ObservableList
<
T
>
{
private
val
LIST_LOCK
=
Object
()
private
var
list
:
MutableList
<
T
>
=
ArrayList
()
private
val
listeners
=
ListChangeRegistry
()
private
val
listCallback
=
ObservableListUpdateCallback
()
override
val
size
:
Int
get
()
=
list
.
size
/**
* Calculates the list of update operations that can convert this list into the given one.
*
* @param newItems The items that this list will be set to.
* @return A DiffResult that contains the information about the edit sequence to covert this
* list into the given one.
*/
fun
calculateDiff
(
newItems
:
List
<
T
>):
DiffUtil
.
DiffResult
{
val
frozenList
=
synchronized
(
LIST_LOCK
)
{
ArrayList
(
list
)
}
return
doCalculateDiff
(
frozenList
,
newItems
)
}
private
fun
doCalculateDiff
(
oldItems
:
List
<
T
>,
newItems
:
List
<
T
>?):
DiffUtil
.
DiffResult
{
return
DiffUtil
.
calculateDiff
(
object
:
DiffUtil
.
Callback
()
{
override
fun
getOldListSize
()
=
oldItems
.
size
override
fun
getNewListSize
()
=
newItems
?.
size
?:
0
override
fun
areItemsTheSame
(
oldItemPosition
:
Int
,
newItemPosition
:
Int
):
Boolean
{
val
oldItem
=
oldItems
[
oldItemPosition
]
val
newItem
=
newItems
!!
[
newItemPosition
]
return
callback
.
areItemsTheSame
(
oldItem
,
newItem
)
}
override
fun
areContentsTheSame
(
oldItemPosition
:
Int
,
newItemPosition
:
Int
):
Boolean
{
val
oldItem
=
oldItems
[
oldItemPosition
]
val
newItem
=
newItems
!!
[
newItemPosition
]
return
callback
.
areContentsTheSame
(
oldItem
,
newItem
)
}
},
detectMoves
)
}
/**
* Updates the contents of this list to the given one using the DiffResults to dispatch change
* notifications.
*
* @param newItems The items to set this list to.
* @param diffResult The diff results to dispatch change notifications.
*/
@MainThread
fun
update
(
newItems
:
List
<
T
>,
diffResult
:
DiffUtil
.
DiffResult
)
{
synchronized
(
LIST_LOCK
)
{
list
=
newItems
.
toMutableList
()
}
diffResult
.
dispatchUpdatesTo
(
listCallback
)
}
/**
* Sets this list to the given items. This is a convenience method for calling [ ][.calculateDiff] followed by [.update].
*
*
* **Warning!** If the lists are large this operation may be too slow for the main thread. In
* that case, you should call [.calculateDiff] on a background thread and then
* [.update] on the main thread.
*
* @param newItems The items to set this list to.
*/
@MainThread
fun
update
(
newItems
:
List
<
T
>)
{
val
diffResult
=
doCalculateDiff
(
list
,
newItems
)
list
=
newItems
.
toMutableList
()
diffResult
.
dispatchUpdatesTo
(
listCallback
)
}
override
fun
addOnListChangedCallback
(
listener
:
ObservableList
.
OnListChangedCallback
<
out
ObservableList
<
T
>>)
{
listeners
.
add
(
listener
)
}
override
fun
removeOnListChangedCallback
(
listener
:
ObservableList
.
OnListChangedCallback
<
out
ObservableList
<
T
>>)
{
listeners
.
remove
(
listener
)
}
override
fun
get
(
index
:
Int
):
T
{
return
list
[
index
]
}
override
fun
add
(
element
:
T
):
Boolean
{
list
.
add
(
element
)
notifyAdd
(
size
-
1
,
1
)
return
true
}
override
fun
add
(
index
:
Int
,
element
:
T
)
{
list
.
add
(
index
,
element
)
notifyAdd
(
index
,
1
)
}
override
fun
addAll
(
elements
:
Collection
<
T
>):
Boolean
{
val
oldSize
=
size
val
added
=
list
.
addAll
(
elements
)
if
(
added
)
{
notifyAdd
(
oldSize
,
size
-
oldSize
)
}
return
added
}
override
fun
addAll
(
index
:
Int
,
elements
:
Collection
<
T
>):
Boolean
{
val
added
=
list
.
addAll
(
index
,
elements
)
if
(
added
)
{
notifyAdd
(
index
,
elements
.
size
)
}
return
added
}
override
fun
clear
()
{
val
oldSize
=
size
list
.
clear
()
if
(
oldSize
!=
0
)
{
notifyRemove
(
0
,
oldSize
)
}
}
override
fun
remove
(
element
:
T
):
Boolean
{
val
index
=
indexOf
(
element
)
return
if
(
index
>=
0
)
{
removeAt
(
index
)
true
}
else
{
false
}
}
override
fun
removeAt
(
index
:
Int
):
T
{
val
element
=
list
.
removeAt
(
index
)
notifyRemove
(
index
,
1
)
return
element
}
fun
removeLast
():
T
?
{
if
(
size
>
0
)
{
val
index
=
size
-
1
return
removeAt
(
index
)
}
return
null
}
override
fun
set
(
index
:
Int
,
element
:
T
):
T
{
val
old
=
list
.
set
(
index
,
element
)
listeners
.
notifyChanged
(
this
,
index
,
1
)
return
old
}
private
fun
notifyAdd
(
start
:
Int
,
count
:
Int
)
{
listeners
.
notifyInserted
(
this
,
start
,
count
)
}
private
fun
notifyRemove
(
start
:
Int
,
count
:
Int
)
{
listeners
.
notifyRemoved
(
this
,
start
,
count
)
}
/**
* A Callback class used by DiffUtil while calculating the diff between two lists.
*/
interface
Callback
<
T
>
{
/**
* Called by the DiffUtil to decide whether two object represent the same Item.
*
*
* For example, if your items have unique ids, this method should check their id equality.
*
* @param oldItem The old item.
* @param newItem The new item.
* @return True if the two items represent the same object or false if they are different.
*/
fun
areItemsTheSame
(
oldItem
:
T
,
newItem
:
T
):
Boolean
/**
* Called by the DiffUtil when it wants to check whether two items have the same data.
* DiffUtil uses this information to detect if the contents of an item has changed.
*
*
* DiffUtil uses this method to check equality instead of [Object.equals] so
* that you can change its behavior depending on your UI.
*
*
* This method is called only if [.areItemsTheSame] returns `true` for
* these items.
*
* @param oldItem The old item.
* @param newItem The new item which replaces the old item.
* @return True if the contents of the items are the same or false if they are different.
*/
fun
areContentsTheSame
(
oldItem
:
T
,
newItem
:
T
):
Boolean
}
inner
class
ObservableListUpdateCallback
:
ListUpdateCallback
{
override
fun
onChanged
(
position
:
Int
,
count
:
Int
,
payload
:
Any
?)
{
listeners
.
notifyChanged
(
this
@DiffObservableList
,
position
,
count
)
}
override
fun
onMoved
(
fromPosition
:
Int
,
toPosition
:
Int
)
{
listeners
.
notifyMoved
(
this
@DiffObservableList
,
fromPosition
,
toPosition
,
1
)
}
override
fun
onInserted
(
position
:
Int
,
count
:
Int
)
{
modCount
+=
1
listeners
.
notifyInserted
(
this
@DiffObservableList
,
position
,
count
)
}
override
fun
onRemoved
(
position
:
Int
,
count
:
Int
)
{
modCount
+=
1
listeners
.
notifyRemoved
(
this
@DiffObservableList
,
position
,
count
)
}
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/utils/KItemDecoration.kt
0 → 100644
View file @
fc886a5a
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.extensions.drawableCompat
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
+
Math
.
round
(
child
.
translationY
)
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
+
Math
.
round
(
child
.
translationX
)
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
)
}
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/utils/KObservableField.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.utils
import
androidx.databinding.Observable
import
androidx.databinding.ObservableField
import
java.io.Serializable
/**
* Kotlin version of [ObservableField].
* You can define if wrapped type is Nullable or not.
* You can use kotlin get/set syntax for value
*/
class
KObservableField
<
T
>
:
ObservableField
<
T
>,
Serializable
{
var
value
:
T
set
(
value
)
{
if
(
field
!=
value
)
{
field
=
value
notifyChange
()
}
}
constructor
(
init
:
T
)
{
value
=
init
}
constructor
(
init
:
T
,
vararg
dependencies
:
Observable
)
:
super
(*
dependencies
)
{
value
=
init
}
@Deprecated
(
message
=
"Needed for data binding, use KObservableField.value syntax from code"
,
replaceWith
=
ReplaceWith
(
"value"
)
)
override
fun
get
():
T
{
return
value
}
@Deprecated
(
message
=
"Needed for data binding, use KObservableField.value = ... syntax from code"
,
replaceWith
=
ReplaceWith
(
"value = newValue"
)
)
override
fun
set
(
newValue
:
T
)
{
value
=
newValue
}
override
fun
toString
():
String
{
return
"KObservableField(value=$value)"
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/utils/PatchAPK.kt
View file @
fc886a5a
...
...
@@ -3,8 +3,8 @@ package com.topjohnwu.magisk.utils
import
android.content.ComponentName
import
android.content.Context
import
android.widget.Toast
import
com.skoumal.teanity.extensions.subscribeK
import
com.topjohnwu.magisk.*
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.ui.SplashActivity
import
com.topjohnwu.magisk.view.Notifications
import
com.topjohnwu.signing.JarMap
...
...
app/src/main/java/com/topjohnwu/magisk/utils/RxBus.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.utils
import
io.reactivex.Observable
import
io.reactivex.subjects.PublishSubject
class
RxBus
{
private
val
_bus
=
PublishSubject
.
create
<
Event
>()
val
bus
:
Observable
<
Event
>
get
()
=
_bus
fun
post
(
event
:
Event
)
{
_bus
.
onNext
(
event
)
}
fun
post
(
event
:
Int
)
{
_bus
.
onNext
(
SimpleEvent
(
event
))
}
inline
fun
<
reified
T
:
Event
>
register
(
noinline
predicate
:
(
T
)
->
Boolean
=
{
true
}):
Observable
<
T
>
{
return
bus
.
ofType
(
T
::
class
.
java
)
.
filter
(
predicate
)
}
fun
register
(
eventId
:
Int
):
Observable
<
Int
>
{
return
bus
.
ofType
(
SimpleEvent
::
class
.
java
)
.
map
{
it
.
eventId
}
.
filter
{
it
==
eventId
}
}
interface
Event
private
class
SimpleEvent
(
val
eventId
:
Int
)
:
Event
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/view/MagiskDialog.kt
deleted
100644 → 0
View file @
0cb90e2e
package
com.topjohnwu.magisk.view
import
android.content.Context
import
android.content.DialogInterface
import
android.graphics.Color
import
android.graphics.drawable.ColorDrawable
import
android.graphics.drawable.Drawable
import
android.os.Bundle
import
android.view.LayoutInflater
import
androidx.annotation.DrawableRes
import
androidx.annotation.StringRes
import
androidx.appcompat.app.AlertDialog
import
androidx.databinding.DataBindingUtil
import
androidx.databinding.ViewDataBinding
import
com.skoumal.teanity.util.KObservableField
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.DialogMagiskBaseBinding
class
MagiskDialog
@JvmOverloads
constructor
(
context
:
Context
,
theme
:
Int
=
0
)
:
AlertDialog
(
context
,
theme
)
{
private
val
binding
:
DialogMagiskBaseBinding
private
val
data
=
Data
()
init
{
val
layoutInflater
=
LayoutInflater
.
from
(
context
)
binding
=
DataBindingUtil
.
inflate
(
layoutInflater
,
R
.
layout
.
dialog_magisk_base
,
null
,
false
)
binding
.
setVariable
(
BR
.
data
,
data
)
super
.
setView
(
binding
.
root
)
}
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
window
?.
setBackgroundDrawable
(
ColorDrawable
(
Color
.
TRANSPARENT
))
}
inner
class
Data
{
val
icon
=
KObservableField
(
0
)
val
iconRaw
=
KObservableField
<
Drawable
?>(
null
)
val
title
=
KObservableField
<
CharSequence
>(
""
)
val
message
=
KObservableField
<
CharSequence
>(
""
)
val
buttonPositive
=
Button
()
val
buttonNeutral
=
Button
()
val
buttonNegative
=
Button
()
val
buttonIDGAF
=
Button
()
}
enum
class
ButtonType
{
POSITIVE
,
NEUTRAL
,
NEGATIVE
,
IDGAF
}
inner
class
Button
{
val
icon
=
KObservableField
(
0
)
val
title
=
KObservableField
<
CharSequence
>(
""
)
val
isEnabled
=
KObservableField
(
true
)
var
onClickAction
:
OnDialogButtonClickListener
=
{}
fun
clicked
()
{
onClickAction
(
this
@MagiskDialog
)
dismiss
()
}
}
inner
class
ButtonBuilder
(
private
val
button
:
Button
)
{
var
icon
:
Int
get
()
=
button
.
icon
.
value
set
(
value
)
{
button
.
icon
.
value
=
value
}
var
title
:
CharSequence
get
()
=
button
.
title
.
value
set
(
value
)
{
button
.
title
.
value
=
value
}
var
titleRes
:
Int
get
()
=
0
set
(
value
)
{
button
.
title
.
value
=
context
.
getString
(
value
)
}
var
isEnabled
:
Boolean
get
()
=
button
.
isEnabled
.
value
set
(
value
)
{
button
.
isEnabled
.
value
=
value
}
fun
onClick
(
listener
:
OnDialogButtonClickListener
)
{
button
.
onClickAction
=
listener
}
}
fun
applyTitle
(
@StringRes
stringRes
:
Int
)
=
apply
{
data
.
title
.
value
=
context
.
getString
(
stringRes
)
}
fun
applyTitle
(
title
:
CharSequence
)
=
apply
{
data
.
title
.
value
=
title
}
fun
applyMessage
(
@StringRes
stringRes
:
Int
)
=
apply
{
data
.
message
.
value
=
context
.
getString
(
stringRes
)
}
fun
applyMessage
(
message
:
CharSequence
)
=
apply
{
data
.
message
.
value
=
message
}
fun
applyIcon
(
@DrawableRes
drawableRes
:
Int
)
=
apply
{
data
.
icon
.
value
=
drawableRes
}
fun
applyIcon
(
drawable
:
Drawable
)
=
apply
{
data
.
iconRaw
.
value
=
drawable
}
fun
applyButton
(
buttonType
:
ButtonType
,
builder
:
ButtonBuilder
.()
->
Unit
)
=
apply
{
val
button
=
when
(
buttonType
)
{
ButtonType
.
POSITIVE
->
data
.
buttonPositive
ButtonType
.
NEUTRAL
->
data
.
buttonNeutral
ButtonType
.
NEGATIVE
->
data
.
buttonNegative
ButtonType
.
IDGAF
->
data
.
buttonIDGAF
}
ButtonBuilder
(
button
).
apply
(
builder
)
}
fun
cancellable
(
isCancellable
:
Boolean
)
=
apply
{
setCancelable
(
isCancellable
)
}
fun
<
Binding
:
ViewDataBinding
>
applyView
(
binding
:
Binding
,
body
:
Binding
.()
->
Unit
)
=
apply
{
this
.
binding
.
dialogBaseContainer
.
removeAllViews
()
this
.
binding
.
dialogBaseContainer
.
addView
(
binding
.
root
)
binding
.
apply
(
body
)
}
fun
onDismiss
(
callback
:
OnDialogButtonClickListener
)
=
apply
{
setOnDismissListener
(
callback
)
}
fun
onShow
(
callback
:
OnDialogButtonClickListener
)
=
apply
{
setOnShowListener
(
callback
)
}
fun
reveal
()
=
apply
{
super
.
show
()
}
//region Deprecated Members
@Deprecated
(
"Use applyTitle instead"
,
ReplaceWith
(
"applyTitle"
))
override
fun
setTitle
(
title
:
CharSequence
?)
=
Unit
@Deprecated
(
"Use applyTitle instead"
,
ReplaceWith
(
"applyTitle"
))
override
fun
setTitle
(
titleId
:
Int
)
=
Unit
@Deprecated
(
"Use reveal()"
,
ReplaceWith
(
"reveal()"
))
override
fun
show
()
{
}
//endregion
}
typealias
OnDialogButtonClickListener
=
(
DialogInterface
)
->
Unit
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/view/MarkDownWindow.kt
View file @
fc886a5a
...
...
@@ -4,10 +4,10 @@ import android.content.Context
import
android.view.LayoutInflater
import
android.widget.TextView
import
androidx.appcompat.app.AlertDialog
import
com.skoumal.teanity.extensions.subscribeK
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.repository.StringRepository
import
com.topjohnwu.magisk.extensions.inject
import
com.topjohnwu.magisk.extensions.subscribeK
import
io.reactivex.Completable
import
io.reactivex.Single
import
ru.noties.markwon.Markwon
...
...
app/src/main/java/com/topjohnwu/magisk/view/dialogs/EnvFixDialog.kt
View file @
fc886a5a
...
...
@@ -8,9 +8,9 @@ import com.topjohnwu.magisk.Info
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.extensions.cachedFile
import
com.topjohnwu.magisk.extensions.reboot
import
com.topjohnwu.magisk.net.Networking
import
com.topjohnwu.magisk.tasks.MagiskInstaller
import
com.topjohnwu.magisk.utils.Utils
import
com.topjohnwu.magisk.net.Networking
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.ShellUtils
import
com.topjohnwu.superuser.internal.UiThreadHandler
...
...
app/src/main/java/com/topjohnwu/magisk/viewmodel/LoadingViewModel.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.viewmodel
import
androidx.databinding.Bindable
import
com.topjohnwu.magisk.BR
import
io.reactivex.*
abstract
class
LoadingViewModel
(
defaultState
:
State
=
State
.
LOADING
)
:
StatefulViewModel
<
LoadingViewModel
.
State
>(
defaultState
)
{
val
loading
@Bindable
get
()
=
state
==
State
.
LOADING
val
loaded
@Bindable
get
()
=
state
==
State
.
LOADED
val
loadingFailed
@Bindable
get
()
=
state
==
State
.
LOADING_FAILED
@Deprecated
(
"Direct access is recommended since 0.2. This access method will be removed in 1.0"
,
ReplaceWith
(
"state = State.LOADING"
,
"com.topjohnwu.magisk.viewmodel.LoadingViewModel.State"
),
DeprecationLevel
.
WARNING
)
fun
setLoading
()
{
state
=
State
.
LOADING
}
@Deprecated
(
"Direct access is recommended since 0.2. This access method will be removed in 1.0"
,
ReplaceWith
(
"state = State.LOADED"
,
"com.topjohnwu.magisk.viewmodel.LoadingViewModel.State"
),
DeprecationLevel
.
WARNING
)
fun
setLoaded
()
{
state
=
State
.
LOADED
}
@Deprecated
(
"Direct access is recommended since 0.2. This access method will be removed in 1.0"
,
ReplaceWith
(
"state = State.LOADING_FAILED"
,
"com.topjohnwu.magisk.viewmodel.LoadingViewModel.State"
),
DeprecationLevel
.
WARNING
)
fun
setLoadingFailed
()
{
state
=
State
.
LOADING_FAILED
}
override
fun
notifyStateChanged
()
{
notifyPropertyChanged
(
BR
.
loading
)
notifyPropertyChanged
(
BR
.
loaded
)
notifyPropertyChanged
(
BR
.
loadingFailed
)
}
enum
class
State
{
LOADED
,
LOADING
,
LOADING_FAILED
}
//region Rx
protected
fun
<
T
>
Observable
<
T
>.
applyViewModel
(
viewModel
:
LoadingViewModel
,
allowFinishing
:
Boolean
=
true
)
=
doOnSubscribe
{
viewModel
.
state
=
State
.
LOADING
}
.
doOnError
{
viewModel
.
state
=
State
.
LOADING_FAILED
}
.
doOnNext
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
protected
fun
<
T
>
Single
<
T
>.
applyViewModel
(
viewModel
:
LoadingViewModel
,
allowFinishing
:
Boolean
=
true
)
=
doOnSubscribe
{
viewModel
.
state
=
State
.
LOADING
}
.
doOnError
{
viewModel
.
state
=
State
.
LOADING_FAILED
}
.
doOnSuccess
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
protected
fun
<
T
>
Maybe
<
T
>.
applyViewModel
(
viewModel
:
LoadingViewModel
,
allowFinishing
:
Boolean
=
true
)
=
doOnSubscribe
{
viewModel
.
state
=
State
.
LOADING
}
.
doOnError
{
viewModel
.
state
=
State
.
LOADING_FAILED
}
.
doOnComplete
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
.
doOnSuccess
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
protected
fun
<
T
>
Flowable
<
T
>.
applyViewModel
(
viewModel
:
LoadingViewModel
,
allowFinishing
:
Boolean
=
true
)
=
doOnSubscribe
{
viewModel
.
state
=
State
.
LOADING
}
.
doOnError
{
viewModel
.
state
=
State
.
LOADING_FAILED
}
.
doOnNext
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
protected
fun
Completable
.
applyViewModel
(
viewModel
:
LoadingViewModel
,
allowFinishing
:
Boolean
=
true
)
=
doOnSubscribe
{
viewModel
.
state
=
State
.
LOADING
}
.
doOnError
{
viewModel
.
state
=
State
.
LOADING_FAILED
}
.
doOnComplete
{
if
(
allowFinishing
)
viewModel
.
state
=
State
.
LOADED
}
//endregion
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/viewmodel/ObservableViewModel.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.viewmodel
import
androidx.databinding.Observable
import
androidx.databinding.PropertyChangeRegistry
import
androidx.lifecycle.ViewModel
/**
* Copy of [android.databinding.BaseObservable] which extends [ViewModel]
*/
abstract
class
ObservableViewModel
:
TeanityViewModel
(),
Observable
{
@Transient
private
var
callbacks
:
PropertyChangeRegistry
?
=
null
@Synchronized
override
fun
addOnPropertyChangedCallback
(
callback
:
Observable
.
OnPropertyChangedCallback
)
{
if
(
callbacks
==
null
)
{
callbacks
=
PropertyChangeRegistry
()
}
callbacks
?.
add
(
callback
)
}
@Synchronized
override
fun
removeOnPropertyChangedCallback
(
callback
:
Observable
.
OnPropertyChangedCallback
)
{
callbacks
?.
remove
(
callback
)
}
/**
* Notifies listeners that all properties of this instance have changed.
*/
@Synchronized
fun
notifyChange
()
{
callbacks
?.
notifyCallbacks
(
this
,
0
,
null
)
}
/**
* Notifies listeners that a specific property has changed. The getter for the property
* that changes should be marked with [android.databinding.Bindable] to generate a field in
* `BR` to be used as `fieldId`.
*
* @param fieldId The generated BR id for the Bindable field.
*/
fun
notifyPropertyChanged
(
fieldId
:
Int
)
{
callbacks
?.
notifyCallbacks
(
this
,
fieldId
,
null
)
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/viewmodel/StatefulViewModel.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.viewmodel
abstract
class
StatefulViewModel
<
State
:
Enum
<*>>(
val
defaultState
:
State
)
:
ObservableViewModel
()
{
var
state
:
State
=
defaultState
set
(
value
)
{
field
=
value
notifyStateChanged
()
}
open
fun
notifyStateChanged
()
=
Unit
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/viewmodel/TeanityViewModel.kt
0 → 100644
View file @
fc886a5a
package
com.topjohnwu.magisk.viewmodel
import
androidx.lifecycle.LiveData
import
androidx.lifecycle.MutableLiveData
import
androidx.lifecycle.ViewModel
import
com.topjohnwu.magisk.model.events.SimpleViewEvent
import
com.topjohnwu.magisk.model.events.ViewEvent
import
io.reactivex.disposables.CompositeDisposable
import
io.reactivex.disposables.Disposable
abstract
class
TeanityViewModel
:
ViewModel
()
{
private
val
disposables
=
CompositeDisposable
()
private
val
_viewEvents
=
MutableLiveData
<
ViewEvent
>()
val
viewEvents
:
LiveData
<
ViewEvent
>
get
()
=
_viewEvents
override
fun
onCleared
()
{
super
.
onCleared
()
disposables
.
clear
()
}
fun
<
Event
:
ViewEvent
>
Event
.
publish
()
{
_viewEvents
.
value
=
this
}
fun
Int
.
publish
()
{
_viewEvents
.
value
=
SimpleViewEvent
(
this
)
}
fun
Disposable
.
add
()
{
disposables
.
add
(
this
)
}
}
\ No newline at end of file
app/src/main/res/layout/dialog_magisk_base.xml
deleted
100644 → 0
View file @
0cb90e2e
This diff is collapsed.
Click to expand it.
app/src/main/res/layout/fragment_magisk.xml
View file @
fc886a5a
...
...
@@ -5,7 +5,7 @@
<data>
<import
type=
"com.
skoumal.teanity
.viewmodel.LoadingViewModel.State"
/>
<import
type=
"com.
topjohnwu.magisk
.viewmodel.LoadingViewModel.State"
/>
<import
type=
"com.topjohnwu.magisk.ui.home.SafetyNetState"
/>
...
...
build.gradle
View file @
fc886a5a
...
...
@@ -7,7 +7,7 @@ if (configPath.exists())
configPath
.
withInputStream
{
is
->
props
.
load
(
is
)
}
buildscript
{
ext
.
kotlinVer
=
'1.3.50'
ext
.
vKotlin
=
'1.3.50'
repositories
{
google
()
...
...
@@ -17,7 +17,7 @@ buildscript {
}
dependencies
{
classpath
'com.android.tools.build:gradle:3.5.0'
classpath
"org.jetbrains.kotlin:kotlin-gradle-plugin:${
kotlinVer
}"
classpath
"org.jetbrains.kotlin:kotlin-gradle-plugin:${
vKotlin
}"
// NOTE: Do not place your application dependencies here; they belong
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment