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
9094cf7c
Commit
9094cf7c
authored
Jan 12, 2020
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Replace old design with redesign (p2)
parent
df0a5b59
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
51 changed files
with
22 additions
and
4354 deletions
+22
-4354
g.java
app/src/main/java/a/g.java
+2
-2
Hacks.kt
app/src/main/java/com/topjohnwu/magisk/Hacks.kt
+2
-4
ViewModelsModule.kt
...src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt
+0
-12
HideRvItem.kt
.../com/topjohnwu/magisk/model/entity/recycler/HideRvItem.kt
+0
-85
LogRvItem.kt
...a/com/topjohnwu/magisk/model/entity/recycler/LogRvItem.kt
+1
-71
ModuleRvItem.kt
...om/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt
+1
-69
PolicyRvItem.kt
...om/topjohnwu/magisk/model/entity/recycler/PolicyRvItem.kt
+1
-44
RxEvents.kt
...c/main/java/com/topjohnwu/magisk/model/events/RxEvents.kt
+1
-9
Navigation.kt
.../java/com/topjohnwu/magisk/model/navigation/Navigation.kt
+2
-8
HomeViewModel.kt
.../java/com/topjohnwu/magisk/redesign/home/HomeViewModel.kt
+4
-1
SafetynetViewModel.kt
...topjohnwu/magisk/redesign/safetynet/SafetynetViewModel.kt
+6
-2
MainActivity.kt
app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.kt
+0
-252
MainViewModel.kt
app/src/main/java/com/topjohnwu/magisk/ui/MainViewModel.kt
+0
-29
HideViewModel.kt
...c/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt
+0
-96
MagiskHideFragment.kt
...n/java/com/topjohnwu/magisk/ui/hide/MagiskHideFragment.kt
+0
-71
HomeFragment.kt
...rc/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
+0
-132
HomeViewModel.kt
...c/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt
+0
-259
LogFragment.kt
app/src/main/java/com/topjohnwu/magisk/ui/log/LogFragment.kt
+0
-57
LogViewModel.kt
...src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
+0
-120
ModuleViewModel.kt
...in/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt
+0
-111
ModulesFragment.kt
...in/java/com/topjohnwu/magisk/ui/module/ModulesFragment.kt
+0
-99
ReposFragment.kt
...main/java/com/topjohnwu/magisk/ui/module/ReposFragment.kt
+0
-116
SettingsFragment.kt
...java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt
+0
-347
SuperuserFragment.kt
...va/com/topjohnwu/magisk/ui/superuser/SuperuserFragment.kt
+0
-25
SuperuserViewModel.kt
...a/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt
+0
-151
Shortcuts.kt
app/src/main/java/com/topjohnwu/magisk/view/Shortcuts.kt
+0
-13
activity_main.xml
app/src/main/res/layout/activity_main.xml
+0
-38
activity_main_content.xml
app/src/main/res/layout/activity_main_content.xml
+0
-46
custom_channel_dialog.xml
app/src/main/res/layout/custom_channel_dialog.xml
+0
-24
custom_download_dialog.xml
app/src/main/res/layout/custom_download_dialog.xml
+0
-46
dialog_custom_name.xml
app/src/main/res/layout/dialog_custom_name.xml
+0
-46
fragment_home_md2.xml
app/src/main/res/layout/fragment_home_md2.xml
+2
-2
fragment_log.xml
app/src/main/res/layout/fragment_log.xml
+0
-37
fragment_magisk.xml
app/src/main/res/layout/fragment_magisk.xml
+0
-503
fragment_magisk_hide.xml
app/src/main/res/layout/fragment_magisk_hide.xml
+0
-36
fragment_modules.xml
app/src/main/res/layout/fragment_modules.xml
+0
-70
fragment_repos.xml
app/src/main/res/layout/fragment_repos.xml
+0
-56
fragment_superuser.xml
app/src/main/res/layout/fragment_superuser.xml
+0
-53
include_update_card.xml
app/src/main/res/layout/include_update_card.xml
+0
-151
item_hide_app.xml
app/src/main/res/layout/item_hide_app.xml
+0
-126
item_hide_process.xml
app/src/main/res/layout/item_hide_process.xml
+0
-57
item_module.xml
app/src/main/res/layout/item_module.xml
+0
-149
item_page_log.xml
app/src/main/res/layout/item_page_log.xml
+0
-37
item_page_magisk_log.xml
app/src/main/res/layout/item_page_magisk_log.xml
+0
-56
item_policy.xml
app/src/main/res/layout/item_policy.xml
+0
-211
item_repo.xml
app/src/main/res/layout/item_repo.xml
+0
-130
item_superuser_log.xml
app/src/main/res/layout/item_superuser_log.xml
+0
-84
item_superuser_log_entry.xml
app/src/main/res/layout/item_superuser_log_entry.xml
+0
-112
drawer.xml
app/src/main/res/menu/drawer.xml
+0
-59
menu_log.xml
app/src/main/res/menu/menu_log.xml
+0
-24
menu_magiskhide.xml
app/src/main/res/menu/menu_magiskhide.xml
+0
-16
No files found.
app/src/main/java/a/g.java
View file @
9094cf7c
...
...
@@ -2,11 +2,11 @@ package a;
import
android.content.Context
;
import
com.topjohnwu.magisk.model.update.UpdateCheckService
;
import
androidx.annotation.NonNull
;
import
androidx.work.WorkerParameters
;
import
com.topjohnwu.magisk.model.update.UpdateCheckService
;
public
class
g
extends
w
<
UpdateCheckService
>
{
/* Stub */
public
g
(
@NonNull
Context
context
,
@NonNull
WorkerParameters
workerParams
)
{
...
...
app/src/main/java/com/topjohnwu/magisk/Hacks.kt
View file @
9094cf7c
...
...
@@ -18,13 +18,12 @@ import com.topjohnwu.magisk.extensions.forceGetDeclaredField
import
com.topjohnwu.magisk.model.download.DownloadService
import
com.topjohnwu.magisk.model.receiver.GeneralReceiver
import
com.topjohnwu.magisk.model.update.UpdateCheckService
import
com.topjohnwu.magisk.
ui
.MainActivity
import
com.topjohnwu.magisk.
redesign
.MainActivity
import
com.topjohnwu.magisk.ui.SplashActivity
import
com.topjohnwu.magisk.ui.flash.FlashActivity
import
com.topjohnwu.magisk.ui.surequest.SuRequestActivity
import
com.topjohnwu.magisk.utils.refreshLocale
import
com.topjohnwu.magisk.utils.updateConfig
import
com.topjohnwu.magisk.redesign.MainActivity
as
RedesignActivity
fun
AssetManager
.
addAssetPath
(
path
:
String
)
{
DynAPK
.
addAssetPath
(
this
,
path
)
...
...
@@ -150,8 +149,7 @@ object ClassMap {
GeneralReceiver
::
class
.
java
to
a
.
h
::
class
.
java
,
DownloadService
::
class
.
java
to
a
.
j
::
class
.
java
,
SuRequestActivity
::
class
.
java
to
a
.
m
::
class
.
java
,
ProcessPhoenix
::
class
.
java
to
a
.
r
::
class
.
java
,
RedesignActivity
::
class
.
java
to
a
.
b
::
class
.
java
ProcessPhoenix
::
class
.
java
to
a
.
r
::
class
.
java
)
operator
fun
get
(
c
:
Class
<
*
>)
=
map
.
getOrElse
(
c
)
{
c
}
...
...
app/src/main/java/com/topjohnwu/magisk/di/ViewModelsModule.kt
View file @
9094cf7c
package
com.topjohnwu.magisk.di
import
android.net.Uri
import
com.topjohnwu.magisk.ui.MainViewModel
import
com.topjohnwu.magisk.ui.flash.FlashViewModel
import
com.topjohnwu.magisk.ui.hide.HideViewModel
import
com.topjohnwu.magisk.ui.home.HomeViewModel
import
com.topjohnwu.magisk.ui.log.LogViewModel
import
com.topjohnwu.magisk.ui.module.ModuleViewModel
import
com.topjohnwu.magisk.ui.superuser.SuperuserViewModel
import
com.topjohnwu.magisk.ui.surequest.SuRequestViewModel
import
org.koin.androidx.viewmodel.dsl.viewModel
import
org.koin.dsl.module
val
viewModelModules
=
module
{
viewModel
{
MainViewModel
()
}
viewModel
{
HomeViewModel
(
get
())
}
viewModel
{
SuperuserViewModel
(
get
(),
get
(),
get
(),
get
())
}
viewModel
{
HideViewModel
(
get
(),
get
())
}
viewModel
{
ModuleViewModel
(
get
(),
get
(),
get
())
}
viewModel
{
LogViewModel
(
get
(),
get
())
}
viewModel
{
(
action
:
String
,
file
:
Uri
,
additional
:
Uri
)
->
FlashViewModel
(
action
,
file
,
additional
,
get
())
}
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/HideRvItem.kt
View file @
9094cf7c
...
...
@@ -5,20 +5,13 @@ import android.view.ViewGroup
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.startAnimations
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.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.model.observer.Observer
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
import
kotlin.math.roundToInt
class
HideItem
(
val
item
:
ProcessHideApp
)
:
ComparableRvItem
<
HideItem
>()
{
...
...
@@ -86,81 +79,3 @@ class HideProcessItem(val item: StatefulProcess) : ComparableRvItem<HideProcessI
override
fun
itemSameAs
(
other
:
HideProcessItem
)
=
item
.
name
==
other
.
item
.
name
}
class
HideRvItem
(
val
item
:
HideAppInfo
,
targets
:
List
<
HideTarget
>)
:
ComparableRvItem
<
HideRvItem
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
item_hide_app
val
packageName
=
item
.
info
.
packageName
.
orEmpty
()
val
items
=
DiffObservableList
(
callback
).
also
{
val
items
=
item
.
processes
.
map
{
val
isHidden
=
targets
.
any
{
target
->
packageName
==
target
.
packageName
&&
it
==
target
.
process
}
HideProcessRvItem
(
packageName
,
it
,
isHidden
)
}
it
.
update
(
items
)
}
val
isHiddenState
=
KObservableField
(
currentState
)
val
isExpanded
=
KObservableField
(
false
)
private
val
itemsProcess
get
()
=
items
.
filterIsInstance
<
HideProcessRvItem
>()
private
val
currentState
get
()
=
when
(
itemsProcess
.
count
{
it
.
isHidden
.
value
})
{
items
.
size
->
IndeterminateState
.
CHECKED
in
1
until
items
.
size
->
IndeterminateState
.
INDETERMINATE
else
->
IndeterminateState
.
UNCHECKED
}
init
{
itemsProcess
.
forEach
{
it
.
isHidden
.
addOnPropertyChangedCallback
{
isHiddenState
.
value
=
currentState
}
}
}
fun
toggle
()
{
val
desiredState
=
when
(
isHiddenState
.
value
)
{
IndeterminateState
.
INDETERMINATE
,
IndeterminateState
.
UNCHECKED
->
true
IndeterminateState
.
CHECKED
->
false
}
itemsProcess
.
forEach
{
it
.
isHidden
.
value
=
desiredState
}
isHiddenState
.
value
=
currentState
}
fun
toggleExpansion
()
{
if
(
items
.
size
<=
1
)
return
isExpanded
.
toggle
()
}
override
fun
contentSameAs
(
other
:
HideRvItem
):
Boolean
=
items
.
all
{
other
.
items
.
contains
(
it
)
}
override
fun
itemSameAs
(
other
:
HideRvItem
):
Boolean
=
item
.
info
==
other
.
item
.
info
}
class
HideProcessRvItem
(
val
packageName
:
String
,
val
process
:
String
,
isHidden
:
Boolean
)
:
ComparableRvItem
<
HideProcessRvItem
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
item_hide_process
val
isHidden
=
KObservableField
(
isHidden
)
private
val
rxBus
:
RxBus
by
inject
()
init
{
this
.
isHidden
.
addOnPropertyChangedCallback
{
rxBus
.
post
(
HideProcessEvent
(
this
@HideProcessRvItem
))
}
}
fun
toggle
()
=
isHidden
.
toggle
()
override
fun
contentSameAs
(
other
:
HideProcessRvItem
):
Boolean
=
itemSameAs
(
other
)
override
fun
itemSameAs
(
other
:
HideProcessRvItem
):
Boolean
=
packageName
==
other
.
packageName
&&
process
==
other
.
process
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/LogRvItem.kt
View file @
9094cf7c
...
...
@@ -3,79 +3,9 @@ package com.topjohnwu.magisk.model.entity.recycler
import
androidx.databinding.Bindable
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.ComparableRvItem
import
com.topjohnwu.magisk.extensions.timeDateFormat
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
val
items
=
DiffObservableList
(
callback
)
fun
update
(
list
:
List
<
LogItemRvItem
>)
{
list
.
firstOrNull
()
?.
isExpanded
?.
value
=
true
items
.
update
(
list
)
}
//two of these will never be present, safe to assume it's unique
override
fun
contentSameAs
(
other
:
LogRvItem
):
Boolean
=
false
override
fun
itemSameAs
(
other
:
LogRvItem
):
Boolean
=
false
}
class
LogItemRvItem
(
item
:
WrappedMagiskLog
)
:
ComparableRvItem
<
LogItemRvItem
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
item_superuser_log
val
date
=
item
.
time
.
toTime
(
timeFormatMedium
)
val
items
:
List
<
ComparableRvItem
<*>>
=
item
.
items
.
map
{
LogItemEntryRvItem
(
it
)
}
val
isExpanded
=
KObservableField
(
false
)
fun
toggle
()
=
isExpanded
.
toggle
()
override
fun
contentSameAs
(
other
:
LogItemRvItem
):
Boolean
{
if
(
items
.
size
!=
other
.
items
.
size
)
return
false
return
items
.
all
{
it
in
other
.
items
}
}
override
fun
itemSameAs
(
other
:
LogItemRvItem
):
Boolean
=
date
==
other
.
date
}
class
LogItemEntryRvItem
(
val
item
:
MagiskLog
)
:
ComparableRvItem
<
LogItemEntryRvItem
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
item_superuser_log_entry
val
isExpanded
=
KObservableField
(
false
)
fun
toggle
()
=
isExpanded
.
toggle
()
override
fun
contentSameAs
(
other
:
LogItemEntryRvItem
)
=
item
==
other
.
item
override
fun
itemSameAs
(
other
:
LogItemEntryRvItem
)
=
item
.
appName
==
other
.
item
.
appName
}
class
MagiskLogRvItem
:
ComparableRvItem
<
MagiskLogRvItem
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
item_page_magisk_log
val
items
=
DiffObservableList
(
callback
)
fun
update
(
list
:
List
<
ConsoleRvItem
>)
{
items
.
update
(
list
)
}
//two of these will never be present, safe to assume it's unique
override
fun
contentSameAs
(
other
:
MagiskLogRvItem
):
Boolean
=
false
override
fun
itemSameAs
(
other
:
MagiskLogRvItem
):
Boolean
=
false
}
// ---
class
LogItem
(
val
item
:
MagiskLog
)
:
ObservableItem
<
LogItem
>()
{
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt
View file @
9094cf7c
package
com.topjohnwu.magisk.model.entity.recycler
import
android.content.res.Resources
import
androidx.annotation.StringRes
import
androidx.databinding.Bindable
import
androidx.databinding.Observable
import
androidx.databinding.PropertyChangeRegistry
...
...
@@ -10,77 +8,11 @@ import androidx.recyclerview.widget.StaggeredGridLayoutManager
import
com.topjohnwu.magisk.BR
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.redesign.module.ModuleViewModel
import
com.topjohnwu.magisk.utils.KObservableField
class
ModuleRvItem
(
val
item
:
Module
)
:
ComparableRvItem
<
ModuleRvItem
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
item_module
val
lastActionNotice
=
KObservableField
(
""
)
val
isChecked
=
KObservableField
(
item
.
enable
)
val
isDeletable
=
KObservableField
(
item
.
remove
)
init
{
isChecked
.
addOnPropertyChangedCallback
{
when
(
it
)
{
true
->
{
item
.
enable
=
true
notice
(
R
.
string
.
disable_file_removed
)
}
false
->
{
item
.
enable
=
false
notice
(
R
.
string
.
disable_file_created
)
}
}
}
isDeletable
.
addOnPropertyChangedCallback
{
when
(
it
)
{
true
->
{
item
.
remove
=
true
notice
(
R
.
string
.
remove_file_created
)
}
false
->
{
item
.
remove
=
false
notice
(
R
.
string
.
remove_file_deleted
)
}
}
}
when
{
item
.
updated
->
notice
(
R
.
string
.
update_file_created
)
item
.
remove
->
notice
(
R
.
string
.
remove_file_created
)
}
}
fun
toggle
()
=
isChecked
.
toggle
()
fun
toggleDelete
()
=
isDeletable
.
toggle
()
private
fun
notice
(
@StringRes
info
:
Int
)
{
lastActionNotice
.
value
=
get
<
Resources
>().
getString
(
info
)
}
override
fun
contentSameAs
(
other
:
ModuleRvItem
):
Boolean
=
item
.
version
==
other
.
item
.
version
&&
item
.
versionCode
==
other
.
item
.
versionCode
&&
item
.
description
==
other
.
item
.
description
&&
item
.
name
==
other
.
item
.
name
override
fun
itemSameAs
(
other
:
ModuleRvItem
):
Boolean
=
item
.
id
==
other
.
item
.
id
}
class
RepoRvItem
(
val
item
:
Repo
)
:
ComparableRvItem
<
RepoRvItem
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
item_repo
override
fun
contentSameAs
(
other
:
RepoRvItem
):
Boolean
=
item
==
other
.
item
override
fun
itemSameAs
(
other
:
RepoRvItem
):
Boolean
=
item
.
id
==
other
.
item
.
id
}
object
SafeModeNotice
:
ComparableRvItem
<
SafeModeNotice
>()
{
override
val
layoutRes
=
R
.
layout
.
item_safe_mode_notice
...
...
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/PolicyRvItem.kt
View file @
9094cf7c
...
...
@@ -3,54 +3,11 @@ package com.topjohnwu.magisk.model.entity.recycler
import
android.graphics.drawable.Drawable
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.redesign.superuser.SuperuserViewModel
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.RxBus
class
PolicyRvItem
(
val
item
:
MagiskPolicy
,
val
icon
:
Drawable
)
:
ComparableRvItem
<
PolicyRvItem
>()
{
override
val
layoutRes
=
R
.
layout
.
item_policy
val
isExpanded
=
KObservableField
(
false
)
val
isEnabled
=
KObservableField
(
item
.
policy
==
MagiskPolicy
.
ALLOW
)
val
shouldNotify
=
KObservableField
(
item
.
notification
)
val
shouldLog
=
KObservableField
(
item
.
logging
)
fun
toggle
()
=
isExpanded
.
toggle
()
private
val
rxBus
:
RxBus
by
inject
()
private
val
currentStateItem
get
()
=
item
.
copy
(
policy
=
if
(
isEnabled
.
value
)
MagiskPolicy
.
ALLOW
else
MagiskPolicy
.
DENY
,
notification
=
shouldNotify
.
value
,
logging
=
shouldLog
.
value
)
init
{
isEnabled
.
addOnPropertyChangedCallback
{
it
?:
return
@addOnPropertyChangedCallback
rxBus
.
post
(
PolicyEnableEvent
(
this
@PolicyRvItem
,
it
))
}
shouldNotify
.
addOnPropertyChangedCallback
{
it
?:
return
@addOnPropertyChangedCallback
rxBus
.
post
(
PolicyUpdateEvent
.
Notification
(
currentStateItem
))
}
shouldLog
.
addOnPropertyChangedCallback
{
it
?:
return
@addOnPropertyChangedCallback
rxBus
.
post
(
PolicyUpdateEvent
.
Log
(
currentStateItem
))
}
}
override
fun
contentSameAs
(
other
:
PolicyRvItem
):
Boolean
=
itemSameAs
(
other
)
override
fun
itemSameAs
(
other
:
PolicyRvItem
):
Boolean
=
item
.
uid
==
other
.
item
.
uid
}
class
PolicyItem
(
val
item
:
MagiskPolicy
,
val
icon
:
Drawable
)
:
ComparableRvItem
<
PolicyItem
>()
{
override
val
layoutRes
=
R
.
layout
.
item_policy_md2
...
...
app/src/main/java/com/topjohnwu/magisk/model/events/RxEvents.kt
View file @
9094cf7c
package
com.topjohnwu.magisk.model.events
import
com.topjohnwu.magisk.model.entity.MagiskPolicy
import
com.topjohnwu.magisk.model.entity.recycler.HideProcessRvItem
import
com.topjohnwu.magisk.model.entity.recycler.ModuleRvItem
import
com.topjohnwu.magisk.model.entity.recycler.PolicyRvItem
import
com.topjohnwu.magisk.utils.RxBus
class
HideProcessEvent
(
val
item
:
HideProcessRvItem
)
:
RxBus
.
Event
class
PolicyEnableEvent
(
val
item
:
PolicyRvItem
,
val
enable
:
Boolean
)
:
RxBus
.
Event
sealed
class
PolicyUpdateEvent
(
val
item
:
MagiskPolicy
)
:
RxBus
.
Event
{
class
Notification
(
item
:
MagiskPolicy
)
:
PolicyUpdateEvent
(
item
)
class
Log
(
item
:
MagiskPolicy
)
:
PolicyUpdateEvent
(
item
)
}
class
ModuleUpdatedEvent
(
val
item
:
ModuleRvItem
)
:
RxBus
.
Event
data class
SafetyNetResult
(
val
responseCode
:
Int
)
:
RxBus
.
Event
app/src/main/java/com/topjohnwu/magisk/model/navigation/Navigation.kt
View file @
9094cf7c
...
...
@@ -10,12 +10,11 @@ import com.topjohnwu.magisk.redesign.hide.HideFragment
import
com.topjohnwu.magisk.redesign.home.HomeFragment
import
com.topjohnwu.magisk.redesign.install.InstallFragment
import
com.topjohnwu.magisk.redesign.log.LogFragment
import
com.topjohnwu.magisk.redesign.module.ModuleFragment
import
com.topjohnwu.magisk.redesign.safetynet.SafetynetFragment
import
com.topjohnwu.magisk.redesign.settings.SettingsFragment
import
com.topjohnwu.magisk.redesign.superuser.SuperuserFragment
import
com.topjohnwu.magisk.redesign.theme.ThemeFragment
import
com.topjohnwu.magisk.ui.module.ModulesFragment
import
com.topjohnwu.magisk.ui.module.ReposFragment
object
Navigation
{
...
...
@@ -36,14 +35,10 @@ object Navigation {
fun
modules
()
=
MagiskNavigationEvent
{
navDirections
{
destination
=
Module
s
Fragment
::
class
destination
=
ModuleFragment
::
class
}
}
fun
repos
()
=
MagiskNavigationEvent
{
navDirections
{
destination
=
ReposFragment
::
class
}
}
fun
hide
()
=
MagiskNavigationEvent
{
navDirections
{
destination
=
HideFragment
::
class
...
...
@@ -77,7 +72,6 @@ object Navigation {
fun
fromSection
(
section
:
String
)
=
when
(
section
)
{
"superuser"
->
superuser
()
"modules"
->
modules
()
"downloads"
->
repos
()
"magiskhide"
->
hide
()
"log"
->
log
()
"settings"
->
settings
()
...
...
app/src/main/java/com/topjohnwu/magisk/redesign/home/HomeViewModel.kt
View file @
9094cf7c
...
...
@@ -24,12 +24,15 @@ import com.topjohnwu.magisk.model.navigation.Navigation
import
com.topjohnwu.magisk.model.observer.Observer
import
com.topjohnwu.magisk.redesign.compat.CompatViewModel
import
com.topjohnwu.magisk.redesign.compat.itemBindingOf
import
com.topjohnwu.magisk.ui.home.MagiskState
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.superuser.Shell
import
me.tatarka.bindingcollectionadapter2.BR
import
kotlin.math.roundToInt
enum
class
MagiskState
{
NOT_INSTALLED
,
UP_TO_DATE
,
OBSOLETE
,
LOADING
}
class
HomeViewModel
(
private
val
repoMagisk
:
MagiskRepository
)
:
CompatViewModel
()
{
...
...
app/src/main/java/com/topjohnwu/magisk/redesign/safetynet/SafetynetViewModel.kt
View file @
9094cf7c
...
...
@@ -7,11 +7,15 @@ import com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.model.events.SafetyNetResult
import
com.topjohnwu.magisk.model.events.UpdateSafetyNetEvent
import
com.topjohnwu.magisk.redesign.compat.CompatViewModel
import
com.topjohnwu.magisk.
ui.home
.SafetyNetState.*
import
com.topjohnwu.magisk.
redesign.safetynet
.SafetyNetState.*
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.RxBus
import
com.topjohnwu.magisk.utils.SafetyNetHelper
enum
class
SafetyNetState
{
LOADING
,
PASS
,
FAILED
,
IDLE
}
class
SafetynetViewModel
(
rxBus
:
RxBus
)
:
CompatViewModel
()
{
...
...
app/src/main/java/com/topjohnwu/magisk/ui/MainActivity.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui
import
android.content.Intent
import
android.os.Bundle
import
androidx.appcompat.app.AlertDialog
import
androidx.core.view.GravityCompat
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.FragmentTransaction
import
com.ncapdevi.fragnav.FragNavController
import
com.ncapdevi.fragnav.FragNavTransactionOptions
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.Const.Key.OPEN_SECTION
import
com.topjohnwu.magisk.Info
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.BaseActivity
import
com.topjohnwu.magisk.base.BaseFragment
import
com.topjohnwu.magisk.databinding.ActivityMainBinding
import
com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
import
com.topjohnwu.magisk.extensions.snackbar
import
com.topjohnwu.magisk.intent
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.Navigation
import
com.topjohnwu.magisk.model.navigation.Navigator
import
com.topjohnwu.magisk.ui.hide.MagiskHideFragment
import
com.topjohnwu.magisk.ui.home.HomeFragment
import
com.topjohnwu.magisk.ui.log.LogFragment
import
com.topjohnwu.magisk.ui.module.ModulesFragment
import
com.topjohnwu.magisk.ui.module.ReposFragment
import
com.topjohnwu.magisk.ui.settings.SettingsFragment
import
com.topjohnwu.magisk.ui.superuser.SuperuserFragment
import
com.topjohnwu.magisk.utils.Utils
import
org.koin.androidx.viewmodel.ext.android.viewModel
import
timber.log.Timber
import
kotlin.reflect.KClass
open
class
MainActivity
:
BaseActivity
<
MainViewModel
,
ActivityMainBinding
>(),
Navigator
,
FragNavController
.
RootFragmentListener
,
FragNavController
.
TransactionListener
{
override
val
layoutRes
:
Int
=
R
.
layout
.
activity_main
override
val
viewModel
:
MainViewModel
by
viewModel
()
private
val
navHostId
:
Int
=
R
.
id
.
main_nav_host
private
val
defaultPosition
:
Int
=
0
private
val
navigationController
by
lazy
{
FragNavController
(
supportFragmentManager
,
navHostId
)
}
private
val
isRootFragment
get
()
=
navigationController
.
currentStackIndex
!=
defaultPosition
override
val
baseFragments
:
List
<
KClass
<
out
Fragment
>>
=
listOf
(
HomeFragment
::
class
,
SuperuserFragment
::
class
,
MagiskHideFragment
::
class
,
ModulesFragment
::
class
,
ReposFragment
::
class
,
LogFragment
::
class
,
SettingsFragment
::
class
)
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
if
(!
SplashActivity
.
DONE
)
{
startActivity
(
intent
<
SplashActivity
>())
finish
()
}
super
.
onCreate
(
savedInstanceState
)
if
(
Info
.
env
.
isUnsupported
&&
!
viewModel
.
shownUnsupportedDialog
)
{
viewModel
.
shownUnsupportedDialog
=
true
AlertDialog
.
Builder
(
this
)
.
setTitle
(
R
.
string
.
unsupport_magisk_title
)
.
setMessage
(
getString
(
R
.
string
.
unsupport_magisk_msg
,
Const
.
Version
.
MIN_VERSION
))
.
setPositiveButton
(
android
.
R
.
string
.
ok
,
null
)
.
show
()
}
navigationController
.
apply
{
rootFragmentListener
=
this
@MainActivity
transactionListener
=
this
@MainActivity
initialize
(
defaultPosition
,
savedInstanceState
)
}
checkHideSection
()
setSupportActionBar
(
binding
.
mainInclude
.
mainToolbar
)
viewModel
.
isConnected
.
addOnPropertyChangedCallback
{
checkHideSection
()
}
if
(
savedInstanceState
==
null
)
{
intent
.
getStringExtra
(
OPEN_SECTION
)
?.
let
{
onEventDispatched
(
Navigation
.
fromSection
(
it
))
}
}
}
override
fun
onSaveInstanceState
(
outState
:
Bundle
)
{
super
.
onSaveInstanceState
(
outState
)
navigationController
.
onSaveInstanceState
(
outState
)
}
override
fun
setTitle
(
title
:
CharSequence
?)
{
supportActionBar
?.
title
=
title
}
override
fun
setTitle
(
titleId
:
Int
)
{
supportActionBar
?.
setTitle
(
titleId
)
}
override
fun
onBackPressed
()
{
if
(
binding
.
drawerLayout
.
isDrawerOpen
(
binding
.
navView
))
{
binding
.
drawerLayout
.
closeDrawer
(
binding
.
navView
)
}
else
{
val
fragment
=
navigationController
.
currentFrag
as
?
BaseFragment
<*,
*>
if
(
fragment
?.
onBackPressed
()
==
true
)
{
return
}
try
{
navigationController
.
popFragment
()
}
catch
(
e
:
UnsupportedOperationException
)
{
when
{
isRootFragment
->
{
val
options
=
FragNavTransactionOptions
.
newBuilder
()
.
transition
(
FragmentTransaction
.
TRANSIT_FRAGMENT_CLOSE
)
.
build
()
navigationController
.
switchTab
(
defaultPosition
,
options
)
}
else
->
super
.
onBackPressed
()
}
}
}
}
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
)
is
PermissionEvent
->
withPermissions
(*
event
.
permissions
.
toTypedArray
())
{
onSuccess
{
event
.
callback
.
onNext
(
true
)
}
onFailure
{
event
.
callback
.
onNext
(
false
)
event
.
callback
.
onError
(
SecurityException
(
"User refused permissions"
))
}
}
}
}
override
fun
onSimpleEventDispatched
(
event
:
Int
)
{
super
.
onSimpleEventDispatched
(
event
)
when
(
event
)
{
Navigation
.
Main
.
OPEN_NAV
->
openNav
()
}
}
private
fun
openNav
()
=
binding
.
drawerLayout
.
openDrawer
(
GravityCompat
.
START
)
private
fun
checkHideSection
()
{
val
menu
=
binding
.
navView
.
menu
menu
.
findItem
(
R
.
id
.
magiskHideFragment
).
isVisible
=
Info
.
env
.
isActive
&&
Info
.
env
.
magiskHide
menu
.
findItem
(
R
.
id
.
modulesFragment
).
isVisible
=
Info
.
env
.
isActive
menu
.
findItem
(
R
.
id
.
reposFragment
).
isVisible
=
Info
.
isConnected
.
value
&&
Info
.
env
.
isActive
menu
.
findItem
(
R
.
id
.
logFragment
).
isVisible
=
Info
.
env
.
isActive
menu
.
findItem
(
R
.
id
.
superuserFragment
).
isVisible
=
Utils
.
showSuperUser
()
}
private
fun
FragNavTransactionOptions
.
Builder
.
customAnimations
(
options
:
MagiskAnimBuilder
)
=
customAnimations
(
options
.
enter
,
options
.
exit
,
options
.
popEnter
,
options
.
popExit
).
apply
{
if
(!
options
.
anySet
)
{
transition
(
FragmentTransaction
.
TRANSIT_FRAGMENT_OPEN
)
}
}
override
val
numberOfRootFragments
:
Int
get
()
=
baseFragments
.
size
override
fun
getRootFragment
(
index
:
Int
)
=
baseFragments
[
index
].
java
.
newInstance
()
override
fun
onTabTransaction
(
fragment
:
Fragment
?,
index
:
Int
)
{
val
fragmentId
=
when
(
fragment
)
{
is
HomeFragment
->
R
.
id
.
magiskFragment
is
SuperuserFragment
->
R
.
id
.
superuserFragment
is
MagiskHideFragment
->
R
.
id
.
magiskHideFragment
is
ModulesFragment
->
R
.
id
.
modulesFragment
is
ReposFragment
->
R
.
id
.
reposFragment
is
LogFragment
->
R
.
id
.
logFragment
is
SettingsFragment
->
R
.
id
.
settings
else
->
return
}
binding
.
navView
.
setCheckedItem
(
fragmentId
)
}
override
fun
navigateTo
(
event
:
MagiskNavigationEvent
)
{
val
directions
=
event
.
navDirections
navigationController
.
defaultTransactionOptions
=
FragNavTransactionOptions
.
newBuilder
()
.
customAnimations
(
event
.
animOptions
)
.
build
()
navigationController
.
currentStack
?.
indexOfFirst
{
it
.
javaClass
==
event
.
navOptions
.
popUpTo
}
?.
let
{
if
(
it
==
-
1
)
null
else
it
}
// invalidate if class is not found
?.
let
{
if
(
event
.
navOptions
.
inclusive
)
it
+
1
else
it
}
?.
let
{
navigationController
.
popFragments
(
it
)
}
when
(
directions
.
isActivity
)
{
true
->
navigateToActivity
(
event
)
else
->
navigateToFragment
(
event
)
}
}
private
fun
navigateToActivity
(
event
:
MagiskNavigationEvent
)
{
val
destination
=
event
.
navDirections
.
destination
?.
java
?:
let
{
Timber
.
e
(
"Cannot navigate to null destination"
)
return
}
val
options
=
event
.
navOptions
Intent
(
this
,
destination
)
.
putExtras
(
event
.
navDirections
.
args
)
.
apply
{
if
(
options
.
singleTop
)
addFlags
(
Intent
.
FLAG_ACTIVITY_SINGLE_TOP
)
if
(
options
.
clearTask
)
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
)
}
.
let
{
startActivity
(
it
)
}
}
private
fun
navigateToFragment
(
event
:
MagiskNavigationEvent
)
{
val
destination
=
event
.
navDirections
.
destination
?.
java
?:
let
{
Timber
.
e
(
"Cannot navigate to null destination"
)
return
}
when
(
val
index
=
baseFragments
.
indexOfFirst
{
it
.
java
.
name
==
destination
.
name
})
{
-
1
->
destination
.
newInstance
()
.
apply
{
arguments
=
event
.
navDirections
.
args
}
.
let
{
navigationController
.
pushFragment
(
it
)
}
// When it's desired that fragments of same class are put on top of one another edit this
else
->
navigationController
.
switchTab
(
index
)
}
}
override
fun
onFragmentTransaction
(
fragment
:
Fragment
?,
transactionType
:
FragNavController
.
TransactionType
)
=
Unit
}
app/src/main/java/com/topjohnwu/magisk/ui/MainViewModel.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui
import
android.view.MenuItem
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.viewmodel.BaseViewModel
import
com.topjohnwu.magisk.model.navigation.Navigation
class
MainViewModel
:
BaseViewModel
()
{
var
shownUnsupportedDialog
=
false
fun
navPressed
()
=
Navigation
.
Main
.
OPEN_NAV
.
publish
()
fun
navigationItemPressed
(
item
:
MenuItem
):
Boolean
{
when
(
item
.
itemId
)
{
R
.
id
.
magiskFragment
->
Navigation
.
home
()
R
.
id
.
superuserFragment
->
Navigation
.
superuser
()
R
.
id
.
magiskHideFragment
->
Navigation
.
hide
()
R
.
id
.
modulesFragment
->
Navigation
.
modules
()
R
.
id
.
reposFragment
->
Navigation
.
repos
()
R
.
id
.
logFragment
->
Navigation
.
log
()
R
.
id
.
settings
->
Navigation
.
settings
()
else
->
null
}
?.
publish
()
?.
let
{
return
@navigationItemPressed
true
}
return
false
}
}
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.hide
import
android.content.pm.ApplicationInfo
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.base.viewmodel.BaseViewModel
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
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.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.RxBus
import
me.tatarka.bindingcollectionadapter2.OnItemBind
import
timber.log.Timber
class
HideViewModel
(
private
val
magiskRepo
:
MagiskRepository
,
rxBus
:
RxBus
)
:
BaseViewModel
()
{
val
query
=
KObservableField
(
""
)
val
isShowSystem
=
KObservableField
(
false
)
private
val
allItems
=
mutableListOf
<
ComparableRvItem
<*>>()
val
items
=
DiffObservableList
(
ComparableRvItem
.
callback
)
val
itemBinding
=
OnItemBind
<
ComparableRvItem
<*>>
{
itemBinding
,
_
,
item
->
item
.
bind
(
itemBinding
)
itemBinding
.
bindExtra
(
BR
.
viewModel
,
this
@HideViewModel
)
}
init
{
rxBus
.
register
<
HideProcessEvent
>()
.
subscribeK
{
toggleItem
(
it
.
item
)
}
.
add
()
isShowSystem
.
addOnPropertyChangedCallback
{
query
()
}
query
.
addOnPropertyChangedCallback
{
query
()
}
refresh
()
}
fun
refresh
()
{
// fetching this for every item is nonsensical, so we add .cache() so the response is all
// the same for every single mapped item, it only actually executes the whole thing the
// first time around.
val
hideTargets
=
magiskRepo
.
fetchHideTargets
().
cache
()
magiskRepo
.
fetchApps
()
.
flattenAsFlowable
{
it
}
.
map
{
HideRvItem
(
it
,
hideTargets
.
blockingGet
())
}
.
toList
()
.
map
{
it
.
sortedWith
(
compareBy
(
{
it
.
isHiddenState
.
value
},
{
it
.
item
.
name
.
toLowerCase
()
},
{
it
.
packageName
}
))
}
.
doOnSuccess
{
allItems
.
update
(
it
)
}
.
flatMap
{
queryRaw
()
}
.
applyViewModel
(
this
)
.
subscribeK
(
onError
=
Timber
::
e
)
{
items
.
update
(
it
.
first
,
it
.
second
)
}
.
add
()
}
private
fun
query
()
=
queryRaw
()
.
subscribeK
{
items
.
update
(
it
.
first
,
it
.
second
)
}
.
add
()
private
fun
queryRaw
(
showSystem
:
Boolean
=
isShowSystem
.
value
,
query
:
String
=
this
.
query
.
value
)
=
allItems
.
toSingle
()
.
map
{
it
.
filterIsInstance
<
HideRvItem
>()
}
.
flattenAsFlowable
{
it
}
.
filter
{
it
.
item
.
name
.
contains
(
query
,
ignoreCase
=
true
)
||
it
.
item
.
processes
.
any
{
it
.
contains
(
query
,
ignoreCase
=
true
)
}
}
.
filter
{
showSystem
||
(
it
.
isHiddenState
.
value
!=
IndeterminateState
.
UNCHECKED
)
||
(
it
.
item
.
info
.
flags
and
ApplicationInfo
.
FLAG_SYSTEM
==
0
)
}
.
toList
()
.
map
{
it
to
items
.
calculateDiff
(
it
)
}
private
fun
toggleItem
(
item
:
HideProcessRvItem
)
=
magiskRepo
.
toggleHide
(
item
.
isHidden
.
value
,
item
.
packageName
,
item
.
process
)
}
app/src/main/java/com/topjohnwu/magisk/ui/hide/MagiskHideFragment.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.hide
import
android.view.Menu
import
android.view.MenuInflater
import
android.view.MenuItem
import
android.widget.SearchView
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.BaseFragment
import
com.topjohnwu.magisk.databinding.FragmentMagiskHideBinding
import
org.koin.androidx.viewmodel.ext.android.viewModel
class
MagiskHideFragment
:
BaseFragment
<
HideViewModel
,
FragmentMagiskHideBinding
>(),
SearchView
.
OnQueryTextListener
{
override
val
layoutRes
:
Int
=
R
.
layout
.
fragment_magisk_hide
override
val
viewModel
:
HideViewModel
by
viewModel
()
override
fun
onStart
()
{
super
.
onStart
()
setHasOptionsMenu
(
true
)
requireActivity
().
setTitle
(
R
.
string
.
magiskhide
)
}
override
fun
onCreateOptionsMenu
(
menu
:
Menu
,
inflater
:
MenuInflater
)
{
inflater
.
inflate
(
R
.
menu
.
menu_magiskhide
,
menu
)
menu
.
apply
{
val
query
=
viewModel
.
query
.
value
val
searchItem
=
menu
.
findItem
(
R
.
id
.
app_search
)
val
searchView
=
searchItem
.
actionView
as
?
SearchView
searchView
?.
run
{
setOnQueryTextListener
(
this
@MagiskHideFragment
)
setQuery
(
query
,
false
)
}
if
(
query
.
isNotBlank
())
{
searchItem
.
expandActionView
()
searchView
?.
isIconified
=
false
}
else
{
searchItem
.
collapseActionView
()
searchView
?.
isIconified
=
true
}
val
showSystem
=
Config
.
showSystemApp
findItem
(
R
.
id
.
show_system
).
isChecked
=
showSystem
viewModel
.
isShowSystem
.
value
=
showSystem
}
}
override
fun
onOptionsItemSelected
(
item
:
MenuItem
):
Boolean
{
if
(
item
.
itemId
==
R
.
id
.
show_system
)
{
val
showSystem
=
!
item
.
isChecked
item
.
isChecked
=
showSystem
Config
.
showSystemApp
=
showSystem
viewModel
.
isShowSystem
.
value
=
showSystem
}
return
true
}
override
fun
onQueryTextSubmit
(
query
:
String
?):
Boolean
{
viewModel
.
query
.
value
=
query
.
orEmpty
()
return
false
}
override
fun
onQueryTextChange
(
query
:
String
?):
Boolean
{
viewModel
.
query
.
value
=
query
.
orEmpty
()
return
false
}
}
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.home
import
android.content.Context
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.Info
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.BaseActivity
import
com.topjohnwu.magisk.base.BaseFragment
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.databinding.FragmentMagiskBinding
import
com.topjohnwu.magisk.extensions.DynamicClassLoader
import
com.topjohnwu.magisk.extensions.openUrl
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.writeTo
import
com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.utils.SafetyNetHelper
import
com.topjohnwu.magisk.view.MarkDownWindow
import
com.topjohnwu.magisk.view.dialogs.*
import
com.topjohnwu.superuser.Shell
import
dalvik.system.DexFile
import
io.reactivex.Completable
import
org.koin.android.ext.android.inject
import
org.koin.androidx.viewmodel.ext.android.viewModel
import
java.io.File
import
java.lang.reflect.InvocationHandler
class
HomeFragment
:
BaseFragment
<
HomeViewModel
,
FragmentMagiskBinding
>(),
SafetyNetHelper
.
Callback
{
override
val
layoutRes
:
Int
=
R
.
layout
.
fragment_magisk
override
val
viewModel
:
HomeViewModel
by
viewModel
()
private
val
magiskRepo
:
MagiskRepository
by
inject
()
private
val
EXT_APK
by
lazy
{
File
(
"${activity.filesDir.parent}/snet"
,
"snet.jar"
)
}
private
val
EXT_DEX
by
lazy
{
File
(
EXT_APK
.
parent
,
"snet.dex"
)
}
override
fun
onResponse
(
responseCode
:
Int
)
=
viewModel
.
finishSafetyNetCheck
(
responseCode
)
override
fun
onEventDispatched
(
event
:
ViewEvent
)
{
super
.
onEventDispatched
(
event
)
when
(
event
)
{
is
OpenLinkEvent
->
activity
.
openUrl
(
event
.
url
)
is
ManagerInstallEvent
->
installManager
()
is
MagiskInstallEvent
->
installMagisk
()
is
UninstallEvent
->
uninstall
()
is
ManagerChangelogEvent
->
changelogManager
()
is
EnvFixEvent
->
fixEnv
()
is
UpdateSafetyNetEvent
->
updateSafetyNet
(
false
)
}
}
override
fun
onStart
()
{
super
.
onStart
()
setHasOptionsMenu
(
true
)
requireActivity
().
setTitle
(
R
.
string
.
magisk
)
}
private
fun
installMagisk
()
{
// Show Manager update first
if
(
Info
.
remote
.
app
.
versionCode
>
BuildConfig
.
VERSION_CODE
)
{
installManager
()
return
}
MagiskInstallDialog
(
requireActivity
()
as
BaseActivity
<*,
*>).
show
()
}
private
fun
installManager
()
=
ManagerInstallDialog
(
requireActivity
()).
show
()
private
fun
uninstall
()
=
UninstallDialog
(
requireActivity
()).
show
()
private
fun
fixEnv
()
=
EnvFixDialog
(
requireActivity
()).
show
()
private
fun
changelogManager
()
=
MarkDownWindow
.
show
(
requireActivity
(),
null
,
resources
.
openRawResource
(
R
.
raw
.
changelog
))
private
fun
downloadSafetyNet
(
requiresUserInput
:
Boolean
=
true
)
{
fun
download
()
=
magiskRepo
.
fetchSafetynet
()
.
map
{
it
.
byteStream
().
writeTo
(
EXT_APK
)
}
.
subscribeK
{
updateSafetyNet
(
true
)
}
if
(!
requiresUserInput
)
{
download
()
return
}
CustomAlertDialog
(
requireActivity
())
.
setTitle
(
R
.
string
.
proprietary_title
)
.
setMessage
(
R
.
string
.
proprietary_notice
)
.
setCancelable
(
false
)
.
setPositiveButton
(
android
.
R
.
string
.
yes
)
{
_
,
_
->
download
()
}
.
setNegativeButton
(
android
.
R
.
string
.
no
)
{
_
,
_
->
viewModel
.
finishSafetyNetCheck
(-
2
)
}
.
show
()
}
private
fun
updateSafetyNet
(
dieOnError
:
Boolean
)
{
Completable
.
fromAction
{
val
loader
=
DynamicClassLoader
(
EXT_APK
)
val
dex
=
DexFile
.
loadDex
(
EXT_APK
.
path
,
EXT_DEX
.
path
,
0
)
// Scan through the dex and find our helper class
var
helperClass
:
Class
<*>?
=
null
for
(
className
in
dex
.
entries
())
{
if
(
className
.
startsWith
(
"x."
))
{
val
cls
=
loader
.
loadClass
(
className
)
if
(
InvocationHandler
::
class
.
java
.
isAssignableFrom
(
cls
))
{
helperClass
=
cls
break
}
}
}
helperClass
?:
throw
Exception
()
val
helper
=
helperClass
.
getMethod
(
"get"
,
Class
::
class
.
java
,
Context
::
class
.
java
,
Any
::
class
.
java
)
.
invoke
(
null
,
SafetyNetHelper
::
class
.
java
,
activity
,
this
)
as
SafetyNetHelper
if
(
helper
.
version
<
Const
.
SNET_EXT_VER
)
throw
Exception
()
helper
.
attest
()
}.
subscribeK
(
onError
=
{
if
(
dieOnError
)
{
viewModel
.
finishSafetyNetCheck
(-
1
)
}
else
{
Shell
.
sh
(
"rm -rf "
+
EXT_APK
.
parent
).
exec
()
EXT_APK
.
parentFile
?.
mkdir
()
downloadSafetyNet
(!
dieOnError
)
}
})
}
}
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.home
import
android.content.pm.PackageManager
import
com.topjohnwu.magisk.*
import
com.topjohnwu.magisk.base.viewmodel.BaseViewModel
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.extensions.*
import
com.topjohnwu.magisk.model.events.*
import
com.topjohnwu.magisk.model.observer.Observer
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.SafetyNetHelper
import
com.topjohnwu.superuser.Shell
import
io.reactivex.Completable
enum
class
SafetyNetState
{
LOADING
,
PASS
,
FAILED
,
IDLE
}
enum
class
MagiskState
{
NOT_INSTALLED
,
UP_TO_DATE
,
OBSOLETE
,
LOADING
}
enum
class
MagiskItem
{
MANAGER
,
MAGISK
}
class
HomeViewModel
(
private
val
magiskRepo
:
MagiskRepository
)
:
BaseViewModel
(
State
.
LOADED
)
{
val
hasGMS
=
runCatching
{
get
<
PackageManager
>().
getPackageInfo
(
"com.google.android.gms"
,
0
);
true
}.
getOrElse
{
false
}
val
isAdvancedExpanded
=
KObservableField
(
false
)
val
isForceEncryption
=
KObservableField
(
Info
.
keepEnc
)
val
isKeepVerity
=
KObservableField
(
Info
.
keepVerity
)
val
isRecovery
=
KObservableField
(
Info
.
recovery
)
val
magiskState
=
KObservableField
(
MagiskState
.
LOADING
)
val
magiskStateText
=
Observer
(
magiskState
)
{
when
(
magiskState
.
value
)
{
MagiskState
.
NOT_INSTALLED
->
R
.
string
.
magisk_version_error
.
res
()
MagiskState
.
UP_TO_DATE
->
R
.
string
.
magisk_up_to_date
.
res
()
MagiskState
.
LOADING
->
R
.
string
.
checking_for_updates
.
res
()
MagiskState
.
OBSOLETE
->
R
.
string
.
magisk_update_title
.
res
()
}
}
val
magiskCurrentVersion
=
KObservableField
(
""
)
val
magiskLatestVersion
=
KObservableField
(
""
)
val
magiskAdditionalInfo
=
Observer
(
magiskState
)
{
if
(
Config
.
coreOnly
)
R
.
string
.
core_only_enabled
.
res
()
else
""
}
private
val
_managerState
=
KObservableField
(
MagiskState
.
LOADING
)
val
managerState
=
Observer
(
_managerState
,
isConnected
)
{
if
(
isConnected
.
value
)
_managerState
.
value
else
MagiskState
.
UP_TO_DATE
}
val
managerStateText
=
Observer
(
managerState
)
{
when
(
managerState
.
value
)
{
MagiskState
.
NOT_INSTALLED
->
R
.
string
.
invalid_update_channel
.
res
()
MagiskState
.
UP_TO_DATE
->
R
.
string
.
manager_up_to_date
.
res
()
MagiskState
.
LOADING
->
R
.
string
.
checking_for_updates
.
res
()
MagiskState
.
OBSOLETE
->
R
.
string
.
manager_update_title
.
res
()
}
}
val
managerCurrentVersion
=
KObservableField
(
""
)
val
managerLatestVersion
=
KObservableField
(
""
)
val
managerAdditionalInfo
=
Observer
(
managerState
)
{
if
(
packageName
!=
BuildConfig
.
APPLICATION_ID
)
"($packageName)"
else
""
}
val
safetyNetTitle
=
KObservableField
(
R
.
string
.
safetyNet_check_text
.
res
())
val
ctsState
=
KObservableField
(
SafetyNetState
.
IDLE
)
val
basicIntegrityState
=
KObservableField
(
SafetyNetState
.
IDLE
)
val
safetyNetState
=
Observer
(
ctsState
,
basicIntegrityState
)
{
val
cts
=
ctsState
.
value
val
basic
=
basicIntegrityState
.
value
val
states
=
listOf
(
cts
,
basic
)
when
{
states
.
any
{
it
==
SafetyNetState
.
LOADING
}
->
State
.
LOADING
states
.
any
{
it
==
SafetyNetState
.
IDLE
}
->
State
.
LOADING
else
->
State
.
LOADED
}
}
val
isActive
=
KObservableField
(
false
)
private
var
shownDialog
=
false
init
{
isForceEncryption
.
addOnPropertyChangedCallback
{
Info
.
keepEnc
=
it
?:
return
@addOnPropertyChangedCallback
}
isKeepVerity
.
addOnPropertyChangedCallback
{
Info
.
keepVerity
=
it
?:
return
@addOnPropertyChangedCallback
}
isRecovery
.
addOnPropertyChangedCallback
{
Info
.
recovery
=
it
?:
return
@addOnPropertyChangedCallback
}
isConnected
.
addOnPropertyChangedCallback
{
if
(
it
==
true
)
refresh
(
false
)
}
refresh
(
false
)
}
fun
paypalPressed
()
=
OpenLinkEvent
(
Const
.
Url
.
PAYPAL_URL
).
publish
()
fun
patreonPressed
()
=
OpenLinkEvent
(
Const
.
Url
.
PATREON_URL
).
publish
()
fun
twitterPressed
()
=
OpenLinkEvent
(
Const
.
Url
.
TWITTER_URL
).
publish
()
fun
githubPressed
()
=
OpenLinkEvent
(
Const
.
Url
.
SOURCE_CODE_URL
).
publish
()
fun
xdaPressed
()
=
OpenLinkEvent
(
Const
.
Url
.
XDA_THREAD
).
publish
()
fun
uninstallPressed
()
=
UninstallEvent
().
publish
()
fun
advancedPressed
()
=
isAdvancedExpanded
.
toggle
()
fun
installPressed
(
item
:
MagiskItem
)
=
when
(
item
)
{
MagiskItem
.
MANAGER
->
ManagerInstallEvent
().
publish
()
MagiskItem
.
MAGISK
->
MagiskInstallEvent
().
publish
()
}
fun
cardPressed
(
item
:
MagiskItem
)
=
when
(
item
)
{
MagiskItem
.
MANAGER
->
ManagerChangelogEvent
().
publish
()
MagiskItem
.
MAGISK
->
MagiskChangelogEvent
().
publish
()
}
fun
safetyNetPressed
()
{
ctsState
.
value
=
SafetyNetState
.
LOADING
basicIntegrityState
.
value
=
SafetyNetState
.
LOADING
safetyNetTitle
.
value
=
R
.
string
.
checking_safetyNet_status
.
res
()
UpdateSafetyNetEvent
().
publish
()
}
fun
finishSafetyNetCheck
(
response
:
Int
)
=
when
{
response
and
0
x0F
==
0
->
{
val
hasCtsPassed
=
response
and
SafetyNetHelper
.
CTS_PASS
!=
0
val
hasBasicIntegrityPassed
=
response
and
SafetyNetHelper
.
BASIC_PASS
!=
0
safetyNetTitle
.
value
=
R
.
string
.
safetyNet_check_success
.
res
()
ctsState
.
value
=
if
(
hasCtsPassed
)
{
SafetyNetState
.
PASS
}
else
{
SafetyNetState
.
FAILED
}
basicIntegrityState
.
value
=
if
(
hasBasicIntegrityPassed
)
{
SafetyNetState
.
PASS
}
else
{
SafetyNetState
.
FAILED
}
}
response
==
-
2
->
{
ctsState
.
value
=
SafetyNetState
.
IDLE
basicIntegrityState
.
value
=
SafetyNetState
.
IDLE
}
else
->
{
ctsState
.
value
=
SafetyNetState
.
IDLE
basicIntegrityState
.
value
=
SafetyNetState
.
IDLE
safetyNetTitle
.
value
=
when
(
response
)
{
SafetyNetHelper
.
RESPONSE_ERR
->
R
.
string
.
safetyNet_res_invalid
.
res
()
else
->
R
.
string
.
safetyNet_api_error
.
res
()
}
}
}
@JvmOverloads
fun
refresh
(
invalidate
:
Boolean
=
true
)
{
if
(
invalidate
)
Info
.
envRef
.
invalidate
()
isActive
.
value
=
Info
.
env
.
isActive
val
fetchUpdate
=
if
(
isConnected
.
value
)
magiskRepo
.
fetchUpdate
().
ignoreElement
()
else
Completable
.
complete
()
Completable
.
fromAction
{
// Ensure value is ready
Info
.
env
}.
andThen
(
fetchUpdate
)
.
applyViewModel
(
this
)
.
doOnSubscribeUi
{
magiskState
.
value
=
MagiskState
.
LOADING
_managerState
.
value
=
MagiskState
.
LOADING
ctsState
.
value
=
SafetyNetState
.
IDLE
basicIntegrityState
.
value
=
SafetyNetState
.
IDLE
safetyNetTitle
.
value
=
R
.
string
.
safetyNet_check_text
.
res
()
}.
subscribeK
{
updateSelf
()
ensureEnv
()
refreshVersions
()
}
}
private
fun
refreshVersions
()
{
magiskCurrentVersion
.
value
=
if
(
magiskState
.
value
!=
MagiskState
.
NOT_INSTALLED
)
{
VERSION_FMT
.
format
(
Info
.
env
.
magiskVersionString
,
Info
.
env
.
magiskVersionCode
)
}
else
{
""
}
managerCurrentVersion
.
value
=
if
(
isRunningAsStub
)
MGR_VER_FMT
.
format
(
BuildConfig
.
VERSION_NAME
,
BuildConfig
.
VERSION_CODE
,
Info
.
stub
!!
.
version
)
else
VERSION_FMT
.
format
(
BuildConfig
.
VERSION_NAME
,
BuildConfig
.
VERSION_CODE
)
}
private
fun
updateSelf
()
{
magiskState
.
value
=
when
(
Info
.
env
.
magiskVersionCode
)
{
in
Int
.
MIN_VALUE
..
0
->
MagiskState
.
NOT_INSTALLED
in
1
until
Info
.
remote
.
magisk
.
versionCode
->
MagiskState
.
OBSOLETE
else
->
MagiskState
.
UP_TO_DATE
}
magiskLatestVersion
.
value
=
VERSION_FMT
.
format
(
Info
.
remote
.
magisk
.
version
,
Info
.
remote
.
magisk
.
versionCode
)
_managerState
.
value
=
when
(
Info
.
remote
.
app
.
versionCode
)
{
in
Int
.
MIN_VALUE
..
0
->
MagiskState
.
NOT_INSTALLED
//wrong update channel
in
(
BuildConfig
.
VERSION_CODE
+
1
)
..
Int
.
MAX_VALUE
->
MagiskState
.
OBSOLETE
else
->
{
if
(
Info
.
stub
?.
version
?:
Int
.
MAX_VALUE
<
Info
.
remote
.
stub
.
versionCode
)
MagiskState
.
OBSOLETE
else
MagiskState
.
UP_TO_DATE
}
}
managerLatestVersion
.
value
=
MGR_VER_FMT
.
format
(
Info
.
remote
.
app
.
version
,
Info
.
remote
.
app
.
versionCode
,
Info
.
remote
.
stub
.
versionCode
)
}
private
fun
ensureEnv
()
{
val
invalidStates
=
listOf
(
MagiskState
.
NOT_INSTALLED
,
MagiskState
.
LOADING
)
// Don't bother checking env when magisk is not installed, loading or already has been shown
if
(
invalidStates
.
any
{
it
==
magiskState
.
value
}
||
shownDialog
)
return
if
(!
Shell
.
su
(
"env_check"
).
exec
().
isSuccess
)
{
shownDialog
=
true
EnvFixEvent
().
publish
()
}
}
companion
object
{
private
const
val
VERSION_FMT
=
"%s (%d)"
private
const
val
MGR_VER_FMT
=
"%s (%d) (%d)"
}
}
app/src/main/java/com/topjohnwu/magisk/ui/log/LogFragment.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.log
import
android.os.Bundle
import
android.view.Menu
import
android.view.MenuInflater
import
android.view.MenuItem
import
android.view.View
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.BaseFragment
import
com.topjohnwu.magisk.databinding.FragmentLogBinding
import
com.topjohnwu.magisk.model.events.PageChangedEvent
import
com.topjohnwu.magisk.model.events.ViewEvent
import
org.koin.androidx.viewmodel.ext.android.viewModel
class
LogFragment
:
BaseFragment
<
LogViewModel
,
FragmentLogBinding
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
fragment_log
override
val
viewModel
:
LogViewModel
by
viewModel
()
override
fun
onEventDispatched
(
event
:
ViewEvent
)
{
super
.
onEventDispatched
(
event
)
when
(
event
)
{
is
PageChangedEvent
->
activity
.
invalidateOptionsMenu
()
}
}
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
binding
.
logTabs
.
setupWithViewPager
(
binding
.
logContainer
,
true
)
}
override
fun
onStart
()
{
super
.
onStart
()
setHasOptionsMenu
(
true
)
activity
.
setTitle
(
R
.
string
.
log
)
}
override
fun
onCreateOptionsMenu
(
menu
:
Menu
,
inflater
:
MenuInflater
)
{
inflater
.
inflate
(
R
.
menu
.
menu_log
,
menu
)
menu
.
findItem
(
R
.
id
.
menu_save
).
isVisible
=
viewModel
.
currentPage
.
value
==
1
}
override
fun
onOptionsItemSelected
(
item
:
MenuItem
):
Boolean
{
when
(
item
.
itemId
)
{
R
.
id
.
menu_save
->
activity
.
withExternalRW
{
onSuccess
{
viewModel
.
saveLog
()
}
}
R
.
id
.
menu_clear
->
viewModel
.
clearLog
()
R
.
id
.
menu_refresh
->
viewModel
.
refresh
()
}
return
true
}
}
app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.log
import
android.content.res.Resources
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.viewmodel.BaseViewModel
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
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.model.events.SnackbarEvent
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
import
timber.log.Timber
import
java.io.File
import
java.util.*
class
LogViewModel
(
private
val
resources
:
Resources
,
private
val
logRepo
:
LogRepository
)
:
BaseViewModel
(),
BindingViewPagerAdapter
.
PageTitles
<
ComparableRvItem
<*>>
{
val
itemsAdapter
=
BindingAdapter
()
val
items
=
DiffObservableList
(
ComparableRvItem
.
callback
)
val
itemBinding
=
OnItemBind
<
ComparableRvItem
<*>>
{
itemBinding
,
_
,
item
->
item
.
bind
(
itemBinding
)
itemBinding
.
bindExtra
(
BR
.
viewModel
,
this
@LogViewModel
)
}
val
currentPage
=
KObservableField
(
0
)
private
val
currentItem
get
()
=
items
[
currentPage
.
value
]
private
val
logItem
get
()
=
items
[
0
]
as
LogRvItem
private
val
magiskLogItem
get
()
=
items
[
1
]
as
MagiskLogRvItem
val
scrollPosition
=
KObservableField
(
0
)
init
{
currentPage
.
addOnPropertyChangedCallback
{
it
?:
return
@addOnPropertyChangedCallback
PageChangedEvent
().
publish
()
}
items
.
addAll
(
listOf
(
LogRvItem
(),
MagiskLogRvItem
()))
refresh
()
}
override
fun
getPageTitle
(
position
:
Int
,
item
:
ComparableRvItem
<
*
>?)
=
when
(
item
)
{
is
LogRvItem
->
resources
.
getString
(
R
.
string
.
superuser
)
is
MagiskLogRvItem
->
resources
.
getString
(
R
.
string
.
magisk
)
else
->
""
}
fun
scrollDownPressed
()
{
scrollPosition
.
value
=
magiskLogItem
.
items
.
size
-
1
}
fun
refresh
()
{
fetchLogs
().
subscribeK
{
logItem
.
update
(
it
)
}
fetchMagiskLog
().
subscribeK
{
magiskLogItem
.
update
(
it
)
}
}
fun
saveLog
()
{
val
now
=
Calendar
.
getInstance
()
val
filename
=
"magisk_log_%04d%02d%02d_%02d%02d%02d.log"
.
format
(
now
.
get
(
Calendar
.
YEAR
),
now
.
get
(
Calendar
.
MONTH
)
+
1
,
now
.
get
(
Calendar
.
DAY_OF_MONTH
),
now
.
get
(
Calendar
.
HOUR_OF_DAY
),
now
.
get
(
Calendar
.
MINUTE
),
now
.
get
(
Calendar
.
SECOND
)
)
val
logFile
=
File
(
Config
.
downloadDirectory
,
filename
)
runCatching
{
logFile
.
createNewFile
()
}.
onFailure
{
Timber
.
e
(
it
)
return
}
Shell
.
su
(
"cat ${Const.MAGISK_LOG} > $logFile"
).
submit
{
SnackbarEvent
(
logFile
.
path
).
publish
()
}
}
fun
clearLog
()
=
when
(
currentItem
)
{
is
LogRvItem
->
clearLogs
{
refresh
()
}
is
MagiskLogRvItem
->
clearMagiskLogs
{
refresh
()
}
else
->
Unit
}
private
fun
clearLogs
(
callback
:
()
->
Unit
)
=
logRepo
.
clearLogs
()
.
doOnSubscribeUi
(
callback
)
.
subscribeK
{
SnackbarEvent
(
R
.
string
.
logs_cleared
).
publish
()
}
.
add
()
private
fun
clearMagiskLogs
(
callback
:
()
->
Unit
)
=
logRepo
.
clearMagiskLogs
()
.
doOnComplete
(
callback
)
.
subscribeK
{
SnackbarEvent
(
R
.
string
.
logs_cleared
).
publish
()
}
.
add
()
private
fun
fetchLogs
()
=
logRepo
.
fetchLogs
()
.
flattenAsFlowable
{
it
}
.
map
{
LogItemRvItem
(
it
)
}
.
toList
()
private
fun
fetchMagiskLog
()
=
logRepo
.
fetchMagiskLogs
()
.
map
{
ConsoleRvItem
(
it
)
}
.
toList
()
}
app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.module
import
android.content.res.Resources
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.viewmodel.BaseViewModel
import
com.topjohnwu.magisk.data.database.RepoDao
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
import
com.topjohnwu.magisk.model.entity.recycler.SectionRvItem
import
com.topjohnwu.magisk.model.events.InstallModuleEvent
import
com.topjohnwu.magisk.model.events.OpenChangelogEvent
import
com.topjohnwu.magisk.model.events.OpenFilePickerEvent
import
com.topjohnwu.magisk.tasks.RepoUpdater
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
class
ModuleViewModel
(
private
val
resources
:
Resources
,
private
val
repoUpdater
:
RepoUpdater
,
private
val
repoDB
:
RepoDao
)
:
BaseViewModel
()
{
val
query
=
KObservableField
(
""
)
private
val
allItems
=
mutableListOf
<
ComparableRvItem
<*>>()
val
itemsInstalled
=
DiffObservableList
(
ComparableRvItem
.
callback
)
val
itemsRemote
=
DiffObservableList
(
ComparableRvItem
.
callback
)
val
itemBinding
=
OnItemBind
<
ComparableRvItem
<*>>
{
itemBinding
,
_
,
item
->
item
.
bind
(
itemBinding
)
itemBinding
.
bindExtra
(
BR
.
viewModel
,
this
@ModuleViewModel
)
}
private
var
queryDisposable
:
Disposable
?
=
null
init
{
query
.
addOnPropertyChangedCallback
{
queryDisposable
?.
dispose
()
queryDisposable
=
query
()
}
refresh
(
false
)
}
fun
fabPressed
()
=
OpenFilePickerEvent
().
publish
()
fun
repoPressed
(
item
:
RepoRvItem
)
=
OpenChangelogEvent
(
item
.
item
).
publish
()
fun
downloadPressed
(
item
:
RepoRvItem
)
=
InstallModuleEvent
(
item
.
item
).
publish
()
fun
refresh
(
force
:
Boolean
)
{
Single
.
fromCallable
{
Module
.
loadModules
()
}
.
flattenAsFlowable
{
it
}
.
map
{
ModuleRvItem
(
it
)
}
.
toList
()
.
map
{
it
to
itemsInstalled
.
calculateDiff
(
it
)
}
.
doOnSuccessUi
{
itemsInstalled
.
update
(
it
.
first
,
it
.
second
)
}
.
flatMap
{
repoUpdater
(
force
)
}
.
flattenAsFlowable
{
repoDB
.
repos
}
.
map
{
RepoRvItem
(
it
)
}
.
toList
()
.
doOnSuccess
{
allItems
.
update
(
it
)
}
.
flatMap
{
queryRaw
()
}
.
applyViewModel
(
this
)
.
subscribeK
{
itemsRemote
.
update
(
it
.
first
,
it
.
second
)
}
}
private
fun
query
()
=
queryRaw
()
.
subscribeK
{
itemsRemote
.
update
(
it
.
first
,
it
.
second
)
}
private
fun
queryRaw
(
query
:
String
=
this
.
query
.
value
)
=
allItems
.
toSingle
()
.
map
{
it
.
filterIsInstance
<
RepoRvItem
>()
}
.
flattenAsFlowable
{
it
}
.
filter
{
it
.
item
.
name
.
contains
(
query
,
ignoreCase
=
true
)
||
it
.
item
.
author
.
contains
(
query
,
ignoreCase
=
true
)
||
it
.
item
.
description
.
contains
(
query
,
ignoreCase
=
true
)
}
.
toList
()
.
map
{
if
(
query
.
isEmpty
())
it
.
divide
()
else
it
}
.
map
{
it
to
itemsRemote
.
calculateDiff
(
it
)
}
private
fun
List
<
RepoRvItem
>.
divide
():
List
<
ComparableRvItem
<*
>>
{
val
installed
=
itemsInstalled
.
filterIsInstance
<
ModuleRvItem
>()
fun
<
T
:
ComparableRvItem
<*
>
>
List
<
T
>.
withTitle
(
text
:
Int
)
=
if
(
isEmpty
())
this
else
listOf
(
SectionRvItem
(
resources
.
getString
(
text
)))
+
this
val
groupedItems
=
groupBy
{
repo
->
installed
.
firstOrNull
{
it
.
item
.
id
==
repo
.
item
.
id
}
?.
let
{
if
(
it
.
item
.
versionCode
<
repo
.
item
.
versionCode
)
MODULE_UPDATABLE
else
MODULE_INSTALLED
}
?:
MODULE_REMOTE
}
return
groupedItems
.
getOrElse
(
MODULE_UPDATABLE
)
{
listOf
()
}.
withTitle
(
R
.
string
.
update_available
)
+
groupedItems
.
getOrElse
(
MODULE_INSTALLED
)
{
listOf
()
}.
withTitle
(
R
.
string
.
installed
)
+
groupedItems
.
getOrElse
(
MODULE_REMOTE
)
{
listOf
()
}.
withTitle
(
R
.
string
.
not_installed
)
}
companion
object
{
protected
const
val
MODULE_INSTALLED
=
0
protected
const
val
MODULE_REMOTE
=
1
protected
const
val
MODULE_UPDATABLE
=
2
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/ui/module/ModulesFragment.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.module
import
android.app.Activity
import
android.content.Intent
import
android.os.Bundle
import
android.view.Menu
import
android.view.MenuInflater
import
android.view.MenuItem
import
android.view.View
import
androidx.recyclerview.widget.RecyclerView
import
com.topjohnwu.magisk.Const
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.BaseFragment
import
com.topjohnwu.magisk.databinding.FragmentModulesBinding
import
com.topjohnwu.magisk.extensions.reboot
import
com.topjohnwu.magisk.intent
import
com.topjohnwu.magisk.model.events.OpenFilePickerEvent
import
com.topjohnwu.magisk.model.events.ViewEvent
import
com.topjohnwu.magisk.ui.flash.FlashActivity
import
com.topjohnwu.superuser.Shell
import
org.koin.androidx.viewmodel.ext.android.sharedViewModel
class
ModulesFragment
:
BaseFragment
<
ModuleViewModel
,
FragmentModulesBinding
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
fragment_modules
override
val
viewModel
:
ModuleViewModel
by
sharedViewModel
()
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
if
(
requestCode
==
Const
.
ID
.
FETCH_ZIP
&&
resultCode
==
Activity
.
RESULT_OK
&&
data
!=
null
)
{
// Get the URI of the selected file
val
intent
=
activity
.
intent
<
FlashActivity
>()
intent
.
setData
(
data
.
data
).
putExtra
(
Const
.
Key
.
FLASH_ACTION
,
Const
.
Value
.
FLASH_ZIP
)
startActivity
(
intent
)
}
}
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
binding
.
modulesContent
.
addOnScrollListener
(
object
:
RecyclerView
.
OnScrollListener
()
{
override
fun
onScrolled
(
recyclerView
:
RecyclerView
,
dx
:
Int
,
dy
:
Int
)
{
binding
.
modulesRefreshLayout
.
isEnabled
=
recyclerView
.
getChildAt
(
0
).
top
>=
0
}
})
}
override
fun
onEventDispatched
(
event
:
ViewEvent
)
{
super
.
onEventDispatched
(
event
)
when
(
event
)
{
is
OpenFilePickerEvent
->
selectFile
()
}
}
override
fun
onStart
()
{
super
.
onStart
()
setHasOptionsMenu
(
true
)
requireActivity
().
setTitle
(
R
.
string
.
modules
)
}
override
fun
onCreateOptionsMenu
(
menu
:
Menu
,
inflater
:
MenuInflater
)
{
inflater
.
inflate
(
R
.
menu
.
menu_reboot
,
menu
)
}
override
fun
onOptionsItemSelected
(
item
:
MenuItem
):
Boolean
{
when
(
item
.
itemId
)
{
R
.
id
.
reboot
->
{
reboot
()
return
true
}
R
.
id
.
reboot_recovery
->
{
Shell
.
su
(
"/system/bin/reboot recovery"
).
submit
()
return
true
}
R
.
id
.
reboot_bootloader
->
{
reboot
(
"bootloader"
)
return
true
}
R
.
id
.
reboot_download
->
{
reboot
(
"download"
)
return
true
}
R
.
id
.
reboot_edl
->
{
reboot
(
"edl"
)
return
true
}
else
->
return
false
}
}
private
fun
selectFile
()
{
activity
.
withExternalRW
{
onSuccess
{
val
intent
=
Intent
(
Intent
.
ACTION_GET_CONTENT
)
intent
.
type
=
"application/zip"
startActivityForResult
(
intent
,
Const
.
ID
.
FETCH_ZIP
)
}
}
}
}
app/src/main/java/com/topjohnwu/magisk/ui/module/ReposFragment.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.module
import
android.annotation.SuppressLint
import
android.app.AlertDialog
import
android.view.Menu
import
android.view.MenuInflater
import
android.view.MenuItem
import
android.widget.SearchView
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.BaseFragment
import
com.topjohnwu.magisk.databinding.FragmentReposBinding
import
com.topjohnwu.magisk.model.download.DownloadService
import
com.topjohnwu.magisk.model.entity.internal.Configuration
import
com.topjohnwu.magisk.model.entity.internal.DownloadSubject
import
com.topjohnwu.magisk.model.entity.module.Repo
import
com.topjohnwu.magisk.model.events.InstallModuleEvent
import
com.topjohnwu.magisk.model.events.OpenChangelogEvent
import
com.topjohnwu.magisk.model.events.ViewEvent
import
com.topjohnwu.magisk.view.MarkDownWindow
import
com.topjohnwu.magisk.view.dialogs.CustomAlertDialog
import
org.koin.androidx.viewmodel.ext.android.sharedViewModel
class
ReposFragment
:
BaseFragment
<
ModuleViewModel
,
FragmentReposBinding
>(),
SearchView
.
OnQueryTextListener
{
override
val
layoutRes
:
Int
=
R
.
layout
.
fragment_repos
override
val
viewModel
:
ModuleViewModel
by
sharedViewModel
()
override
fun
onStart
()
{
super
.
onStart
()
setHasOptionsMenu
(
true
)
requireActivity
().
setTitle
(
R
.
string
.
downloads
)
}
override
fun
onEventDispatched
(
event
:
ViewEvent
)
{
super
.
onEventDispatched
(
event
)
when
(
event
)
{
is
OpenChangelogEvent
->
openChangelog
(
event
.
item
)
is
InstallModuleEvent
->
installModule
(
event
.
item
)
}
}
override
fun
onCreateOptionsMenu
(
menu
:
Menu
,
inflater
:
MenuInflater
)
{
inflater
.
inflate
(
R
.
menu
.
menu_repo
,
menu
)
val
query
=
viewModel
.
query
.
value
val
searchItem
=
menu
.
findItem
(
R
.
id
.
repo_search
)
val
searchView
=
searchItem
.
actionView
as
?
SearchView
searchView
?.
run
{
setOnQueryTextListener
(
this
@ReposFragment
)
setQuery
(
query
,
false
)
}
if
(
query
.
isNotBlank
())
{
searchItem
.
expandActionView
()
searchView
?.
isIconified
=
false
}
else
{
searchItem
.
collapseActionView
()
searchView
?.
isIconified
=
true
}
}
override
fun
onOptionsItemSelected
(
item
:
MenuItem
):
Boolean
{
if
(
item
.
itemId
==
R
.
id
.
repo_sort
)
{
AlertDialog
.
Builder
(
activity
)
.
setTitle
(
R
.
string
.
sorting_order
)
.
setSingleChoiceItems
(
R
.
array
.
sorting_orders
,
Config
.
repoOrder
)
{
d
,
which
->
Config
.
repoOrder
=
which
viewModel
.
refresh
(
false
)
d
.
dismiss
()
}.
show
()
}
return
true
}
override
fun
onQueryTextSubmit
(
p0
:
String
?):
Boolean
{
viewModel
.
query
.
value
=
p0
.
orEmpty
()
return
false
}
override
fun
onQueryTextChange
(
p0
:
String
?):
Boolean
{
viewModel
.
query
.
value
=
p0
.
orEmpty
()
return
false
}
private
fun
openChangelog
(
item
:
Repo
)
{
MarkDownWindow
.
show
(
requireActivity
(),
null
,
item
.
readme
)
}
@SuppressLint
(
"MissingPermission"
)
private
fun
installModule
(
item
:
Repo
)
{
val
context
=
activity
fun
download
(
install
:
Boolean
)
=
context
.
withExternalRW
{
onSuccess
{
DownloadService
(
context
)
{
val
config
=
if
(
install
)
Configuration
.
Flash
.
Primary
else
Configuration
.
Download
subject
=
DownloadSubject
.
Module
(
item
,
config
)
}
}
}
CustomAlertDialog
(
context
)
.
setTitle
(
context
.
getString
(
R
.
string
.
repo_install_title
,
item
.
name
))
.
setMessage
(
context
.
getString
(
R
.
string
.
repo_install_msg
,
item
.
downloadFilename
))
.
setCancelable
(
true
)
.
setPositiveButton
(
R
.
string
.
install
)
{
_
,
_
->
download
(
true
)
}
.
setNeutralButton
(
R
.
string
.
download
)
{
_
,
_
->
download
(
false
)
}
.
show
()
}
}
app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt
deleted
100644 → 0
View file @
df0a5b59
This diff is collapsed.
Click to expand it.
app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserFragment.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.superuser
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.BaseFragment
import
com.topjohnwu.magisk.databinding.FragmentSuperuserBinding
import
org.koin.androidx.viewmodel.ext.android.viewModel
class
SuperuserFragment
:
BaseFragment
<
SuperuserViewModel
,
FragmentSuperuserBinding
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
fragment_superuser
override
val
viewModel
:
SuperuserViewModel
by
viewModel
()
override
fun
onStart
()
{
super
.
onStart
()
setHasOptionsMenu
(
true
)
requireActivity
().
setTitle
(
R
.
string
.
superuser
)
}
override
fun
onResume
()
{
super
.
onResume
()
viewModel
.
updatePolicies
()
}
}
app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt
deleted
100644 → 0
View file @
df0a5b59
package
com.topjohnwu.magisk.ui.superuser
import
android.content.pm.PackageManager
import
android.content.res.Resources
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.base.viewmodel.BaseViewModel
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.model.events.SnackbarEvent
import
com.topjohnwu.magisk.utils.BiometricHelper
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.RxBus
import
com.topjohnwu.magisk.view.dialogs.CustomAlertDialog
import
io.reactivex.Single
import
io.reactivex.disposables.Disposable
import
me.tatarka.bindingcollectionadapter2.ItemBinding
class
SuperuserViewModel
(
private
val
policyDB
:
PolicyDao
,
private
val
packageManager
:
PackageManager
,
private
val
resources
:
Resources
,
rxBus
:
RxBus
)
:
BaseViewModel
()
{
val
items
=
DiffObservableList
(
ComparableRvItem
.
callback
)
val
itemBinding
=
ItemBinding
.
of
<
ComparableRvItem
<*>>
{
itemBinding
,
_
,
item
->
item
.
bind
(
itemBinding
)
itemBinding
.
bindExtra
(
BR
.
viewModel
,
this
@SuperuserViewModel
)
}
private
var
ignoreNext
:
PolicyRvItem
?
=
null
private
var
fetchTask
:
Disposable
?
=
null
init
{
rxBus
.
register
<
PolicyEnableEvent
>()
.
filter
{
val
isIgnored
=
it
.
item
==
ignoreNext
if
(
isIgnored
)
ignoreNext
=
null
!
isIgnored
}
.
subscribeK
{
togglePolicy
(
it
.
item
,
it
.
enable
)
}
.
add
()
rxBus
.
register
<
PolicyUpdateEvent
>()
.
subscribeK
{
updatePolicy
(
it
)
}
.
add
()
updatePolicies
()
}
fun
updatePolicies
()
{
if
(
fetchTask
?.
isDisposed
?.
not
()
==
true
)
return
fetchTask
=
policyDB
.
fetchAll
()
.
flattenAsFlowable
{
it
}
.
map
{
PolicyRvItem
(
it
,
it
.
applicationInfo
.
loadIcon
(
packageManager
))
}
.
toList
()
.
map
{
it
.
sortedWith
(
compareBy
(
{
it
.
item
.
appName
.
toLowerCase
()
},
{
it
.
item
.
packageName
}
))
}
.
map
{
it
to
items
.
calculateDiff
(
it
)
}
.
applySchedulers
()
.
applyViewModel
(
this
)
.
subscribeK
{
items
.
update
(
it
.
first
,
it
.
second
)
}
}
fun
deletePressed
(
item
:
PolicyRvItem
)
{
fun
updateState
()
=
deletePolicy
(
item
.
item
)
.
map
{
items
.
filterIsInstance
<
PolicyRvItem
>().
toMutableList
()
}
.
map
{
it
.
removeAll
{
it
.
item
.
packageName
==
item
.
item
.
packageName
};
it
}
.
map
{
it
to
items
.
calculateDiff
(
it
)
}
.
subscribeK
{
items
.
update
(
it
.
first
,
it
.
second
)
}
.
add
()
withView
{
if
(
BiometricHelper
.
isEnabled
)
{
BiometricHelper
.
authenticate
(
this
)
{
updateState
()
}
}
else
{
CustomAlertDialog
(
this
)
.
setTitle
(
R
.
string
.
su_revoke_title
)
.
setMessage
(
getString
(
R
.
string
.
su_revoke_msg
,
item
.
item
.
appName
))
.
setPositiveButton
(
android
.
R
.
string
.
yes
)
{
_
,
_
->
updateState
()
}
.
setNegativeButton
(
android
.
R
.
string
.
no
,
null
)
.
setCancelable
(
true
)
.
show
()
}
}
}
private
fun
updatePolicy
(
it
:
PolicyUpdateEvent
)
=
when
(
it
)
{
is
PolicyUpdateEvent
.
Notification
->
updatePolicy
(
it
.
item
)
{
val
textId
=
if
(
it
.
notification
)
R
.
string
.
su_snack_notif_on
else
R
.
string
.
su_snack_notif_off
val
text
=
resources
.
getString
(
textId
).
format
(
it
.
appName
)
SnackbarEvent
(
text
).
publish
()
}
is
PolicyUpdateEvent
.
Log
->
updatePolicy
(
it
.
item
)
{
val
textId
=
if
(
it
.
logging
)
R
.
string
.
su_snack_log_on
else
R
.
string
.
su_snack_log_off
val
text
=
resources
.
getString
(
textId
).
format
(
it
.
appName
)
SnackbarEvent
(
text
).
publish
()
}
}
private
fun
updatePolicy
(
item
:
MagiskPolicy
,
onSuccess
:
(
MagiskPolicy
)
->
Unit
)
=
updatePolicy
(
item
)
.
subscribeK
{
onSuccess
(
it
)
}
.
add
()
private
fun
togglePolicy
(
item
:
PolicyRvItem
,
enable
:
Boolean
)
{
fun
updateState
()
{
val
app
=
item
.
item
.
copy
(
policy
=
if
(
enable
)
MagiskPolicy
.
ALLOW
else
MagiskPolicy
.
DENY
)
updatePolicy
(
app
)
.
map
{
it
.
policy
==
MagiskPolicy
.
ALLOW
}
.
subscribeK
{
val
textId
=
if
(
it
)
R
.
string
.
su_snack_grant
else
R
.
string
.
su_snack_deny
val
text
=
resources
.
getString
(
textId
).
format
(
item
.
item
.
appName
)
SnackbarEvent
(
text
).
publish
()
}
.
add
()
}
if
(
BiometricHelper
.
isEnabled
)
{
withView
{
BiometricHelper
.
authenticate
(
this
,
onError
=
{
ignoreNext
=
item
item
.
isEnabled
.
toggle
()
})
{
updateState
()
}
}
}
else
{
updateState
()
}
}
private
fun
updatePolicy
(
policy
:
MagiskPolicy
)
=
policyDB
.
update
(
policy
).
andThen
(
Single
.
just
(
policy
))
private
fun
deletePolicy
(
policy
:
MagiskPolicy
)
=
policyDB
.
delete
(
policy
.
uid
).
andThen
(
Single
.
just
(
policy
))
}
app/src/main/java/com/topjohnwu/magisk/view/Shortcuts.kt
View file @
9094cf7c
...
...
@@ -77,19 +77,6 @@ object Shortcuts {
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
)
)
.
setIcon
(
getIcon
(
R
.
drawable
.
sc_extension
))
.
setRank
(
3
)
.
build
()
)
shortCuts
.
add
(
ShortcutInfo
.
Builder
(
context
,
"downloads"
)
.
setShortLabel
(
context
.
getString
(
R
.
string
.
downloads
))
.
setIntent
(
Intent
(
intent
)
.
putExtra
(
Const
.
Key
.
OPEN_SECTION
,
"downloads"
)
.
setAction
(
Intent
.
ACTION_VIEW
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
)
)
.
setIcon
(
getIcon
(
R
.
drawable
.
sc_cloud_download
))
.
setRank
(
2
)
.
build
()
)
...
...
app/src/main/res/layout/activity_main.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.MainViewModel"
/>
</data>
<androidx.drawerlayout.widget.DrawerLayout
android:id=
"@+id/drawer_layout"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:fitsSystemWindows=
"true"
tools:openDrawer=
"start"
>
<include
android:id=
"@+id/main_include"
layout=
"@layout/activity_main_content"
viewModel=
"@{viewModel}"
/>
<com.google.android.material.navigation.NavigationView
android:id=
"@+id/nav_view"
android:layout_width=
"wrap_content"
android:layout_height=
"match_parent"
android:layout_gravity=
"start"
android:fitsSystemWindows=
"true"
onNavigationClick=
"@{(item) -> viewModel.navigationItemPressed(item)}"
app:menu=
"@menu/drawer"
/>
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
app/src/main/res/layout/activity_main_content.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
>
<data>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.MainViewModel"
/>
</data>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<com.google.android.material.appbar.AppBarLayout
android:layout_width=
"match_parent"
app:elevation=
"0dp"
android:layout_height=
"wrap_content"
>
<androidx.appcompat.widget.Toolbar
android:id=
"@+id/main_toolbar"
onNavigationClick=
"@{() -> viewModel.navPressed()}"
android:layout_width=
"match_parent"
android:layout_height=
"?attr/actionBarSize"
android:background=
"@color/primary"
app:navigationIcon=
"@drawable/ic_menu"
app:title=
"@string/magisk"
app:titleTextColor=
"@android:color/white"
/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id=
"@+id/main_nav_host"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"?android:windowBackground"
app:layout_behavior=
"@string/appbar_scrolling_view_behavior"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>
app/src/main/res/layout/custom_channel_dialog.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
android:padding=
"@dimen/margin_generic"
>
<com.google.android.material.textfield.TextInputLayout
style=
"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:hint=
"@string/settings_update_custom_msg"
app:hintEnabled=
"true"
>
<com.google.android.material.textfield.TextInputEditText
android:id=
"@+id/custom_url"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:inputType=
"textUri"
/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
\ No newline at end of file
app/src/main/res/layout/custom_download_dialog.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"data"
type=
"com.topjohnwu.magisk.ui.settings.SettingsFragment.DownloadDialogData"
/>
</data>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
android:padding=
"@dimen/margin_generic"
>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/dialog_custom_download_title"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:text=
"@{@string/settings_download_path_message(data.path)}"
tools:text=
"@string/settings_download_path_message"
/>
<com.google.android.material.textfield.TextInputLayout
style=
"@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"@dimen/margin_generic"
android:hint=
"@string/settings_download_path_title"
app:hintEnabled=
"true"
>
<com.google.android.material.textfield.TextInputEditText
android:id=
"@+id/dialog_custom_download_text"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:inputType=
"textUri"
android:text=
"@={data.text}"
/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</layout>
app/src/main/res/layout/dialog_custom_name.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<import
type=
"com.topjohnwu.magisk.extensions.XStringKt"
/>
<variable
name=
"data"
type=
"com.topjohnwu.magisk.ui.settings.SettingsFragment.ManagerNameData"
/>
</data>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:clipToPadding=
"false"
android:orientation=
"vertical"
android:paddingStart=
"@dimen/margin_generic"
android:paddingTop=
"@dimen/margin_generic"
android:paddingEnd=
"@dimen/margin_generic"
>
<com.google.android.material.textfield.TextInputLayout
android:id=
"@+id/dialog_name_input"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:hint=
"@string/settings_app_name_hint"
app:counterEnabled=
"true"
app:counterMaxLength=
"14"
app:counterOverflowTextColor=
"@color/colorError"
app:error=
"@{data.name.length() > 14 || data.name.empty || XStringKt.isEmptyInternal(data.name) ? @string/settings_app_name_error : @string/empty}"
app:errorEnabled=
"true"
app:helperText=
"@string/settings_app_name_helper"
>
<com.google.android.material.textfield.TextInputEditText
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:text=
"@={data.name}"
tools:text=
"@string/re_app_name"
/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</layout>
\ No newline at end of file
app/src/main/res/layout/fragment_home_md2.xml
View file @
9094cf7c
...
...
@@ -17,7 +17,7 @@
<import
type=
"com.topjohnwu.magisk.BuildConfig"
/>
<import
type=
"com.topjohnwu.magisk.
ui
.home.MagiskState"
/>
<import
type=
"com.topjohnwu.magisk.
redesign
.home.MagiskState"
/>
<import
type=
"com.topjohnwu.magisk.extensions.XAndroidKt"
/>
...
...
app/src/main/res/layout/fragment_log.xml
deleted
100644 → 0
View file @
df0a5b59
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
>
<data>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.log.LogViewModel"
/>
</data>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<com.google.android.material.tabs.TabLayout
android:id=
"@+id/log_tabs"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"?attr/colorPrimary"
app:elevation=
"4dp"
app:tabSelectedTextColor=
"@android:color/white"
app:tabTextColor=
"@android:color/secondary_text_dark"
/>
<androidx.viewpager.widget.ViewPager
android:id=
"@+id/log_container"
itemBinding=
"@{viewModel.itemBinding}"
items=
"@{viewModel.items}"
pageTitles=
"@{viewModel}"
position=
"@={viewModel.currentPage}"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
</LinearLayout>
</layout>
\ No newline at end of file
app/src/main/res/layout/fragment_magisk.xml
deleted
100644 → 0
View file @
df0a5b59
This diff is collapsed.
Click to expand it.
app/src/main/res/layout/fragment_magisk_hide.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.hide.HideViewModel"
/>
</data>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
app:onRefreshListener=
"@{() -> viewModel.refresh()}"
app:refreshing=
"@{viewModel.loading}"
>
<androidx.recyclerview.widget.RecyclerView
dividerColor=
"@{@android:color/transparent}"
dividerSize=
"@{@dimen/margin_generic}"
itemBinding=
"@{viewModel.itemBinding}"
items=
"@{viewModel.items}"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:clipToPadding=
"false"
android:orientation=
"vertical"
android:padding=
"@dimen/margin_generic"
app:layoutManager=
"androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem=
"@layout/item_hide_app"
/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</layout>
app/src/main/res/layout/fragment_modules.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.module.ModuleViewModel"
/>
</data>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id=
"@+id/modules_refresh_layout"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
app:layout_behavior=
"@string/appbar_scrolling_view_behavior"
app:onRefreshListener=
"@{() -> viewModel.refresh(false)}"
app:refreshing=
"@{viewModel.loading}"
>
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/modules_content"
dividerColor=
"@{@android:color/transparent}"
dividerSize=
"@{@dimen/margin_generic}"
itemBinding=
"@{viewModel.itemBinding}"
items=
"@{viewModel.itemsInstalled}"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:clipToPadding=
"false"
android:orientation=
"vertical"
android:padding=
"@dimen/margin_generic"
app:layoutManager=
"androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem=
"@layout/item_module"
/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/modules_status_text"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"center"
android:fontFamily=
"sans-serif-light"
android:gravity=
"center"
android:text=
"@string/no_modules_found"
android:textSize=
"20sp"
android:textStyle=
"italic"
android:visibility=
"gone"
tools:visibility=
"visible"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"bottom|center_horizontal"
android:layout_margin=
"@dimen/fab_padding"
android:onClick=
"@{() -> viewModel.fabPressed()}"
android:focusable=
"true"
android:clickable=
"true"
app:fabSize=
"normal"
app:layout_behavior=
"com.google.android.material.floatingactionbutton.FloatingActionButton$Behavior"
app:srcCompat=
"@drawable/ic_add"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>
app/src/main/res/layout/fragment_repos.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.module.ModuleViewModel"
/>
</data>
<FrameLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id=
"@+id/repos_refresh_layout"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
app:onRefreshListener=
"@{() -> viewModel.refresh(true)}"
app:refreshing=
"@{viewModel.loading}"
>
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/repos_content"
dividerColor=
"@{@android:color/transparent}"
dividerSize=
"@{@dimen/margin_generic}"
itemBinding=
"@{viewModel.itemBinding}"
items=
"@{viewModel.itemsRemote}"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:clipToPadding=
"false"
android:orientation=
"vertical"
android:padding=
"@dimen/margin_generic"
app:layoutManager=
"androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem=
"@layout/item_repo"
/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/repos_status_text"
gone=
"@{!(viewModel.loaded && viewModel.itemsRemote.size == 0)}"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"center"
android:fontFamily=
"sans-serif-light"
android:gravity=
"center"
android:text=
"@string/no_modules_found"
android:textSize=
"20sp"
android:textStyle=
"italic"
/>
</FrameLayout>
</layout>
\ No newline at end of file
app/src/main/res/layout/fragment_superuser.xml
deleted
100644 → 0
View file @
df0a5b59
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.superuser.SuperuserViewModel"
/>
</data>
<FrameLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/superuser_content"
dividerColor=
"@{@android:color/transparent}"
dividerSize=
"@{@dimen/margin_generic}"
gone=
"@{!viewModel.loaded}"
itemBinding=
"@{viewModel.itemBinding}"
items=
"@{viewModel.items}"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:clipToPadding=
"false"
android:orientation=
"vertical"
android:padding=
"@dimen/margin_generic"
app:layoutManager=
"androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem=
"@layout/item_policy"
/>
<ProgressBar
style=
"@style/Widget.Progress"
gone=
"@{!viewModel.loading}"
android:layout_gravity=
"center"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/superuser_empty"
gone=
"@{!viewModel.loaded || viewModel.items.size > 0}"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"center"
android:fontFamily=
"sans-serif-light"
android:gravity=
"center"
android:text=
"@string/no_apps_found"
android:textSize=
"20sp"
android:textStyle=
"italic"
/>
</FrameLayout>
</layout>
app/src/main/res/layout/include_update_card.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<import
type=
"com.topjohnwu.magisk.ui.home.MagiskState"
/>
<import
type=
"com.topjohnwu.magisk.ui.home.MagiskItem"
/>
<import
type=
"com.topjohnwu.magisk.R"
/>
<variable
name=
"item"
type=
"com.topjohnwu.magisk.ui.home.MagiskItem"
/>
<variable
name=
"state"
type=
"com.topjohnwu.magisk.ui.home.MagiskState"
/>
<variable
name=
"text"
type=
"String"
/>
<variable
name=
"currentVersion"
type=
"String"
/>
<variable
name=
"latestVersion"
type=
"String"
/>
<variable
name=
"additionalInfo"
type=
"String"
/>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.home.HomeViewModel"
/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:animateLayoutChanges=
"true"
android:background=
"?android:attr/selectableItemBackground"
android:onClick=
"@{() -> viewModel.cardPressed(item)}"
>
<com.google.android.material.button.MaterialButton
android:id=
"@+id/install"
style=
"@style/Widget.Button.Text"
gone=
"@{state == MagiskState.LOADING || !viewModel.isConnected}"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"8dp"
android:onClick=
"@{() -> viewModel.installPressed(item)}"
android:text=
"@{state != MagiskState.OBSOLETE ? @string/install : @string/update}"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:text=
"@string/install"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/status_icon"
invisible=
"@{state == MagiskState.LOADING}"
srcCompat=
"@{state == MagiskState.UP_TO_DATE ? R.drawable.ic_check_circle : (state == MagiskState.OBSOLETE ? R.drawable.ic_update : R.drawable.ic_help)}"
android:layout_width=
"25dp"
android:layout_height=
"25dp"
android:layout_marginStart=
"16dp"
android:layout_marginEnd=
"16dp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toStartOf=
"@+id/status"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:tint=
"@{state == MagiskState.UP_TO_DATE ? @color/colorCorrect : (state == MagiskState.OBSOLETE ? @color/colorUpdate : @color/colorError)}"
/>
<ProgressBar
android:id=
"@+id/progress"
style=
"@style/Widget.Progress"
gone=
"@{state != MagiskState.LOADING}"
android:layout_width=
"0dp"
android:layout_height=
"0dp"
app:layout_constraintBottom_toBottomOf=
"@+id/status_icon"
app:layout_constraintEnd_toEndOf=
"@+id/status_icon"
app:layout_constraintStart_toStartOf=
"@+id/status_icon"
app:layout_constraintTop_toTopOf=
"@+id/status_icon"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/status"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"8dp"
style=
"@style/Widget.Text.Emphasize"
android:paddingTop=
"3dp"
android:paddingBottom=
"3dp"
android:text=
"@{text}"
android:maxLines=
"2"
app:layout_constraintBottom_toTopOf=
"@+id/current_version"
app:layout_constraintEnd_toStartOf=
"@+id/install"
app:layout_constraintStart_toEndOf=
"@+id/status_icon"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintVertical_chainStyle=
"packed"
tools:text=
"@tools:sample/lorem/random"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/current_version"
gone=
"@{state == MagiskState.LOADING || currentVersion.length == 0}"
android:layout_width=
"0dp"
style=
"@style/Widget.Text.Caption.Inactive"
android:layout_height=
"wrap_content"
android:maxLines=
"2"
android:text=
"@{state != MagiskState.LOADING ? @string/current_installed(currentVersion) : @string/checking_for_updates}"
app:layout_constraintBottom_toTopOf=
"@+id/latest_version"
app:layout_constraintEnd_toEndOf=
"@+id/status"
app:layout_constraintStart_toStartOf=
"@+id/status"
app:layout_constraintTop_toBottomOf=
"@+id/status"
tools:text=
"@tools:sample/lorem/random"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/latest_version"
gone=
"@{currentVersion == latestVersion || !viewModel.isConnected}"
android:layout_width=
"0dp"
style=
"@style/Widget.Text.Caption.Inactive"
android:layout_height=
"wrap_content"
android:maxLines=
"2"
android:text=
"@{state != MagiskState.LOADING ? @string/latest_version(latestVersion) : @string/checking_for_updates}"
app:layout_constraintBottom_toTopOf=
"@+id/additional"
app:layout_constraintEnd_toEndOf=
"@+id/status"
app:layout_constraintStart_toStartOf=
"@+id/status"
app:layout_constraintTop_toBottomOf=
"@+id/current_version"
tools:text=
"@tools:sample/lorem/random"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/additional"
gone=
"@{additionalInfo.length == 0}"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
style=
"@style/Widget.Text.Caption.Inactive"
android:maxLines=
"2"
android:text=
"@{additionalInfo}"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"@+id/status"
app:layout_constraintStart_toStartOf=
"@+id/status"
app:layout_constraintTop_toBottomOf=
"@+id/latest_version"
tools:text=
"@tools:sample/lorem/random"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
app/src/main/res/layout/item_hide_app.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"item"
type=
"com.topjohnwu.magisk.model.entity.recycler.HideRvItem"
/>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.hide.HideViewModel"
/>
</data>
<com.google.android.material.card.MaterialCardView
style=
"@style/Widget.Card"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:foreground=
"?attr/selectableItemBackground"
android:minHeight=
"?android:attr/listPreferredItemHeight"
android:onClick=
"@{() -> item.toggleExpansion()}"
app:cardElevation=
"@dimen/card_elevation"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:padding=
"@dimen/margin_generic_half"
>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/hide_app_icon"
android:layout_width=
"48dp"
android:layout_height=
"48dp"
android:gravity=
"end"
android:src=
"@{item.item.icon}"
app:layout_constraintBottom_toTopOf=
"@+id/hide_app_processes"
app:layout_constraintEnd_toStartOf=
"@+id/hide_app_name"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:src=
"@drawable/ic_magisk"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/hide_app_name"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"@dimen/margin_generic"
android:layout_marginEnd=
"@dimen/margin_generic"
android:ellipsize=
"end"
android:maxLines=
"1"
android:text=
"@{item.item.name}"
android:textAppearance=
"?android:attr/textAppearanceMedium"
android:textIsSelectable=
"false"
app:layout_constraintBottom_toTopOf=
"@+id/hide_app_package"
app:layout_constraintEnd_toStartOf=
"@+id/hide_app_checkbox"
app:layout_constraintStart_toEndOf=
"@+id/hide_app_icon"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintVertical_chainStyle=
"packed"
tools:text=
"Magisk"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/hide_app_package"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:ellipsize=
"end"
android:maxLines=
"1"
android:text=
"@{item.packageName}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"@android:color/tertiary_text_dark"
android:textIsSelectable=
"false"
app:layout_constraintBottom_toTopOf=
"@+id/hide_app_processes"
app:layout_constraintEnd_toStartOf=
"@id/hide_app_arrow"
app:layout_constraintStart_toStartOf=
"@+id/hide_app_name"
app:layout_constraintTop_toBottomOf=
"@+id/hide_app_name"
tools:text=
"com.topjohnwu.magisk"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/hide_app_arrow"
gone=
"@{item.items.size == 1}"
android:layout_width=
"24dp"
android:layout_height=
"24dp"
android:layout_marginStart=
"5dp"
android:layout_marginEnd=
"5dp"
android:background=
"@android:color/transparent"
android:rotation=
"@{item.isExpanded() ? 180 : 0}"
app:layout_constraintBottom_toBottomOf=
"@+id/hide_app_package"
app:layout_constraintEnd_toEndOf=
"@+id/hide_app_name"
app:layout_constraintStart_toEndOf=
"@+id/hide_app_package"
app:layout_constraintTop_toTopOf=
"@+id/hide_app_package"
app:srcCompat=
"@drawable/ic_arrow"
app:tint=
"?attr/imageColorTint"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/hide_app_checkbox"
android:focusable=
"true"
android:clickable=
"true"
style=
"@style/Widget.Icon"
isChecked=
"@{item.isHiddenState}"
android:onClick=
"@{() -> item.toggle()}"
app:layout_constraintBottom_toTopOf=
"@+id/hide_app_processes"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toEndOf=
"@+id/hide_app_name"
app:layout_constraintTop_toTopOf=
"parent"
app:tint=
"?attr/imageColorTint"
tools:src=
"@drawable/ic_checked"
/>
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/hide_app_processes"
gone=
"@{!item.isExpanded}"
itemBinding=
"@{viewModel.itemBinding}"
items=
"@{item.items}"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:orientation=
"vertical"
android:paddingTop=
"@dimen/margin_generic_half"
app:layoutManager=
"androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf=
"parent"
tools:listitem=
"@layout/item_hide_process"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</layout>
app/src/main/res/layout/item_hide_process.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"item"
type=
"com.topjohnwu.magisk.model.entity.recycler.HideProcessRvItem"
/>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.hide.HideViewModel"
/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"?selectableItemBackground"
android:clickable=
"false"
android:focusable=
"false"
android:onClick=
"@{() -> item.toggle()}"
>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"@dimen/margin_generic"
android:ellipsize=
"marquee"
android:singleLine=
"true"
android:text=
"@{item.process}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"@android:color/tertiary_text_dark"
android:textIsSelectable=
"false"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toStartOf=
"@+id/hide_process_icon"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:text=
"com.topjohnwu.magisk.process"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/hide_process_icon"
style=
"@style/Widget.Icon"
isChecked=
"@{item.isHidden}"
android:background=
"@null"
android:clickable=
"false"
android:focusable=
"false"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:tint=
"?attr/imageColorTint"
tools:src=
"@drawable/ic_checked"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
app/src/main/res/layout/item_module.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<import
type=
"com.topjohnwu.magisk.R"
/>
<variable
name=
"item"
type=
"com.topjohnwu.magisk.model.entity.recycler.ModuleRvItem"
/>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.module.ModuleViewModel"
/>
</data>
<com.google.android.material.card.MaterialCardView
style=
"@style/Widget.Card"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:foreground=
"?attr/selectableItemBackground"
android:minHeight=
"?android:attr/listPreferredItemHeight"
app:cardElevation=
"2dp"
tools:layout_gravity=
"center"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:padding=
"@dimen/margin_generic"
>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/title"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:text=
"@{item.item.name}"
android:textAppearance=
"?android:attr/textAppearanceMedium"
android:textIsSelectable=
"false"
app:layout_constraintBottom_toTopOf=
"@+id/version_name"
app:layout_constraintEnd_toStartOf=
"@+id/checkbox"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:text=
"Magisk Module"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/version_name"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:text=
"@{item.item.version.length == 0 ? @string/no_info_provided : item.item.version}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"@android:color/tertiary_text_dark"
android:textIsSelectable=
"false"
android:textStyle=
"bold|italic"
app:layout_constraintBottom_toTopOf=
"@+id/author"
app:layout_constraintEnd_toEndOf=
"@+id/title"
app:layout_constraintStart_toStartOf=
"@+id/title"
app:layout_constraintTop_toBottomOf=
"@+id/title"
tools:text=
"v1"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/author"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:text=
"@{item.item.author.length == 0 ? @string/no_info_provided : @string/author(item.item.author)}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"@android:color/tertiary_text_dark"
android:textIsSelectable=
"false"
android:textStyle=
"bold|italic"
app:layout_constraintBottom_toTopOf=
"@+id/description"
app:layout_constraintEnd_toEndOf=
"@+id/title"
app:layout_constraintStart_toStartOf=
"@+id/title"
app:layout_constraintTop_toBottomOf=
"@+id/version_name"
tools:text=
"topjohnwu"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/description"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:text=
"@{item.item.description.length == 0 ? @string/no_info_provided : item.item.description}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textIsSelectable=
"false"
app:layout_constraintBottom_toTopOf=
"@+id/notice"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"@+id/title"
app:layout_constraintTop_toBottomOf=
"@+id/author"
tools:lines=
"4"
tools:text=
"@tools:sample/lorem/random"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/notice"
gone=
"@{item.lastActionNotice.length == 0}"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:text=
"@{item.lastActionNotice}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"@color/red500"
android:visibility=
"visible"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"@+id/title"
app:layout_constraintTop_toBottomOf=
"@+id/description"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/checkbox"
android:focusable=
"true"
android:clickable=
"true"
style=
"@style/Widget.Icon"
isChecked=
"@{item.isChecked}"
android:layout_marginEnd=
"@dimen/margin_generic"
android:onClick=
"@{() -> item.toggle()}"
app:layout_constraintBottom_toTopOf=
"@+id/description"
app:layout_constraintEnd_toStartOf=
"@+id/delete"
app:layout_constraintStart_toEndOf=
"@+id/title"
app:layout_constraintTop_toTopOf=
"parent"
app:tint=
"?attr/imageColorTint"
tools:src=
"@drawable/ic_checked"
/>
<View
style=
"@style/Widget.Divider.Vertical"
android:backgroundTint=
"?attr/imageColorTint"
app:layout_constraintBottom_toBottomOf=
"@+id/checkbox"
app:layout_constraintEnd_toStartOf=
"@+id/delete"
app:layout_constraintStart_toEndOf=
"@+id/checkbox"
app:layout_constraintTop_toTopOf=
"@+id/checkbox"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/delete"
android:focusable=
"true"
android:clickable=
"true"
style=
"@style/Widget.Icon"
srcCompat=
"@{item.isDeletable ? R.drawable.ic_undelete : R.drawable.ic_delete}"
android:onClick=
"@{() -> item.toggleDelete()}"
app:layout_constraintBottom_toBottomOf=
"@+id/checkbox"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toEndOf=
"@+id/checkbox"
app:layout_constraintTop_toTopOf=
"@+id/checkbox"
app:tint=
"?attr/imageColorTint"
tools:ignore=
"ContentDescription"
tools:src=
"@drawable/ic_delete"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</layout>
app/src/main/res/layout/item_page_log.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"item"
type=
"com.topjohnwu.magisk.model.entity.recycler.LogRvItem"
/>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.log.LogViewModel"
/>
</data>
<FrameLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<androidx.recyclerview.widget.RecyclerView
dividerColor=
"@{@android:color/transparent}"
dividerSize=
"@{@dimen/margin_generic}"
itemBinding=
"@{viewModel.itemBinding}"
items=
"@{item.items}"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:clipToPadding=
"false"
android:orientation=
"vertical"
android:padding=
"@dimen/margin_generic"
app:layoutManager=
"androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem=
"@layout/item_superuser_log"
/>
</FrameLayout>
</layout>
\ No newline at end of file
app/src/main/res/layout/item_page_magisk_log.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"item"
type=
"com.topjohnwu.magisk.model.entity.recycler.MagiskLogRvItem"
/>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.log.LogViewModel"
/>
</data>
<FrameLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<HorizontalScrollView
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<androidx.recyclerview.widget.RecyclerView
adapter=
"@{viewModel.itemsAdapter}"
itemBinding=
"@{viewModel.itemBinding}"
items=
"@{item.items}"
scrollPosition=
"@={viewModel.scrollPosition}"
scrollPositionSmooth=
"@{true}"
android:focusable=
"true"
android:layout_width=
"wrap_content"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
app:layoutManager=
"androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem=
"@layout/item_console"
/>
</HorizontalScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
hide=
"@{viewModel.scrollPosition == item.items.size - 1 || item.items.size == 0}"
android:focusable=
"true"
android:clickable=
"true"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"bottom|end"
android:layout_margin=
"@dimen/margin_generic"
android:onClick=
"@{() -> viewModel.scrollDownPressed()}"
app:srcCompat=
"@drawable/ic_arrow_down"
app:tint=
"@color/colorTextInverse"
/>
</FrameLayout>
</layout>
app/src/main/res/layout/item_policy.xml
deleted
100644 → 0
View file @
df0a5b59
This diff is collapsed.
Click to expand it.
app/src/main/res/layout/item_repo.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"item"
type=
"com.topjohnwu.magisk.model.entity.recycler.RepoRvItem"
/>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.module.ModuleViewModel"
/>
</data>
<com.google.android.material.card.MaterialCardView
style=
"@style/Widget.Card"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:foreground=
"?attr/selectableItemBackground"
android:minHeight=
"?android:attr/listPreferredItemHeight"
android:onClick=
"@{() -> viewModel.repoPressed(item)}"
app:cardElevation=
"2dp"
tools:layout_gravity=
"center"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:padding=
"@dimen/margin_generic"
>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/title"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:text=
"@{item.item.name}"
android:textAppearance=
"?android:attr/textAppearanceMedium"
android:textIsSelectable=
"false"
app:layout_constraintBottom_toTopOf=
"@+id/version_name"
app:layout_constraintEnd_toStartOf=
"@+id/download"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:text=
"Magisk Module"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/version_name"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:text=
"@{item.item.version.length == 0 ? @string/no_info_provided : item.item.version}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"@android:color/tertiary_text_dark"
android:textIsSelectable=
"false"
android:textStyle=
"bold|italic"
app:layout_constraintBottom_toTopOf=
"@+id/author"
app:layout_constraintEnd_toEndOf=
"@+id/title"
app:layout_constraintStart_toStartOf=
"@+id/title"
app:layout_constraintTop_toBottomOf=
"@+id/title"
tools:text=
"v1"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/author"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:text=
"@{item.item.author.length == 0 ? @string/no_info_provided : @string/author(item.item.author)}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"@android:color/tertiary_text_dark"
android:textIsSelectable=
"false"
android:textStyle=
"bold|italic"
app:layout_constraintBottom_toTopOf=
"@+id/description"
app:layout_constraintEnd_toEndOf=
"@+id/title"
app:layout_constraintStart_toStartOf=
"@+id/title"
app:layout_constraintTop_toBottomOf=
"@+id/version_name"
tools:text=
"topjohnwu"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/description"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:text=
"@{item.item.description.length == 0 ? @string/no_info_provided : item.item.description}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textIsSelectable=
"false"
app:layout_constraintBottom_toTopOf=
"@+id/update_time"
app:layout_constraintEnd_toEndOf=
"@id/title"
app:layout_constraintStart_toStartOf=
"@+id/title"
app:layout_constraintTop_toBottomOf=
"@+id/author"
tools:lines=
"4"
tools:text=
"@tools:sample/lorem/random"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/update_time"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:text=
"@{@string/updated_on(item.item.lastUpdateString)}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"@android:color/tertiary_text_dark"
android:textStyle=
"bold|italic"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"@+id/title"
app:layout_constraintStart_toStartOf=
"@+id/title"
app:layout_constraintTop_toBottomOf=
"@+id/description"
tools:text=
"@tools:sample/date/ddmmyy"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/download"
android:focusable=
"true"
android:clickable=
"true"
style=
"@style/Widget.Icon"
isEnabled=
"@{viewModel.isConnected}"
android:alpha=
"@{viewModel.isConnected ? 1f : .2f}"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:layout_marginStart=
"8dp"
android:onClick=
"@{() -> viewModel.downloadPressed(item)}"
android:tint=
"?attr/imageColorTint"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toEndOf=
"@+id/title"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/ic_file_download_black"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</layout>
app/src/main/res/layout/item_superuser_log.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"item"
type=
"com.topjohnwu.magisk.model.entity.recycler.LogItemRvItem"
/>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.log.LogViewModel"
/>
</data>
<com.google.android.material.card.MaterialCardView
style=
"@style/Widget.Card"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
app:cardElevation=
"2dp"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:animateLayoutChanges=
"true"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:id=
"@+id/log_header"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"?attr/selectableItemBackground"
android:onClick=
"@{() -> item.toggle()}"
android:orientation=
"horizontal"
android:paddingLeft=
"@dimen/margin_generic"
android:paddingTop=
"@dimen/margin_generic_half"
android:paddingRight=
"@dimen/margin_generic"
android:paddingBottom=
"@dimen/margin_generic_half"
app:layout_constraintTop_toTopOf=
"parent"
>
<androidx.appcompat.widget.AppCompatTextView
style=
"@style/Widget.Text.Emphasize"
android:layout_width=
"0dp"
android:layout_height=
"0dp"
android:gravity=
"center_vertical"
android:text=
"@{item.date}"
android:textColor=
"?android:attr/textColorPrimary"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toStartOf=
"@+id/log_header_indicator"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:text=
"@tools:sample/date/ddmmyy"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/log_header_indicator"
style=
"@style/Widget.Icon"
android:background=
"@android:color/transparent"
android:rotation=
"@{item.isExpanded() ? 180 : 0}"
android:tint=
"?attr/imageColorTint"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/ic_arrow"
tools:rotation=
"180"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
gone=
"@{!item.isExpanded}"
itemBinding=
"@{viewModel.itemBinding}"
items=
"@{item.items}"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:orientation=
"vertical"
app:layoutManager=
"androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toBottomOf=
"@+id/log_header"
tools:itemCount=
"3"
tools:listitem=
"@layout/item_superuser_log_entry"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</layout>
\ No newline at end of file
app/src/main/res/layout/item_superuser_log_entry.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
>
<data>
<variable
name=
"item"
type=
"com.topjohnwu.magisk.model.entity.recycler.LogItemEntryRvItem"
/>
<variable
name=
"viewModel"
type=
"com.topjohnwu.magisk.ui.log.LogViewModel"
/>
</data>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:animateLayoutChanges=
"true"
android:background=
"?attr/selectableItemBackground"
android:onClick=
"@{() -> item.toggle()}"
android:orientation=
"vertical"
>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:orientation=
"horizontal"
android:paddingLeft=
"@dimen/margin_generic"
android:paddingTop=
"@dimen/margin_generic_half"
android:paddingRight=
"@dimen/margin_generic"
android:paddingBottom=
"@dimen/margin_generic_half"
>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_weight=
"2"
android:ellipsize=
"end"
android:maxLines=
"1"
android:text=
"@{item.item.appName}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"?android:attr/textColorPrimary"
android:textIsSelectable=
"false"
tools:text=
"@tools:sample/lorem"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_weight=
"1"
android:gravity=
"center_horizontal"
android:text=
"@{item.item.action ? @string/grant : @string/deny}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"?android:attr/textColorSecondary"
tools:text=
"@string/grant"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/time"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_weight=
"1"
android:gravity=
"center_horizontal"
android:text=
"@{item.item.timeString}"
android:textAppearance=
"?android:attr/textAppearanceSmall"
android:textColor=
"?android:attr/textColorSecondary"
tools:text=
"@tools:sample/date/hhmm"
/>
</LinearLayout>
<LinearLayout
gone=
"@{!item.isExpanded}"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
android:gravity=
"center"
android:orientation=
"horizontal"
android:paddingStart=
"@dimen/margin_generic"
android:paddingTop=
"@dimen/margin_generic_half"
android:paddingEnd=
"@dimen/margin_generic"
android:paddingBottom=
"@dimen/margin_generic_half"
>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_weight=
"1"
android:text=
"@{@string/pid(item.item.fromPid)}"
android:textColor=
"?android:attr/textColorSecondary"
android:textSize=
"12sp"
tools:text=
"@string/pid"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_weight=
"1"
android:text=
"@{@string/target_uid(item.item.toUid)}"
android:textColor=
"?android:attr/textColorSecondary"
android:textSize=
"12sp"
tools:text=
"@string/target_uid"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_weight=
"2"
android:text=
"@{@string/command(item.item.command)}"
android:textColor=
"?android:attr/textColorSecondary"
android:textSize=
"12sp"
tools:text=
"@string/command"
/>
</LinearLayout>
</LinearLayout>
</layout>
\ No newline at end of file
app/src/main/res/menu/drawer.xml
deleted
100644 → 0
View file @
df0a5b59
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<group
android:checkableBehavior=
"single"
android:id=
"@+id/main_group"
>
<item
android:id=
"@+id/magiskFragment"
android:icon=
"@drawable/ic_magisk_outline"
android:title=
"@string/magisk"
/>
<item
android:id=
"@+id/superuserFragment"
android:icon=
"@drawable/ic_superuser"
android:title=
"@string/superuser"
android:visible=
"false"
/>
<item
android:id=
"@+id/magiskHideFragment"
android:icon=
"@drawable/ic_magiskhide"
android:title=
"@string/magiskhide"
android:visible=
"false"
/>
</group>
<group
android:checkableBehavior=
"single"
android:id=
"@+id/second_group"
>
<item
android:id=
"@+id/modulesFragment"
android:icon=
"@drawable/ic_extension"
android:title=
"@string/modules"
android:visible=
"false"
/>
<item
android:id=
"@+id/reposFragment"
android:icon=
"@drawable/ic_cloud_download"
android:title=
"@string/downloads"
/>
</group>
<group
android:checkableBehavior=
"single"
android:id=
"@+id/third_group"
>
<item
android:id=
"@+id/logFragment"
android:icon=
"@drawable/ic_bug_report"
android:title=
"@string/log"
/>
<item
android:id=
"@+id/settings"
android:icon=
"@drawable/ic_settings"
android:title=
"@string/settings"
/>
</group>
</menu>
app/src/main/res/menu/menu_log.xml
deleted
100644 → 0
View file @
df0a5b59
<?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/menu_save"
android:icon=
"@drawable/ic_save"
android:title=
"@string/menuSaveLog"
app:showAsAction=
"ifRoom"
/>
<item
android:id=
"@+id/menu_clear"
android:icon=
"@drawable/ic_delete"
android:title=
"@string/menuClearLog"
app:showAsAction=
"ifRoom"
/>
<item
android:id=
"@+id/menu_refresh"
android:icon=
"@drawable/ic_refresh"
android:title=
"@string/menuReload"
app:showAsAction=
"ifRoom"
/>
</menu>
\ No newline at end of file
app/src/main/res/menu/menu_magiskhide.xml
deleted
100644 → 0
View file @
df0a5b59
<?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/app_search"
android:title=
""
app:actionViewClass=
"android.widget.SearchView"
app:showAsAction=
"always"
/>
<item
android:id=
"@+id/show_system"
android:title=
"@string/show_system_app"
android:checkable=
"true"
/>
</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