Skip to content

Commit 8b927ba

Browse files
authored
Merge pull request #320 from GuoXiCheng/dev-c
add query to WhiteListActivity
2 parents 4a8c19d + 3c8ce7b commit 8b927ba

File tree

11 files changed

+142
-15
lines changed

11 files changed

+142
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
- 修复加载的配置文件包含 Unicode 编码时未转换为中文的问题
44
- 修复点击右上角「功能介绍」后菜单未自动关闭的问题
55
- 新增「悬浮窗按钮」用于执行布局检查功能
6+
- 应用白名单增加搜索功能
67
- TODO: 断网无法访问的问题
7-
- TODO: 应用白名单增加搜索功能
88

99
## v3.0.0 - 2024.09.27
1010

app/src/main/java/com/android/skip/ui/theme/AppTheme.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,19 @@ private val darkScheme = darkColorScheme(
1919
secondary = PurpleGrey80,
2020
tertiary = Pink80,
2121
background = Black,
22-
onBackground = White
22+
onBackground = White,
23+
primaryContainer = Black54,
24+
onPrimaryContainer = Black91
2325
)
2426

2527
private val lightScheme = lightColorScheme(
2628
primary = Purple40,
2729
secondary = PurpleGrey40,
2830
tertiary = Pink40,
2931
background = White,
30-
onBackground = Black
32+
onBackground = Black,
33+
primaryContainer = Gray232,
34+
onPrimaryContainer = Gray172
3135
)
3236

3337
@Composable

app/src/main/java/com/android/skip/ui/theme/Color.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ val Purple40 = Color(0xFF6650a4)
99
val PurpleGrey40 = Color(0xFF625b71)
1010
val Pink40 = Color(0xFF7D5260)
1111
val White = Color.White
12-
val Black = Color.Black
12+
val Black = Color.Black
13+
val Gray232 = Color(0xFFE8E8E8)
14+
val Gray172 = Color(0xFFACACAC)
15+
val Black54 = Color(0xFF363636)
16+
val Black91 = Color(0xFF5B5B5B)

app/src/main/java/com/android/skip/ui/whitelist/WhiteListActivity.kt

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ import android.os.Bundle
55
import androidx.activity.compose.setContent
66
import androidx.activity.viewModels
77
import androidx.appcompat.app.AppCompatActivity
8+
import androidx.compose.foundation.layout.Column
9+
import androidx.compose.foundation.layout.Spacer
10+
import androidx.compose.foundation.layout.height
811
import androidx.compose.material3.DropdownMenuItem
912
import androidx.compose.material3.Text
13+
import androidx.compose.ui.Modifier
1014
import androidx.compose.ui.res.stringResource
15+
import androidx.compose.ui.unit.dp
1116
import com.android.skip.MyApp
1217
import com.android.skip.R
1318
import com.android.skip.ui.components.ResourceIcon
@@ -18,6 +23,8 @@ import com.android.skip.ui.theme.AppTheme
1823
import com.android.skip.ui.webview.WebViewActivity
1924
import com.android.skip.ui.whitelist.list.AppListColumn
2025
import com.android.skip.ui.whitelist.list.AppListViewModel
26+
import com.android.skip.ui.whitelist.search.SearchTextField
27+
import com.android.skip.ui.whitelist.search.SearchViewModel
2128
import com.android.skip.ui.whitelist.system.ShowSystemButton
2229
import com.android.skip.ui.whitelist.system.ShowSystemViewModel
2330
import dagger.hilt.android.AndroidEntryPoint
@@ -32,12 +39,21 @@ class WhiteListActivity : AppCompatActivity() {
3239

3340
private val switchThemeViewModel by viewModels<SwitchThemeViewModel>()
3441

42+
private val searchViewModel by viewModels<SearchViewModel>()
43+
3544
override fun onCreate(savedInstanceState: Bundle?) {
3645
super.onCreate(savedInstanceState)
3746
setContent {
3847
AppTheme(switchThemeViewModel) {
3948
ScaffoldPage(R.string.whitelist, { finish() }, {
40-
AppListColumn(appListViewModel, whiteListViewModel)
49+
// 添加搜索栏和应用列表
50+
Column {
51+
// 搜索栏
52+
SearchTextField(searchViewModel)
53+
Spacer(modifier = Modifier.height(8.dp))
54+
// 应用列表
55+
AppListColumn(appListViewModel, whiteListViewModel)
56+
}
4157
}, {
4258
DropdownMenuItem(
4359
leadingIcon = { ResourceIcon(iconResource = R.drawable.help) },
@@ -55,7 +71,11 @@ class WhiteListActivity : AppCompatActivity() {
5571
}
5672

5773
showSystemViewModel.isShowSystem.observe(this) {
58-
appListViewModel.reloadData(it)
74+
appListViewModel.reloadData(it, searchViewModel.getQuery())
75+
}
76+
77+
searchViewModel.query.observe(this) {
78+
appListViewModel.reloadData(showSystemViewModel.getIsShowSystem(), it)
5979
}
6080
}
6181
}

app/src/main/java/com/android/skip/ui/whitelist/list/AppListPagingSource.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import javax.inject.Inject
77

88
class AppListPagingSource @Inject constructor(
99
private val appListRepository: AppListRepository,
10-
private val isShowSystem: Boolean
10+
private val isShowSystem: Boolean,
11+
private val query: String
1112
) : PagingSource<Int, AppListItem>() {
1213
override fun getRefreshKey(state: PagingState<Int, AppListItem>): Int? {
1314
return state.anchorPosition?.let { anchorPosition ->
@@ -20,7 +21,7 @@ class AppListPagingSource @Inject constructor(
2021
val currentPage = params.key ?: 0
2122
val pageSize = params.loadSize
2223

23-
val pageData = appListRepository.getData(currentPage, pageSize, isShowSystem)
24+
val pageData = appListRepository.getData(currentPage, pageSize, isShowSystem, query)
2425

2526
return LoadResult.Page(
2627
data = pageData,

app/src/main/java/com/android/skip/ui/whitelist/list/AppListRepository.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,28 @@ class AppListRepository @Inject constructor() {
1616
MyApp.context.packageManager.getInstalledApplications(PackageManager.GET_META_DATA)
1717
}
1818

19-
fun getData(currentPage: Int, pageSize: Int, isShowSystem: Boolean): List<AppListItem> {
19+
fun getData(currentPage: Int, pageSize: Int, isShowSystem: Boolean, query: String = ""): List<AppListItem> {
2020
try {
2121
val pkgManager = MyApp.context.packageManager
2222

23+
// 是否显示系统应用的过滤
2324
val apps = if (isShowSystem) {
2425
appInfos
2526
} else {
2627
appInfos.filter { (it.flags and ApplicationInfo.FLAG_SYSTEM) == 0 }
2728
}
29+
30+
// 根据关键字进行过滤
31+
val filteredApps = if (query.isNotEmpty()) {
32+
apps.filter { it.loadLabel(pkgManager).toString().contains(query, ignoreCase = true) }
33+
} else {
34+
apps
35+
}
36+
2837
val fromIndex = currentPage * pageSize
29-
val toIndex = minOf(fromIndex + pageSize, apps.size)
38+
val toIndex = minOf(fromIndex + pageSize, filteredApps.size)
3039

31-
return apps.subList(fromIndex, toIndex)
40+
return filteredApps.subList(fromIndex, toIndex)
3241
.map {
3342
AppListItem(
3443
it.loadLabel(pkgManager).toString(),

app/src/main/java/com/android/skip/ui/whitelist/list/AppListViewModel.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@ class AppListViewModel @Inject constructor(
2222

2323
private var currentPagingSource: AppListPagingSource? = null
2424

25-
fun reloadData(isShowSystem: Boolean) {
25+
fun reloadData(isShowSystem: Boolean, query: String = "") {
2626
currentPagingSource?.invalidate()
27-
_pagingData.value = createPager(isShowSystem).flow.cachedIn(viewModelScope)
27+
_pagingData.value = createPager(isShowSystem, query).flow.cachedIn(viewModelScope)
2828
}
2929

30-
private fun createPager(isShowSystem: Boolean): Pager<Int, AppListItem> {
30+
private fun createPager(isShowSystem: Boolean, query: String = ""): Pager<Int, AppListItem> {
3131
return Pager(
3232
config = PagingConfig(
3333
pageSize = 20,
3434
enablePlaceholders = false
3535
),
3636
pagingSourceFactory = {
37-
val newPagingSource = AppListPagingSource(appListRepository, isShowSystem)
37+
val newPagingSource = AppListPagingSource(appListRepository, isShowSystem, query)
3838
currentPagingSource = newPagingSource
3939
newPagingSource
4040
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.android.skip.ui.whitelist.search
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.layout.fillMaxWidth
5+
import androidx.compose.foundation.layout.height
6+
import androidx.compose.foundation.layout.padding
7+
import androidx.compose.foundation.shape.RoundedCornerShape
8+
import androidx.compose.material.icons.Icons
9+
import androidx.compose.material.icons.filled.Search
10+
import androidx.compose.material3.Icon
11+
import androidx.compose.material3.MaterialTheme
12+
import androidx.compose.material3.OutlinedTextField
13+
import androidx.compose.material3.OutlinedTextFieldDefaults
14+
import androidx.compose.material3.Text
15+
import androidx.compose.runtime.Composable
16+
import androidx.compose.runtime.livedata.observeAsState
17+
import androidx.compose.ui.Modifier
18+
import androidx.compose.ui.draw.clip
19+
import androidx.compose.ui.graphics.Color
20+
import androidx.compose.ui.res.stringResource
21+
import androidx.compose.ui.unit.dp
22+
import androidx.compose.ui.unit.sp
23+
import com.android.skip.R
24+
25+
@Composable
26+
fun SearchTextField(
27+
searchViewModel: SearchViewModel
28+
) {
29+
val queryValue = searchViewModel.query.observeAsState()
30+
31+
OutlinedTextField(
32+
value = queryValue.value ?: "",
33+
onValueChange = {
34+
searchViewModel.changeQuery(it)
35+
},
36+
placeholder = {
37+
Text(
38+
stringResource(id = R.string.search_hint),
39+
fontSize = 14.sp,
40+
color = Color.Gray
41+
)
42+
},
43+
leadingIcon = {
44+
Icon(
45+
imageVector = Icons.Default.Search,
46+
contentDescription = stringResource(id = R.string.search_hint)
47+
)
48+
},
49+
modifier = Modifier
50+
.fillMaxWidth()
51+
.height(56.dp)
52+
.padding(horizontal = 16.dp)
53+
.clip(RoundedCornerShape(16.dp)) // 圆角效果
54+
.background(color = MaterialTheme.colorScheme.primaryContainer), // 灰色背景
55+
colors = OutlinedTextFieldDefaults.colors(
56+
focusedBorderColor = Color.Transparent,
57+
unfocusedBorderColor = Color.Transparent,
58+
cursorColor = MaterialTheme.colorScheme.onBackground,
59+
focusedTextColor = MaterialTheme.colorScheme.onBackground,
60+
unfocusedTextColor = MaterialTheme.colorScheme.onBackground
61+
)
62+
)
63+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.android.skip.ui.whitelist.search
2+
3+
import androidx.lifecycle.LiveData
4+
import androidx.lifecycle.MutableLiveData
5+
import androidx.lifecycle.ViewModel
6+
import dagger.hilt.android.lifecycle.HiltViewModel
7+
import javax.inject.Inject
8+
9+
@HiltViewModel
10+
class SearchViewModel @Inject constructor(): ViewModel() {
11+
private val _query = MutableLiveData("")
12+
val query: LiveData<String> = _query
13+
14+
fun changeQuery(query: String) {
15+
_query.postValue(query)
16+
}
17+
18+
fun getQuery(): String {
19+
return _query.value ?: ""
20+
}
21+
}

app/src/main/java/com/android/skip/ui/whitelist/system/ShowSystemViewModel.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ class ShowSystemViewModel @Inject constructor():ViewModel() {
1414
fun changeIsShowSystem(isShow: Boolean) {
1515
_isShowSystem.postValue(isShow)
1616
}
17+
18+
fun getIsShowSystem(): Boolean {
19+
return _isShowSystem.value ?: false
20+
}
1721
}

0 commit comments

Comments
 (0)