Initial commit

This commit is contained in:
MM20
2021-09-18 23:37:52 +02:00
commit 749e4e3073
938 changed files with 50475 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/build
+48
View File
@@ -0,0 +1,48 @@
plugins {
id("com.android.library")
id("kotlin-android")
id("kotlin-android-extensions")
}
android {
compileSdk = sdk.versions.compileSdk.get().toInt()
defaultConfig {
minSdk = sdk.versions.minSdk.get().toInt()
targetSdk = sdk.versions.targetSdk.get().toInt()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
implementation(libs.bundles.kotlin)
implementation(libs.androidx.core)
implementation(libs.androidx.appcompat)
implementation(libs.bundles.androidx.lifecycle)
implementation(project(":ktx"))
implementation(project(":preferences"))
}
View File
+21
View File
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.kts.kts.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
+5
View File
@@ -0,0 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.mm20.launcher2.badges">
/
</manifest>
@@ -0,0 +1,10 @@
package de.mm20.launcher2.badges
import android.graphics.drawable.Drawable
data class Badge(
var number: Int? = null,
var progress: Float? = null,
var iconRes: Int? = null,
var icon: Drawable? = null
)
@@ -0,0 +1,150 @@
package de.mm20.launcher2.badges
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.LauncherApps
import android.os.Build
import android.os.Process
import androidx.annotation.RequiresApi
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import de.mm20.launcher2.ktx.getSerialNumber
import de.mm20.launcher2.ktx.isAtLeastApiLevel
import de.mm20.launcher2.preferences.LauncherPreferences
import kotlinx.coroutines.*
class BadgeProvider private constructor(val context: Context) {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private val badges = mutableMapOf<String, MutableLiveData<Badge>>()
init {
if (LauncherPreferences.instance.cloudBadges) {
addCloudBadges()
}
if (LauncherPreferences.instance.suspendBadges) {
addSuspendBadges()
}
if (LauncherPreferences.instance.profileBadges && isAtLeastApiLevel(Build.VERSION_CODES.O)) {
addProfileBadges()
}
}
fun setBadge(key: String, badge: Badge) {
if (badges.containsKey(key)) {
badges[key]?.postValue(badge)
return
}
badges[key] = MutableLiveData(badge)
}
/**
* Updates a badge with all set values of another badge but keeps all other values
*/
fun updateBadge(key: String,
badge: Badge) {
if (badges.containsKey(key)) {
badges[key]?.run {
val updatedBadge = value?.also {
if (badge.number != null) it.number = badge.number
if (badge.progress != null) it.progress = badge.progress
if (badge.iconRes != null) it.iconRes = badge.iconRes
if (badge.icon != null) it.icon = badge.icon
}
postValue(updatedBadge)
}
} else {
badges[key] = MutableLiveData(badge)
}
}
fun removeBadge(key: String) {
badges[key]?.postValue(Badge())
}
fun getBadge(key: String): Badge? {
return badges[key]?.value
}
fun getLiveBadge(key: String): LiveData<Badge> {
return badges[key] ?: MutableLiveData<Badge>(Badge()).also { badges[key] = it }
}
fun removeNotificationBadges() {
for (k in badges.keys) {
if (k.startsWith("app://")) {
val badge = getBadge(k) ?: continue
badge.number = null
badge.progress = null
updateBadge(k, badge)
}
}
}
fun removeSuspendBadges() {
for ((k, v) in badges) {
if (k.startsWith("app://") && v.value?.iconRes == R.drawable.ic_badge_suspended) {
val badge = getBadge(k) ?: continue
badge.iconRes = null
updateBadge(k, badge)
}
}
}
fun addSuspendBadges() {
scope.launch {
withContext(Dispatchers.IO) {
val apps = context.packageManager.getInstalledApplications(0)
for (app in apps) {
if (app.flags and ApplicationInfo.FLAG_SUSPENDED != 0) {
setBadge("app://${app.packageName}", Badge(iconRes = R.drawable.ic_badge_suspended))
}
}
}
}
}
fun addCloudBadges() {
setBadge("gdrive://", Badge(iconRes = R.drawable.ic_badge_gdrive))
setBadge("onedrive://", Badge(iconRes = R.drawable.ic_badge_onedrive))
setBadge("nextcloud://", Badge(iconRes = R.drawable.ic_badge_nextcloud))
setBadge("owncloud://", Badge(iconRes = R.drawable.ic_badge_owncloud))
}
@RequiresApi(Build.VERSION_CODES.O)
fun addProfileBadges() {
val profiles = (context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps).profiles
for (p in profiles) {
if (p == Process.myUserHandle()) continue
setBadge("profile://${p.getSerialNumber(context)}", Badge(
iconRes = R.drawable.ic_badge_workprofile
))
}
}
fun removeCloudBadges() {
removeBadge("gdrive://")
removeBadge("onedrive://")
removeBadge("nextcloud://")
removeBadge("owncloud://")
}
fun removeShortcutBadges() {
for (k in badges.keys) {
if (k.startsWith("shortcut://")) {
removeBadge(k)
}
}
}
companion object {
private lateinit var instance: BadgeProvider
fun getInstance(context: Context): BadgeProvider {
if (!::instance.isInitialized) instance = BadgeProvider(context.applicationContext)
return instance
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp"
android:height="12dp"
android:viewportWidth="12"
android:viewportHeight="12">
<path
android:pathData="M6,3.9609C5.0708,3.9609 4.2897,4.5951 4.0469,5.4492 3.8356,4.9971 3.382,4.6777 2.8535,4.6777 2.1275,4.6777 1.5313,5.274 1.5313,6 1.5313,6.726 2.1275,7.3223 2.8535,7.3223 3.382,7.3223 3.8356,7.0029 4.0469,6.5508 4.2897,7.4049 5.0708,8.0391 6,8.0391 6.9292,8.0391 7.7103,7.4049 7.9531,6.5508 8.1644,7.0029 8.618,7.3223 9.1465,7.3223 9.8725,7.3223 10.4688,6.726 10.4688,6 10.4688,5.274 9.8725,4.6777 9.1465,4.6777 8.618,4.6777 8.1644,4.9971 7.9531,5.4492 7.7103,4.5951 6.9292,3.9609 6,3.9609ZM6,4.748C6.6958,4.748 7.252,5.3042 7.252,6 7.252,6.6958 6.6958,7.252 6,7.252 5.3042,7.252 4.748,6.6958 4.748,6 4.748,5.3042 5.3042,4.748 6,4.748ZM2.8535,5.4629C3.1544,5.4629 3.3906,5.6991 3.3906,6 3.3906,6.3009 3.1544,6.5371 2.8535,6.5371 2.5526,6.5371 2.3164,6.3009 2.3164,6 2.3164,5.6991 2.5526,5.4629 2.8535,5.4629ZM9.1465,5.4629C9.4474,5.4629 9.6836,5.6991 9.6836,6 9.6836,6.3009 9.4474,6.5371 9.1465,6.5371 8.8456,6.5371 8.6094,6.3009 8.6094,6 8.6094,5.6991 8.8456,5.4629 9.1465,5.4629Z"
android:fillColor="#0082c9"
android:fillAlpha="1"/>
</vector>
@@ -0,0 +1,7 @@
<vector android:height="12dp" android:viewportHeight="32"
android:viewportWidth="32" android:width="12dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#0364b8" android:pathData="M12.9264,12.0618L12.9264,12.061L18.3634,15.3177 21.6031,13.954A5.242,5.242 0,0 1,23.6887 13.5243C23.8085,13.5243 23.9266,13.53 24.044,13.5372A8.0932,8.0932 77.497,0 0,9.443 11.0988L9.5256,11.0963A6.4422,6.4422 0,0 1,12.9264 12.0618Z"/>
<path android:fillColor="#0078d4" android:pathData="M12.9272,12.061A6.4422,6.4422 45,0 0,9.5256 11.0963L9.443,11.0988A6.4721,6.4721 0,0 0,4.2148 21.2719L9.0076,19.2543 11.1394,18.3575 15.8844,16.3601 18.3626,15.3177Z"/>
<path android:fillColor="#1490df" android:pathData="M24.044,13.5372A5.3229,5.3229 0,0 0,23.6887 13.5243,5.242 5.242,135 0,0 21.6039,13.9548L18.3634,15.3177 19.303,15.8802 22.3824,17.7247 23.7259,18.5291 28.3204,21.2808A5.2606,5.2606 0,0 0,24.044 13.5372Z"/>
<path android:fillColor="#28a8ea" android:pathData="M23.7259,18.5291 L22.3824,17.7247 19.303,15.8794 18.3642,15.3177 15.8852,16.3601 11.1402,18.3575 9.0076,19.2543 4.2132,21.2719A6.4657,6.4657 45,0 0,9.5256 24.0454L23.6887,24.0454A5.259,5.259 45,0 0,28.3204 21.2808Z"/>
</vector>
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<group
android:pivotX="12"
android:pivotY="12"
android:scaleX="0.75"
android:scaleY="0.75">
<path
android:fillColor="@color/badge_text"
android:pathData="M 6.0001504,1.9998779 C 6.0001398,4.0032011 6.0001647,6.0065239 6.0001504,8.009847 7.3334024,9.3398262 8.6666543,10.669805 9.9999063,11.999784 8.668341,13.338163 7.3234967,14.663325 6.0001504,16.009875 6.0001504,18.006653 6.0001504,20.00343 6.0001504,22.000207 10.000079,22.000207 14.000006,22.000207 17.999935,22.000207 17.999945,20.000157 17.99992,18.000107 17.999935,16.000057 16.666683,14.666633 15.333431,13.333208 14.000179,11.999784 15.331753,10.664856 16.676576,9.343147 17.999935,8.0000283 17.999935,5.9999781 17.999935,3.9999282 17.999935,1.9998779 14.000006,1.9998779 10.000079,1.9998779 6.0001504,1.9998779 Z M 8.0000283,3.9997559 C 10.666704,3.9997559 13.333381,3.9997559 16.000057,3.9997559 16.000057,5.1664375 16.000057,6.333119 16.000057,7.4998005 14.666633,8.8332248 13.333208,10.166649 11.999784,11.500073 10.666532,10.166649 9.3332804,8.8332248 8.0000283,7.4998005 8.0000283,6.333119 8.0000283,5.1664375 8.0000283,3.9997559 Z" />
</group>
</vector>
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<group
android:pivotX="12"
android:pivotY="12"
android:scaleX="0.75"
android:scaleY="0.75">
<path
android:fillColor="@color/badge_text"
android:pathData="M20,6h-4L16,4c0,-1.11 -0.89,-2 -2,-2h-4c-1.11,0 -2,0.89 -2,2v2L4,6c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM14,6h-4L10,4h4v2z" />
</group>
</vector>