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
9d1d1710
Commit
9d1d1710
authored
Nov 14, 2019
by
Viktor De Pasquale
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added new search functionality to module screen
parent
c69dcf3e
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
395 additions
and
56 deletions
+395
-56
Repo.kt
app/src/main/java/com/topjohnwu/magisk/data/database/Repo.kt
+33
-1
MainActivity.kt
...c/main/java/com/topjohnwu/magisk/redesign/MainActivity.kt
+16
-13
CompatFragment.kt
...va/com/topjohnwu/magisk/redesign/compat/CompatFragment.kt
+1
-1
Queryable.kt
...in/java/com/topjohnwu/magisk/redesign/compat/Queryable.kt
+26
-0
HideViewModel.kt
.../java/com/topjohnwu/magisk/redesign/hide/HideViewModel.kt
+7
-11
ModuleFragment.kt
...va/com/topjohnwu/magisk/redesign/module/ModuleFragment.kt
+31
-4
ModuleViewModel.kt
...a/com/topjohnwu/magisk/redesign/module/ModuleViewModel.kt
+68
-8
bg_shadow.xml
app/src/main/res/drawable/bg_shadow.xml
+8
-0
fragment_module_md2.xml
app/src/main/res/layout/fragment_module_md2.xml
+55
-17
include_module_filter.xml
app/src/main/res/layout/include_module_filter.xml
+131
-0
styles_md2_impl.xml
app/src/main/res/values-v21/styles_md2_impl.xml
+7
-0
attrs.xml
app/src/main/res/values/attrs.xml
+1
-0
styles_md2.xml
app/src/main/res/values/styles_md2.xml
+5
-1
styles_md2_impl.xml
app/src/main/res/values/styles_md2_impl.xml
+6
-0
No files found.
app/src/main/java/com/topjohnwu/magisk/data/database/Repo.kt
View file @
9d1d1710
...
@@ -8,7 +8,12 @@ import com.topjohnwu.magisk.model.entity.module.Repo
...
@@ -8,7 +8,12 @@ import com.topjohnwu.magisk.model.entity.module.Repo
interface
RepoBase
{
interface
RepoBase
{
fun
getRepos
(
offset
:
Int
,
limit
:
Int
=
10
):
List
<
Repo
>
fun
getRepos
(
offset
:
Int
,
limit
:
Int
=
LIMIT
):
List
<
Repo
>
fun
searchRepos
(
query
:
String
,
offset
:
Int
,
limit
:
Int
=
LIMIT
):
List
<
Repo
>
companion
object
{
const
val
LIMIT
=
10
}
}
}
...
@@ -18,6 +23,19 @@ interface RepoByUpdatedDao : RepoBase {
...
@@ -18,6 +23,19 @@ interface RepoByUpdatedDao : RepoBase {
@Query
(
"SELECT * FROM repos ORDER BY last_update DESC LIMIT :limit OFFSET :offset"
)
@Query
(
"SELECT * FROM repos ORDER BY last_update DESC LIMIT :limit OFFSET :offset"
)
override
fun
getRepos
(
offset
:
Int
,
limit
:
Int
):
List
<
Repo
>
override
fun
getRepos
(
offset
:
Int
,
limit
:
Int
):
List
<
Repo
>
@Query
(
"""SELECT *
FROM repos
WHERE
(author LIKE '%' || :query || '%') ||
(name LIKE '%' || :query || '%') ||
(description LIKE '%' || :query || '%')
ORDER BY last_update DESC
LIMIT :limit
OFFSET :offset"""
)
override
fun
searchRepos
(
query
:
String
,
offset
:
Int
,
limit
:
Int
):
List
<
Repo
>
}
}
@Dao
@Dao
...
@@ -26,4 +44,18 @@ interface RepoByNameDao : RepoBase {
...
@@ -26,4 +44,18 @@ interface RepoByNameDao : RepoBase {
@Query
(
"SELECT * FROM repos ORDER BY name COLLATE NOCASE LIMIT :limit OFFSET :offset"
)
@Query
(
"SELECT * FROM repos ORDER BY name COLLATE NOCASE LIMIT :limit OFFSET :offset"
)
override
fun
getRepos
(
offset
:
Int
,
limit
:
Int
):
List
<
Repo
>
override
fun
getRepos
(
offset
:
Int
,
limit
:
Int
):
List
<
Repo
>
@Query
(
"""SELECT *
FROM repos
WHERE
(author LIKE '%' || :query || '%') ||
(name LIKE '%' || :query || '%') ||
(description LIKE '%' || :query || '%')
ORDER BY name COLLATE NOCASE
LIMIT :limit
OFFSET :offset"""
)
override
fun
searchRepos
(
query
:
String
,
offset
:
Int
,
limit
:
Int
):
List
<
Repo
>
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/redesign/MainActivity.kt
View file @
9d1d1710
...
@@ -116,19 +116,7 @@ open class MainActivity : CompatActivity<MainViewModel, ActivityMainMd2Binding>(
...
@@ -116,19 +116,7 @@ open class MainActivity : CompatActivity<MainViewModel, ActivityMainMd2Binding>(
transactionType
:
FragNavController
.
TransactionType
transactionType
:
FragNavController
.
TransactionType
)
{
)
{
setDisplayHomeAsUpEnabled
(!
navigation
.
isRoot
)
setDisplayHomeAsUpEnabled
(!
navigation
.
isRoot
)
requestNavigationHidden
(!
navigation
.
isRoot
)
val
lapam
=
binding
.
mainBottomBar
.
layoutParams
as
ViewGroup
.
MarginLayoutParams
val
height
=
binding
.
mainBottomBar
.
measuredHeight
val
verticalMargin
=
lapam
.
let
{
it
.
topMargin
+
it
.
bottomMargin
}
val
maxTranslation
=
height
+
verticalMargin
val
translation
=
if
(
navigation
.
isRoot
)
0
else
maxTranslation
binding
.
mainBottomBar
.
animate
()
.
translationY
(
translation
.
toFloat
())
.
setInterpolator
(
FastOutSlowInInterpolator
())
.
withStartAction
{
if
(
navigation
.
isRoot
)
binding
.
mainBottomBar
.
isVisible
=
true
}
.
withEndAction
{
if
(!
navigation
.
isRoot
)
binding
.
mainBottomBar
.
isVisible
=
false
}
.
start
()
}
}
override
fun
peekSystemWindowInsets
(
insets
:
Insets
)
{
override
fun
peekSystemWindowInsets
(
insets
:
Insets
)
{
...
@@ -143,4 +131,19 @@ open class MainActivity : CompatActivity<MainViewModel, ActivityMainMd2Binding>(
...
@@ -143,4 +131,19 @@ open class MainActivity : CompatActivity<MainViewModel, ActivityMainMd2Binding>(
}
}
}
}
internal
fun
requestNavigationHidden
(
hide
:
Boolean
=
true
)
{
val
lapam
=
binding
.
mainBottomBar
.
layoutParams
as
ViewGroup
.
MarginLayoutParams
val
height
=
binding
.
mainBottomBar
.
measuredHeight
val
verticalMargin
=
lapam
.
let
{
it
.
topMargin
+
it
.
bottomMargin
}
val
maxTranslation
=
height
+
verticalMargin
val
translation
=
if
(!
hide
)
0
else
maxTranslation
binding
.
mainBottomBar
.
animate
()
.
translationY
(
translation
.
toFloat
())
.
setInterpolator
(
FastOutSlowInInterpolator
())
.
withStartAction
{
if
(!
hide
)
binding
.
mainBottomBar
.
isVisible
=
true
}
.
withEndAction
{
if
(
hide
)
binding
.
mainBottomBar
.
isVisible
=
false
}
.
start
()
}
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/redesign/compat/CompatFragment.kt
View file @
9d1d1710
...
@@ -18,7 +18,7 @@ abstract class CompatFragment<ViewModel : CompatViewModel, Binding : ViewDataBin
...
@@ -18,7 +18,7 @@ abstract class CompatFragment<ViewModel : CompatViewModel, Binding : ViewDataBin
private
val
delegate
by
lazy
{
CompatDelegate
(
this
)
}
private
val
delegate
by
lazy
{
CompatDelegate
(
this
)
}
pr
ivate
val
compatActivity
get
()
=
requireActivity
()
as
CompatActivity
<*,
*>
pr
otected
val
compatActivity
get
()
=
requireActivity
()
as
CompatActivity
<*,
*>
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
super
.
onViewCreated
(
view
,
savedInstanceState
)
...
...
app/src/main/java/com/topjohnwu/magisk/redesign/compat/Queryable.kt
0 → 100644
View file @
9d1d1710
package
com.topjohnwu.magisk.redesign.compat
import
android.os.Handler
import
android.os.Looper
interface
Queryable
{
val
queryDelay
:
Long
val
queryHandler
:
Handler
val
queryRunnable
:
Runnable
fun
submitQuery
()
companion
object
{
fun
impl
(
delay
:
Long
=
1000L
)
=
object
:
Queryable
{
override
val
queryDelay
=
delay
override
val
queryHandler
=
Handler
(
Looper
.
getMainLooper
())
override
val
queryRunnable
=
Runnable
{
TODO
()
}
override
fun
submitQuery
()
{
queryHandler
.
removeCallbacks
(
queryRunnable
)
queryHandler
.
postDelayed
(
queryRunnable
,
queryDelay
)
}
}
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/redesign/hide/HideViewModel.kt
View file @
9d1d1710
package
com.topjohnwu.magisk.redesign.hide
package
com.topjohnwu.magisk.redesign.hide
import
android.content.pm.ApplicationInfo
import
android.content.pm.ApplicationInfo
import
android.os.Handler
import
android.os.Looper
import
androidx.databinding.Bindable
import
androidx.databinding.Bindable
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.data.repository.MagiskRepository
import
com.topjohnwu.magisk.data.repository.MagiskRepository
...
@@ -16,20 +14,18 @@ import com.topjohnwu.magisk.model.entity.StatefulProcess
...
@@ -16,20 +14,18 @@ import com.topjohnwu.magisk.model.entity.StatefulProcess
import
com.topjohnwu.magisk.model.entity.recycler.HideItem
import
com.topjohnwu.magisk.model.entity.recycler.HideItem
import
com.topjohnwu.magisk.model.entity.recycler.HideProcessItem
import
com.topjohnwu.magisk.model.entity.recycler.HideProcessItem
import
com.topjohnwu.magisk.redesign.compat.CompatViewModel
import
com.topjohnwu.magisk.redesign.compat.CompatViewModel
import
com.topjohnwu.magisk.redesign.compat.Queryable
import
com.topjohnwu.magisk.redesign.home.itemBindingOf
import
com.topjohnwu.magisk.redesign.home.itemBindingOf
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.DiffObservableList
import
com.topjohnwu.magisk.utils.FilterableDiffObservableList
import
com.topjohnwu.magisk.utils.FilterableDiffObservableList
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.currentLocale
import
com.topjohnwu.magisk.utils.currentLocale
import
io.reactivex.Single
import
io.reactivex.android.schedulers.AndroidSchedulers
class
HideViewModel
(
class
HideViewModel
(
private
val
magiskRepo
:
MagiskRepository
private
val
magiskRepo
:
MagiskRepository
)
:
CompatViewModel
()
{
)
:
CompatViewModel
()
,
Queryable
by
Queryable
.
impl
(
1000
)
{
private
val
queryHandler
=
Handler
(
Looper
.
getMainLooper
())
override
val
queryRunnable
=
Runnable
{
query
()
}
private
val
queryRunnable
=
Runnable
{
query
()
}
var
isShowSystem
=
false
var
isShowSystem
=
false
@Bindable
get
@Bindable
get
...
@@ -67,7 +63,7 @@ class HideViewModel(
...
@@ -67,7 +63,7 @@ class HideViewModel(
.
applyViewModel
(
this
)
.
applyViewModel
(
this
)
.
subscribeK
{
.
subscribeK
{
items
.
update
(
it
.
first
,
it
.
second
)
items
.
update
(
it
.
first
,
it
.
second
)
q
uery
()
submitQ
uery
()
}
}
// ---
// ---
...
@@ -87,9 +83,9 @@ class HideViewModel(
...
@@ -87,9 +83,9 @@ class HideViewModel(
// ---
// ---
privat
e
fun
submitQuery
()
{
overrid
e
fun
submitQuery
()
{
queryHandler
.
removeCallbacks
(
queryRunnable
)
queryHandler
.
removeCallbacks
(
queryRunnable
)
queryHandler
.
postDelayed
(
queryRunnable
,
1000
)
queryHandler
.
postDelayed
(
queryRunnable
,
queryDelay
)
}
}
private
fun
query
(
private
fun
query
(
...
@@ -130,7 +126,7 @@ class HideViewModel(
...
@@ -130,7 +126,7 @@ class HideViewModel(
}
}
inline
fun
<
T
:
ComparableRvItem
<
T
>
>
filterableListOf
(
inline
fun
<
T
:
ComparableRvItem
<
*
>
>
filterableListOf
(
vararg
newItems
:
T
vararg
newItems
:
T
)
=
FilterableDiffObservableList
(
object
:
DiffObservableList
.
Callback
<
T
>
{
)
=
FilterableDiffObservableList
(
object
:
DiffObservableList
.
Callback
<
T
>
{
override
fun
areItemsTheSame
(
oldItem
:
T
,
newItem
:
T
)
=
oldItem
.
genericItemSameAs
(
newItem
)
override
fun
areItemsTheSame
(
oldItem
:
T
,
newItem
:
T
)
=
oldItem
.
genericItemSameAs
(
newItem
)
...
...
app/src/main/java/com/topjohnwu/magisk/redesign/module/ModuleFragment.kt
View file @
9d1d1710
...
@@ -5,7 +5,10 @@ import android.os.Bundle
...
@@ -5,7 +5,10 @@ import android.os.Bundle
import
android.view.View
import
android.view.View
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding
import
com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding
import
com.topjohnwu.magisk.redesign.MainActivity
import
com.topjohnwu.magisk.redesign.compat.CompatFragment
import
com.topjohnwu.magisk.redesign.compat.CompatFragment
import
com.topjohnwu.magisk.redesign.compat.hideKeyboard
import
com.topjohnwu.magisk.redesign.hide.MotionRevealHelper
import
com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
import
com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
import
org.koin.androidx.viewmodel.ext.android.viewModel
import
org.koin.androidx.viewmodel.ext.android.viewModel
...
@@ -14,7 +17,7 @@ class ModuleFragment : CompatFragment<ModuleViewModel, FragmentModuleMd2Binding>
...
@@ -14,7 +17,7 @@ class ModuleFragment : CompatFragment<ModuleViewModel, FragmentModuleMd2Binding>
override
val
layoutRes
=
R
.
layout
.
fragment_module_md2
override
val
layoutRes
=
R
.
layout
.
fragment_module_md2
override
val
viewModel
by
viewModel
<
ModuleViewModel
>()
override
val
viewModel
by
viewModel
<
ModuleViewModel
>()
private
lateinit
var
listener
:
EndlessRecyclerScrollListener
private
val
listeners
=
hashSetOf
<
EndlessRecyclerScrollListener
>()
override
fun
consumeSystemWindowInsets
(
insets
:
Insets
)
=
insets
override
fun
consumeSystemWindowInsets
(
insets
:
Insets
)
=
insets
...
@@ -26,21 +29,45 @@ class ModuleFragment : CompatFragment<ModuleViewModel, FragmentModuleMd2Binding>
...
@@ -26,21 +29,45 @@ class ModuleFragment : CompatFragment<ModuleViewModel, FragmentModuleMd2Binding>
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
super
.
onViewCreated
(
view
,
savedInstanceState
)
setEndlessScroller
()
setEndlessScroller
()
setEndlessSearch
()
binding
.
moduleFilterToggle
.
setOnClickListener
{
(
activity
as
?
MainActivity
)
?.
requestNavigationHidden
()
MotionRevealHelper
.
withViews
(
binding
.
moduleFilter
,
binding
.
moduleFilterToggle
,
true
)
}
binding
.
moduleFilterInclude
.
moduleFilterDone
.
setOnClickListener
{
(
activity
as
?
MainActivity
)
?.
requestNavigationHidden
(
false
)
hideKeyboard
()
MotionRevealHelper
.
withViews
(
binding
.
moduleFilter
,
binding
.
moduleFilterToggle
,
false
)
}
}
}
override
fun
onDestroyView
()
{
override
fun
onDestroyView
()
{
if
(
this
::
listener
.
isInitialized
)
{
listeners
.
forEach
{
binding
.
moduleRemote
.
removeOnScrollListener
(
listener
)
binding
.
moduleRemote
.
removeOnScrollListener
(
it
)
binding
.
moduleFilterInclude
.
moduleFilterList
.
removeOnScrollListener
(
it
)
}
}
super
.
onDestroyView
()
super
.
onDestroyView
()
}
}
override
fun
onPreBind
(
binding
:
FragmentModuleMd2Binding
)
=
Unit
private
fun
setEndlessScroller
()
{
private
fun
setEndlessScroller
()
{
val
lama
=
binding
.
moduleRemote
.
layoutManager
?:
return
val
lama
=
binding
.
moduleRemote
.
layoutManager
?:
return
lama
.
isAutoMeasureEnabled
=
false
lama
.
isAutoMeasureEnabled
=
false
listener
=
EndlessRecyclerScrollListener
(
lama
,
viewModel
::
loadRemote
)
val
listener
=
EndlessRecyclerScrollListener
(
lama
,
viewModel
::
loadRemote
)
binding
.
moduleRemote
.
addOnScrollListener
(
listener
)
binding
.
moduleRemote
.
addOnScrollListener
(
listener
)
listeners
.
add
(
listener
)
}
private
fun
setEndlessSearch
()
{
val
lama
=
binding
.
moduleFilterInclude
.
moduleFilterList
.
layoutManager
?:
return
lama
.
isAutoMeasureEnabled
=
false
val
listener
=
EndlessRecyclerScrollListener
(
lama
,
viewModel
::
loadMoreQuery
)
binding
.
moduleFilterInclude
.
moduleFilterList
.
addOnScrollListener
(
listener
)
listeners
.
add
(
listener
)
}
}
}
}
\ No newline at end of file
app/src/main/java/com/topjohnwu/magisk/redesign/module/ModuleViewModel.kt
View file @
9d1d1710
package
com.topjohnwu.magisk.redesign.module
package
com.topjohnwu.magisk.redesign.module
import
androidx.annotation.WorkerThread
import
androidx.annotation.WorkerThread
import
androidx.databinding.Bindable
import
androidx.databinding.ViewDataBinding
import
androidx.databinding.ViewDataBinding
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.BR
import
com.topjohnwu.magisk.Config
import
com.topjohnwu.magisk.Config
...
@@ -19,11 +20,14 @@ import com.topjohnwu.magisk.model.entity.recycler.RepoItem
...
@@ -19,11 +20,14 @@ import com.topjohnwu.magisk.model.entity.recycler.RepoItem
import
com.topjohnwu.magisk.model.entity.recycler.SectionTitle
import
com.topjohnwu.magisk.model.entity.recycler.SectionTitle
import
com.topjohnwu.magisk.model.events.dialog.ModuleInstallDialog
import
com.topjohnwu.magisk.model.events.dialog.ModuleInstallDialog
import
com.topjohnwu.magisk.redesign.compat.CompatViewModel
import
com.topjohnwu.magisk.redesign.compat.CompatViewModel
import
com.topjohnwu.magisk.redesign.compat.Queryable
import
com.topjohnwu.magisk.redesign.home.itemBindingOf
import
com.topjohnwu.magisk.redesign.home.itemBindingOf
import
com.topjohnwu.magisk.redesign.superuser.diffListOf
import
com.topjohnwu.magisk.redesign.superuser.diffListOf
import
com.topjohnwu.magisk.tasks.RepoUpdater
import
com.topjohnwu.magisk.tasks.RepoUpdater
import
com.topjohnwu.magisk.utils.KObservableField
import
com.topjohnwu.magisk.utils.currentLocale
import
com.topjohnwu.magisk.utils.currentLocale
import
io.reactivex.Single
import
io.reactivex.Single
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
timber.log.Timber
import
timber.log.Timber
...
@@ -33,7 +37,27 @@ class ModuleViewModel(
...
@@ -33,7 +37,27 @@ class ModuleViewModel(
private
val
repoName
:
RepoByNameDao
,
private
val
repoName
:
RepoByNameDao
,
private
val
repoUpdated
:
RepoByUpdatedDao
,
private
val
repoUpdated
:
RepoByUpdatedDao
,
private
val
repoUpdater
:
RepoUpdater
private
val
repoUpdater
:
RepoUpdater
)
:
CompatViewModel
()
{
)
:
CompatViewModel
(),
Queryable
by
Queryable
.
impl
(
1000
)
{
override
val
queryRunnable
=
Runnable
{
query
()
}
var
query
=
""
@Bindable
get
set
(
value
)
{
if
(
field
==
value
)
return
field
=
value
notifyPropertyChanged
(
BR
.
query
)
submitQuery
()
// Yes we do lie about the search being loaded
searchLoading
.
value
=
true
}
private
var
queryJob
:
Disposable
?
=
null
val
searchLoading
=
KObservableField
(
false
)
val
itemsSearch
=
diffListOf
<
RepoItem
>()
val
itemSearchBinding
=
itemBindingOf
<
RepoItem
>
{
it
.
bindExtra
(
BR
.
viewModel
,
this
)
}
val
adapter
=
adapterOf
<
ComparableRvItem
<*>>()
val
adapter
=
adapterOf
<
ComparableRvItem
<*>>()
val
items
=
diffListOf
<
ComparableRvItem
<*>>()
val
items
=
diffListOf
<
ComparableRvItem
<*>>()
...
@@ -102,7 +126,7 @@ class ModuleViewModel(
...
@@ -102,7 +126,7 @@ class ModuleViewModel(
return
return
}
}
remoteJob
=
Single
.
fromCallable
{
itemsRemote
.
size
}
remoteJob
=
Single
.
fromCallable
{
itemsRemote
.
size
}
.
flatMap
{
loadRe
pos
(
offset
=
it
)
}
.
flatMap
{
loadRe
moteInternal
(
offset
=
it
)
}
.
map
{
it
.
map
{
RepoItem
(
it
)
}
}
.
map
{
it
.
map
{
RepoItem
(
it
)
}
}
.
subscribeK
(
onError
=
{
.
subscribeK
(
onError
=
{
Timber
.
e
(
it
)
Timber
.
e
(
it
)
...
@@ -114,14 +138,49 @@ class ModuleViewModel(
...
@@ -114,14 +138,49 @@ class ModuleViewModel(
}
}
}
}
private
fun
loadRepos
(
// ---
override
fun
submitQuery
()
{
queryHandler
.
removeCallbacks
(
queryRunnable
)
queryHandler
.
postDelayed
(
queryRunnable
,
queryDelay
)
}
private
fun
queryInternal
(
query
:
String
,
offset
:
Int
):
Single
<
List
<
RepoItem
>>
{
if
(
query
.
isBlank
())
{
return
Single
.
just
(
listOf
<
RepoItem
>())
.
doOnSubscribe
{
itemsSearch
.
clear
()
}
.
subscribeOn
(
AndroidSchedulers
.
mainThread
())
}
return
Single
.
fromCallable
{
dao
.
searchRepos
(
query
,
offset
)
}
.
map
{
it
.
map
{
RepoItem
(
it
)
}
}
}
private
fun
query
(
query
:
String
=
this
.
query
,
offset
:
Int
=
0
)
{
queryJob
?.
dispose
()
queryJob
=
queryInternal
(
query
,
offset
)
.
map
{
it
to
itemsSearch
.
calculateDiff
(
it
)
}
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
doOnSuccess
{
searchLoading
.
value
=
false
}
.
subscribeK
{
itemsSearch
.
update
(
it
.
first
,
it
.
second
)
}
}
@Synchronized
fun
loadMoreQuery
()
{
if
(
queryJob
?.
isDisposed
==
false
)
return
queryJob
=
queryInternal
(
query
,
itemsSearch
.
size
)
.
subscribeK
{
itemsSearch
.
addAll
(
it
)
}
}
// ---
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
<
Repo
>>
=
Single
.
fromCallable
{
dao
.
getRepos
(
offset
)
}.
flatMap
{
when
{
when
{
// in case we find result empty and offset is initial we need to refresh the repos.
// in case we find result empty and offset is initial we need to refresh the repos.
downloadRepos
&&
it
.
isEmpty
()
&&
offset
==
0
->
downloadRepos
()
downloadRepos
&&
it
.
isEmpty
()
&&
offset
==
0
->
downloadRepos
()
.
andThen
(
loadRe
pos
(
downloadRepos
=
false
))
.
andThen
(
loadRe
moteInternal
(
downloadRepos
=
false
))
else
->
Single
.
just
(
it
)
else
->
Single
.
just
(
it
)
}
}
}
}
...
@@ -137,7 +196,8 @@ class ModuleViewModel(
...
@@ -137,7 +196,8 @@ class ModuleViewModel(
.
sortedBy
{
it
.
item
.
name
.
toLowerCase
(
currentLocale
)
}
.
sortedBy
{
it
.
item
.
name
.
toLowerCase
(
currentLocale
)
}
.
toList
()
.
toList
()
private
fun
update
(
repo
:
Repo
,
progress
:
Int
)
=
Single
.
fromCallable
{
itemsRemote
}
private
fun
update
(
repo
:
Repo
,
progress
:
Int
)
=
Single
.
fromCallable
{
itemsRemote
+
itemsSearch
}
.
map
{
it
.
first
{
it
.
item
.
id
==
repo
.
id
}
}
.
map
{
it
.
first
{
it
.
item
.
id
==
repo
.
id
}
}
.
subscribeK
{
it
.
progress
.
value
=
progress
}
.
subscribeK
{
it
.
progress
.
value
=
progress
}
.
add
()
.
add
()
...
...
app/src/main/res/drawable/bg_shadow.xml
0 → 100644
View file @
9d1d1710
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"rectangle"
>
<gradient
android:angle=
"270"
android:endColor=
"?colorSurfaceVariant"
android:startColor=
"@android:color/transparent"
/>
</shape>
\ No newline at end of file
app/src/main/res/layout/fragment_module_md2.xml
View file @
9d1d1710
...
@@ -15,6 +15,10 @@
...
@@ -15,6 +15,10 @@
</data>
</data>
<FrameLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/module_remote"
android:id=
"@+id/module_remote"
adapter=
"@{viewModel.adapter}"
adapter=
"@{viewModel.adapter}"
...
@@ -34,4 +38,38 @@
...
@@ -34,4 +38,38 @@
app:spanCount=
"2"
app:spanCount=
"2"
tools:listitem=
"@layout/item_module_md2"
/>
tools:listitem=
"@layout/item_module_md2"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id=
"@+id/module_filter_toggle"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"bottom|end"
android:layout_marginStart=
"@dimen/l1"
android:layout_marginEnd=
"@dimen/l1"
android:layout_marginBottom=
"@{viewModel.insets.bottom + (int) @dimen/l1}"
app:backgroundTint=
"?colorSurface"
app:srcCompat=
"@drawable/ic_filter"
app:tint=
"?colorPrimary"
tools:layout_marginBottom=
"64dp"
/>
<com.google.android.material.circularreveal.cardview.CircularRevealCardView
android:id=
"@+id/module_filter"
style=
"?styleCardVariant"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"bottom"
android:visibility=
"invisible"
app:cardCornerRadius=
"0dp"
>
<include
android:id=
"@+id/module_filter_include"
layout=
"@layout/include_module_filter"
viewModel=
"@{viewModel}"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
</com.google.android.material.circularreveal.cardview.CircularRevealCardView>
</FrameLayout>
</layout>
</layout>
\ No newline at end of file
app/src/main/res/layout/include_module_filter.xml
0 → 100644
View file @
9d1d1710
<?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=
"viewModel"
type=
"com.topjohnwu.magisk.redesign.module.ModuleViewModel"
/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:clipToPadding=
"false"
android:orientation=
"vertical"
android:paddingBottom=
"@{viewModel.insets.bottom + (int) @dimen/l1}"
tools:layout_gravity=
"bottom"
tools:paddingBottom=
"64dp"
>
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/module_filter_list"
dividerHorizontal=
"@{R.drawable.divider_l1}"
dividerVertical=
"@{R.drawable.divider_l1}"
itemBinding=
"@{viewModel.itemSearchBinding}"
items=
"@{viewModel.itemsSearch}"
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
android:layout_marginBottom=
"@dimen/l1"
android:clipToPadding=
"false"
android:orientation=
"vertical"
android:paddingStart=
"@dimen/l1"
android:paddingTop=
"@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}"
app:layoutManager=
"androidx.recyclerview.widget.StaggeredGridLayoutManager"
app:layout_constrainedHeight=
"true"
app:layout_constraintBottom_toTopOf=
"@+id/module_filter_title_search"
app:layout_constraintTop_toTopOf=
"parent"
app:reverseLayout=
"false"
app:spanCount=
"2"
tools:listitem=
"@layout/item_repo_md2"
/>
<View
android:layout_width=
"match_parent"
android:layout_height=
"@dimen/l_50"
android:background=
"@drawable/bg_shadow"
app:layout_constraintBottom_toBottomOf=
"@+id/module_filter_list"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/module_filter_title_search"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"@dimen/l1"
android:layout_marginEnd=
"@dimen/l1"
android:layout_marginBottom=
"@dimen/l1"
android:text=
"@string/hide_search"
android:textAllCaps=
"true"
android:textAppearance=
"?appearanceTextCaptionNormal"
android:textColor=
"?colorPrimary"
android:textStyle=
"bold"
app:layout_constraintBottom_toTopOf=
"@+id/module_filter_search"
/>
<com.google.android.material.card.MaterialCardView
android:id=
"@+id/module_filter_search"
style=
"?styleCardNormal"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"@dimen/l1"
android:layout_marginEnd=
"@dimen/l1"
android:layout_marginBottom=
"@dimen/l_50"
app:cardCornerRadius=
"18dp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toStartOf=
"@+id/module_filter_done"
app:layout_constraintStart_toStartOf=
"parent"
>
<androidx.appcompat.widget.AppCompatImageView
style=
"?styleIconNormal"
android:layout_width=
"48dp"
android:layout_height=
"36dp"
android:layout_gravity=
"center_vertical|start"
android:padding=
"6dp"
app:srcCompat=
"@drawable/ic_search_md2"
app:tint=
"?colorDisabled"
/>
<androidx.appcompat.widget.AppCompatEditText
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"48dp"
android:background=
"@null"
android:hint=
"@string/hide_filter_hint"
android:inputType=
"textUri"
android:minHeight=
"36dp"
android:paddingStart=
"0dp"
android:paddingEnd=
"@dimen/l1"
android:singleLine=
"true"
android:text=
"@={viewModel.query}"
android:textAppearance=
"?appearanceTextBodyNormal"
android:textColor=
"?colorTextTransient"
android:textColorHint=
"?colorOnSurfaceVariant"
/>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id=
"@+id/module_filter_done"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"@dimen/l1"
app:backgroundTint=
"?colorPrimary"
app:elevation=
"0dp"
app:fabSize=
"mini"
app:layout_constraintBottom_toBottomOf=
"@+id/module_filter_search"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toTopOf=
"@+id/module_filter_search"
app:srcCompat=
"@drawable/ic_check_md2"
/>
<ProgressBar
style=
"?styleProgressIndeterminateCircular"
goneUnless=
"@{viewModel.searchLoading}"
android:layout_width=
"56dp"
android:layout_height=
"56dp"
app:layout_constraintBottom_toBottomOf=
"@+id/module_filter_done"
app:layout_constraintEnd_toEndOf=
"@+id/module_filter_done"
app:layout_constraintStart_toStartOf=
"@+id/module_filter_done"
app:layout_constraintTop_toTopOf=
"@+id/module_filter_done"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
app/src/main/res/values-v21/styles_md2_impl.xml
View file @
9d1d1710
...
@@ -8,4 +8,11 @@
...
@@ -8,4 +8,11 @@
<item
name=
"android:indeterminateTint"
>
?colorPrimary
</item>
<item
name=
"android:indeterminateTint"
>
?colorPrimary
</item>
</style>
</style>
<style
name=
"WidgetFoundation.ProgressBar.Indeterminate.Circular"
parent=
"Widget.AppCompat.ProgressBar"
>
<item
name=
"android:indeterminate"
>
true
</item>
<item
name=
"android:layout_height"
>
wrap_content
</item>
<item
name=
"android:layout_width"
>
wrap_content
</item>
<item
name=
"android:indeterminateTint"
>
?colorPrimary
</item>
</style>
</resources>
</resources>
\ No newline at end of file
app/src/main/res/values/attrs.xml
View file @
9d1d1710
...
@@ -50,6 +50,7 @@
...
@@ -50,6 +50,7 @@
<!--Progress-->
<!--Progress-->
<attr
name=
"styleProgressDeterminate"
format=
"reference"
/>
<attr
name=
"styleProgressDeterminate"
format=
"reference"
/>
<attr
name=
"styleProgressIndeterminate"
format=
"reference"
/>
<attr
name=
"styleProgressIndeterminate"
format=
"reference"
/>
<attr
name=
"styleProgressIndeterminateCircular"
format=
"reference"
/>
<!--endregion-->
<!--endregion-->
...
...
app/src/main/res/values/styles_md2.xml
View file @
9d1d1710
...
@@ -56,7 +56,11 @@
...
@@ -56,7 +56,11 @@
<item
name=
"styleRadioNormal"
>
@style/WidgetFoundation.RadioButton
</item>
<item
name=
"styleRadioNormal"
>
@style/WidgetFoundation.RadioButton
</item>
<item
name=
"styleProgressDeterminate"
>
@style/WidgetFoundation.ProgressBar
</item>
<item
name=
"styleProgressDeterminate"
>
@style/WidgetFoundation.ProgressBar
</item>
<item
name=
"styleProgressIndeterminate"
>
@style/WidgetFoundation.ProgressBar.Indeterminate
<item
name=
"styleProgressIndeterminate"
>
@style/WidgetFoundation.ProgressBar.Indeterminate
</item>
<item
name=
"styleProgressIndeterminateCircular"
>
@style/WidgetFoundation.ProgressBar.Indeterminate.Circular
</item>
</item>
<!--///-->
<!--///-->
...
...
app/src/main/res/values/styles_md2_impl.xml
View file @
9d1d1710
...
@@ -162,4 +162,10 @@ variant. Make sure to use style referenced by attribute defined it attrs.xml.
...
@@ -162,4 +162,10 @@ variant. Make sure to use style referenced by attribute defined it attrs.xml.
<item
name=
"android:layout_width"
>
100dp
</item>
<item
name=
"android:layout_width"
>
100dp
</item>
</style>
</style>
<style
name=
"WidgetFoundation.ProgressBar.Indeterminate.Circular"
parent=
"Widget.AppCompat.ProgressBar"
>
<item
name=
"android:indeterminate"
>
true
</item>
<item
name=
"android:layout_height"
>
wrap_content
</item>
<item
name=
"android:layout_width"
>
wrap_content
</item>
</style>
</resources>
</resources>
\ 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