Skip to content

Commit

Permalink
Merge branch 'zjyzip:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
wfvw126 authored Feb 13, 2024
2 parents 6b05a93 + 2dd60e8 commit 795cde8
Show file tree
Hide file tree
Showing 15 changed files with 390 additions and 410 deletions.
9 changes: 9 additions & 0 deletions app/src/main/java/com/close/hook/ads/data/dao/UrlDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,18 @@ interface UrlDao {
@Update
fun update(url: Url): Int

@Insert
fun insertAll(urls: List<Url>)

@Query("select * from url_info ORDER BY id DESC")
fun loadAllList(): List<Url>

@Query("SELECT url FROM url_info")
fun getAllUrls(): List<String>

@Query("SELECT * FROM url_info WHERE url LIKE :searchText")
fun searchUrls(searchText: String): List<Url>

@Query("SELECT 1 FROM url_info WHERE url = :url LIMIT 1")
fun isExist(url: String): Boolean

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ abstract class UrlDatabase : RoomDatabase() {
context.applicationContext,
UrlDatabase::class.java, "url_database"
)
.addMigrations(MIGRATION_1_2)
.addMigrations(MIGRATION_2_3)
.allowMainThreadQueries()
.addMigrations(MIGRATION_1_2, MIGRATION_2_3)
.build().apply {
instance = this
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.close.hook.ads.data.repository

import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import com.close.hook.ads.data.model.AppInfo
import com.close.hook.ads.ui.activity.MainActivity
import com.close.hook.ads.util.AppUtils
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.schedulers.Schedulers
import java.io.File

class AppRepository(private val packageManager: PackageManager) {

companion object {
private const val TAG = "AppRepository"
}

fun getInstalledUserApps(): Observable<List<AppInfo>> = getInstalledApps(false)

fun getInstalledSystemApps(): Observable<List<AppInfo>> = getInstalledApps(true)

private fun getInstalledApps(isSystem: Boolean): Observable<List<AppInfo>> =
Observable.fromCallable { fetchInstalledApps(isSystem) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError { e -> Log.e(TAG, "Error fetching apps: ", e) }
.onErrorReturnItem(ArrayList())

private fun fetchInstalledApps(isSystem: Boolean): List<AppInfo> {
val allPackages = packageManager.getInstalledPackages(0)
return allPackages.filter {
isSystemApp(it.applicationInfo) == isSystem
}.map { packageInfo ->
createAppInfo(packageInfo)
}.sortedBy { it.appName.toLowerCase() }
}

private fun isSystemApp(applicationInfo: ApplicationInfo): Boolean =
applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0

private fun createAppInfo(packageInfo: android.content.pm.PackageInfo): AppInfo {
val appName = packageManager.getApplicationLabel(packageInfo.applicationInfo).toString()
val appIcon = packageManager.getApplicationIcon(packageInfo.applicationInfo)
val size = File(packageInfo.applicationInfo.sourceDir).length()
val versionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
packageInfo.longVersionCode.toInt()
} else {
packageInfo.versionCode
}
val isAppEnable = getIsAppEnable(packageInfo.packageName)
val isEnable = if (MainActivity.isModuleActivated()) AppUtils.isAppEnabled(packageInfo.packageName) else 0

return AppInfo(
appName,
packageInfo.packageName,
appIcon,
packageInfo.versionName,
versionCode,
packageInfo.firstInstallTime,
packageInfo.lastUpdateTime,
size,
packageInfo.applicationInfo.targetSdkVersion,
isAppEnable,
isEnable
)
}

private fun getIsAppEnable(packageName: String): Int =
if (packageManager.getApplicationEnabledSetting(packageName) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED) 1 else 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import com.google.android.material.textfield.TextInputEditText
import android.net.Uri
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand All @@ -42,6 +44,7 @@ class BlockListActivity : BaseActivity() {
private val viewModel by lazy { ViewModelProvider(this)[BlockListViewModel::class.java] }
private lateinit var mAdapter: BlockListAdapter
private lateinit var mLayoutManager: RecyclerView.LayoutManager
private var searchJob: Job? = null
private val urlDao by lazy {
UrlDatabase.getDatabase(this).urlDao
}
Expand All @@ -53,7 +56,7 @@ class BlockListActivity : BaseActivity() {

initView()
if (viewModel.blockList.isEmpty()) {
viewModel.getBlackList(this)
viewModel.getBlackList()
} else {
submitList()
}
Expand All @@ -63,11 +66,10 @@ class BlockListActivity : BaseActivity() {
initEditText()
initButton()

viewModel.blackListLiveData.observe(this) {
if (viewModel.blockList.isEmpty()) {
viewModel.blockList.addAll(it)
submitList()
}
viewModel.blackListLiveData.observe(this) { newList ->
viewModel.blockList.clear()
viewModel.blockList.addAll(newList)
submitList()
}
}

Expand Down Expand Up @@ -166,10 +168,17 @@ class BlockListActivity : BaseActivity() {
val newType = type.text.toString()
val newUrl = editText.text.toString()
CoroutineScope(Dispatchers.IO).launch {
urlDao.insert(Url(newType, newUrl))
withContext(Dispatchers.Main) {
viewModel.blockList.add(0, Item(newType, newUrl))
submitList()
val isExist = urlDao.isExist(newUrl)
if (!isExist) {
urlDao.insert(Url(newType, newUrl))
withContext(Dispatchers.Main) {
viewModel.blockList.add(0, Item(newType, newUrl))
submitList()
}
} else {
withContext(Dispatchers.Main) {
Toast.makeText(this@BlockListActivity, "规则已存在", Toast.LENGTH_SHORT).show()
}
}
}
}
Expand Down Expand Up @@ -205,33 +214,42 @@ class BlockListActivity : BaseActivity() {

private fun search() {
val searchText = binding.editText.text.toString()
if (searchText.isNotEmpty()) {
val filteredList = viewModel.blockList.filter { it.url.contains(searchText, ignoreCase = true) }
searchJob?.cancel()
searchJob = CoroutineScope(Dispatchers.Main).launch {
val filteredList = withContext(Dispatchers.IO) {
urlDao.searchUrls("%$searchText%").map { Item(it.type, it.url) }
}
mAdapter.submitList(filteredList)
} else {
mAdapter.submitList(viewModel.blockList)
}
}

private fun initEditText() {
binding.editText.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
binding.editText.apply {
addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}

override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
binding.clear.visibility = if (binding.editText.text.isNullOrEmpty()) View.GONE else View.VISIBLE
search()
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
binding.clear.visibility = if (s.isEmpty()) View.GONE else View.VISIBLE
searchJob?.cancel()
searchJob = CoroutineScope(Dispatchers.Main).launch {
delay(300)
search()
}
}

override fun afterTextChanged(s: Editable) {}
})
override fun afterTextChanged(s: Editable) {}
})

binding.editText.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(binding.editText.windowToken, 0)
true
} else {
false
setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
searchJob?.cancel()
search()
(getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)
?.hideSoftInputFromWindow(windowToken, 0)
true
} else {
false
}
}
}
}
Expand All @@ -249,23 +267,22 @@ class BlockListActivity : BaseActivity() {
uri?.let { uri ->
CoroutineScope(Dispatchers.IO).launch {
try {
val newItems = contentResolver.openInputStream(uri)?.bufferedReader()?.useLines { lines ->
val existingUrls = urlDao.getAllUrls().toSet() // 获取所有现有的URLs并转换为集合
val inputStream = contentResolver.openInputStream(uri)
val newItems = inputStream?.bufferedReader()?.useLines { lines ->
lines.mapNotNull { line ->
val parts = line.split(",\\s*".toRegex()).map { it.trim() }
if (parts.size == 2) Item(parts[0], parts[1]) else null
}
.distinct()
.sortedBy { it.url }
.toList()
if (parts.size == 2 && parts[1] !in existingUrls) Url(parts[0], parts[1]) else null
}.toList()
} ?: listOf()

newItems.forEach { item ->
if (viewModel.blockList.indexOf(Item(item.type, item.url)) == -1) {
urlDao.insert(Url(item.type, item.url))
viewModel.blockList.add(0, Item(item.type, item.url))
}
if (newItems.isNotEmpty()) {
urlDao.insertAll(newItems)
}

val newBlockItems = newItems.map { Item(it.type, it.url) }
viewModel.blockList.addAll(0, newBlockItems)

withContext(Dispatchers.Main) {
submitList()
Toast.makeText(this@BlockListActivity, "导入成功", Toast.LENGTH_SHORT).show()
Expand Down
Loading

0 comments on commit 795cde8

Please sign in to comment.