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
6aa22267
Commit
6aa22267
authored
Oct 31, 2019
by
Viktor De Pasquale
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated Hide screen to be fully functioning
...although still misses search :(
parent
f76c020d
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
202 additions
and
69 deletions
+202
-69
RedesignModule.kt
app/src/main/java/com/topjohnwu/magisk/di/RedesignModule.kt
+1
-1
HideAppInfo.kt
...ain/java/com/topjohnwu/magisk/model/entity/HideAppInfo.kt
+1
-0
HideRvItem.kt
.../com/topjohnwu/magisk/model/entity/recycler/HideRvItem.kt
+22
-2
HideFragment.kt
...n/java/com/topjohnwu/magisk/redesign/hide/HideFragment.kt
+13
-1
HideViewModel.kt
.../java/com/topjohnwu/magisk/redesign/hide/HideViewModel.kt
+46
-59
DataBindingAdapters.kt
...in/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt
+5
-0
DiffObservableList.kt
...ain/java/com/topjohnwu/magisk/utils/DiffObservableList.kt
+3
-3
FilterableDiffObservableList.kt
...om/topjohnwu/magisk/utils/FilterableDiffObservableList.kt
+85
-0
item_hide_md2.xml
app/src/main/res/layout/item_hide_md2.xml
+5
-0
item_hide_process_md2.xml
app/src/main/res/layout/item_hide_process_md2.xml
+3
-3
menu_hide_item.xml
app/src/main/res/menu/menu_hide_item.xml
+9
-0
menu_hide_md2.xml
app/src/main/res/menu/menu_hide_md2.xml
+9
-0
No files found.
app/src/main/java/com/topjohnwu/magisk/di/RedesignModule.kt
View file @
6aa22267
...
...
@@ -17,7 +17,7 @@ import org.koin.dsl.module
val
redesignModule
=
module
{
viewModel
{
FlashViewModel
()
}
viewModel
{
HideViewModel
(
get
()
,
get
()
)
}
viewModel
{
HideViewModel
(
get
())
}
viewModel
{
HomeViewModel
(
get
())
}
viewModel
{
LogViewModel
()
}
viewModel
{
ModuleViewModel
()
}
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/HideAppInfo.kt
View file @
6aa22267
...
...
@@ -17,6 +17,7 @@ class HideAppInfo(
data class
StatefulProcess
(
val
name
:
String
,
val
packageName
:
String
,
val
isHidden
:
Boolean
)
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/HideRvItem.kt
View file @
6aa22267
package
com.topjohnwu.magisk.model.entity.recycler
import
android.view.MenuItem
import
android.view.View
import
android.view.ViewGroup
import
com.topjohnwu.magisk.R
...
...
@@ -14,6 +15,7 @@ import com.topjohnwu.magisk.model.entity.ProcessHideApp
import
com.topjohnwu.magisk.model.entity.StatefulProcess
import
com.topjohnwu.magisk.model.entity.state.IndeterminateState
import
com.topjohnwu.magisk.model.events.HideProcessEvent
import
com.topjohnwu.magisk.redesign.hide.HideViewModel
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.RxBus
...
...
@@ -22,14 +24,18 @@ class HideItem(val item: ProcessHideApp) : ComparableRvItem<HideItem>() {
override
val
layoutRes
=
R
.
layout
.
item_hide_md2
val
packageName
=
item
.
info
.
info
.
packageName
.
orEmpty
()
val
items
=
item
.
processes
.
map
{
HideProcessItem
(
it
)
}
val
isExpanded
=
KObservableField
(
false
)
val
itemsChecked
=
KObservableField
(
0
)
val
isHidden
get
()
=
itemsChecked
.
value
==
items
.
size
/** [toggle] depends on this functionality */
private
val
isHidden
get
()
=
itemsChecked
.
value
==
items
.
size
init
{
items
.
forEach
{
it
.
isHidden
.
addOnPropertyChangedCallback
{
recalculateChecked
()
}
}
recalculateChecked
()
}
fun
collapse
(
v
:
View
)
{
...
...
@@ -42,6 +48,17 @@ class HideItem(val item: ProcessHideApp) : ComparableRvItem<HideItem>() {
isExpanded
.
value
=
true
}
fun
toggle
(
menuItem
:
MenuItem
,
viewModel
:
HideViewModel
):
Boolean
{
if
(
menuItem
.
itemId
!=
R
.
id
.
action_toggle
)
return
false
// contract implies that isHidden == all checked
if
(!
isHidden
)
{
items
.
filterNot
{
it
.
isHidden
.
value
}
}
else
{
items
}.
forEach
{
it
.
toggle
(
viewModel
)
}
return
true
}
private
fun
recalculateChecked
()
{
itemsChecked
.
value
=
items
.
count
{
it
.
isHidden
.
value
}
}
...
...
@@ -57,7 +74,10 @@ class HideProcessItem(val item: StatefulProcess) : ComparableRvItem<HideProcessI
val
isHidden
=
KObservableField
(
item
.
isHidden
)
fun
toggle
()
=
isHidden
.
toggle
()
fun
toggle
(
viewModel
:
HideViewModel
)
{
isHidden
.
toggle
()
viewModel
.
toggleItem
(
this
)
}
override
fun
contentSameAs
(
other
:
HideProcessItem
)
=
item
==
other
.
item
override
fun
itemSameAs
(
other
:
HideProcessItem
)
=
item
.
name
==
other
.
item
.
name
...
...
app/src/main/java/com/topjohnwu/magisk/redesign/hide/HideFragment.kt
View file @
6aa22267
...
...
@@ -2,6 +2,9 @@ package com.topjohnwu.magisk.redesign.hide
import
android.content.Context
import
android.graphics.Insets
import
android.view.Menu
import
android.view.MenuInflater
import
android.view.MenuItem
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.FragmentHideMd2Binding
import
com.topjohnwu.magisk.redesign.compat.CompatFragment
...
...
@@ -16,8 +19,17 @@ class HideFragment : CompatFragment<HideViewModel, FragmentHideMd2Binding>() {
override
fun
onAttach
(
context
:
Context
)
{
super
.
onAttach
(
context
)
activity
.
setTitle
(
R
.
string
.
magiskhide
)
setHasOptionsMenu
(
true
)
}
override
fun
onCreateOptionsMenu
(
menu
:
Menu
,
inflater
:
MenuInflater
)
{
inflater
.
inflate
(
R
.
menu
.
menu_hide_md2
,
menu
)
menu
.
findItem
(
R
.
id
.
action_show_system
)
?.
isChecked
=
viewModel
.
isShowSystem
}
override
fun
onOptionsItemSelected
(
item
:
MenuItem
):
Boolean
{
return
viewModel
.
menuItemPressed
(
item
)
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/redesign/hide/HideViewModel.kt
View file @
6aa22267
package
com.topjohnwu.magisk.redesign.hide
import
android.content.pm.ApplicationInfo
import
android.view.MenuItem
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.toSingle
import
com.topjohnwu.magisk.model.entity.HideAppInfo
import
com.topjohnwu.magisk.model.entity.HideTarget
import
com.topjohnwu.magisk.model.entity.ProcessHideApp
import
com.topjohnwu.magisk.model.entity.StatefulProcess
import
com.topjohnwu.magisk.model.entity.recycler.HideItem
import
com.topjohnwu.magisk.model.entity.recycler.HideProcessItem
import
com.topjohnwu.magisk.model.entity.recycler.HideProcessRvItem
import
com.topjohnwu.magisk.model.events.HideProcessEvent
import
com.topjohnwu.magisk.redesign.compat.CompatViewModel
import
com.topjohnwu.magisk.redesign.home.itemBindingOf
import
com.topjohnwu.magisk.redesign.superuser.diffListOf
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.FilterableDiffObservableList
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.RxBus
import
com.topjohnwu.magisk.utils.currentLocale
import
io.reactivex.disposables.Disposable
import
java.util.*
class
HideViewModel
(
private
val
magiskRepo
:
MagiskRepository
,
rxBus
:
RxBus
private
val
magiskRepo
:
MagiskRepository
)
:
CompatViewModel
()
{
@Volatile
private
var
cache
=
listOf
<
HideItem
>()
var
isShowSystem
=
false
set
(
value
)
{
field
=
Collections
.
synchronizedList
(
value
)
}
private
var
queryJob
:
Disposable
?
=
null
set
(
value
)
{
field
?.
dispose
()
field
=
value
query
()
}
val
query
=
KObservableField
(
""
)
val
isShowSystem
=
KObservableField
(
true
)
val
items
=
diffListOf
<
HideItem
>()
val
items
=
filterableListOf
<
HideItem
>()
val
itemBinding
=
itemBindingOf
<
HideItem
>
{
it
.
bindExtra
(
BR
.
viewModel
,
this
)
}
...
...
@@ -48,12 +39,6 @@ class HideViewModel(
it
.
bindExtra
(
BR
.
viewModel
,
this
)
}
init
{
rxBus
.
register
<
HideProcessEvent
>()
.
subscribeK
{
toggleItem
(
it
.
item
)
}
.
add
()
}
override
fun
refresh
()
=
magiskRepo
.
fetchApps
()
.
map
{
it
to
magiskRepo
.
fetchHideTargets
().
blockingGet
()
}
.
map
{
pair
->
pair
.
first
.
map
{
mergeAppTargets
(
it
,
pair
.
second
)
}
}
...
...
@@ -61,64 +46,66 @@ class HideViewModel(
.
map
{
HideItem
(
it
)
}
.
toList
()
.
map
{
it
.
sort
()
}
.
map
{
it
to
items
.
calculateDiff
(
it
)
}
.
subscribeK
{
cache
=
it
query
IfNecessary
()
items
.
update
(
it
.
first
,
it
.
second
)
query
()
}
override
fun
onCleared
()
{
queryJob
?.
dispose
()
super
.
onCleared
()
}
// ---
private
fun
mergeAppTargets
(
a
:
HideAppInfo
,
ts
:
List
<
HideTarget
>):
ProcessHideApp
{
val
relevantTargets
=
ts
.
filter
{
it
.
packageName
==
a
.
info
.
packageName
}
val
packageName
=
a
.
info
.
packageName
val
processes
=
a
.
processes
.
map
{
StatefulProcess
(
it
,
relevantTargets
.
any
{
i
->
it
==
i
.
process
})
}
.
map
{
StatefulProcess
(
it
,
packageName
,
relevantTargets
.
any
{
i
->
it
==
i
.
process
})
}
return
ProcessHideApp
(
a
,
processes
)
}
private
fun
List
<
HideItem
>.
sort
()
=
sortedWith
(
compareBy
(
{
it
.
isHidden
},
{
it
.
item
.
info
.
name
.
toLowerCase
(
currentLocale
)
},
{
it
.
item
.
info
.
info
.
packageName
}
))
private
fun
List
<
HideItem
>.
sort
()
=
compareByDescending
<
HideItem
>
{
it
.
itemsChecked
.
value
}
.
thenBy
{
it
.
item
.
info
.
name
.
toLowerCase
(
currentLocale
)
}
.
thenBy
{
it
.
item
.
info
.
info
.
packageName
}
.
let
{
sortedWith
(
it
)
}
// ---
/** We don't need to re-query when the app count matches. */
private
fun
queryIfNecessary
()
{
if
(
items
.
size
!=
cache
.
size
)
{
query
()
}
}
private
fun
query
(
query
:
String
=
this
.
query
.
value
,
showSystem
:
Boolean
=
isShowSystem
.
value
)
=
cache
.
toSingle
()
.
flattenAsFlowable
{
it
}
.
parallel
()
.
filter
{
showSystem
||
it
.
item
.
info
.
info
.
flags
and
ApplicationInfo
.
FLAG_SYSTEM
==
0
}
.
filter
{
showSystem
:
Boolean
=
isShowSystem
)
=
items
.
filter
{
fun
filterSystem
():
Boolean
{
return
showSystem
||
it
.
item
.
info
.
info
.
flags
and
ApplicationInfo
.
FLAG_SYSTEM
==
0
}
fun
filterQuery
():
Boolean
{
val
inName
=
it
.
item
.
info
.
name
.
contains
(
query
,
true
)
val
inPackage
=
it
.
item
.
info
.
info
.
packageName
.
contains
(
query
,
true
)
val
inProcesses
=
it
.
item
.
processes
.
any
{
it
.
name
.
contains
(
query
,
true
)
}
inName
||
inPackage
||
inProcesses
return
inName
||
inPackage
||
inProcesses
}
.
sequential
()
.
toList
()
.
map
{
it
to
items
.
calculateDiff
(
it
)
}
.
subscribeK
{
items
.
update
(
it
.
first
,
it
.
second
)
}
.
let
{
queryJob
=
it
}
filterSystem
()
&&
filterQuery
()
}
// ---
private
fun
toggleItem
(
item
:
HideProcessRvItem
)
=
magiskRepo
.
toggleHide
(
item
.
isHidden
.
value
,
item
.
packageName
,
item
.
process
)
fun
menuItemPressed
(
menuItem
:
MenuItem
)
=
when
(
menuItem
.
itemId
)
{
R
.
id
.
action_show_system
->
isShowSystem
=
(!
menuItem
.
isChecked
)
.
also
{
menuItem
.
isChecked
=
it
}
else
->
null
}
?.
let
{
true
}
?:
false
fun
toggleItem
(
item
:
HideProcessItem
)
=
magiskRepo
.
toggleHide
(
item
.
isHidden
.
value
,
item
.
item
.
packageName
,
item
.
item
.
name
)
// might wanna reorder the list to display the item at the top
.
subscribeK
()
.
add
()
}
\ No newline at end of file
}
inline
fun
<
T
:
ComparableRvItem
<
T
>
>
filterableListOf
(
vararg
newItems
:
T
)
=
FilterableDiffObservableList
(
object
:
DiffObservableList
.
Callback
<
T
>
{
override
fun
areItemsTheSame
(
oldItem
:
T
,
newItem
:
T
)
=
oldItem
.
genericItemSameAs
(
newItem
)
override
fun
areContentsTheSame
(
oldItem
:
T
,
newItem
:
T
)
=
oldItem
.
genericContentSameAs
(
newItem
)
}).
also
{
it
.
update
(
newItems
.
toList
())
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt
View file @
6aa22267
...
...
@@ -403,4 +403,9 @@ fun MaterialCardView.setCardElevationBound(elevation: Float) {
@BindingAdapter
(
"strokeWidth"
)
fun
MaterialCardView
.
setCardStrokeWidthBound
(
stroke
:
Float
)
{
strokeWidth
=
stroke
.
roundToInt
()
}
@BindingAdapter
(
"onMenuClick"
)
fun
Toolbar
.
setOnMenuClickListener
(
listener
:
Toolbar
.
OnMenuItemClickListener
)
{
setOnMenuItemClickListener
(
listener
)
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/utils/DiffObservableList.kt
View file @
6aa22267
...
...
@@ -18,9 +18,9 @@ open class DiffObservableList<T>(
)
:
AbstractList
<
T
>(),
ObservableList
<
T
>
{
private
val
LIST_LOCK
=
Object
()
pr
ivate
var
list
:
MutableList
<
T
>
=
ArrayList
()
pr
otected
var
list
:
MutableList
<
T
>
=
ArrayList
()
private
val
listeners
=
ListChangeRegistry
()
pr
ivate
val
listCallback
=
ObservableListUpdateCallback
()
pr
otected
val
listCallback
=
ObservableListUpdateCallback
()
override
val
size
:
Int
get
()
=
list
.
size
...
...
@@ -38,7 +38,7 @@ open class DiffObservableList<T>(
return
doCalculateDiff
(
frozenList
,
newItems
)
}
pr
ivate
fun
doCalculateDiff
(
oldItems
:
List
<
T
>,
newItems
:
List
<
T
>?):
DiffUtil
.
DiffResult
{
pr
otected
fun
doCalculateDiff
(
oldItems
:
List
<
T
>,
newItems
:
List
<
T
>?):
DiffUtil
.
DiffResult
{
return
DiffUtil
.
calculateDiff
(
object
:
DiffUtil
.
Callback
()
{
override
fun
getOldListSize
()
=
oldItems
.
size
...
...
app/src/main/java/com/topjohnwu/magisk/utils/FilterableDiffObservableList.kt
0 → 100644
View file @
6aa22267
package
com.topjohnwu.magisk.utils
import
android.os.Handler
import
android.os.HandlerThread
import
android.os.Looper
import
java.util.*
class
FilterableDiffObservableList
<
T
>(
callback
:
Callback
<
T
>
)
:
DiffObservableList
<
T
>(
callback
)
{
var
filter
:
((
T
)
->
Boolean
)?
=
null
set
(
value
)
{
field
=
value
queueUpdate
()
}
@Volatile
private
var
sublist
:
MutableList
<
T
>
=
super
.
list
// ---
private
val
ui
by
lazy
{
Handler
(
Looper
.
getMainLooper
())
}
private
val
handler
=
Handler
(
HandlerThread
(
"List${hashCode()}"
).
apply
{
start
()
}.
looper
)
private
val
updater
=
Runnable
{
val
filter
=
filter
?:
{
true
}
val
newList
=
super
.
list
.
filter
(
filter
)
val
diff
=
synchronized
(
this
)
{
doCalculateDiff
(
sublist
,
newList
)
}
ui
.
post
{
sublist
=
Collections
.
synchronizedList
(
newList
)
diff
.
dispatchUpdatesTo
(
listCallback
)
}
}
private
fun
queueUpdate
()
{
handler
.
removeCallbacks
(
updater
)
handler
.
post
(
updater
)
}
fun
hasFilter
()
=
filter
!=
null
fun
filter
(
switch
:
(
T
)
->
Boolean
)
{
filter
=
switch
}
fun
reset
()
{
filter
=
null
}
// ---
override
fun
get
(
index
:
Int
):
T
{
return
sublist
.
get
(
index
)
}
override
fun
add
(
element
:
T
):
Boolean
{
return
sublist
.
add
(
element
)
}
override
fun
add
(
index
:
Int
,
element
:
T
)
{
sublist
.
add
(
index
,
element
)
}
override
fun
addAll
(
elements
:
Collection
<
T
>):
Boolean
{
return
sublist
.
addAll
(
elements
)
}
override
fun
addAll
(
index
:
Int
,
elements
:
Collection
<
T
>):
Boolean
{
return
sublist
.
addAll
(
index
,
elements
)
}
override
fun
remove
(
element
:
T
):
Boolean
{
return
sublist
.
remove
(
element
)
}
override
fun
removeAt
(
index
:
Int
):
T
{
return
sublist
.
removeAt
(
index
)
}
override
fun
set
(
index
:
Int
,
element
:
T
):
T
{
return
sublist
.
set
(
index
,
element
)
}
override
val
size
:
Int
get
()
=
sublist
.
size
}
\ No newline at end of file
app/src/main/res/layout/item_hide_md2.xml
View file @
6aa22267
...
...
@@ -59,6 +59,8 @@
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/hide_package"
android:layout_width=
"0dp"
gone=
"@{item.item.info.info.packageName.empty}"
android:text=
"@{item.item.info.info.packageName}"
android:layout_height=
"wrap_content"
android:textAppearance=
"?appearanceTextCaptionVariant"
app:layout_constraintBottom_toBottomOf=
"parent"
...
...
@@ -90,6 +92,8 @@
style=
"?styleToolbar"
onNavigationClick=
"@{(v) -> item.collapse(v)}"
android:layout_width=
"match_parent"
onMenuClick=
"@{(it) -> item.toggle(it, viewModel)}"
app:menu=
"@menu/menu_hide_item"
android:layout_height=
"48dp"
app:navigationIcon=
"@drawable/ic_back_md2"
app:title=
"Processes"
...
...
@@ -100,6 +104,7 @@
items=
"@{item.items}"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
tools:itemCount=
"2"
android:orientation=
"vertical"
app:layoutManager=
"androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem=
"@layout/item_hide_process_md2"
/>
...
...
app/src/main/res/layout/item_hide_process_md2.xml
View file @
6aa22267
...
...
@@ -17,6 +17,8 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:background=
"?selectableItemBackground"
android:onClick=
"@{() -> item.toggle(viewModel)}"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
>
...
...
@@ -41,10 +43,8 @@
style=
"?styleImageSmall"
isSelected=
"@{item.isHidden}"
android:layout_marginTop=
"@dimen/l_50"
android:layout_marginEnd=
"@dimen/l
1
"
android:layout_marginEnd=
"@dimen/l
_75
"
android:layout_marginBottom=
"@dimen/l_50"
android:background=
"?selectableItemBackgroundBorderless"
android:onClick=
"@{() -> item.toggle()}"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
...
...
app/src/main/res/menu/menu_hide_item.xml
0 → 100644
View file @
6aa22267
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
>
<item
android:id=
"@+id/action_toggle"
android:icon=
"@drawable/ic_hide_md2"
android:title=
""
app:showAsAction=
"always"
/>
</menu>
\ No newline at end of file
app/src/main/res/menu/menu_hide_md2.xml
0 → 100644
View file @
6aa22267
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
>
<item
android:id=
"@+id/action_show_system"
android:checkable=
"true"
android:title=
"@string/show_system_app"
app:showAsAction=
"never"
/>
</menu>
\ No newline at end of file
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