diff --git a/.idea/misc.xml b/.idea/misc.xml
index 0682c959..31799fa1 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -9,8 +9,10 @@
+
+
diff --git a/README.md b/README.md
index 3521350b..35e1e243 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
# MIUI 原生通知图标
-![Eclipse Marketplace](https://img.shields.io/badge/build-pending-dbab09)
+![Eclipse Marketplace](https://img.shields.io/badge/build-passing-brightgreen)
![Eclipse Marketplace](https://img.shields.io/badge/license-AGPL3.0-blue)
-![Eclipse Marketplace](https://img.shields.io/badge/version-v1.36-green)
+![Eclipse Marketplace](https://img.shields.io/badge/version-v1.5-green)
@@ -12,7 +12,7 @@ Fix the native notification bar icon function abandoned by the MIUI development
# 开始使用
点击下载最新版本
-![Eclipse Marketplace](https://img.shields.io/badge/download-v1.36-green)
+![Eclipse Marketplace](https://img.shields.io/badge/download-v1.5-green)
⚠️ 适配说明
diff --git a/app/build.gradle b/app/build.gradle
index 3519878a..b98b7e93 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -20,7 +20,7 @@ android {
defaultConfig {
applicationId "com.fankes.miui.notify"
- minSdk 23
+ minSdk 28
targetSdk 31
versionCode rootProject.ext.appVersionCode
versionName rootProject.ext.appVersionName
@@ -42,6 +42,9 @@ android {
kotlinOptions {
jvmTarget = '1.8'
}
+ buildFeatures {
+ viewBinding true
+ }
}
/** 移除无效耗时 lint Task */
@@ -57,6 +60,9 @@ tasks.whenTaskAdded {
dependencies {
implementation "com.github.topjohnwu.libsu:core:3.1.2"
+ implementation 'androidx.annotation:annotation:1.3.0'
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
compileOnly 'de.robv.android.xposed:api:82'
implementation 'com.highcapable.yukihookapi:api:1.0.1'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.1'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e84fd702..596c36e8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -16,43 +16,42 @@
-
-
-
+
-
+ android:targetActivity=".ui.MainActivity">
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/data/LoginDataSource.kt b/app/src/main/java/com/fankes/miui/notify/data/LoginDataSource.kt
new file mode 100644
index 00000000..b295bf62
--- /dev/null
+++ b/app/src/main/java/com/fankes/miui/notify/data/LoginDataSource.kt
@@ -0,0 +1,24 @@
+package com.fankes.miui.notify.data
+
+import com.fankes.miui.notify.data.model.LoggedInUser
+import java.io.IOException
+
+/**
+ * Class that handles authentication w/ login credentials and retrieves user information.
+ */
+class LoginDataSource {
+
+ fun login(username: String, password: String): Result {
+ try {
+ // TODO: handle loggedInUser authentication
+ val fakeUser = LoggedInUser(java.util.UUID.randomUUID().toString(), "Jane Doe")
+ return Result.Success(fakeUser)
+ } catch (e: Throwable) {
+ return Result.Error(IOException("Error logging in", e))
+ }
+ }
+
+ fun logout() {
+ // TODO: revoke authentication
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/data/LoginRepository.kt b/app/src/main/java/com/fankes/miui/notify/data/LoginRepository.kt
new file mode 100644
index 00000000..43dc2d9b
--- /dev/null
+++ b/app/src/main/java/com/fankes/miui/notify/data/LoginRepository.kt
@@ -0,0 +1,46 @@
+package com.fankes.miui.notify.data
+
+import com.fankes.miui.notify.data.model.LoggedInUser
+
+/**
+ * Class that requests authentication and user information from the remote data source and
+ * maintains an in-memory cache of login status and user credentials information.
+ */
+
+class LoginRepository(val dataSource: LoginDataSource) {
+
+ // in-memory cache of the loggedInUser object
+ var user: LoggedInUser? = null
+ private set
+
+ val isLoggedIn: Boolean
+ get() = user != null
+
+ init {
+ // If user credentials will be cached in local storage, it is recommended it be encrypted
+ // @see https://developer.android.com/training/articles/keystore
+ user = null
+ }
+
+ fun logout() {
+ user = null
+ dataSource.logout()
+ }
+
+ fun login(username: String, password: String): Result {
+ // handle login
+ val result = dataSource.login(username, password)
+
+ if (result is Result.Success) {
+ setLoggedInUser(result.data)
+ }
+
+ return result
+ }
+
+ private fun setLoggedInUser(loggedInUser: LoggedInUser) {
+ this.user = loggedInUser
+ // If user credentials will be cached in local storage, it is recommended it be encrypted
+ // @see https://developer.android.com/training/articles/keystore
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/data/Result.kt b/app/src/main/java/com/fankes/miui/notify/data/Result.kt
new file mode 100644
index 00000000..01cbbeb0
--- /dev/null
+++ b/app/src/main/java/com/fankes/miui/notify/data/Result.kt
@@ -0,0 +1,18 @@
+package com.fankes.miui.notify.data
+
+/**
+ * A generic class that holds a value with its loading status.
+ * @param
+ */
+sealed class Result {
+
+ data class Success(val data: T) : Result()
+ data class Error(val exception: Exception) : Result()
+
+ override fun toString(): String {
+ return when (this) {
+ is Success<*> -> "Success[data=$data]"
+ is Error -> "Error[exception=$exception]"
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/data/model/LoggedInUser.kt b/app/src/main/java/com/fankes/miui/notify/data/model/LoggedInUser.kt
new file mode 100644
index 00000000..d2f3ff55
--- /dev/null
+++ b/app/src/main/java/com/fankes/miui/notify/data/model/LoggedInUser.kt
@@ -0,0 +1,9 @@
+package com.fankes.miui.notify.data.model
+
+/**
+ * Data class that captures user information for logged in users retrieved from LoginRepository
+ */
+data class LoggedInUser(
+ val userId: String,
+ val displayName: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/ui/ConfigureActivity.kt b/app/src/main/java/com/fankes/miui/notify/ui/ConfigureActivity.kt
index 3e5acf99..9bb0623f 100644
--- a/app/src/main/java/com/fankes/miui/notify/ui/ConfigureActivity.kt
+++ b/app/src/main/java/com/fankes/miui/notify/ui/ConfigureActivity.kt
@@ -35,6 +35,7 @@ import android.widget.ListView
import android.widget.TextView
import android.widget.Toast
import androidx.constraintlayout.utils.widget.ImageFilterView
+import androidx.core.view.isVisible
import com.fankes.miui.notify.R
import com.fankes.miui.notify.hook.factory.isAppNotifyHookAllOf
import com.fankes.miui.notify.hook.factory.isAppNotifyHookOf
@@ -43,20 +44,58 @@ import com.fankes.miui.notify.hook.factory.putAppNotifyHookOf
import com.fankes.miui.notify.params.IconPackParams
import com.fankes.miui.notify.ui.base.BaseActivity
import com.fankes.miui.notify.utils.SystemUITool
+import com.fankes.miui.notify.utils.showDialog
import com.fankes.miui.notify.view.MaterialSwitch
+import com.google.android.material.textfield.TextInputEditText
class ConfigureActivity : BaseActivity() {
+ /** 当前筛选条件 */
+ private var filterText = ""
+
+ /** 回调适配器改变 */
+ private var onChanged: (() -> Unit)? = null
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_config)
/** 返回按钮点击事件 */
findViewById(R.id.title_back_icon).setOnClickListener { onBackPressed() }
- /** 设置标题个数文本 */
- findViewById(R.id.config_title_count_text).text = "已适配 ${IconPackParams.iconDatas.size} 个 APP 的通知图标"
- /** 设置搜索按钮点击事件 */
- findViewById(R.id.config_title_search).setOnClickListener {
- Toast.makeText(this, "后期开放", Toast.LENGTH_SHORT).show()
+ /** 刷新适配器结果相关 */
+ refreshAdapterResult()
+ /** 设置过滤按钮点击事件 */
+ findViewById(R.id.config_title_filter).setOnClickListener {
+ showDialog {
+ title = "按条件过滤"
+ var editText: TextInputEditText
+ addView(R.layout.dia_icon_filter).apply {
+ editText = findViewById(R.id.dia_icon_filter_input_edit).apply {
+ requestFocus()
+ invalidate()
+ if (filterText.isNotBlank()) {
+ setText(filterText)
+ setSelection(filterText.length)
+ }
+ }
+ }
+ confirmButton {
+ if (editText.text.toString().isNotBlank()) {
+ filterText = editText.text.toString().trim()
+ onChanged?.invoke()
+ refreshAdapterResult()
+ } else {
+ Toast.makeText(applicationContext, "条件不能为空", Toast.LENGTH_SHORT).show()
+ it.performClick()
+ }
+ }
+ cancelButton()
+ if (filterText.isNotBlank())
+ neutralButton(text = "清除条件") {
+ filterText = ""
+ onChanged?.invoke()
+ refreshAdapterResult()
+ }
+ }
}
/** 设置列表元素和 Adapter */
findViewById(R.id.config_list_view).apply {
@@ -64,9 +103,9 @@ class ConfigureActivity : BaseActivity() {
private val inflater = LayoutInflater.from(context)
- override fun getCount() = IconPackParams.iconDatas.size
+ override fun getCount() = iconDatas.size
- override fun getItem(position: Int) = IconPackParams.iconDatas[position]
+ override fun getItem(position: Int) = iconDatas[position]
override fun getItemId(position: Int) = position.toLong()
@@ -118,7 +157,7 @@ class ConfigureActivity : BaseActivity() {
lateinit var switchOpen: MaterialSwitch
lateinit var switchAll: MaterialSwitch
}
- }
+ }.apply { onChanged = { notifyDataSetChanged() } }
}
/** 设置点击事件 */
findViewById(R.id.config_cbr_button).setOnClickListener {
@@ -134,4 +173,22 @@ class ConfigureActivity : BaseActivity() {
}
}
}
+
+ /** 刷新适配器结果相关 */
+ private fun refreshAdapterResult() {
+ findViewById(R.id.config_title_count_text).text =
+ if (filterText.isBlank()) "已适配 ${iconDatas.size} 个 APP 的通知图标"
+ else "“${filterText}” 匹配到 ${iconDatas.size} 个结果"
+ findViewById(R.id.config_list_no_data_view).isVisible = iconDatas.isEmpty()
+ }
+
+ /**
+ * 当前结果下的图标数组
+ * @return [Array]
+ */
+ private val iconDatas
+ get() = if (filterText.isBlank()) IconPackParams.iconDatas
+ else IconPackParams.iconDatas.filter {
+ it.appName.lowercase().contains(filterText.lowercase()) || it.packageName.lowercase().contains(filterText.lowercase())
+ }.toTypedArray()
}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/utils/DialogBuilder.kt b/app/src/main/java/com/fankes/miui/notify/utils/DialogBuilder.kt
index 605ca663..5b98646f 100644
--- a/app/src/main/java/com/fankes/miui/notify/utils/DialogBuilder.kt
+++ b/app/src/main/java/com/fankes/miui/notify/utils/DialogBuilder.kt
@@ -20,7 +20,7 @@
*
* This file is Created by fankes on 2022/1/7.
*/
-@file:Suppress("unused")
+@file:Suppress("unused", "DEPRECATION")
package com.fankes.miui.notify.utils
@@ -28,7 +28,11 @@ import android.app.AlertDialog
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
-
+import android.util.DisplayMetrics
+import android.view.LayoutInflater
+import android.view.View
+import android.view.WindowManager
+import kotlin.math.round
/**
* 构造对话框
@@ -44,6 +48,8 @@ class DialogBuilder(private val context: Context) {
private var instance: AlertDialog.Builder? = null // 实例对象
+ private var customLayoutView: View? = null // 自定义布局
+
init {
instance = AlertDialog.Builder(context, android.R.style.Theme_Material_Light_Dialog)
}
@@ -65,6 +71,16 @@ class DialogBuilder(private val context: Context) {
instance?.setMessage(value)
}
+ /**
+ * 设置对话框自定义布局
+ * @param resId 属性资源 Id
+ * @return [View]
+ */
+ fun addView(resId: Int): View {
+ customLayoutView = LayoutInflater.from(context).inflate(resId, null)
+ return customLayoutView ?: error("Inflate $resId failed")
+ }
+
/**
* 设置对话框确定按钮
* @param text 按钮文本内容
@@ -91,6 +107,9 @@ class DialogBuilder(private val context: Context) {
/** 显示对话框 */
internal fun show() = instance?.create()?.apply {
+ val dm = DisplayMetrics()
+ (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.getMetrics(dm)
+ customLayoutView?.let { setView(it.apply { minimumWidth = round(dm.widthPixels / 1.3).toInt() }) }
window?.setBackgroundDrawable(GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
intArrayOf(Color.WHITE, Color.WHITE)
diff --git a/app/src/main/res/layout/activity_config.xml b/app/src/main/res/layout/activity_config.xml
index c782c845..06908911 100644
--- a/app/src/main/res/layout/activity_config.xml
+++ b/app/src/main/res/layout/activity_config.xml
@@ -26,11 +26,13 @@
android:layout_marginStart="10dp"
android:layout_marginEnd="25dp"
android:src="@mipmap/back"
- android:tint="@color/colorTextGray" />
+ android:tint="@color/colorTextGray"
+ android:tooltipText="返回" />
@@ -56,12 +58,13 @@
+ android:src="@mipmap/icon_filter"
+ android:tint="@color/colorTextGray"
+ android:tooltipText="按条件过滤" />
-
+ android:layout_weight="1">
+
+
+
+
+
@@ -359,7 +359,7 @@
android:layout_marginBottom="10dp"
android:alpha="0.8"
android:lineSpacingExtra="6dp"
- android:text="Q.这个模块是如何诞生的?\nA.这个模块诞生来源于 MIUI 的乱改和不规范,本来 MIUI 9 之后,官方给出了原生通知图标样式,后面由于用户反应通知栏经常出现黑白块,这当然不是系统的错,而是国内 APP 极其不规范的通知图标设计,于是 MIUI 选择直接忽略这个问题把全部图标都改成了 APP 的彩色图标,使得之前拥有自有样式的原生图标也被破坏,通知中“setSmallIcon”不再有效,这个模块就是为了修复被 MIUI 开发组忽略的图标问题,并完美地给 MIUI 修复了黑白块图标的问题。"
+ android:text="Q.这个模块是如何诞生的?\nA.这个模块诞生来源于 MIUI 的乱改和不规范,本来 MIUI 9 之后,官方给出了原生通知图标样式,后面由于用户反应通知栏经常出现黑白块。\n这当然不是系统的错,而是国内 APP 和 MIPUSH 的通知极其不规范的通知图标设计。\n但是呢,接到反馈后 MIUI 开发组选择直接忽略这个问题,在 2021-5-18 的开发版开始,把全部通知图标都改成了 APP 的彩色图标,使得之前拥有自有样式的原生图标也被破坏。\n对于 Android 开发者来说,官方文档中的 “setSmallIcon” 不再适用于魔改后的 MIUI,这将会严重破坏非常多的状态图标。\n当然,国内的手机生态除了 MIPUSH 的营销通知就是社交软件的通知,可能大部分人都不会在意这件事情。\n但是,这个模块就是为了修复被 MIUI 开发组忽略的图标问题才诞生的,并完美地给 MIUI 修复了黑白块图标的问题。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
@@ -435,7 +435,7 @@
android:layout_height="wrap_content"
android:alpha="0.8"
android:lineSpacingExtra="6dp"
- android:text="本软件是免费开源项目,遵循 GPL 协议,你可以点击这里前往 Github 查看源码以及获取模块更新。\n严禁以任何形式贩卖、商用本软件,否则开发者有权追究其法律责任。"
+ android:text="本软件是免费开源项目,遵循 AGPL3.0 协议,你可以点击这里前往 Github 查看源码以及获取模块更新。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
diff --git a/app/src/main/res/layout/dia_icon_filter.xml b/app/src/main/res/layout/dia_icon_filter.xml
new file mode 100644
index 00000000..dfdbfbba
--- /dev/null
+++ b/app/src/main/res/layout/dia_icon_filter.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_search.png b/app/src/main/res/mipmap-xxhdpi/icon_search.png
deleted file mode 100644
index 35ebe1d2..00000000
Binary files a/app/src/main/res/mipmap-xxhdpi/icon_search.png and /dev/null differ
diff --git a/build.gradle b/build.gradle
index 8c9ed4fa..11024061 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,8 +5,8 @@ plugins {
}
ext {
- appVersionName = "1.36(pending)"
- appVersionCode = 8
+ appVersionName = "1.5"
+ appVersionCode = 9
}
task clean(type: Delete) {