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
2926772b
Commit
2926772b
authored
Nov 17, 2019
by
Viktor De Pasquale
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added checks for updatable state on remote repos
parent
a7f4496d
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
72 additions
and
16 deletions
+72
-16
ModuleRvItem.kt
...om/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt
+1
-1
ModuleViewModel.kt
...a/com/topjohnwu/magisk/redesign/module/ModuleViewModel.kt
+66
-13
item_repo_md2.xml
app/src/main/res/layout/item_repo_md2.xml
+5
-2
No files found.
app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt
View file @
2926772b
...
@@ -121,10 +121,10 @@ class SectionTitle(
...
@@ -121,10 +121,10 @@ class SectionTitle(
}
}
class
RepoItem
(
val
item
:
Repo
)
:
ComparableRvItem
<
RepoItem
>()
{
class
RepoItem
(
val
item
:
Repo
)
:
ComparableRvItem
<
RepoItem
>()
{
override
val
layoutRes
:
Int
=
R
.
layout
.
item_repo_md2
override
val
layoutRes
:
Int
=
R
.
layout
.
item_repo_md2
val
progress
=
KObservableField
(
0
)
val
progress
=
KObservableField
(
0
)
val
isUpdate
=
KObservableField
(
false
)
override
fun
contentSameAs
(
other
:
RepoItem
):
Boolean
=
item
==
other
.
item
override
fun
contentSameAs
(
other
:
RepoItem
):
Boolean
=
item
==
other
.
item
override
fun
itemSameAs
(
other
:
RepoItem
):
Boolean
=
item
.
id
==
other
.
item
.
id
override
fun
itemSameAs
(
other
:
RepoItem
):
Boolean
=
item
.
id
==
other
.
item
.
id
...
...
app/src/main/java/com/topjohnwu/magisk/redesign/module/ModuleViewModel.kt
View file @
2926772b
...
@@ -33,6 +33,7 @@ import io.reactivex.Single
...
@@ -33,6 +33,7 @@ import io.reactivex.Single
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.android.schedulers.AndroidSchedulers
import
io.reactivex.disposables.Disposable
import
io.reactivex.disposables.Disposable
import
me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter
import
me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter
import
org.jetbrains.annotations.NotNull
import
timber.log.Timber
import
timber.log.Timber
import
kotlin.math.roundToInt
import
kotlin.math.roundToInt
...
@@ -132,6 +133,10 @@ class ModuleViewModel(
...
@@ -132,6 +133,10 @@ class ModuleViewModel(
items
.
update
(
it
.
first
,
it
.
second
)
items
.
update
(
it
.
first
,
it
.
second
)
if
(!
items
.
contains
(
sectionRemote
))
{
if
(!
items
.
contains
(
sectionRemote
))
{
loadRemote
()
loadRemote
()
}
else
{
Single
.
fromCallable
{
itemsRemote
}
.
subscribeK
{
it
.
ensureUpdateState
()
}
.
add
()
}
}
moveToState
()
moveToState
()
}
}
...
@@ -150,10 +155,7 @@ class ModuleViewModel(
...
@@ -150,10 +155,7 @@ class ModuleViewModel(
}
}
remoteJob
=
Single
.
fromCallable
{
itemsRemote
.
size
}
remoteJob
=
Single
.
fromCallable
{
itemsRemote
.
size
}
.
flatMap
{
loadRemoteInternal
(
offset
=
it
)
}
.
flatMap
{
loadRemoteInternal
(
offset
=
it
)
}
.
map
{
it
.
map
{
RepoItem
(
it
)
}
}
.
subscribeK
(
onError
=
Timber
::
e
)
{
.
subscribeK
(
onError
=
{
Timber
.
e
(
it
)
})
{
if
(!
items
.
contains
(
sectionRemote
))
{
if
(!
items
.
contains
(
sectionRemote
))
{
items
.
add
(
sectionRemote
)
items
.
add
(
sectionRemote
)
}
}
...
@@ -176,6 +178,7 @@ class ModuleViewModel(
...
@@ -176,6 +178,7 @@ class ModuleViewModel(
}
}
return
Single
.
fromCallable
{
dao
.
searchRepos
(
query
,
offset
)
}
return
Single
.
fromCallable
{
dao
.
searchRepos
(
query
,
offset
)
}
.
map
{
it
.
map
{
RepoItem
(
it
)
}
}
.
map
{
it
.
map
{
RepoItem
(
it
)
}
}
.
doOnSuccess
{
it
.
ensureUpdateState
()
}
}
}
private
fun
query
(
query
:
String
=
this
.
query
,
offset
:
Int
=
0
)
{
private
fun
query
(
query
:
String
=
this
.
query
,
offset
:
Int
=
0
)
{
...
@@ -199,14 +202,17 @@ class ModuleViewModel(
...
@@ -199,14 +202,17 @@ class ModuleViewModel(
private
fun
loadRemoteInternal
(
private
fun
loadRemoteInternal
(
offset
:
Int
=
0
,
offset
:
Int
=
0
,
downloadRepos
:
Boolean
=
offset
==
0
downloadRepos
:
Boolean
=
offset
==
0
):
Single
<
List
<
Repo
>>
=
Single
.
fromCallable
{
dao
.
getRepos
(
offset
)
}.
flatMap
{
):
Single
<
List
<
RepoItem
>>
=
Single
.
fromCallable
{
dao
.
getRepos
(
offset
)
}
when
{
.
map
{
it
.
map
{
RepoItem
(
it
)
}
}
// in case we find result empty and offset is initial we need to refresh the repos.
.
flatMap
{
downloadRepos
&&
it
.
isEmpty
()
&&
offset
==
0
->
downloadRepos
()
when
{
.
andThen
(
loadRemoteInternal
(
downloadRepos
=
false
))
// in case we find result empty and offset is initial we need to refresh the repos.
else
->
Single
.
just
(
it
)
downloadRepos
&&
it
.
isEmpty
()
&&
offset
==
0
->
downloadRepos
()
.
andThen
(
loadRemoteInternal
(
downloadRepos
=
false
))
else
->
Single
.
just
(
it
)
}
}
}
}
.
doOnSuccess
{
it
.
ensureUpdateState
()
}
private
fun
downloadRepos
()
=
Single
.
just
(
Unit
)
private
fun
downloadRepos
()
=
Single
.
just
(
Unit
)
.
flatMap
{
repoUpdater
()
}
.
flatMap
{
repoUpdater
()
}
...
@@ -227,12 +233,58 @@ class ModuleViewModel(
...
@@ -227,12 +233,58 @@ class ModuleViewModel(
// ---
// ---
/**
* Dynamically allocated list of [itemsInstalled]. It might be invalidated any time on any
* thread hence it needs to be volatile.
*
* There might be a state where this field gets assigned `null` whilst being used by another
* instance of any job, so the list will be immediately reinstated back.
*
* ### Note:
*
* It is caller's responsibility to invalidate this variable at the end of every job to save
* memory.
* */
@Volatile
private
var
cachedItemsInstalled
:
List
<
ModuleItem
>?
=
null
@WorkerThread
@NotNull
get
()
=
field
?:
itemsInstalled
.
also
{
field
=
it
}
private
val
Repo
.
isUpdatable
:
Boolean
@WorkerThread
get
()
{
val
installed
=
cachedItemsInstalled
!!
.
firstOrNull
{
it
.
item
.
id
==
id
}
?:
return
false
return
installed
.
item
.
versionCode
<
versionCode
}
/**
* Asynchronously updates state of all repo items so the loading speed is not impaired by this
* seemingly unnecessary operation. Because of the nature of this operation, the "update" status
* is not guaranteed for all items and can change any time.
*
* It is permitted running this function in parallel; it will also attempt to run in parallel
* by itself to finish the job as quickly as possible.
*
* No list manipulations should be done in this method whatsoever! By being heavily parallelized
* is will inevitably throw exceptions by simultaneously accessing the same list.
*
* In order to save time it uses helper [cachedItemsInstalled].
* */
private
fun
List
<
RepoItem
>.
ensureUpdateState
()
=
Single
.
just
(
this
)
.
flattenAsFlowable
{
it
}
.
parallel
()
.
map
{
it
to
it
.
item
.
isUpdatable
}
.
sequential
()
.
doOnComplete
{
cachedItemsInstalled
=
null
}
.
subscribeK
{
it
.
first
.
isUpdate
.
value
=
it
.
second
}
.
add
()
// ---
fun
moveToState
()
=
Single
.
fromCallable
{
itemsInstalled
.
any
{
it
.
isModified
}
}
fun
moveToState
()
=
Single
.
fromCallable
{
itemsInstalled
.
any
{
it
.
isModified
}
}
.
subscribeK
{
sectionActive
.
hasButton
.
value
=
it
}
.
subscribeK
{
sectionActive
.
hasButton
.
value
=
it
}
.
add
()
.
add
()
fun
download
(
item
:
RepoItem
)
=
ModuleInstallDialog
(
item
.
item
).
publish
()
fun
sectionPressed
(
item
:
SectionTitle
)
=
when
(
item
)
{
fun
sectionPressed
(
item
:
SectionTitle
)
=
when
(
item
)
{
sectionActive
->
reboot
()
//TODO add reboot picker, regular reboot is not always preferred
sectionActive
->
reboot
()
//TODO add reboot picker, regular reboot is not always preferred
sectionRemote
->
{
sectionRemote
->
{
...
@@ -252,6 +304,7 @@ class ModuleViewModel(
...
@@ -252,6 +304,7 @@ class ModuleViewModel(
else
->
Unit
else
->
Unit
}
}
fun
downloadPressed
(
item
:
RepoItem
)
=
ModuleInstallDialog
(
item
.
item
).
publish
()
fun
installPressed
()
=
InstallExternalModuleEvent
().
publish
()
fun
installPressed
()
=
InstallExternalModuleEvent
().
publish
()
fun
infoPressed
(
item
:
RepoItem
)
=
OpenChangelogEvent
(
item
.
item
).
publish
()
fun
infoPressed
(
item
:
RepoItem
)
=
OpenChangelogEvent
(
item
.
item
).
publish
()
...
...
app/src/main/res/layout/item_repo_md2.xml
View file @
2926772b
...
@@ -5,6 +5,8 @@
...
@@ -5,6 +5,8 @@
<data>
<data>
<import
type=
"com.topjohnwu.magisk.R"
/>
<variable
<variable
name=
"item"
name=
"item"
type=
"com.topjohnwu.magisk.model.entity.recycler.RepoItem"
/>
type=
"com.topjohnwu.magisk.model.entity.recycler.RepoItem"
/>
...
@@ -108,11 +110,12 @@
...
@@ -108,11 +110,12 @@
android:paddingStart=
"@dimen/l_50"
android:paddingStart=
"@dimen/l_50"
isEnabled=
"@{!(item.progress == -100 || (item.progress > 0 && item.progress < 100))}"
isEnabled=
"@{!(item.progress == -100 || (item.progress > 0 && item.progress < 100))}"
android:contentDescription=
"@string/download"
android:contentDescription=
"@string/download"
android:onClick=
"@{() -> viewModel.download(item)
}"
srcCompat=
"@{item.isUpdate() ? R.drawable.ic_update_md2 : R.drawable.ic_download_md2
}"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/module_divider"
app:layout_constraintTop_toBottomOf=
"@+id/module_divider"
app:srcCompat=
"@drawable/ic_download_md2"
/>
android:onClick=
"@{() -> viewModel.downloadPressed(item)}"
tools:srcCompat=
"@drawable/ic_download_md2"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
...
...
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