Compare commits
71 Commits
Author | SHA1 | Date | |
---|---|---|---|
07fa6965ad | |||
4c88a5fbc6 | |||
da61a52c13 | |||
3314f9fb57 | |||
ebb1bec36f | |||
|
d5d2e2107c | ||
|
c39d03f8c9 | ||
|
e20dfab5b1 | ||
|
ffc9be3721 | ||
|
126aedabfd | ||
56661b03e6 | |||
|
c45658be68 | ||
e0443ff97c | |||
9af735e252 | |||
c67fe2fa31 | |||
b03cf30e0a | |||
09191802ad | |||
64f252986b | |||
c073d350d0 | |||
cbeaaa8733 | |||
3b5e066e2d | |||
79843eb0d0 | |||
7a4e254230 | |||
0534ab9218 | |||
5cee229a99 | |||
b6920e3ca1 | |||
|
a4f7c95f84 | ||
38803846cd | |||
fb44c4e945 | |||
a2fc95d765 | |||
0e3ef5418c | |||
4e5e2cee09 | |||
7b4b728523 | |||
9b6540df65 | |||
3e8982aad0 | |||
085f2498c8 | |||
a1e01d1d33 | |||
03aa550487 | |||
ea632b8892 | |||
|
69847a0b0b | ||
|
4cdbfa944d | ||
|
9edb04cf08 | ||
|
071c98e8f3 | ||
|
a317cc07f5 | ||
ef0392a168 | |||
32e9ee3c8b | |||
296f12d07a | |||
df99256231 | |||
60128bcb1a | |||
54aec1051f | |||
121170ba65 | |||
a2d282c3f1 | |||
4d0098f1b8 | |||
49f6bc921c | |||
f94286351b | |||
faad964359 | |||
78308ac558 | |||
03fd389e13 | |||
fb067577af | |||
da5d4eba1b | |||
|
aa22ee05c6 | ||
08873b3e1f | |||
7bfd2046ca | |||
f57e658900 | |||
|
b7ec4559cf | ||
c707f8a3f7 | |||
|
350823f4ec | ||
|
26c6241d38 | ||
|
6e0c42638f | ||
|
8c6d7d7258 | ||
8b9ecc1d87 |
29
.github/ISSUE_TEMPLATE/----------.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: 通知优化图标适配反馈
|
||||||
|
about: 提交通知图标优化适配必须使用此模板提交
|
||||||
|
title: "[通知优化图标适配反馈]"
|
||||||
|
labels: To be adapted
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**需要适配的 APP 名称/包名/通知图标颜色 (必填)**
|
||||||
|
|
||||||
|
* (示例:小米音乐/com.miui.player/#fff16033)
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
**提供相关 APP 的下载渠道截图以及简要说明用途 (必填)**
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
**提供相关 APP 的通知单色图标适配素材 大小 50x50 (选填)**
|
||||||
|
|
||||||
|
* (可填写资源下载地址或直接添加附件提交,不接受百度网盘、天翼云盘以及各种快传、私有云盘)
|
||||||
|
|
||||||
|
* (若直接在附件提交这里可不填)
|
||||||
|
|
||||||
|
<!--- 提交时请将括号内容包括括号全部删除,填入你自己的内容 --->
|
||||||
|
<!--- 请保留模板原始标题 --->
|
||||||
|
<!--- 不按规定提交的 issues 将直接被关闭 --->
|
||||||
|
<!--- Create by Template --->
|
54
.github/ISSUE_TEMPLATE/----bug---.md
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
name: 问题与 BUG 反馈
|
||||||
|
about: 问题反馈必须使用此模板进行提交
|
||||||
|
title: "[问题与 BUG 反馈] *简要描述问题原因*"
|
||||||
|
labels: bug
|
||||||
|
assignees: fankes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**MIUI 版本(必填)**
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
**MIUI 版本类型(请保留一个)**
|
||||||
|
|
||||||
|
* 公测版/内测版/稳定版
|
||||||
|
|
||||||
|
**Android 版本(必填)**
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
**模块版本(必填)**
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
**使用的 Xposed 框架名称与框架版本(必填)**
|
||||||
|
|
||||||
|
* (例如:LSPosed Zygisk/Riru 版本号)
|
||||||
|
|
||||||
|
**同时使用的带有系统界面作用域的 Xposed 模块(选填)**
|
||||||
|
|
||||||
|
* (没有可空)
|
||||||
|
|
||||||
|
**问题的具体描述**
|
||||||
|
|
||||||
|
* (复现步骤、前提以及详细截图和录屏演示)
|
||||||
|
|
||||||
|
|
||||||
|
**提供模块问题 Log 或必要 Log**
|
||||||
|
|
||||||
|
* (LSPosed 可在日志管理中查看并筛选包含 `MIUINativeNotifyIcon` 的日志)
|
||||||
|
|
||||||
|
<details><summary>展开查看</summary><pre><code>
|
||||||
|
|
||||||
|
(此处粘贴问题Log)
|
||||||
|
|
||||||
|
</code></pre></details>
|
||||||
|
|
||||||
|
<!--- 注意:只接受 MIUI 正规官方版本系统,如果你正在使用 MIUI 官改(第三方改版)请不要提交任何 BUG 与问题,开发者无义务解决 --->
|
||||||
|
|
||||||
|
<!--- 提交时请将括号内容包括括号全部删除,填入你自己的内容 --->
|
||||||
|
<!--- 请保留模板原始标题 --->
|
||||||
|
<!--- 不按规定提交的 issues 将直接被关闭 --->
|
||||||
|
<!--- Create by Template --->
|
2
.idea/misc.xml
generated
@@ -10,7 +10,7 @@
|
|||||||
<entry key="app/src/main/res/drawable/white_round.xml" value="0.256" />
|
<entry key="app/src/main/res/drawable/white_round.xml" value="0.256" />
|
||||||
<entry key="app/src/main/res/layout/activity_config.xml" value="0.42168674698795183" />
|
<entry key="app/src/main/res/layout/activity_config.xml" value="0.42168674698795183" />
|
||||||
<entry key="app/src/main/res/layout/activity_login.xml" value="0.4375" />
|
<entry key="app/src/main/res/layout/activity_login.xml" value="0.4375" />
|
||||||
<entry key="app/src/main/res/layout/activity_main.xml" value="0.37516748548459133" />
|
<entry key="app/src/main/res/layout/activity_main.xml" value="0.36160137752905724" />
|
||||||
<entry key="app/src/main/res/layout/adapter_config.xml" value="0.4375" />
|
<entry key="app/src/main/res/layout/adapter_config.xml" value="0.4375" />
|
||||||
<entry key="app/src/main/res/layout/dia_icon_search.xml" value="0.4307692307692308" />
|
<entry key="app/src/main/res/layout/dia_icon_search.xml" value="0.4307692307692308" />
|
||||||
<entry key="app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml" value="0.44871794871794873" />
|
<entry key="app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml" value="0.44871794871794873" />
|
||||||
|
@@ -13,26 +13,33 @@
|
|||||||
|
|
||||||
## 贡献方法
|
## 贡献方法
|
||||||
|
|
||||||
- 在下方的类中添加新的 APP 通知图标适配条目
|
- 2022.02.25 适配数据已变更为云端更新
|
||||||
- [IconPackParams.kt](https://github.com/fankes/MIUINativeNotifyIcon/blob/master/app/src/main/java/com/fankes/miui/notify/params/IconPackParams.kt)
|
- 在下方的 JSON 文件中添加新的 APP 通知图标适配条目
|
||||||
|
- [NotifyIconsSupportConfig.json](https://github.com/fankes/MIUINativeNotifyIcon/blob/master/iconPack/NotifyIconsSupportConfig.json)
|
||||||
- 使用灰度位图转 Base64 来得到 Base64 的位图数据字符串
|
- 使用灰度位图转 Base64 来得到 Base64 的位图数据字符串
|
||||||
- [BitmapToBase64](https://github.com/fankes/BitmapToBase64)
|
- [BitmapToBase64](https://github.com/fankes/BitmapToBase64)
|
||||||
- 新增条目的模板如下所示
|
- 新增条目的模板如下所示
|
||||||
|
|
||||||
```kotlin
|
```json
|
||||||
IconDataBean(
|
{
|
||||||
isEnabled = true, // 是否默认启用替换彩色图标 - 关闭后将全部停止替换
|
"appName": "", // APP 名称
|
||||||
isEnabledAll = false, // 是否默认启用替换全部图标
|
"packageName": "", // APP 包名
|
||||||
appName = "", // APP 名称
|
"isEnabled": true, // 是否默认启用替换彩色图标 - 关闭后将全部停止替换
|
||||||
packageName = "", // APP 包名
|
"isEnabledAll": false, // 是否默认启用替换全部图标
|
||||||
iconBitmap = ("").bitmap, // 位图数据 Base64
|
"iconBitmap": "", // 位图数据 Base64 字符串
|
||||||
iconColor = 0, // 通知栏中显示的图标颜色 - 设置为 0 使用系统默认颜色 (不设置颜色可不写)
|
"iconColor": "#ff232323", // 通知栏中显示的图标颜色 - 不设置使用系统默认颜色 (不设置颜色可删除此项)
|
||||||
contributorName = "" // 贡献者昵称
|
"contributorName": "" // 贡献者昵称
|
||||||
)
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- 图标大小建议保持在 50x50
|
||||||
- 提交时请将后方的注释删除,否则不予合并代码
|
- 提交时请将后方的注释删除,否则不予合并代码
|
||||||
|
|
||||||
|
## 同步列表地址
|
||||||
|
|
||||||
|
- Github 直连地址 [Raw](https://raw.githubusercontent.com/fankes/MIUINativeNotifyIcon/master/iconPack/NotifyIconsSupportConfig.json)
|
||||||
|
- 数据将在稍后同步至 [Surge](https://fankes.mnn.surge.sh/NotifyIconsSupportConfig.json)
|
||||||
|
|
||||||
## 其它要求
|
## 其它要求
|
||||||
|
|
||||||
- 1.调试性质或大批量注释代码,禁止提交
|
- 1.调试性质或大批量注释代码,禁止提交
|
||||||
|
10
README.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
<img src="https://github.com/fankes/MIUINativeNotifyIcon/blob/master/app/src/main/ic_launcher-playstore.png" width = "100" height = "100"/>
|
<img src="https://github.com/fankes/MIUINativeNotifyIcon/blob/master/app/src/main/ic_launcher-playstore.png" width = "100" height = "100"/>
|
||||||
<br/>
|
<br/>
|
||||||
@@ -12,12 +12,14 @@ Fix the native notification bar icon function abandoned by the MIUI development
|
|||||||
# 开始使用
|
# 开始使用
|
||||||
|
|
||||||
点击下载最新版本
|
点击下载最新版本
|
||||||
<a href='https://github.com/fankes/MIUINativeNotifyIcon/releases'></a>
|
<a href='https://github.com/fankes/MIUINativeNotifyIcon/releases'></a>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
⚠️ 适配说明<br/>
|
⚠️ 适配说明<br/>
|
||||||
|
|
||||||
- 此模块仅支持 LSPosed(作用域“系统界面”)、~~EdXposed(随时停止支持)~~、不支持太极无极
|
- 此模块仅支持 LSPosed(作用域“系统界面”)、~~EdXposed(随时停止支持)~~、不支持太极无极
|
||||||
|
- 请确保你使用的是 MIUI 官方版本,任何第三方官改包发生的问题,开发者没有义务去解决和修复,请自求多福
|
||||||
- 目前最低支持基于 Android 9 版本的 MIUI 12 或 MIUI 12.5(最低建议)
|
- 目前最低支持基于 Android 9 版本的 MIUI 12 或 MIUI 12.5(最低建议)
|
||||||
|
- 建议最低从 MIUI 12.5 `2021-5-18` 开发版以后开始使用模块,之前的版本可能或多或少存在 MIUI 自身 BUG 不生效、黑白块的问题
|
||||||
- 请始终保持最新版本的 LSPosed,旧版本可能会出现 Hook 不生效的问题
|
- 请始终保持最新版本的 LSPosed,旧版本可能会出现 Hook 不生效的问题
|
||||||
|
|
||||||
# 请勿用于非法用途
|
# 请勿用于非法用途
|
||||||
@@ -34,6 +36,10 @@ Fix the native notification bar icon function abandoned by the MIUI development
|
|||||||
|
|
||||||
- [CONTRIBUTING](https://github.com/fankes/MIUINativeNotifyIcon/blob/master/CONTRIBUTING.md)
|
- [CONTRIBUTING](https://github.com/fankes/MIUINativeNotifyIcon/blob/master/CONTRIBUTING.md)
|
||||||
|
|
||||||
|
# 通知测试
|
||||||
|
|
||||||
|
你可以 [点击这里](https://github.com/fankes/MIUINativeNotifyIcon/blob/master/tool/NotifyTester.apk) 下载工具测试通知图标是否生效。
|
||||||
|
|
||||||
# 历史背景
|
# 历史背景
|
||||||
|
|
||||||
这个模块诞生来源于 MIUI 的乱改和不规范,本来 MIUI 9 之后,官方给出了原生通知图标样式,后面由于用户反应通知栏经常出现黑白块。<br/><br/>
|
这个模块诞生来源于 MIUI 的乱改和不规范,本来 MIUI 9 之后,官方给出了原生通知图标样式,后面由于用户反应通知栏经常出现黑白块。<br/><br/>
|
||||||
|
@@ -51,9 +51,13 @@ android {
|
|||||||
tasks.whenTaskAdded {
|
tasks.whenTaskAdded {
|
||||||
task -> if (task.name == "lintVitalRelease") task.enabled = false
|
task -> if (task.name == "lintVitalRelease") task.enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 移除无效耗时 lint Task */
|
||||||
tasks.whenTaskAdded {
|
tasks.whenTaskAdded {
|
||||||
task -> if (task.name == "lintVitalAnalyzeRelease") task.enabled = false
|
task -> if (task.name == "lintVitalAnalyzeRelease") task.enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 移除无效耗时 lint Task */
|
||||||
tasks.whenTaskAdded {
|
tasks.whenTaskAdded {
|
||||||
task -> if (task.name == "lintVitalReportRelease") task.enabled = false
|
task -> if (task.name == "lintVitalReportRelease") task.enabled = false
|
||||||
}
|
}
|
||||||
@@ -64,10 +68,11 @@ dependencies {
|
|||||||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
|
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
|
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
|
||||||
compileOnly 'de.robv.android.xposed:api:82'
|
compileOnly 'de.robv.android.xposed:api:82'
|
||||||
implementation 'com.highcapable.yukihookapi:api:1.0.1'
|
implementation 'com.highcapable.yukihookapi:api:1.0.2'
|
||||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.1'
|
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.2'
|
||||||
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.0'
|
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.0'
|
||||||
implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.0'
|
implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.0'
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
implementation 'com.google.android.material:material:1.5.0'
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.fankes.miui.notify">
|
package="com.fankes.miui.notify">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".application.MNNApplication"
|
android:name=".application.MNNApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
@@ -18,7 +20,7 @@
|
|||||||
android:value="true" />
|
android:value="true" />
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="xposeddescription"
|
android:name="xposeddescription"
|
||||||
android:value="MIUI 状态栏原生图标,修复 12.5、13 后期被破坏的彩色图标。\n开发者:酷安 @星夜不荟" />
|
android:value="MIUI 原生通知图标,修复 12.5、13 后期被破坏的彩色图标。\n开发者:酷安 @星夜不荟" />
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="xposedminversion"
|
android:name="xposedminversion"
|
||||||
android:value="93" />
|
android:value="93" />
|
||||||
@@ -53,5 +55,4 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:screenOrientation="behind" />
|
android:screenOrientation="behind" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
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<LoggedInUser> {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,46 +0,0 @@
|
|||||||
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<LoggedInUser> {
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,18 +0,0 @@
|
|||||||
package com.fankes.miui.notify.data
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A generic class that holds a value with its loading status.
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
sealed class Result<out T : Any> {
|
|
||||||
|
|
||||||
data class Success<out T : Any>(val data: T) : Result<T>()
|
|
||||||
data class Error(val exception: Exception) : Result<Nothing>()
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return when (this) {
|
|
||||||
is Success<*> -> "Success[data=$data]"
|
|
||||||
is Error -> "Error[exception=$exception]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
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
|
|
||||||
)
|
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -30,7 +30,9 @@ object HookConst {
|
|||||||
const val ENABLE_MODULE_LOG = "_enable_module_log"
|
const val ENABLE_MODULE_LOG = "_enable_module_log"
|
||||||
const val ENABLE_HIDE_ICON = "_hide_icon"
|
const val ENABLE_HIDE_ICON = "_hide_icon"
|
||||||
const val ENABLE_COLOR_ICON_HOOK = "_color_icon_hook"
|
const val ENABLE_COLOR_ICON_HOOK = "_color_icon_hook"
|
||||||
const val ENABLE_NOTIFY_ICON_HOOK = "_notify_icon_hook"
|
const val ENABLE_COLOR_ICON_COMPAT = "_color_icon_compat"
|
||||||
|
const val ENABLE_NOTIFY_ICON_FIX = "_notify_icon_fix"
|
||||||
|
const val NOTIFY_ICON_DATAS = "_notify_icon_datas"
|
||||||
|
|
||||||
const val SYSTEMUI_PACKAGE_NAME = "com.android.systemui"
|
const val SYSTEMUI_PACKAGE_NAME = "com.android.systemui"
|
||||||
}
|
}
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -28,15 +28,18 @@ import android.graphics.Color
|
|||||||
import android.graphics.Outline
|
import android.graphics.Outline
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.graphics.drawable.Icon
|
import android.graphics.drawable.Icon
|
||||||
|
import android.os.Build
|
||||||
import android.service.notification.StatusBarNotification
|
import android.service.notification.StatusBarNotification
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewOutlineProvider
|
import android.view.ViewOutlineProvider
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.core.graphics.drawable.toBitmap
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
|
import com.fankes.miui.notify.bean.IconDataBean
|
||||||
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_COLOR_ICON_COMPAT
|
||||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_COLOR_ICON_HOOK
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_COLOR_ICON_HOOK
|
||||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE
|
||||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE_LOG
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE_LOG
|
||||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_NOTIFY_ICON_HOOK
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_NOTIFY_ICON_FIX
|
||||||
import com.fankes.miui.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME
|
import com.fankes.miui.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME
|
||||||
import com.fankes.miui.notify.hook.factory.isAppNotifyHookAllOf
|
import com.fankes.miui.notify.hook.factory.isAppNotifyHookAllOf
|
||||||
import com.fankes.miui.notify.hook.factory.isAppNotifyHookOf
|
import com.fankes.miui.notify.hook.factory.isAppNotifyHookOf
|
||||||
@@ -46,6 +49,7 @@ import com.fankes.miui.notify.utils.drawable.drawabletoolbox.DrawableBuilder
|
|||||||
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
|
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
|
||||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||||
import com.highcapable.yukihookapi.hook.factory.*
|
import com.highcapable.yukihookapi.hook.factory.*
|
||||||
|
import com.highcapable.yukihookapi.hook.log.loggerD
|
||||||
import com.highcapable.yukihookapi.hook.log.loggerW
|
import com.highcapable.yukihookapi.hook.log.loggerW
|
||||||
import com.highcapable.yukihookapi.hook.param.PackageParam
|
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||||
import com.highcapable.yukihookapi.hook.type.android.ContextClass
|
import com.highcapable.yukihookapi.hook.type.android.ContextClass
|
||||||
@@ -74,15 +78,12 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
private const val NotificationViewWrapperClass =
|
private const val NotificationViewWrapperClass =
|
||||||
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationViewWrapper"
|
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationViewWrapper"
|
||||||
|
|
||||||
/** 原生存在的类 */
|
/** 未确定是否只有旧版本存在的类 */
|
||||||
private const val StatusBarIconViewClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.StatusBarIconView"
|
private const val ExpandableNotificationRowClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.ExpandableNotificationRow"
|
||||||
|
|
||||||
/** 原生存在的类 */
|
/** 原生存在的类 */
|
||||||
private const val ContrastColorUtilClass = "com.android.internal.util.ContrastColorUtil"
|
private const val ContrastColorUtilClass = "com.android.internal.util.ContrastColorUtil"
|
||||||
|
|
||||||
/** 未确定是否只有旧版本存在的类 */
|
|
||||||
private const val ExpandableNotificationRowClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.ExpandableNotificationRow"
|
|
||||||
|
|
||||||
/** 根据多个版本存在不同的包名相同的类 */
|
/** 根据多个版本存在不同的包名相同的类 */
|
||||||
private val NotificationUtilClass = VariousClass(
|
private val NotificationUtilClass = VariousClass(
|
||||||
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationUtil",
|
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationUtil",
|
||||||
@@ -96,6 +97,9 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 缓存的通知优化图标数组 */
|
||||||
|
private var iconDatas = ArrayList<IconDataBean>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* - 这个是修复彩色图标的关键核心代码判断
|
* - 这个是修复彩色图标的关键核心代码判断
|
||||||
*
|
*
|
||||||
@@ -104,20 +108,18 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
* @param drawable 要判断的图标
|
* @param drawable 要判断的图标
|
||||||
* @return [Boolean]
|
* @return [Boolean]
|
||||||
*/
|
*/
|
||||||
private fun PackageParam.isGrayscaleIcon(context: Context, drawable: Drawable) = safeOfFalse {
|
private fun PackageParam.isGrayscaleIcon(context: Context, drawable: Drawable) =
|
||||||
ContrastColorUtilClass.clazz.let {
|
if (!prefs.getBoolean(ENABLE_COLOR_ICON_COMPAT)) safeOfFalse {
|
||||||
it.method(name = "isGrayscaleIcon", DrawableClass)
|
ContrastColorUtilClass.clazz.let {
|
||||||
?.call<Boolean>(it.method(name = "getInstance", ContextClass)?.callStatic(context), drawable) ?: false
|
it.method {
|
||||||
}
|
name = "isGrayscaleIcon"
|
||||||
}
|
param(DrawableClass)
|
||||||
|
}.get(it.method {
|
||||||
/**
|
name = "getInstance"
|
||||||
* 获取当前通知栏的样式
|
param(ContextClass)
|
||||||
* @return [Boolean]
|
}.get().invoke(context)).invoke<Boolean>(drawable) ?: false
|
||||||
*/
|
}
|
||||||
private fun PackageParam.isShowMiuiStyle() = safeOfFalse {
|
} else BitmapCompatTool.isGrayscaleDrawable(drawable)
|
||||||
NotificationUtilClass.clazz.method(name = "showMiuiStyle")?.callStatic() ?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为新版本 MIUI 方案
|
* 是否为新版本 MIUI 方案
|
||||||
@@ -125,9 +127,19 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
* 拥有状态栏图标颜色检查功能
|
* 拥有状态栏图标颜色检查功能
|
||||||
* @return [Boolean]
|
* @return [Boolean]
|
||||||
*/
|
*/
|
||||||
private fun PackageParam.hasIgnoreStatusBarIconColor() = safeOfFalse {
|
private val PackageParam.hasIgnoreStatusBarIconColor
|
||||||
NotificationUtilClass.clazz.hasMethod(name = "ignoreStatusBarIconColor", ExpandedNotificationClass.clazz)
|
get() = safeOfFalse {
|
||||||
}
|
NotificationUtilClass.clazz.hasMethod(name = "ignoreStatusBarIconColor", ExpandedNotificationClass.clazz)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前通知栏的样式
|
||||||
|
* @return [Boolean]
|
||||||
|
*/
|
||||||
|
private val PackageParam.isShowMiuiStyle
|
||||||
|
get() = safeOfFalse {
|
||||||
|
NotificationUtilClass.clazz.method { name = "showMiuiStyle" }.get().invoke() ?: false
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 [ExpandedNotificationClass] 的应用名称
|
* 获取 [ExpandedNotificationClass] 的应用名称
|
||||||
@@ -135,14 +147,59 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
* @return [String]
|
* @return [String]
|
||||||
*/
|
*/
|
||||||
private fun PackageParam.findAppName(instance: Any?) = safeOf(default = "<unknown>") {
|
private fun PackageParam.findAppName(instance: Any?) = safeOf(default = "<unknown>") {
|
||||||
ExpandedNotificationClass.clazz.method(name = "getAppName")?.call(instance) ?: "<empty>"
|
ExpandedNotificationClass.clazz.method { name = "getAppName" }.get(instance).invoke() ?: "<empty>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 适配通知栏、状态栏图标
|
||||||
|
*
|
||||||
|
* 适配第三方图标包对系统包管理器更换图标后的彩色图标
|
||||||
|
*
|
||||||
|
* 自动识别 MIPUSH 图标
|
||||||
|
* @param context 实例
|
||||||
|
* @param iconDrawable 原始图标
|
||||||
|
* @return [Drawable] 适配的图标
|
||||||
|
*/
|
||||||
|
private fun StatusBarNotification.compatNotifyIcon(context: Context, iconDrawable: Drawable) = safeOf(iconDrawable) {
|
||||||
|
/** 给 MIPUSH 设置 APP 自己的图标 */
|
||||||
|
if (isXmsf && opPkgName.isNotBlank())
|
||||||
|
context.packageManager.getPackageInfo(opPkgName, 0).applicationInfo.loadIcon(context.packageManager)
|
||||||
|
else iconDrawable
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取推送通知的包名
|
||||||
|
*
|
||||||
|
* 自动兼容旧版本系统
|
||||||
|
* @return [String]
|
||||||
|
*/
|
||||||
|
private val StatusBarNotification.compatOpPkgName
|
||||||
|
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) opPkg else packageName ?: ""
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断通知是否来自 MIPUSH
|
* 判断通知是否来自 MIPUSH
|
||||||
* @return [Boolean]
|
* @return [Boolean]
|
||||||
*/
|
*/
|
||||||
private val StatusBarNotification.isXmsf get() = opPkgName == "com.xiaomi.xmsf"
|
private val StatusBarNotification.isXmsf get() = compatOpPkgName == "com.xiaomi.xmsf"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取推送通知的包名
|
||||||
|
*
|
||||||
|
* 自动判断 MIPUSH
|
||||||
|
* @return [String]
|
||||||
|
*/
|
||||||
|
private val StatusBarNotification.opPkgName get() = if (isXmsf) xmsfPkgName else compatOpPkgName
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 MIPUSH 通知真实包名
|
||||||
|
* @return [String]
|
||||||
|
*/
|
||||||
|
private val StatusBarNotification.xmsfPkgName: String
|
||||||
|
get() {
|
||||||
|
val xmsfPkg = notification.extras.getString("xmsf_target_package") ?: ""
|
||||||
|
val targetPkg = notification.extras.getString("target_package") ?: ""
|
||||||
|
return xmsfPkg.ifBlank { targetPkg.ifBlank { compatOpPkgName } }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取全局上下文
|
* 获取全局上下文
|
||||||
@@ -150,7 +207,9 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
*/
|
*/
|
||||||
private val PackageParam.globalContext
|
private val PackageParam.globalContext
|
||||||
get() = safeOfNull {
|
get() = safeOfNull {
|
||||||
SystemUIApplicationClass.clazz.method(name = "getContext")?.callStatic<Context>()
|
if (SystemUIApplicationClass.clazz.hasMethod(name = "getContext"))
|
||||||
|
SystemUIApplicationClass.clazz.method { name = "getContext" }.get().invoke<Context>()
|
||||||
|
else null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,30 +228,37 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
it: (Bitmap) -> Unit
|
it: (Bitmap) -> Unit
|
||||||
) = safeRun(msg = "GetSmallIconOnSet") {
|
) = safeRun(msg = "GetSmallIconOnSet") {
|
||||||
if (iconDrawable == null) return@safeRun
|
if (iconDrawable == null) return@safeRun
|
||||||
/** 判断是否不是灰度图标 */
|
/** 如果没开启修复 APP 的彩色图标 */
|
||||||
val isNotGrayscaleIcon = !isGrayscaleIcon(context, iconDrawable)
|
if (!prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)) return@safeRun
|
||||||
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
|
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
|
||||||
expandedNf?.also { notifyInstance ->
|
expandedNf?.also { notifyInstance ->
|
||||||
|
/** 判断是否不是灰度图标 */
|
||||||
|
val isNotGrayscaleIcon = notifyInstance.isXmsf || !isGrayscaleIcon(context, iconDrawable)
|
||||||
|
|
||||||
/** 目标彩色通知 APP 图标 */
|
/** 目标彩色通知 APP 图标 */
|
||||||
var customIcon: Bitmap? = null
|
var customIcon: Bitmap? = null
|
||||||
if (prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true))
|
if (prefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true))
|
||||||
run {
|
run {
|
||||||
IconPackParams.iconDatas.forEach {
|
if (iconDatas.isNotEmpty())
|
||||||
if ((notifyInstance.opPkgName == it.packageName ||
|
iconDatas.forEach {
|
||||||
findAppName(notifyInstance) == it.appName) &&
|
if ((notifyInstance.opPkgName == it.packageName ||
|
||||||
isAppNotifyHookOf(it)
|
findAppName(notifyInstance) == it.appName) &&
|
||||||
) {
|
isAppNotifyHookOf(it)
|
||||||
if (isNotGrayscaleIcon || isAppNotifyHookAllOf(it))
|
) {
|
||||||
customIcon = it.iconBitmap
|
if (isNotGrayscaleIcon || isAppNotifyHookAllOf(it))
|
||||||
return@run
|
customIcon = it.iconBitmap
|
||||||
|
return@run
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/** 打印日志 */
|
||||||
|
if (prefs.getBoolean(ENABLE_MODULE_LOG))
|
||||||
|
loggerD(msg = "Icon --> [${findAppName(notifyInstance)}][${notifyInstance.opPkgName}] custom [${customIcon != null}] grayscale [${!isNotGrayscaleIcon}] xmsf [${notifyInstance.isXmsf}]")
|
||||||
when {
|
when {
|
||||||
/** 如果开启了修复 APP 的彩色图标 */
|
/** 处理自定义通知图标优化 */
|
||||||
customIcon != null && prefs.getBoolean(ENABLE_NOTIFY_ICON_HOOK, default = true) -> it(customIcon!!)
|
customIcon != null -> it(customIcon!!)
|
||||||
/** 若不是灰度图标自动处理为圆角 */
|
/** 若不是灰度图标自动处理为圆角 */
|
||||||
isNotGrayscaleIcon -> it(iconDrawable.toBitmap().round(15.dp(context)))
|
isNotGrayscaleIcon -> it(notifyInstance.compatNotifyIcon(context, iconDrawable).toBitmap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,10 +273,12 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
*/
|
*/
|
||||||
private fun PackageParam.hookNotifyIconOnSet(context: Context, expandedNf: StatusBarNotification?, iconImageView: ImageView) =
|
private fun PackageParam.hookNotifyIconOnSet(context: Context, expandedNf: StatusBarNotification?, iconImageView: ImageView) =
|
||||||
safeRun(msg = "AutoSetAppIconOnSet") {
|
safeRun(msg = "AutoSetAppIconOnSet") {
|
||||||
|
/** 如果没开启修复 APP 的彩色图标 */
|
||||||
|
if (!prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)) return@safeRun
|
||||||
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
|
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
|
||||||
expandedNf?.let { notifyInstance ->
|
expandedNf?.let { notifyInstance ->
|
||||||
/** 是否 Hook 彩色通知图标 */
|
/** 是否开启修复 APP 的彩色图标 */
|
||||||
val isHookColorIcon = prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
val isNotifyIconFix = prefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true)
|
||||||
|
|
||||||
/** 新版风格反色 */
|
/** 新版风格反色 */
|
||||||
val newStyle = if (context.isSystemInDarkMode) 0xFF2D2D2D.toInt() else Color.WHITE
|
val newStyle = if (context.isSystemInDarkMode) 0xFF2D2D2D.toInt() else Color.WHITE
|
||||||
@@ -237,7 +305,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
val iconDrawable = notifyInstance.notification.smallIcon.loadDrawable(context)
|
val iconDrawable = notifyInstance.notification.smallIcon.loadDrawable(context)
|
||||||
|
|
||||||
/** 判断图标风格 */
|
/** 判断图标风格 */
|
||||||
val isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable)
|
val isGrayscaleIcon = !notifyInstance.isXmsf && isGrayscaleIcon(context, iconDrawable)
|
||||||
|
|
||||||
/** 自定义默认小图标 */
|
/** 自定义默认小图标 */
|
||||||
var customIcon: Bitmap? = null
|
var customIcon: Bitmap? = null
|
||||||
@@ -245,22 +313,23 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
/** 自定义默认小图标颜色 */
|
/** 自定义默认小图标颜色 */
|
||||||
var customIconColor = 0
|
var customIconColor = 0
|
||||||
|
|
||||||
if (isHookColorIcon) run {
|
if (isNotifyIconFix) run {
|
||||||
IconPackParams.iconDatas.forEach {
|
if (iconDatas.isNotEmpty())
|
||||||
if ((notifyInstance.opPkgName == it.packageName ||
|
iconDatas.forEach {
|
||||||
findAppName(notifyInstance) == it.appName) &&
|
if ((notifyInstance.opPkgName == it.packageName ||
|
||||||
isAppNotifyHookOf(it)
|
findAppName(notifyInstance) == it.appName) &&
|
||||||
) {
|
isAppNotifyHookOf(it)
|
||||||
if (!isGrayscaleIcon || isAppNotifyHookAllOf(it)) {
|
) {
|
||||||
customIcon = it.iconBitmap
|
if (!isGrayscaleIcon || isAppNotifyHookAllOf(it)) {
|
||||||
customIconColor = it.iconColor
|
customIcon = it.iconBitmap
|
||||||
return@run
|
customIconColor = it.iconColor
|
||||||
|
return@run
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/** 如果开启了修复 APP 的彩色图标 */
|
/** 处理自定义通知图标优化 */
|
||||||
if (customIcon != null && prefs.getBoolean(ENABLE_NOTIFY_ICON_HOOK, default = true))
|
if (customIcon != null)
|
||||||
iconImageView.apply {
|
iconImageView.apply {
|
||||||
/** 设置自定义小图标 */
|
/** 设置自定义小图标 */
|
||||||
setImageBitmap(customIcon)
|
setImageBitmap(customIcon)
|
||||||
@@ -273,33 +342,32 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
else {
|
else {
|
||||||
/** 重新设置图标 - 防止系统更改它 */
|
/** 重新设置图标 - 防止系统更改它 */
|
||||||
iconImageView.setImageDrawable(iconDrawable)
|
iconImageView.setImageDrawable(iconDrawable)
|
||||||
/** 判断是否开启 Hook 彩色图标 */
|
/** 判断如果是灰度图标就给他设置一个白色颜色遮罩 */
|
||||||
if (isHookColorIcon) {
|
if (isGrayscaleIcon) iconImageView.apply {
|
||||||
/** 判断如果是灰度图标就给他设置一个白色颜色遮罩 */
|
/** 设置图标着色 */
|
||||||
if (isGrayscaleIcon) iconImageView.apply {
|
setColorFilter(supportColor)
|
||||||
/** 设置图标着色 */
|
/** Android 12 设置图标外圈颜色 */
|
||||||
setColorFilter(supportColor)
|
if (isUpperOfAndroidS && hasIconColor)
|
||||||
/** Android 12 设置图标外圈颜色 */
|
background = DrawableBuilder().rounded().solidColor(iconColor).build()
|
||||||
if (isUpperOfAndroidS && hasIconColor)
|
} else iconImageView.apply {
|
||||||
background = DrawableBuilder().rounded().solidColor(iconColor).build()
|
/** 重新设置图标 */
|
||||||
} else iconImageView.apply {
|
setImageDrawable(notifyInstance.compatNotifyIcon(context, iconDrawable))
|
||||||
clipToOutline = true
|
/** 设置裁切到边界 */
|
||||||
/** 设置一个圆角轮廓裁切 */
|
clipToOutline = true
|
||||||
outlineProvider = object : ViewOutlineProvider() {
|
/** 设置一个圆角轮廓裁切 */
|
||||||
override fun getOutline(view: View, out: Outline) {
|
outlineProvider = object : ViewOutlineProvider() {
|
||||||
out.setRoundRect(
|
override fun getOutline(view: View, out: Outline) {
|
||||||
0, 0,
|
out.setRoundRect(
|
||||||
view.width, view.height, 5.dp(context)
|
0, 0,
|
||||||
)
|
view.width, view.height, 5.dp(context)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
/** 清除原生的背景边距设置 */
|
|
||||||
if (isUpperOfAndroidS) setPadding(0, 0, 0, 0)
|
|
||||||
/** 清除原生的主题色背景圆圈颜色 */
|
|
||||||
if (isUpperOfAndroidS) background = null
|
|
||||||
}
|
}
|
||||||
/** 否则一律设置灰度图标 */
|
/** 清除原生的背景边距设置 */
|
||||||
} else iconImageView.setColorFilter(supportColor)
|
if (isUpperOfAndroidS) setPadding(0, 0, 0, 0)
|
||||||
|
/** 清除原生的主题色背景圆圈颜色 */
|
||||||
|
if (isUpperOfAndroidS) background = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -321,36 +389,36 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
notifyInstance.notification.smallIcon.loadDrawable(context)
|
notifyInstance.notification.smallIcon.loadDrawable(context)
|
||||||
|
|
||||||
/** 判断是否不是灰度图标 */
|
/** 判断是否不是灰度图标 */
|
||||||
val isNotGrayscaleIcon = !isGrayscaleIcon(context, iconDrawable)
|
val isNotGrayscaleIcon = notifyInstance.isXmsf || !isGrayscaleIcon(context, iconDrawable)
|
||||||
|
|
||||||
/** 获取目标修复彩色图标的 APP */
|
/** 获取目标修复彩色图标的 APP */
|
||||||
var isTargetApp = false
|
var isTargetFixApp = false
|
||||||
run {
|
/** 如果开启了自定义通知图标优化 */
|
||||||
IconPackParams.iconDatas.forEach {
|
if (prefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true))
|
||||||
if ((notifyInstance.opPkgName == it.packageName ||
|
run {
|
||||||
findAppName(notifyInstance) == it.appName) &&
|
if (iconDatas.isNotEmpty())
|
||||||
isAppNotifyHookOf(it)
|
iconDatas.forEach {
|
||||||
) {
|
if ((notifyInstance.opPkgName == it.packageName ||
|
||||||
if (isNotGrayscaleIcon || isAppNotifyHookAllOf(it)) isTargetApp = true
|
findAppName(notifyInstance) == it.appName) &&
|
||||||
return@run
|
isAppNotifyHookOf(it)
|
||||||
}
|
) {
|
||||||
|
if (isNotGrayscaleIcon || isAppNotifyHookAllOf(it)) isTargetFixApp = true
|
||||||
|
return@run
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* 如果开启了修复 APP 的彩色图标
|
|
||||||
* 只要不是灰度就返回彩色图标
|
* 只要不是灰度就返回彩色图标
|
||||||
* 否则不对颜色进行反色处理防止一些系统图标出现异常
|
* 否则不对颜色进行反色处理防止一些系统图标出现异常
|
||||||
*/
|
*/
|
||||||
if (isTargetApp && prefs.getBoolean(ENABLE_NOTIFY_ICON_HOOK, default = true))
|
if (isTargetFixApp) false else isNotGrayscaleIcon
|
||||||
false
|
|
||||||
else isNotGrayscaleIcon
|
|
||||||
} ?: true
|
} ?: true
|
||||||
} else false
|
} else false
|
||||||
|
|
||||||
override fun onHook() = encase {
|
override fun onHook() = encase {
|
||||||
configs {
|
configs {
|
||||||
debugTag = "MIUINativeNotifyIcon"
|
debugTag = "MIUINativeNotifyIcon"
|
||||||
isDebug = prefs.getBoolean(ENABLE_MODULE_LOG)
|
isDebug = false
|
||||||
}
|
}
|
||||||
loadApp(SYSTEMUI_PACKAGE_NAME) {
|
loadApp(SYSTEMUI_PACKAGE_NAME) {
|
||||||
when {
|
when {
|
||||||
@@ -364,6 +432,9 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
!prefs.getBoolean(ENABLE_MODULE, default = true) -> loggerW(msg = "Aborted Hook -> Hook Closed")
|
!prefs.getBoolean(ENABLE_MODULE, default = true) -> loggerW(msg = "Aborted Hook -> Hook Closed")
|
||||||
/** 开始 Hook */
|
/** 开始 Hook */
|
||||||
else -> {
|
else -> {
|
||||||
|
/** 缓存图标数据 */
|
||||||
|
iconDatas = IconPackParams(param = this).iconDatas
|
||||||
|
/** 执行 Hook */
|
||||||
NotificationUtilClass.hook {
|
NotificationUtilClass.hook {
|
||||||
/** 强制回写系统的状态栏图标样式为原生 */
|
/** 强制回写系统的状态栏图标样式为原生 */
|
||||||
injectMember {
|
injectMember {
|
||||||
@@ -375,9 +446,9 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
* 因为之前的 MIUI 版本的状态栏图标颜色会全部设置为白色的 - 找不到修复的地方就直接判断版本了
|
* 因为之前的 MIUI 版本的状态栏图标颜色会全部设置为白色的 - 找不到修复的地方就直接判断版本了
|
||||||
* 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook
|
* 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook
|
||||||
*/
|
*/
|
||||||
replaceAny { if (hasIgnoreStatusBarIconColor()) false else isShowMiuiStyle() }
|
replaceAny { if (hasIgnoreStatusBarIconColor) false else isShowMiuiStyle }
|
||||||
}
|
}
|
||||||
if (hasIgnoreStatusBarIconColor())
|
if (hasIgnoreStatusBarIconColor)
|
||||||
injectMember {
|
injectMember {
|
||||||
method {
|
method {
|
||||||
name = "ignoreStatusBarIconColor"
|
name = "ignoreStatusBarIconColor"
|
||||||
@@ -408,7 +479,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
}
|
}
|
||||||
afterHook {
|
afterHook {
|
||||||
/** 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook */
|
/** 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook */
|
||||||
if (hasIgnoreStatusBarIconColor() || !isShowMiuiStyle())
|
if (hasIgnoreStatusBarIconColor || !isShowMiuiStyle)
|
||||||
(globalContext ?: args[0] as Context).also { context ->
|
(globalContext ?: args[0] as Context).also { context ->
|
||||||
hookSmallIconOnSet(
|
hookSmallIconOnSet(
|
||||||
context = context,
|
context = context,
|
||||||
@@ -419,33 +490,8 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
findClass(StatusBarIconViewClass).hook {
|
|
||||||
/** 修复通知图标为彩色 - MIPUSH 修复 */
|
|
||||||
injectMember {
|
|
||||||
method { name = "updateIconColor" }
|
|
||||||
afterHook {
|
|
||||||
/** 获取自身 */
|
|
||||||
val iconImageView = instance<ImageView?>() ?: return@afterHook
|
|
||||||
|
|
||||||
/** 获取通知实例 */
|
|
||||||
val expandedNf = field { name = "mNotification" }.of<StatusBarNotification>(instance)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 强制设置图标 - 防止 MIPUSH 不生效
|
|
||||||
* 由于之前版本没有 [hasIgnoreStatusBarIconColor] 判断 - MIPUSH 的图标颜色也是白色的
|
|
||||||
* 所以之前的版本取消这个 Hook - 实在找不到设置图标的地方 - 状态栏图标就彩色吧
|
|
||||||
*/
|
|
||||||
if (hasIgnoreStatusBarIconColor() && expandedNf?.isXmsf == true)
|
|
||||||
hookSmallIconOnSet(
|
|
||||||
context = iconImageView.context,
|
|
||||||
expandedNf,
|
|
||||||
expandedNf.notification?.smallIcon?.loadDrawable(iconImageView.context)
|
|
||||||
) { icon -> iconImageView.setImageBitmap(icon) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (NotificationHeaderViewWrapperInjectorClass.hasClass)
|
if (NotificationHeaderViewWrapperInjectorClass.hasClass)
|
||||||
findClass(NotificationHeaderViewWrapperInjectorClass).hook {
|
NotificationHeaderViewWrapperInjectorClass.hook {
|
||||||
/** 修复下拉通知图标自动设置回 APP 图标的方法 */
|
/** 修复下拉通知图标自动设置回 APP 图标的方法 */
|
||||||
injectMember {
|
injectMember {
|
||||||
var isUseLegacy = false
|
var isUseLegacy = false
|
||||||
@@ -485,30 +531,30 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
findClass(NotificationHeaderViewWrapperClass).hook {
|
NotificationHeaderViewWrapperClass.hook {
|
||||||
/** 之前的版本解决方案 */
|
/** 之前的版本解决方案 */
|
||||||
injectMember {
|
injectMember {
|
||||||
method { name = "handleHeaderViews" }
|
method { name = "handleHeaderViews" }
|
||||||
afterHook {
|
afterHook {
|
||||||
/** 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook */
|
/** 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook */
|
||||||
if (!hasIgnoreStatusBarIconColor() && isShowMiuiStyle()) return@afterHook
|
if (!hasIgnoreStatusBarIconColor && isShowMiuiStyle) return@afterHook
|
||||||
|
|
||||||
/** 获取小图标 */
|
/** 获取小图标 */
|
||||||
val iconImageView = field {
|
val iconImageView =
|
||||||
classSet = NotificationHeaderViewWrapperClass.clazz
|
NotificationHeaderViewWrapperClass.clazz
|
||||||
name = "mIcon"
|
.field { name = "mIcon" }.of<ImageView>(instance) ?: return@afterHook
|
||||||
}.of<ImageView>(instance) ?: return@afterHook
|
|
||||||
/** 从父类中得到 mRow 变量 - [ExpandableNotificationRowClass] */
|
/**
|
||||||
field {
|
* 从父类中得到 mRow 变量 - [ExpandableNotificationRowClass]
|
||||||
classSet = NotificationViewWrapperClass.clazz
|
* 获取其中的得到通知方法
|
||||||
name = "mRow"
|
*/
|
||||||
}.get(instance).apply {
|
val expandedNf =
|
||||||
/** 获取其中的得到通知方法 */
|
ExpandableNotificationRowClass.clazz
|
||||||
val expandedNf =
|
.method { name = "getStatusBarNotification" }
|
||||||
ExpandableNotificationRowClass.clazz.method(name = "getStatusBarNotification")
|
.get(NotificationViewWrapperClass.clazz.field { name = "mRow" }.get(instance).self)
|
||||||
?.call<StatusBarNotification>(instance = self)
|
.invoke<StatusBarNotification>()
|
||||||
/** 执行 Hook */
|
/** 执行 Hook */
|
||||||
hookNotifyIconOnSet(iconImageView.context, expandedNf, iconImageView)
|
hookNotifyIconOnSet(iconImageView.context, expandedNf, iconImageView)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
package com.fankes.miui.notify.ui
|
package com.fankes.miui.notify.ui
|
||||||
|
|
||||||
|
import android.app.ProgressDialog
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -33,20 +34,20 @@ import android.view.ViewGroup
|
|||||||
import android.widget.BaseAdapter
|
import android.widget.BaseAdapter
|
||||||
import android.widget.ListView
|
import android.widget.ListView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.constraintlayout.utils.widget.ImageFilterView
|
import androidx.constraintlayout.utils.widget.ImageFilterView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.fankes.miui.notify.R
|
import com.fankes.miui.notify.R
|
||||||
|
import com.fankes.miui.notify.bean.IconDataBean
|
||||||
import com.fankes.miui.notify.hook.factory.isAppNotifyHookAllOf
|
import com.fankes.miui.notify.hook.factory.isAppNotifyHookAllOf
|
||||||
import com.fankes.miui.notify.hook.factory.isAppNotifyHookOf
|
import com.fankes.miui.notify.hook.factory.isAppNotifyHookOf
|
||||||
import com.fankes.miui.notify.hook.factory.putAppNotifyHookAllOf
|
import com.fankes.miui.notify.hook.factory.putAppNotifyHookAllOf
|
||||||
import com.fankes.miui.notify.hook.factory.putAppNotifyHookOf
|
import com.fankes.miui.notify.hook.factory.putAppNotifyHookOf
|
||||||
import com.fankes.miui.notify.params.IconPackParams
|
import com.fankes.miui.notify.params.IconPackParams
|
||||||
import com.fankes.miui.notify.ui.base.BaseActivity
|
import com.fankes.miui.notify.ui.base.BaseActivity
|
||||||
import com.fankes.miui.notify.utils.SystemUITool
|
import com.fankes.miui.notify.utils.*
|
||||||
import com.fankes.miui.notify.utils.showDialog
|
|
||||||
import com.fankes.miui.notify.view.MaterialSwitch
|
import com.fankes.miui.notify.view.MaterialSwitch
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
|
||||||
|
|
||||||
class ConfigureActivity : BaseActivity() {
|
class ConfigureActivity : BaseActivity() {
|
||||||
|
|
||||||
@@ -56,13 +57,38 @@ class ConfigureActivity : BaseActivity() {
|
|||||||
/** 回调适配器改变 */
|
/** 回调适配器改变 */
|
||||||
private var onChanged: (() -> Unit)? = null
|
private var onChanged: (() -> Unit)? = null
|
||||||
|
|
||||||
|
/** 回调滚动事件改变 */
|
||||||
|
private var onScrollEvent: ((Boolean) -> Unit)? = null
|
||||||
|
|
||||||
|
/** 全部的通知优化图标数据 */
|
||||||
|
private var iconAllDatas = ArrayList<IconDataBean>()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_config)
|
setContentView(R.layout.activity_config)
|
||||||
|
/** 检查激活状态 */
|
||||||
|
if (!YukiHookModuleStatus.isActive()) {
|
||||||
|
showDialog {
|
||||||
|
title = "模块没有激活"
|
||||||
|
msg = "模块没有激活,你无法使用这里的功能,请先激活模块。"
|
||||||
|
confirmButton(text = "我知道了") { finish() }
|
||||||
|
noCancelable()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
/** 返回按钮点击事件 */
|
/** 返回按钮点击事件 */
|
||||||
findViewById<View>(R.id.title_back_icon).setOnClickListener { onBackPressed() }
|
findViewById<View>(R.id.title_back_icon).setOnClickListener { onBackPressed() }
|
||||||
/** 刷新适配器结果相关 */
|
/** 刷新适配器结果相关 */
|
||||||
refreshAdapterResult()
|
refreshAdapterResult()
|
||||||
|
/** 设置上下按钮点击事件 */
|
||||||
|
findViewById<View>(R.id.config_title_up).setOnClickListener {
|
||||||
|
snake(msg = "滚动到顶部")
|
||||||
|
onScrollEvent?.invoke(false)
|
||||||
|
}
|
||||||
|
findViewById<View>(R.id.config_title_down).setOnClickListener {
|
||||||
|
snake(msg = "滚动到底部")
|
||||||
|
onScrollEvent?.invoke(true)
|
||||||
|
}
|
||||||
/** 设置过滤按钮点击事件 */
|
/** 设置过滤按钮点击事件 */
|
||||||
findViewById<View>(R.id.config_title_filter).setOnClickListener {
|
findViewById<View>(R.id.config_title_filter).setOnClickListener {
|
||||||
showDialog {
|
showDialog {
|
||||||
@@ -81,10 +107,9 @@ class ConfigureActivity : BaseActivity() {
|
|||||||
confirmButton {
|
confirmButton {
|
||||||
if (editText.text.toString().isNotBlank()) {
|
if (editText.text.toString().isNotBlank()) {
|
||||||
filterText = editText.text.toString().trim()
|
filterText = editText.text.toString().trim()
|
||||||
onChanged?.invoke()
|
|
||||||
refreshAdapterResult()
|
refreshAdapterResult()
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(applicationContext, "条件不能为空", Toast.LENGTH_SHORT).show()
|
toast(msg = "条件不能为空")
|
||||||
it.performClick()
|
it.performClick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,11 +117,12 @@ class ConfigureActivity : BaseActivity() {
|
|||||||
if (filterText.isNotBlank())
|
if (filterText.isNotBlank())
|
||||||
neutralButton(text = "清除条件") {
|
neutralButton(text = "清除条件") {
|
||||||
filterText = ""
|
filterText = ""
|
||||||
onChanged?.invoke()
|
|
||||||
refreshAdapterResult()
|
refreshAdapterResult()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/** 设置同步列表按钮点击事件 */
|
||||||
|
findViewById<View>(R.id.config_title_sync).setOnClickListener { onStartRefresh() }
|
||||||
/** 设置列表元素和 Adapter */
|
/** 设置列表元素和 Adapter */
|
||||||
findViewById<ListView>(R.id.config_list_view).apply {
|
findViewById<ListView>(R.id.config_list_view).apply {
|
||||||
adapter = object : BaseAdapter() {
|
adapter = object : BaseAdapter() {
|
||||||
@@ -162,28 +188,93 @@ class ConfigureActivity : BaseActivity() {
|
|||||||
lateinit var switchAll: MaterialSwitch
|
lateinit var switchAll: MaterialSwitch
|
||||||
}
|
}
|
||||||
}.apply { onChanged = { notifyDataSetChanged() } }
|
}.apply { onChanged = { notifyDataSetChanged() } }
|
||||||
|
onScrollEvent = { post { setSelection(if (it) iconDatas.lastIndex else 0) } }
|
||||||
}
|
}
|
||||||
/** 设置点击事件 */
|
/** 设置点击事件 */
|
||||||
findViewById<View>(R.id.config_cbr_button).setOnClickListener {
|
findViewById<View>(R.id.config_cbr_button).setOnClickListener {
|
||||||
runCatching {
|
runCatching {
|
||||||
startActivity(Intent().apply {
|
startActivity(Intent().apply {
|
||||||
action = "android.intent.action.VIEW"
|
action = "android.intent.action.VIEW"
|
||||||
data = Uri.parse("https://github.com/fankes/MIUINativeNotifyIcon")
|
data = Uri.parse("https://github.com/fankes/MIUINativeNotifyIcon/blob/master/CONTRIBUTING.md")
|
||||||
/** 防止顶栈一样重叠在自己的 APP 中 */
|
/** 防止顶栈一样重叠在自己的 APP 中 */
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
})
|
})
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
Toast.makeText(this, "无法启动系统默认浏览器", Toast.LENGTH_SHORT).show()
|
toast(msg = "无法启动系统默认浏览器")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 装载数据 */
|
||||||
|
mockLocalData()
|
||||||
|
/** 更新数据 */
|
||||||
|
onStartRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 装载或刷新本地数据 */
|
||||||
|
private fun mockLocalData() {
|
||||||
|
iconAllDatas = IconPackParams(context = this).iconDatas
|
||||||
|
refreshAdapterResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 首次进入或更新数据 */
|
||||||
|
private fun onStartRefresh() =
|
||||||
|
showDialog {
|
||||||
|
title = if (iconAllDatas.isNotEmpty()) "同步列表" else "初始化"
|
||||||
|
msg = (if (iconAllDatas.isNotEmpty()) "建议定期从云端拉取数据以获得最新的通知图标优化名单适配数据。\n\n"
|
||||||
|
else "首次装载需要从云端下载最新适配数据,后续可继续前往这里检查更新。\n\n") +
|
||||||
|
"[Github] 同步最新数据,无法连接可能需要魔法上网。\n\n[Surge] 缓存 CDN 数据,可以直连,但数据可能会有更新延迟。\n\n" +
|
||||||
|
"如果以上地址均无法使用,建议魔法上网或修改 Host 文件直连。"
|
||||||
|
confirmButton(text = "Surge") {
|
||||||
|
onRefreshing(url = "https://fankes.mnn.surge.sh/NotifyIconsSupportConfig.json")
|
||||||
|
}
|
||||||
|
cancelButton(text = "Github") {
|
||||||
|
onRefreshing(url = "https://raw.githubusercontent.com/fankes/MIUINativeNotifyIcon/master/iconPack/NotifyIconsSupportConfig.json")
|
||||||
|
}
|
||||||
|
neutralButton(text = "取消")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始更新数据
|
||||||
|
* @param url 使用的地址
|
||||||
|
*/
|
||||||
|
private fun onRefreshing(url: String) {
|
||||||
|
ProgressDialog(this).apply {
|
||||||
|
setDefaultStyle(context = this@ConfigureActivity)
|
||||||
|
setCancelable(false)
|
||||||
|
setTitle("同步中")
|
||||||
|
setMessage("正在同步云端数据")
|
||||||
|
show()
|
||||||
|
}.also {
|
||||||
|
ClientRequestTool.wait(context = this, url) { isDone, content ->
|
||||||
|
it.cancel()
|
||||||
|
IconPackParams(context = this).also { params ->
|
||||||
|
if (isDone)
|
||||||
|
if (params.isCompareDifferent(content)) {
|
||||||
|
params.save(content)
|
||||||
|
filterText = ""
|
||||||
|
mockLocalData()
|
||||||
|
SystemUITool.showNeedUpdateApplySnake(context = this)
|
||||||
|
} else snake(msg = "列表数据已是最新")
|
||||||
|
else
|
||||||
|
showDialog {
|
||||||
|
title = "连接失败"
|
||||||
|
msg = "连接失败,错误如下:\n$content"
|
||||||
|
confirmButton(text = "我知道了")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 刷新适配器结果相关 */
|
/** 刷新适配器结果相关 */
|
||||||
private fun refreshAdapterResult() {
|
private fun refreshAdapterResult() {
|
||||||
|
onChanged?.invoke()
|
||||||
findViewById<TextView>(R.id.config_title_count_text).text =
|
findViewById<TextView>(R.id.config_title_count_text).text =
|
||||||
if (filterText.isBlank()) "已适配 ${iconDatas.size} 个 APP 的通知图标"
|
if (filterText.isBlank()) "已适配 ${iconDatas.size} 个 APP 的通知图标"
|
||||||
else "“${filterText}” 匹配到 ${iconDatas.size} 个结果"
|
else "“${filterText}” 匹配到 ${iconDatas.size} 个结果"
|
||||||
findViewById<View>(R.id.config_list_no_data_view).isVisible = iconDatas.isEmpty()
|
findViewById<TextView>(R.id.config_list_no_data_view).apply {
|
||||||
|
text = if (iconAllDatas.isEmpty()) "噫,竟然什么都没有~\n请点击右上角同步按钮获取云端数据" else "噫,竟然什么都没找到~"
|
||||||
|
isVisible = iconDatas.isEmpty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -191,8 +282,8 @@ class ConfigureActivity : BaseActivity() {
|
|||||||
* @return [Array]
|
* @return [Array]
|
||||||
*/
|
*/
|
||||||
private val iconDatas
|
private val iconDatas
|
||||||
get() = if (filterText.isBlank()) IconPackParams.iconDatas
|
get() = if (filterText.isBlank()) iconAllDatas
|
||||||
else IconPackParams.iconDatas.filter {
|
else iconAllDatas.filter {
|
||||||
it.appName.lowercase().contains(filterText.lowercase()) || it.packageName.lowercase().contains(filterText.lowercase())
|
it.appName.lowercase().contains(filterText.lowercase()) || it.packageName.lowercase().contains(filterText.lowercase())
|
||||||
}.toTypedArray()
|
}
|
||||||
}
|
}
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -32,17 +32,17 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.appcompat.widget.SwitchCompat
|
import androidx.appcompat.widget.SwitchCompat
|
||||||
import androidx.constraintlayout.utils.widget.ImageFilterView
|
import androidx.constraintlayout.utils.widget.ImageFilterView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.fankes.miui.notify.BuildConfig
|
import com.fankes.miui.notify.BuildConfig
|
||||||
import com.fankes.miui.notify.R
|
import com.fankes.miui.notify.R
|
||||||
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_COLOR_ICON_COMPAT
|
||||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_COLOR_ICON_HOOK
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_COLOR_ICON_HOOK
|
||||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_HIDE_ICON
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_HIDE_ICON
|
||||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE
|
||||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE_LOG
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE_LOG
|
||||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_NOTIFY_ICON_HOOK
|
import com.fankes.miui.notify.hook.HookConst.ENABLE_NOTIFY_ICON_FIX
|
||||||
import com.fankes.miui.notify.ui.base.BaseActivity
|
import com.fankes.miui.notify.ui.base.BaseActivity
|
||||||
import com.fankes.miui.notify.utils.*
|
import com.fankes.miui.notify.utils.*
|
||||||
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
||||||
@@ -93,9 +93,9 @@ class MainActivity : BaseActivity() {
|
|||||||
noCancelable()
|
noCancelable()
|
||||||
}
|
}
|
||||||
/** 判断是否 Hook */
|
/** 判断是否 Hook */
|
||||||
isHooked() -> {
|
YukiHookModuleStatus.isActive() -> {
|
||||||
findViewById<LinearLayout>(R.id.main_lin_status).setBackgroundResource(R.drawable.green_round)
|
findViewById<LinearLayout>(R.id.main_lin_status).setBackgroundResource(R.drawable.bg_green_round)
|
||||||
findViewById<ImageFilterView>(R.id.main_img_status).setImageResource(R.mipmap.succcess)
|
findViewById<ImageFilterView>(R.id.main_img_status).setImageResource(R.mipmap.ic_success)
|
||||||
findViewById<TextView>(R.id.main_text_status).text = "模块已激活"
|
findViewById<TextView>(R.id.main_text_status).text = "模块已激活"
|
||||||
}
|
}
|
||||||
else ->
|
else ->
|
||||||
@@ -112,24 +112,34 @@ class MainActivity : BaseActivity() {
|
|||||||
/** 初始化 View */
|
/** 初始化 View */
|
||||||
val moduleEnableSwitch = findViewById<SwitchCompat>(R.id.module_enable_switch)
|
val moduleEnableSwitch = findViewById<SwitchCompat>(R.id.module_enable_switch)
|
||||||
val moduleEnableLogSwitch = findViewById<SwitchCompat>(R.id.module_enable_log_switch)
|
val moduleEnableLogSwitch = findViewById<SwitchCompat>(R.id.module_enable_log_switch)
|
||||||
|
val colorIconHookItem = findViewById<View>(R.id.config_item_color_hook)
|
||||||
val notifyIconConfigItem = findViewById<View>(R.id.config_item_notify)
|
val notifyIconConfigItem = findViewById<View>(R.id.config_item_notify)
|
||||||
val hideIconInLauncherSwitch = findViewById<SwitchCompat>(R.id.hide_icon_in_launcher_switch)
|
val hideIconInLauncherSwitch = findViewById<SwitchCompat>(R.id.hide_icon_in_launcher_switch)
|
||||||
val colorIconHookSwitch = findViewById<SwitchCompat>(R.id.color_icon_fix_switch)
|
val colorIconHookSwitch = findViewById<SwitchCompat>(R.id.color_icon_fix_switch)
|
||||||
val notifyIconHookSwitch = findViewById<SwitchCompat>(R.id.notify_icon_fix_switch)
|
val colorIconCompatSwitch = findViewById<SwitchCompat>(R.id.color_icon_compat_switch)
|
||||||
/** 设置旧版本警告 */
|
val colorIconCompatText = findViewById<View>(R.id.color_icon_compat_text)
|
||||||
findViewById<View>(R.id.config_notify_app_icon_warn).isVisible = miuiVersion == "12"
|
val notifyIconFixSwitch = findViewById<SwitchCompat>(R.id.notify_icon_fix_switch)
|
||||||
|
val notifyIconFixButton = findViewById<View>(R.id.config_notify_app_button)
|
||||||
/** 获取 Sp 存储的信息 */
|
/** 获取 Sp 存储的信息 */
|
||||||
notifyIconConfigItem.isVisible = modulePrefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
colorIconHookItem.isVisible = modulePrefs.getBoolean(ENABLE_MODULE, default = true)
|
||||||
|
colorIconCompatSwitch.isVisible = modulePrefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
||||||
|
colorIconCompatText.isVisible = modulePrefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
||||||
|
notifyIconConfigItem.isVisible = modulePrefs.getBoolean(ENABLE_MODULE, default = true) &&
|
||||||
|
modulePrefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
||||||
moduleEnableLogSwitch.isVisible = modulePrefs.getBoolean(ENABLE_MODULE, default = true)
|
moduleEnableLogSwitch.isVisible = modulePrefs.getBoolean(ENABLE_MODULE, default = true)
|
||||||
|
notifyIconFixButton.isVisible = modulePrefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true)
|
||||||
moduleEnableSwitch.isChecked = modulePrefs.getBoolean(ENABLE_MODULE, default = true)
|
moduleEnableSwitch.isChecked = modulePrefs.getBoolean(ENABLE_MODULE, default = true)
|
||||||
moduleEnableLogSwitch.isChecked = modulePrefs.getBoolean(ENABLE_MODULE_LOG, default = false)
|
moduleEnableLogSwitch.isChecked = modulePrefs.getBoolean(ENABLE_MODULE_LOG, default = false)
|
||||||
hideIconInLauncherSwitch.isChecked = modulePrefs.getBoolean(ENABLE_HIDE_ICON)
|
hideIconInLauncherSwitch.isChecked = modulePrefs.getBoolean(ENABLE_HIDE_ICON)
|
||||||
colorIconHookSwitch.isChecked = modulePrefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
colorIconHookSwitch.isChecked = modulePrefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
||||||
notifyIconHookSwitch.isChecked = modulePrefs.getBoolean(ENABLE_NOTIFY_ICON_HOOK, default = true)
|
colorIconCompatSwitch.isChecked = modulePrefs.getBoolean(ENABLE_COLOR_ICON_COMPAT)
|
||||||
|
notifyIconFixSwitch.isChecked = modulePrefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true)
|
||||||
moduleEnableSwitch.setOnCheckedChangeListener { btn, b ->
|
moduleEnableSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
if (!btn.isPressed) return@setOnCheckedChangeListener
|
||||||
modulePrefs.putBoolean(ENABLE_MODULE, b)
|
modulePrefs.putBoolean(ENABLE_MODULE, b)
|
||||||
moduleEnableLogSwitch.isVisible = b
|
moduleEnableLogSwitch.isVisible = b
|
||||||
|
colorIconHookItem.isVisible = b
|
||||||
|
notifyIconConfigItem.isVisible = b && colorIconHookSwitch.isChecked
|
||||||
SystemUITool.showNeedRestartSnake(context = this)
|
SystemUITool.showNeedRestartSnake(context = this)
|
||||||
}
|
}
|
||||||
moduleEnableLogSwitch.setOnCheckedChangeListener { btn, b ->
|
moduleEnableLogSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
@@ -150,19 +160,25 @@ class MainActivity : BaseActivity() {
|
|||||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
if (!btn.isPressed) return@setOnCheckedChangeListener
|
||||||
modulePrefs.putBoolean(ENABLE_COLOR_ICON_HOOK, b)
|
modulePrefs.putBoolean(ENABLE_COLOR_ICON_HOOK, b)
|
||||||
notifyIconConfigItem.isVisible = b
|
notifyIconConfigItem.isVisible = b
|
||||||
|
colorIconCompatSwitch.isVisible = b
|
||||||
|
colorIconCompatText.isVisible = b
|
||||||
SystemUITool.showNeedRestartSnake(context = this)
|
SystemUITool.showNeedRestartSnake(context = this)
|
||||||
}
|
}
|
||||||
notifyIconHookSwitch.setOnCheckedChangeListener { btn, b ->
|
colorIconCompatSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
if (!btn.isPressed) return@setOnCheckedChangeListener
|
||||||
modulePrefs.putBoolean(ENABLE_NOTIFY_ICON_HOOK, b)
|
modulePrefs.putBoolean(ENABLE_COLOR_ICON_COMPAT, b)
|
||||||
SystemUITool.showNeedRestartSnake(context = this)
|
SystemUITool.showNeedRestartSnake(context = this)
|
||||||
}
|
}
|
||||||
|
notifyIconFixSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
|
if (!btn.isPressed) return@setOnCheckedChangeListener
|
||||||
|
modulePrefs.putBoolean(ENABLE_NOTIFY_ICON_FIX, b)
|
||||||
|
notifyIconFixButton.isVisible = b
|
||||||
|
SystemUITool.showNeedRestartSnake(context = this)
|
||||||
|
}
|
||||||
|
/** 通知图标优化名单按钮点击事件 */
|
||||||
|
notifyIconFixButton.setOnClickListener { startActivity(Intent(this, ConfigureActivity::class.java)) }
|
||||||
/** 重启按钮点击事件 */
|
/** 重启按钮点击事件 */
|
||||||
findViewById<View>(R.id.title_restart_icon).setOnClickListener { SystemUITool.restartSystemUI(context = this) }
|
findViewById<View>(R.id.title_restart_icon).setOnClickListener { SystemUITool.restartSystemUI(context = this) }
|
||||||
/** 通知图标优化名单按钮点击事件 */
|
|
||||||
findViewById<View>(R.id.config_notify_app_button).setOnClickListener {
|
|
||||||
startActivity(Intent(this, ConfigureActivity::class.java))
|
|
||||||
}
|
|
||||||
/** 恰饭! */
|
/** 恰饭! */
|
||||||
findViewById<View>(R.id.link_with_follow_me).setOnClickListener {
|
findViewById<View>(R.id.link_with_follow_me).setOnClickListener {
|
||||||
runCatching {
|
runCatching {
|
||||||
@@ -174,7 +190,7 @@ class MainActivity : BaseActivity() {
|
|||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
})
|
})
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
Toast.makeText(this, "你可能没有安装酷安", Toast.LENGTH_SHORT).show()
|
toast(msg = "你可能没有安装酷安")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** 项目地址点击事件 */
|
/** 项目地址点击事件 */
|
||||||
@@ -187,7 +203,7 @@ class MainActivity : BaseActivity() {
|
|||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
})
|
})
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
Toast.makeText(this, "无法启动系统默认浏览器", Toast.LENGTH_SHORT).show()
|
toast(msg = "无法启动系统默认浏览器")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,7 +211,7 @@ class MainActivity : BaseActivity() {
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
/** MIUI 12 的版本特殊 - 所以给出提示 */
|
/** MIUI 12 的版本特殊 - 所以给出提示 */
|
||||||
if (!isWarnDialogShowing && isHooked() && miuiVersion == "12" && isMiuiNotifyStyle)
|
if (!isWarnDialogShowing && YukiHookModuleStatus.isActive() && miuiVersion == "12" && isMiuiNotifyStyle)
|
||||||
showDialog {
|
showDialog {
|
||||||
isWarnDialogShowing = true
|
isWarnDialogShowing = true
|
||||||
title = "经典通知栏样式已启用"
|
title = "经典通知栏样式已启用"
|
||||||
@@ -205,10 +221,4 @@ class MainActivity : BaseActivity() {
|
|||||||
noCancelable()
|
noCancelable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断模块是否激活
|
|
||||||
* @return [Boolean] 激活状态
|
|
||||||
*/
|
|
||||||
private fun isHooked() = YukiHookModuleStatus.isActive()
|
|
||||||
}
|
}
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* MIUINativeNotifyIcon - Fix the native notification bar icon function abandoned by the MIUI development team.
|
||||||
|
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
||||||
|
* https://github.com/fankes/MIUINativeNotifyIcon
|
||||||
|
*
|
||||||
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
|
* as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* This software is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* and eula along with this software. If not, see
|
||||||
|
* <https://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
* This file is Created by fankes on 2022/2/19.
|
||||||
|
*/
|
||||||
|
package com.fankes.miui.notify.utils
|
||||||
|
|
||||||
|
import android.graphics.*
|
||||||
|
import android.graphics.drawable.AnimationDrawable
|
||||||
|
import android.graphics.drawable.BitmapDrawable
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.graphics.drawable.VectorDrawable
|
||||||
|
import android.util.ArrayMap
|
||||||
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这是一个从 AOSP 源码中分离出来的功能
|
||||||
|
*
|
||||||
|
* 主要作用于兼容部分 MIUI 魔改颜色判断代码造成判断位图灰度功能失效
|
||||||
|
*/
|
||||||
|
object BitmapCompatTool {
|
||||||
|
|
||||||
|
/** 缓存已判断的结果防止卡顿 */
|
||||||
|
private var cachedBitmapGrayscales = ArrayMap<Int, Boolean>()
|
||||||
|
|
||||||
|
private var tempBuffer = intArrayOf(0)
|
||||||
|
private var tempCompactBitmap: Bitmap? = null
|
||||||
|
private var tempCompactBitmapCanvas: Canvas? = null
|
||||||
|
private var tempCompactBitmapPaint: Paint? = null
|
||||||
|
private val tempMatrix = Matrix()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 [Drawable] 是否为灰度位图
|
||||||
|
* @param drawable 要判断的 [Drawable]
|
||||||
|
* @return [Boolean] 是否灰度
|
||||||
|
*/
|
||||||
|
fun isGrayscaleDrawable(drawable: Drawable) = safeOfFalse {
|
||||||
|
when (drawable) {
|
||||||
|
is BitmapDrawable -> isGrayscaleBitmap(drawable.bitmap)
|
||||||
|
is AnimationDrawable -> !(drawable.numberOfFrames <= 0 || !isGrayscaleBitmap(drawable.getFrame(0).toBitmap()))
|
||||||
|
is VectorDrawable -> true
|
||||||
|
else -> isGrayscaleBitmap(drawable.toBitmap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 [Bitmap] 是否为灰度位图
|
||||||
|
* @param bitmap 要判断的位图
|
||||||
|
* @return [Boolean] 是否灰度
|
||||||
|
*/
|
||||||
|
private fun isGrayscaleBitmap(bitmap: Bitmap) =
|
||||||
|
cachedBitmapGrayscales[bitmap.generationId] ?: let {
|
||||||
|
var height = bitmap.height
|
||||||
|
var width = bitmap.width
|
||||||
|
if (height > 64 || width > 64) {
|
||||||
|
if (tempCompactBitmap == null) {
|
||||||
|
tempCompactBitmap = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_8888)
|
||||||
|
.also { tempCompactBitmapCanvas = Canvas(it) }
|
||||||
|
tempCompactBitmapPaint = Paint(Paint.FILTER_BITMAP_FLAG).apply { isFilterBitmap = true }
|
||||||
|
}
|
||||||
|
tempMatrix.reset()
|
||||||
|
tempMatrix.setScale(64f / width, 64f / height, 0f, 0f)
|
||||||
|
tempCompactBitmapCanvas?.drawColor(0, PorterDuff.Mode.SRC)
|
||||||
|
tempCompactBitmapCanvas?.drawBitmap(bitmap, tempMatrix, tempCompactBitmapPaint)
|
||||||
|
height = 64
|
||||||
|
width = 64
|
||||||
|
}
|
||||||
|
val size = height * width
|
||||||
|
ensureBufferSize(size)
|
||||||
|
tempCompactBitmap?.getPixels(tempBuffer, 0, width, 0, 0, width, height)
|
||||||
|
for (i in 0 until size)
|
||||||
|
if (!isGrayscaleColor(tempBuffer[i])) {
|
||||||
|
cachedBitmapGrayscales[bitmap.generationId] = false
|
||||||
|
return@let false
|
||||||
|
}
|
||||||
|
cachedBitmapGrayscales[bitmap.generationId] = true
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提纯 [Bitmap] 颜色判断灰度
|
||||||
|
* @param color 颜色
|
||||||
|
* @return [Boolean] 是否灰度
|
||||||
|
*/
|
||||||
|
private fun isGrayscaleColor(color: Int): Boolean {
|
||||||
|
if (color shr 24 and 255 < 50) return true
|
||||||
|
val r = color shr 16 and 255
|
||||||
|
val g = color shr 8 and 255
|
||||||
|
val b = color and 255
|
||||||
|
return !(abs(r - g) >= 20 || abs(r - b) >= 20 || abs(g - b) >= 20)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算字节数组
|
||||||
|
* @param size 大小
|
||||||
|
*/
|
||||||
|
private fun ensureBufferSize(size: Int) {
|
||||||
|
if (tempBuffer.size < size) tempBuffer = IntArray(size)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* MIUINativeNotifyIcon - Fix the native notification bar icon function abandoned by the MIUI development team.
|
||||||
|
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
||||||
|
* https://github.com/fankes/MIUINativeNotifyIcon
|
||||||
|
*
|
||||||
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
|
* as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* This software is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* and eula along with this software. If not, see
|
||||||
|
* <https://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
* This file is Created by fankes on 2022/2/25.
|
||||||
|
*/
|
||||||
|
@file:Suppress("TrustAllX509TrustManager", "CustomX509TrustManager")
|
||||||
|
|
||||||
|
package com.fankes.miui.notify.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import com.highcapable.yukihookapi.hook.log.loggerD
|
||||||
|
import okhttp3.*
|
||||||
|
import java.io.IOException
|
||||||
|
import java.security.SecureRandom
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import javax.net.ssl.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络请求管理类
|
||||||
|
*/
|
||||||
|
object ClientRequestTool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 GET 请求内容并等待
|
||||||
|
* @param context 实例
|
||||||
|
* @param url 请求地址
|
||||||
|
* @param it 回调 - ([Boolean] 是否成功,[String] 成功的内容或失败消息)
|
||||||
|
*/
|
||||||
|
fun wait(context: Activity, url: String, it: (Boolean, String) -> Unit) {
|
||||||
|
OkHttpClient().newBuilder().apply {
|
||||||
|
SSLSocketClient.sSLSocketFactory?.let { sslSocketFactory(it, SSLSocketClient.trustManager) }
|
||||||
|
hostnameVerifier(SSLSocketClient.hostnameVerifier)
|
||||||
|
}.build().newCall(
|
||||||
|
Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.get()
|
||||||
|
.build()
|
||||||
|
).enqueue(object : Callback {
|
||||||
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
context.runOnUiThread { it(false, e.toString()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call, response: Response) {
|
||||||
|
val bodyString = response.body?.string() ?: ""
|
||||||
|
context.runOnUiThread { it(true, bodyString) }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动信任 SSL 证书
|
||||||
|
*
|
||||||
|
* 放行全部加密 SSL 请求
|
||||||
|
*/
|
||||||
|
object SSLSocketClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化实例
|
||||||
|
* @return [SSLSocketFactory] or null
|
||||||
|
*/
|
||||||
|
val sSLSocketFactory
|
||||||
|
get() = safeOfNull {
|
||||||
|
SSLContext.getInstance("TLS").let {
|
||||||
|
it.init(null, arrayOf<TrustManager>(trustManager), SecureRandom())
|
||||||
|
it.socketFactory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用的实例
|
||||||
|
* @return [HostnameVerifier]
|
||||||
|
*/
|
||||||
|
val hostnameVerifier get() = HostnameVerifier { _, _ -> true }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 信任管理者
|
||||||
|
* @return [X509TrustManager]
|
||||||
|
*/
|
||||||
|
val trustManager
|
||||||
|
get() = object : X509TrustManager {
|
||||||
|
|
||||||
|
override fun checkClientTrusted(chain: Array<X509Certificate?>?, authType: String?) {
|
||||||
|
loggerD(msg = "TrustX509 --> $authType")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun checkServerTrusted(chain: Array<X509Certificate?>?, authType: String?) {
|
||||||
|
loggerD(msg = "TrustX509 --> $authType")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAcceptedIssuers() = arrayOf<X509Certificate>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -26,8 +26,6 @@ package com.fankes.miui.notify.utils
|
|||||||
|
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.drawable.GradientDrawable
|
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -109,14 +107,7 @@ class DialogBuilder(private val context: Context) {
|
|||||||
internal fun show() = instance?.create()?.apply {
|
internal fun show() = instance?.create()?.apply {
|
||||||
val dm = DisplayMetrics()
|
val dm = DisplayMetrics()
|
||||||
(context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.getMetrics(dm)
|
(context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.getMetrics(dm)
|
||||||
customLayoutView?.let { setView(it.apply { minimumWidth = round(dm.widthPixels / 1.3).toInt() }) }
|
customLayoutView?.let { setView(it.apply { minimumWidth = round(x = dm.widthPixels / 1.3).toInt() }) }
|
||||||
window?.setBackgroundDrawable(GradientDrawable(
|
setDefaultStyle(context = this@DialogBuilder.context)
|
||||||
GradientDrawable.Orientation.TOP_BOTTOM,
|
|
||||||
intArrayOf(Color.WHITE, Color.WHITE)
|
|
||||||
).apply {
|
|
||||||
shape = GradientDrawable.RECTANGLE
|
|
||||||
gradientType = GradientDrawable.LINEAR_GRADIENT
|
|
||||||
cornerRadius = 15.dp(this@DialogBuilder.context)
|
|
||||||
})
|
|
||||||
}?.show()
|
}?.show()
|
||||||
}
|
}
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -22,11 +22,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.fankes.miui.notify.utils
|
package com.fankes.miui.notify.utils
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Color
|
|
||||||
import android.widget.Toast
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统界面工具
|
* 系统界面工具
|
||||||
@@ -46,7 +44,7 @@ object SystemUITool {
|
|||||||
execShellSu(cmd = "pgrep systemui").also { pid ->
|
execShellSu(cmd = "pgrep systemui").also { pid ->
|
||||||
if (pid.isNotBlank())
|
if (pid.isNotBlank())
|
||||||
execShellSu(cmd = "kill -9 $pid")
|
execShellSu(cmd = "kill -9 $pid")
|
||||||
else Toast.makeText(context, "ROOT 权限获取失败", Toast.LENGTH_SHORT).show()
|
else toast(msg = "ROOT 权限获取失败")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cancelButton()
|
cancelButton()
|
||||||
@@ -57,9 +55,16 @@ object SystemUITool {
|
|||||||
* @param context 实例
|
* @param context 实例
|
||||||
*/
|
*/
|
||||||
fun showNeedRestartSnake(context: Context) =
|
fun showNeedRestartSnake(context: Context) =
|
||||||
Snackbar.make((context as Activity).findViewById(android.R.id.content), "设置需要重启系统界面才能生效", Snackbar.LENGTH_LONG)
|
if (YukiHookModuleStatus.isActive())
|
||||||
.apply {
|
context.snake(msg = "设置需要重启系统界面才能生效", actionText = "立即重启") { restartSystemUI(context) }
|
||||||
setActionTextColor(Color.WHITE)
|
else context.snake(msg = "模块没有激活,更改不会生效")
|
||||||
setAction("立即重启") { restartSystemUI(context) }
|
|
||||||
}.show()
|
/**
|
||||||
|
* 显示更新数据后需要重启系统界面的 [Snackbar]
|
||||||
|
* @param context 实例
|
||||||
|
*/
|
||||||
|
fun showNeedUpdateApplySnake(context: Context) =
|
||||||
|
if (YukiHookModuleStatus.isActive())
|
||||||
|
context.snake(msg = "数据已更新,请重启系统界面使更改生效", actionText = "立即重启") { restartSystemUI(context) }
|
||||||
|
else context.snake(msg = "模块没有激活,更改不会生效")
|
||||||
}
|
}
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@@ -20,22 +20,26 @@
|
|||||||
*
|
*
|
||||||
* This file is Created by fankes on 2022/1/7.
|
* This file is Created by fankes on 2022/1/7.
|
||||||
*/
|
*/
|
||||||
@file:Suppress("DEPRECATION", "PrivateApi", "unused")
|
@file:Suppress("DEPRECATION", "PrivateApi", "unused", "ObsoleteSdkInt")
|
||||||
|
|
||||||
package com.fankes.miui.notify.utils
|
package com.fankes.miui.notify.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.AlertDialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.*
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Bitmap.createBitmap
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.GradientDrawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.service.notification.StatusBarNotification
|
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
|
import android.widget.Toast
|
||||||
import com.fankes.miui.notify.application.MNNApplication.Companion.appContext
|
import com.fankes.miui.notify.application.MNNApplication.Companion.appContext
|
||||||
import com.highcapable.yukihookapi.hook.factory.callStatic
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.highcapable.yukihookapi.hook.factory.classOf
|
import com.highcapable.yukihookapi.hook.factory.classOf
|
||||||
import com.highcapable.yukihookapi.hook.factory.hasClass
|
import com.highcapable.yukihookapi.hook.factory.hasClass
|
||||||
import com.highcapable.yukihookapi.hook.factory.method
|
import com.highcapable.yukihookapi.hook.factory.method
|
||||||
@@ -145,12 +149,6 @@ val miuiFullVersion
|
|||||||
get() = if (isMIUI) (miuiVersion + " " + findPropString(key = "ro.system.build.version.incremental"))
|
get() = if (isMIUI) (miuiVersion + " " + findPropString(key = "ro.system.build.version.incremental"))
|
||||||
else "不是 MIUI 系统"
|
else "不是 MIUI 系统"
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取推送通知的包名
|
|
||||||
* @return [String]
|
|
||||||
*/
|
|
||||||
val StatusBarNotification.opPkgName get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) opPkg else packageName ?: ""
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 得到安装包信息
|
* 得到安装包信息
|
||||||
* @return [PackageInfo]
|
* @return [PackageInfo]
|
||||||
@@ -220,23 +218,19 @@ val ByteArray.bitmap: Bitmap get() = BitmapFactory.decodeByteArray(this, 0, size
|
|||||||
val String.bitmap: Bitmap get() = unbase64.bitmap
|
val String.bitmap: Bitmap get() = unbase64.bitmap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 圆角图片
|
* 设置对话框默认风格
|
||||||
* @param radius 圆角度
|
* @param context 使用的实例
|
||||||
* @return [Bitmap] 圆角后的位图 - 失败会返回处理之前的位图
|
|
||||||
*/
|
*/
|
||||||
fun Bitmap.round(radius: Float): Bitmap =
|
fun AlertDialog.setDefaultStyle(context: Context) =
|
||||||
createBitmap(width, height, Bitmap.Config.ARGB_8888).also { out ->
|
window?.setBackgroundDrawable(
|
||||||
Canvas(out).also { canvas ->
|
GradientDrawable(
|
||||||
Paint().also { paint ->
|
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||||
paint.isAntiAlias = true
|
intArrayOf(Color.WHITE, Color.WHITE)
|
||||||
canvas.drawARGB(0, 0, 0, 0)
|
).apply {
|
||||||
paint.color = Color.WHITE
|
shape = GradientDrawable.RECTANGLE
|
||||||
canvas.drawRoundRect(RectF(Rect(0, 0, width, height)), radius, radius, paint)
|
gradientType = GradientDrawable.LINEAR_GRADIENT
|
||||||
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
|
cornerRadius = 15.dp(context)
|
||||||
canvas.drawBitmap(this, Rect(0, 0, width, height), Rect(0, 0, width, height), paint)
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取系统 Prop 值
|
* 获取系统 Prop 值
|
||||||
@@ -245,9 +239,10 @@ fun Bitmap.round(radius: Float): Bitmap =
|
|||||||
* @return [String]
|
* @return [String]
|
||||||
*/
|
*/
|
||||||
fun findPropString(key: String, default: String = "") = safeOf(default) {
|
fun findPropString(key: String, default: String = "") = safeOf(default) {
|
||||||
(classOf(name = "android.os.SystemProperties").method(
|
(classOf(name = "android.os.SystemProperties").method {
|
||||||
name = "get", StringType, StringType
|
name = "get"
|
||||||
)?.callStatic(key, default)) ?: default
|
param(StringType, StringType)
|
||||||
|
}.get().invoke(key, default)) ?: default
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -261,6 +256,26 @@ fun execShellSu(cmd: String) = safeOfNothing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹出 [Toast]
|
||||||
|
* @param msg 提示内容
|
||||||
|
*/
|
||||||
|
fun toast(msg: String) = Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).show()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹出 [Snackbar]
|
||||||
|
* @param msg 提示内容
|
||||||
|
* @param actionText 按钮文本 - 不写默认取消按钮
|
||||||
|
* @param it 按钮事件回调
|
||||||
|
*/
|
||||||
|
fun Context.snake(msg: String, actionText: String = "", it: () -> Unit = {}) =
|
||||||
|
Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG)
|
||||||
|
.apply {
|
||||||
|
if (actionText.isBlank()) return@apply
|
||||||
|
setActionTextColor(Color.WHITE)
|
||||||
|
setAction(actionText) { it() }
|
||||||
|
}.show()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 忽略异常返回值
|
* 忽略异常返回值
|
||||||
* @param it 回调 - 如果异常为空
|
* @param it 回调 - 如果异常为空
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
* This software is non-free but opensource software: you can redistribute it
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
* and/or modify it under the terms of the GNU Affero General Public License
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
* as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version and our eula as published
|
* version 3 of the License, or any later version.
|
||||||
* by ferredoxin.
|
* <p>
|
||||||
*
|
*
|
||||||
* This software is distributed in the hope that it will be useful,
|
* This software is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
android:layout_height="20dp"
|
android:layout_height="20dp"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginEnd="25dp"
|
android:layout_marginEnd="25dp"
|
||||||
android:src="@mipmap/back"
|
android:src="@mipmap/ic_back"
|
||||||
android:tint="@color/colorTextGray"
|
android:tint="@color/colorTextGray"
|
||||||
android:tooltipText="返回" />
|
android:tooltipText="返回" />
|
||||||
|
|
||||||
@@ -52,19 +52,46 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text="..."
|
android:text="适配列表正在等待装载"
|
||||||
android:textColor="@color/colorTextDark"
|
android:textColor="@color/colorTextDark"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||||
|
android:id="@+id/config_title_up"
|
||||||
|
android:layout_width="22dp"
|
||||||
|
android:layout_height="22dp"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
android:src="@mipmap/ic_page_top"
|
||||||
|
android:tint="@color/colorTextGray"
|
||||||
|
android:tooltipText="滚动到顶部" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||||
|
android:id="@+id/config_title_down"
|
||||||
|
android:layout_width="22dp"
|
||||||
|
android:layout_height="22dp"
|
||||||
|
android:layout_marginEnd="15dp"
|
||||||
|
android:src="@mipmap/ic_page_bottom"
|
||||||
|
android:tint="@color/colorTextGray"
|
||||||
|
android:tooltipText="滚动到底部" />
|
||||||
|
|
||||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||||
android:id="@+id/config_title_filter"
|
android:id="@+id/config_title_filter"
|
||||||
android:layout_width="22dp"
|
android:layout_width="22dp"
|
||||||
android:layout_height="22dp"
|
android:layout_height="22dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:src="@mipmap/icon_filter"
|
android:src="@mipmap/ic_filter"
|
||||||
android:tint="@color/colorTextGray"
|
android:tint="@color/colorTextGray"
|
||||||
android:tooltipText="按条件过滤" />
|
android:tooltipText="按条件过滤" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||||
|
android:id="@+id/config_title_sync"
|
||||||
|
android:layout_width="23dp"
|
||||||
|
android:layout_height="23dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:src="@mipmap/ic_sync"
|
||||||
|
android:tint="@color/colorTextGray"
|
||||||
|
android:tooltipText="同步列表" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -73,7 +100,7 @@
|
|||||||
android:layout_marginLeft="15dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:background="@drawable/permotion_round"
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
@@ -84,7 +111,7 @@
|
|||||||
android:layout_height="15dp"
|
android:layout_height="15dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:alpha="0.85"
|
android:alpha="0.85"
|
||||||
android:src="@mipmap/about"
|
android:src="@mipmap/ic_about"
|
||||||
android:tint="@color/colorTextDark" />
|
android:tint="@color/colorTextDark" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -108,7 +135,9 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:text="噫,竟然什么都没找到~"
|
android:gravity="center"
|
||||||
|
android:lineSpacingExtra="6dp"
|
||||||
|
android:text="没有数据"
|
||||||
android:textColor="@color/colorTextDark"
|
android:textColor="@color/colorTextDark"
|
||||||
android:textSize="17sp"
|
android:textSize="17sp"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
@@ -133,7 +162,7 @@
|
|||||||
android:layout_marginLeft="15dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:layout_marginBottom="15dp"
|
android:layout_marginBottom="15dp"
|
||||||
android:background="@drawable/button_round"
|
android:background="@drawable/bg_button_round"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
|
@@ -36,7 +36,7 @@
|
|||||||
android:layout_height="28dp"
|
android:layout_height="28dp"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:alpha="0.85"
|
android:alpha="0.85"
|
||||||
android:src="@mipmap/restart"
|
android:src="@mipmap/ic_restart"
|
||||||
android:tint="@color/colorTextGray"
|
android:tint="@color/colorTextGray"
|
||||||
android:tooltipText="重启系统界面" />
|
android:tooltipText="重启系统界面" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
android:background="@drawable/dark_round"
|
android:background="@drawable/bg_dark_round"
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center">
|
android:gravity="center">
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
android:layout_height="25dp"
|
android:layout_height="25dp"
|
||||||
android:layout_marginStart="25dp"
|
android:layout_marginStart="25dp"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:src="@mipmap/warn"
|
android:src="@mipmap/ic_warn"
|
||||||
android:tint="@color/white" />
|
android:tint="@color/white" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
android:layout_marginLeft="15dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:background="@drawable/permotion_round"
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
android:layout_height="15dp"
|
android:layout_height="15dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:alpha="0.85"
|
android:alpha="0.85"
|
||||||
android:src="@mipmap/about"
|
android:src="@mipmap/ic_about"
|
||||||
android:tint="@color/colorTextDark" />
|
android:tint="@color/colorTextDark" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:animateLayoutChanges="true"
|
android:animateLayoutChanges="true"
|
||||||
android:background="@drawable/permotion_round"
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -184,18 +184,19 @@
|
|||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:alpha="0.6"
|
android:alpha="0.6"
|
||||||
android:lineSpacingExtra="6dp"
|
android:lineSpacingExtra="6dp"
|
||||||
android:text="模块关闭后功能都将彻底停止工作,以下选项都将不再生效。"
|
android:text="模块关闭后一切功能都将彻底停止工作。"
|
||||||
android:textColor="@color/colorTextDark"
|
android:textColor="@color/colorTextDark"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/config_item_color_hook"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="15dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:background="@drawable/permotion_round"
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -219,6 +220,26 @@
|
|||||||
android:text="此选项默认开启,开启后将自动对 APP 通知图标进行判断,保持高版本 API 的 APP 不规范的彩色图标不被着色为白、黑色块并对图标进行圆角优化,关闭后将按照 Android API 规范对 APP 通知进行图标着色,可能会出现着色为黑白、色块情况。"
|
android:text="此选项默认开启,开启后将自动对 APP 通知图标进行判断,保持高版本 API 的 APP 不规范的彩色图标不被着色为白、黑色块并对图标进行圆角优化,关闭后将按照 Android API 规范对 APP 通知进行图标着色,可能会出现着色为黑白、色块情况。"
|
||||||
android:textColor="@color/colorTextDark"
|
android:textColor="@color/colorTextDark"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<com.fankes.miui.notify.view.MaterialSwitch
|
||||||
|
android:id="@+id/color_icon_compat_switch"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="35dp"
|
||||||
|
android:layout_marginBottom="5dp"
|
||||||
|
android:text="启用兼容模式"
|
||||||
|
android:textColor="@color/colorTextGray"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/color_icon_compat_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:lineSpacingExtra="6dp"
|
||||||
|
android:text="如果发现通知图标颜色判定不正常可启用兼容模式,一般情况下不建议启用兼容模式,发生问题请关闭兼容模式。"
|
||||||
|
android:textColor="@color/colorTextDark"
|
||||||
|
android:textSize="12sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -228,7 +249,8 @@
|
|||||||
android:layout_marginLeft="10dp"
|
android:layout_marginLeft="10dp"
|
||||||
android:layout_marginTop="15dp"
|
android:layout_marginTop="15dp"
|
||||||
android:layout_marginRight="10dp"
|
android:layout_marginRight="10dp"
|
||||||
android:background="@drawable/permotion_round"
|
android:animateLayoutChanges="true"
|
||||||
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -250,7 +272,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:background="@drawable/button_round"
|
android:background="@drawable/bg_button_round"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
@@ -266,12 +288,11 @@
|
|||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:alpha="0.6"
|
android:alpha="0.6"
|
||||||
android:lineSpacingExtra="6dp"
|
android:lineSpacingExtra="6dp"
|
||||||
android:text="此选项默认开启,开启后将对优化名单内 APP 通知小图标进行色彩修复,特别是通过 MIPUSH 推送的通知,它们始终是彩色的,修复后使得它们的图标看起来更加符合原生规范。"
|
android:text="首次安装请打开名单列表从云端更新数据,后期适配的内容也请手动打开名单列表重新拉取数据以检查更新,数据更新后重启系统界面即可生效。"
|
||||||
android:textColor="@color/colorTextDark"
|
android:textColor="@color/colorTextDark"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/config_notify_app_icon_warn"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="5dp"
|
android:layout_marginLeft="5dp"
|
||||||
@@ -279,10 +300,9 @@
|
|||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:alpha="0.6"
|
android:alpha="0.6"
|
||||||
android:lineSpacingExtra="6dp"
|
android:lineSpacingExtra="6dp"
|
||||||
android:text="⚠️ 你的 MIUI 版本过低,状态栏上 MIPUSH 的彩色图标由于不能识别反色将不会被优化为黑白小图标,仅在通知栏生效。"
|
android:text="此选项默认开启,开启后将对优化名单内的 APP 通知小图标使用单色调进行修复,特别是通过 MIPUSH 推送的通知,它们始终是 APP 默认图标(彩色的 APP 图标),修复后使得它们的图标看起来更加符合 Android 原生的统一规范。"
|
||||||
android:textColor="#FF9800"
|
android:textColor="@color/colorTextDark"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp" />
|
||||||
android:visibility="gone" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -291,7 +311,7 @@
|
|||||||
android:layout_marginLeft="15dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginTop="15dp"
|
android:layout_marginTop="15dp"
|
||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:background="@drawable/permotion_round"
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -323,7 +343,7 @@
|
|||||||
android:layout_marginLeft="15dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginTop="15dp"
|
android:layout_marginTop="15dp"
|
||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:background="@drawable/permotion_round"
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -340,7 +360,7 @@
|
|||||||
android:layout_height="15dp"
|
android:layout_height="15dp"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:alpha="0.85"
|
android:alpha="0.85"
|
||||||
android:src="@mipmap/about"
|
android:src="@mipmap/ic_about"
|
||||||
android:tint="@color/colorTextGray" />
|
android:tint="@color/colorTextGray" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -379,7 +399,7 @@
|
|||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:alpha="0.8"
|
android:alpha="0.8"
|
||||||
android:lineSpacingExtra="6dp"
|
android:lineSpacingExtra="6dp"
|
||||||
android:text="Q.哪些是已知问题?\nA.以下是问题描述列表:\n(1) 动态小图标可能会在高版本系统中闪烁,这是 MIUI 自身就存在的问题,后期只能等官方修复。\n(2) 请始终保持最新版本的 LSPosed,旧版本可能会出现 Hook 不生效的问题。"
|
android:text="Q.哪些是已知问题?\nA.以下是问题描述列表:\n(1) 动态小图标可能会在高版本系统中闪烁,这是 MIUI 自身就存在的问题,后期只能等官方修复。\n(2) 请始终保持最新版本的 LSPosed,旧版本可能会出现 Hook 不生效的问题。\n(3) 建议最低从 MIUI 12.5 “2021-5-18” 开发版以后开始使用,之前的版本可能或多或少存在 MIUI 自身 BUG 不生效、黑白块问题,若你的系统不存在原生图标问题不建议使用模块。"
|
||||||
android:textColor="@color/colorTextDark"
|
android:textColor="@color/colorTextDark"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
@@ -400,7 +420,7 @@
|
|||||||
android:layout_marginLeft="15dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginTop="15dp"
|
android:layout_marginTop="15dp"
|
||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:background="@drawable/permotion_round"
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -417,7 +437,7 @@
|
|||||||
android:layout_height="15dp"
|
android:layout_height="15dp"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:alpha="0.85"
|
android:alpha="0.85"
|
||||||
android:src="@mipmap/about"
|
android:src="@mipmap/ic_about"
|
||||||
android:tint="@color/colorTextGray" />
|
android:tint="@color/colorTextGray" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -447,7 +467,7 @@
|
|||||||
android:layout_marginTop="15dp"
|
android:layout_marginTop="15dp"
|
||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:background="@drawable/permotion_round"
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -476,7 +496,7 @@
|
|||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:src="@mipmap/qr_pay" />
|
android:src="@mipmap/bg_qr_pay" />
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -497,7 +517,7 @@
|
|||||||
android:layout_marginRight="15dp"
|
android:layout_marginRight="15dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:autoLink="web"
|
android:autoLink="web"
|
||||||
android:background="@drawable/permotion_round"
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:lineSpacingExtra="6dp"
|
android:lineSpacingExtra="6dp"
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
android:text="此模块使用 YukiHookAPI 构建。\n点击这里了解更多 https://github.com/fankes/YukiHookAPI"
|
android:text="此模块使用 YukiHookAPI 构建。\n点击这里了解更多 https://github.com/fankes/YukiHookAPI"
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/permotion_round"
|
android:background="@drawable/bg_permotion_round"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:gravity="center|start"
|
android:gravity="center|start"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
android:layout_width="15dp"
|
android:layout_width="15dp"
|
||||||
android:layout_height="15dp"
|
android:layout_height="15dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:src="@mipmap/about"
|
android:src="@mipmap/ic_about"
|
||||||
android:tint="@color/colorTextGray" />
|
android:tint="@color/colorTextGray" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 201 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_filter.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_page_bottom.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_page_top.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_sync.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
@@ -2,16 +2,13 @@ package com.fankes.miui.notify
|
|||||||
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
*
|
*
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
*/
|
*/
|
||||||
class ExampleUnitTest {
|
class ExampleUnitTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun addition_isCorrect() {
|
fun main() = println("Hello world")
|
||||||
assertEquals(4, 2 + 2)
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -5,8 +5,8 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
appVersionName = "1.51"
|
appVersionName = "1.8"
|
||||||
appVersionCode = 10
|
appVersionCode = 17
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
|
1102
iconPack/NotifyIconsSupportConfig.json
Normal file
@@ -10,7 +10,8 @@ dependencyResolutionManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
maven { url "https://api.xposed.info/" }
|
maven { url "https://api.xposed.info/" }
|
||||||
maven { url 'https://www.jitpack.io' }
|
maven { url "https://www.jitpack.io" }
|
||||||
|
maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|