Skip to content

Commit

Permalink
feat: all fallback settings as one
Browse files Browse the repository at this point in the history
  • Loading branch information
RichardLuo0 committed Dec 1, 2024
1 parent eb2269e commit 5922c20
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 109 deletions.
12 changes: 4 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,10 @@ This module is designed to extend the customization of icon packs throughout the

## Installation
1. Install the apk.
2. Open Global Icon Pack. Remember to fill the `Icon pack` settings with an icon pack package name.
3. Select the recommend apps in lsposed (Other launcher/apps may also work, depending on the api they use)
4. For pixel launcher and probably other similar launcher 3 based launcher, you will need to delete `/data/data/com.google.android.apps.nexuslauncher/databases/app_icons.db` and then restart the launcher through its settings page.

## Settings
* `Icon pack`: The package name to be used as icon pack.
* `No force shape`: This setting is specific to pixel launcher. Turning it on will prevent it from forcing a uniform icon shape.
* `Icon pack settings`: This section controls whether to use "fallback" elements such as masks. Some icon packs include predefined masks or backgrounds that ensure all icons have a consistent shape or style, even for apps that don't have dedicated icons in the pack. You can choose to enable or disable them.
2. Select the recommend apps in lsposed (Other launcher/apps may also work, depending on the api they use)
3. Open Global Icon Pack. Fill the `Icon pack` settings with an icon pack package name.
4. For pixel launcher and probably other similar launcher 3 based launcher, you will need to delete `/data/data/com.google.android.apps.nexuslauncher/databases/app_icons.db` then restart the launcher through its settings page.
5. Recent screen will use your default launcher unless you use quickswitch. So you will need to select pixel launcher for that to work.

## Known Issues
* ~~When clicking an app, Pixel Launcher triggers an animation, whose starting frame displays an icon with a white border.~~
Expand Down
116 changes: 40 additions & 76 deletions app/src/main/kotlin/com/richardluo/globalIconPack/CustomIconPack.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ class CustomIconPack(pm: PackageManager, private val pref: SharedPreferences) {
private val iconEntryList = mutableListOf<IconEntry?>()

// Fallback settings from icon pack
private var iconBack: Bitmap? = null
private var iconUpon: Bitmap? = null
private var iconMask: Bitmap? = null
private var iconBacks = mutableListOf<Bitmap>()
private var iconUpons = mutableListOf<Bitmap>()
private var iconMasks = mutableListOf<Bitmap>()
private var iconScale: Float = 1f

private var globalScale: Float = pref.getFloat("scale", 1f)
Expand Down Expand Up @@ -62,9 +62,9 @@ class CustomIconPack(pm: PackageManager, private val pref: SharedPreferences) {
IconHelper.processIcon(
packResources,
baseIcon,
iconBack,
iconUpon,
iconMask,
iconBacks.randomOrNull(),
iconUpons.randomOrNull(),
iconMasks.randomOrNull(),
iconScale * globalScale,
)

Expand All @@ -75,83 +75,47 @@ class CustomIconPack(pm: PackageManager, private val pref: SharedPreferences) {
val compStartLength = compStart.length
val compEnd = "}"
val compEndLength = compEnd.length

fun addFallback(parseXml: XmlPullParser, list: MutableList<Bitmap>) {
if (!pref.getBoolean("iconFallback", true)) return
for (i in 0 until parseXml.attributeCount) if (parseXml.getAttributeName(i).startsWith("img"))
packResources
.getIdentifier(parseXml.getAttributeValue(i), "drawable", packPackageName)
.takeIf { it != 0 }
?.let { getDrawable(packResources, it, null)?.toBitmap() }
?.let { list.add(it) }
}

fun addIcon(parseXml: XmlPullParser, iconType: IconType) {
var componentName: String = parseXml["component"] ?: return
val drawableName =
parseXml[if (iconType == IconType.Calendar) "prefix" else "drawable"] ?: return
if (componentName.startsWith(compStart) && componentName.endsWith(compEnd)) {
componentName =
componentName.substring(compStartLength, componentName.length - compEndLength)
}
ComponentName.unflattenFromString(componentName)?.let { cn ->
val iconEntry = IconEntry(drawableName, iconType)
addIconEntry(cn, iconEntry)
// TODO Use the first icon as app icon. I don't see a better way.
addIconEntry(getComponentName(cn.packageName), iconEntry)
}
}

try {
val clockMetaMap = mutableMapOf<String, Int>()
while (parseXml.next() != XmlPullParser.END_DOCUMENT) {
if (parseXml.eventType != XmlPullParser.START_TAG) continue
val name = parseXml.name
when (name) {
"iconback" -> {
if (!pref.getBoolean("iconBack", true)) continue
for (i in 0 until parseXml.attributeCount) {
if (parseXml.getAttributeName(i).startsWith("img")) {
val imgName = parseXml.getAttributeValue(i)
val id = packResources.getIdentifier(imgName, "drawable", packPackageName)
if (id != 0) iconBack = getDrawable(packResources, id, null)?.toBitmap()
}
}
}

"iconupon" -> {
if (!pref.getBoolean("iconUpon", true)) continue
for (i in 0 until parseXml.attributeCount) {
if (parseXml.getAttributeName(i).startsWith("img")) {
val imgName = parseXml.getAttributeValue(i)
val id = packResources.getIdentifier(imgName, "drawable", packPackageName)
if (id != 0) iconUpon = getDrawable(packResources, id, null)?.toBitmap()
}
}
}

"iconmask" -> {
if (!pref.getBoolean("iconMask", true)) continue
for (i in 0 until parseXml.attributeCount) {
if (parseXml.getAttributeName(i).startsWith("img")) {
val imgName = parseXml.getAttributeValue(i)
val id = packResources.getIdentifier(imgName, "drawable", packPackageName)
if (id != 0) iconMask = getDrawable(packResources, id, null)?.toBitmap()
}
}
}

when (parseXml.name) {
"iconback" -> addFallback(parseXml, iconBacks)
"iconupon" -> addFallback(parseXml, iconUpons)
"iconmask" -> addFallback(parseXml, iconMasks)
"scale" -> {
if (!pref.getBoolean("iconScale", true)) continue
if (!pref.getBoolean("iconFallback", true)) continue
iconScale = parseXml.getAttributeValue(null, "factor")?.toFloatOrNull() ?: 1f
}

"item" -> {
var componentName: String? = parseXml["component"]
val drawableName = parseXml["drawable"]
if (componentName != null && drawableName != null) {
if (componentName.startsWith(compStart) && componentName.endsWith(compEnd)) {
componentName =
componentName.substring(compStartLength, componentName.length - compEndLength)
}
ComponentName.unflattenFromString(componentName)?.let { cn ->
val iconEntry = IconEntry(drawableName, IconType.Normal)
addIconEntry(cn, iconEntry)
// TODO Use the first icon as app icon. I don't see a better way.
addIconEntry(getComponentName(cn.packageName), iconEntry)
}
}
}

"calendar" -> {
var componentName: String? = parseXml["component"]
val drawableName = parseXml["prefix"]
if (componentName != null && drawableName != null) {
if (componentName.startsWith(compStart) && componentName.endsWith(compEnd)) {
componentName =
componentName.substring(compStartLength, componentName.length - compEndLength)
}
ComponentName.unflattenFromString(componentName)?.let { cn ->
val iconEntry = IconEntry(drawableName, IconType.Calendar)
addIconEntry(cn, iconEntry)
addIconEntry(getComponentName(cn.packageName), iconEntry)
}
}
}

"item" -> addIcon(parseXml, IconType.Normal)
"calendar" -> addIcon(parseXml, IconType.Calendar)
"dynamic-clock" -> {
val drawableName = parseXml["drawable"]
if (drawableName != null) {
Expand Down
24 changes: 3 additions & 21 deletions app/src/main/kotlin/com/richardluo/globalIconPack/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -118,28 +118,10 @@ fun SampleScreen() {
title = { Text(text = stringResource(R.string.iconPackSettings)) },
)
switchPreference(
key = "iconBack",
key = "iconFallback",
defaultValue = true,
title = { Text(text = stringResource(R.string.iconBack)) },
summary = { Text(text = if (it) "On" else "Off") },
)
switchPreference(
key = "iconUpon",
defaultValue = true,
title = { Text(text = stringResource(R.string.iconUpon)) },
summary = { Text(text = if (it) "On" else "Off") },
)
switchPreference(
key = "iconMask",
defaultValue = true,
title = { Text(text = stringResource(R.string.iconMask)) },
summary = { Text(text = if (it) "On" else "Off") },
)
switchPreference(
key = "iconScale",
defaultValue = true,
title = { Text(text = stringResource(R.string.iconScale)) },
summary = { Text(text = if (it) "On" else "Off") },
title = { Text(text = stringResource(R.string.iconFallback)) },
summary = { Text(text = stringResource(R.string.iconFallbackSummary)) },
)
}
}
Expand Down
6 changes: 2 additions & 4 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
<string name="forceLoadClockAndCalendar">Force load clock and calendar icon</string>

<string name="iconPackSettings">Icon pack settings</string>
<string name="iconBack">Icon back</string>
<string name="iconUpon">Icon upon</string>
<string name="iconMask">Icon mask</string>
<string name="iconScale">Scale</string>
<string name="iconFallback">Fallback</string>
<string name="iconFallbackSummary">Apply background, mask, and scale from the icon pack to apps without dedicated icons.</string>
</resources>

0 comments on commit 5922c20

Please sign in to comment.