Fix unlocked tint refresh
This commit is contained in:
+20
-6
@@ -22,21 +22,30 @@ public final class ClockLayoutTextFactory {
|
||||
}
|
||||
|
||||
public static Model build(TextView source, SbtSettings settings) {
|
||||
return build(source, settings, source != null ? source.getCurrentTextColor() : 0);
|
||||
}
|
||||
|
||||
public static Model build(TextView source, SbtSettings settings, int referenceColor) {
|
||||
Context context = source != null ? source.getContext() : null;
|
||||
if (context == null || settings == null) {
|
||||
return Model.empty();
|
||||
}
|
||||
CacheKey cacheKey = cacheKey(context, source, settings);
|
||||
CacheKey cacheKey = cacheKey(context, source, settings, referenceColor);
|
||||
CachedModel cached = MODEL_CACHE.get(source);
|
||||
if (cached != null && cached.key.equals(cacheKey)) {
|
||||
return cached.model;
|
||||
}
|
||||
Model model = buildUncached(context, source, settings);
|
||||
Model model = buildUncached(context, source, settings, referenceColor);
|
||||
MODEL_CACHE.put(source, new CachedModel(cacheKey, model));
|
||||
return model;
|
||||
}
|
||||
|
||||
private static Model buildUncached(Context context, TextView source, SbtSettings settings) {
|
||||
private static Model buildUncached(
|
||||
Context context,
|
||||
TextView source,
|
||||
SbtSettings settings,
|
||||
int referenceColor
|
||||
) {
|
||||
if (!hasCustomClockTextEnabled(settings)) {
|
||||
ArrayList<Row> rows = new ArrayList<>();
|
||||
CharSequence text = source.getText();
|
||||
@@ -49,7 +58,7 @@ public final class ClockLayoutTextFactory {
|
||||
&& !settings.clockCustomFormat.isEmpty()) {
|
||||
ClockParsedPattern parsedPattern = PATTERN_PARSER.parse(settings.clockCustomFormat);
|
||||
ArrayList<ClockTextRenderer.LayoutRowResult> renderedRows =
|
||||
TEXT_RENDERER.renderLayoutRows(context, parsedPattern, source.getCurrentTextColor());
|
||||
TEXT_RENDERER.renderLayoutRows(context, parsedPattern, referenceColor);
|
||||
ArrayList<Row> rows = new ArrayList<>();
|
||||
StringBuilder description = new StringBuilder();
|
||||
for (int i = 0; i < renderedRows.size(); i++) {
|
||||
@@ -73,7 +82,12 @@ public final class ClockLayoutTextFactory {
|
||||
return new Model(rows, text != null ? text.toString() : "", settings.clockShowSeconds);
|
||||
}
|
||||
|
||||
private static CacheKey cacheKey(Context context, TextView source, SbtSettings settings) {
|
||||
private static CacheKey cacheKey(
|
||||
Context context,
|
||||
TextView source,
|
||||
SbtSettings settings,
|
||||
int referenceColor
|
||||
) {
|
||||
String pattern = settings.clockCustomFormat != null ? settings.clockCustomFormat : "";
|
||||
boolean customPattern = settings.clockCustomFormatEnabled && !pattern.isEmpty();
|
||||
boolean generatedText = hasCustomClockTextEnabled(settings);
|
||||
@@ -85,7 +99,7 @@ public final class ClockLayoutTextFactory {
|
||||
return new CacheKey(
|
||||
localeFor(context).toLanguageTag(),
|
||||
System.currentTimeMillis() / divisor,
|
||||
source.getCurrentTextColor(),
|
||||
referenceColor,
|
||||
settings.clockShowSeconds,
|
||||
settings.clockShowDatePrefix,
|
||||
customPattern,
|
||||
|
||||
+10
@@ -193,6 +193,16 @@ final class StockLayoutCanvasController {
|
||||
removeDebugOverlay(root);
|
||||
}
|
||||
hideTrackedUnlockedStockSurfaces(root);
|
||||
UnlockedHosts unlockedHosts = unlockedHostsByRoot.get(root);
|
||||
if (unlockedHosts != null) {
|
||||
unlockedIconRenderController.refreshUnlockedAppearance(
|
||||
root,
|
||||
unlockedHosts.clockHost,
|
||||
unlockedHosts.chipHost,
|
||||
unlockedHosts.statusHost,
|
||||
unlockedHosts.notificationHost,
|
||||
activeScene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-1
@@ -1,5 +1,7 @@
|
||||
package se.ajpanton.statusbartweak.runtime.render;
|
||||
|
||||
import android.text.Spanned;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -47,7 +49,7 @@ final class ClockProxyRenderer {
|
||||
if (copyTextStyleIfChanged(placement.source, view)) {
|
||||
hostChanged = true;
|
||||
}
|
||||
if (!String.valueOf(view.getText()).contentEquals(row.text)) {
|
||||
if (!sameTextAndColorSpans(view.getText(), row.text)) {
|
||||
view.setText(row.text);
|
||||
hostChanged = true;
|
||||
}
|
||||
@@ -87,6 +89,31 @@ final class ClockProxyRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean sameTextAndColorSpans(CharSequence current, CharSequence desired) {
|
||||
if (!String.valueOf(current).contentEquals(String.valueOf(desired))) {
|
||||
return false;
|
||||
}
|
||||
return colorSpanSignature(current) == colorSpanSignature(desired);
|
||||
}
|
||||
|
||||
private static int colorSpanSignature(CharSequence text) {
|
||||
if (!(text instanceof Spanned spanned)) {
|
||||
return 0;
|
||||
}
|
||||
ForegroundColorSpan[] spans = spanned.getSpans(0, spanned.length(), ForegroundColorSpan.class);
|
||||
if (spans == null || spans.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
int result = 17;
|
||||
for (ForegroundColorSpan span : spans) {
|
||||
result = 31 * result + span.getForegroundColor();
|
||||
result = 31 * result + spanned.getSpanStart(span);
|
||||
result = 31 * result + spanned.getSpanEnd(span);
|
||||
result = 31 * result + spanned.getSpanFlags(span);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void clear(ViewGroup host) {
|
||||
if (host == null) {
|
||||
return;
|
||||
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
package se.ajpanton.statusbartweak.runtime.render;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import se.ajpanton.statusbartweak.runtime.hooks.ReflectionSupport;
|
||||
|
||||
final class SnapshotAppearanceSignature {
|
||||
private static final int NO_COLOR = 0;
|
||||
|
||||
private static final String[] COLOR_FIELD_NAMES = {
|
||||
"mIconColor",
|
||||
"mDecorColor",
|
||||
"mStaticDrawableColor",
|
||||
"mIconTint",
|
||||
"mTint",
|
||||
"mTintColor",
|
||||
"mCurrentColor",
|
||||
"mCurrentIconColor"
|
||||
};
|
||||
|
||||
private SnapshotAppearanceSignature() {
|
||||
}
|
||||
|
||||
static int view(View view) {
|
||||
if (view == null) {
|
||||
return 0;
|
||||
}
|
||||
int result = 17;
|
||||
result = 31 * result + java.util.Arrays.hashCode(view.getDrawableState());
|
||||
if (view instanceof TextView textView) {
|
||||
result = 31 * result + textView.getCurrentTextColor();
|
||||
result = 31 * result + textView.getTextColors().hashCode();
|
||||
}
|
||||
if (view instanceof ImageView imageView) {
|
||||
result = 31 * result + drawable(imageView.getDrawable());
|
||||
result = 31 * result + colorStateList(imageView.getImageTintList());
|
||||
PorterDuff.Mode tintMode = imageView.getImageTintMode();
|
||||
result = 31 * result + (tintMode != null ? tintMode.hashCode() : 0);
|
||||
ColorFilter colorFilter = imageView.getColorFilter();
|
||||
result = 31 * result + (colorFilter != null ? System.identityHashCode(colorFilter) : 0);
|
||||
}
|
||||
result = 31 * result + reflectedColor(view, COLOR_FIELD_NAMES);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int drawable(Drawable drawable) {
|
||||
if (drawable == null) {
|
||||
return 0;
|
||||
}
|
||||
int result = 17;
|
||||
result = 31 * result + System.identityHashCode(drawable);
|
||||
result = 31 * result + drawable.getLevel();
|
||||
result = 31 * result + drawable.getAlpha();
|
||||
result = 31 * result + java.util.Arrays.hashCode(drawable.getState());
|
||||
ColorFilter colorFilter = drawable.getColorFilter();
|
||||
result = 31 * result + (colorFilter != null ? System.identityHashCode(colorFilter) : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int preferredColor(View view, int fallbackColor) {
|
||||
if (view == null) {
|
||||
return fallbackColor;
|
||||
}
|
||||
if (view instanceof TextView textView) {
|
||||
return textView.getCurrentTextColor();
|
||||
}
|
||||
if (view instanceof ImageView imageView) {
|
||||
int tintColor = colorStateListColor(imageView.getImageTintList(), view, NO_COLOR);
|
||||
if (isOpaqueColor(tintColor)) {
|
||||
return tintColor;
|
||||
}
|
||||
}
|
||||
int reflectedColor = reflectedColor(view, COLOR_FIELD_NAMES);
|
||||
if (isOpaqueColor(reflectedColor)) {
|
||||
return reflectedColor;
|
||||
}
|
||||
return fallbackColor;
|
||||
}
|
||||
|
||||
private static int reflectedColor(Object target, String[] fieldNames) {
|
||||
for (String fieldName : fieldNames) {
|
||||
Object value = ReflectionSupport.getFieldValue(target, fieldName);
|
||||
int color = colorValue(value, NO_COLOR);
|
||||
if (isOpaqueColor(color)) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
return NO_COLOR;
|
||||
}
|
||||
|
||||
private static int colorValue(Object value, int fallbackColor) {
|
||||
if (value instanceof Integer integer) {
|
||||
return integer;
|
||||
}
|
||||
if (value instanceof ColorStateList colorStateList) {
|
||||
return colorStateList.getDefaultColor();
|
||||
}
|
||||
return fallbackColor;
|
||||
}
|
||||
|
||||
private static int colorStateListColor(ColorStateList colorStateList, View view, int fallbackColor) {
|
||||
if (colorStateList == null) {
|
||||
return fallbackColor;
|
||||
}
|
||||
return colorStateList.getColorForState(
|
||||
view != null ? view.getDrawableState() : null,
|
||||
colorStateList.getDefaultColor());
|
||||
}
|
||||
|
||||
private static boolean isOpaqueColor(int color) {
|
||||
return Color.alpha(color) != 0;
|
||||
}
|
||||
|
||||
private static int colorStateList(ColorStateList colorStateList) {
|
||||
if (colorStateList == null) {
|
||||
return 0;
|
||||
}
|
||||
int result = 17;
|
||||
result = 31 * result + colorStateList.getDefaultColor();
|
||||
result = 31 * result + (colorStateList.isStateful() ? 1 : 0);
|
||||
result = 31 * result + colorStateList.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package se.ajpanton.statusbartweak.runtime.render;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -34,6 +35,7 @@ final class SnapshotPlacement {
|
||||
final String key;
|
||||
final boolean signal;
|
||||
final boolean overflowDot;
|
||||
final int overflowDotColor;
|
||||
final HeldSignal heldSignal;
|
||||
final Bounds contentBounds;
|
||||
final int sourceOffsetX;
|
||||
@@ -47,12 +49,36 @@ final class SnapshotPlacement {
|
||||
HeldSignal heldSignal,
|
||||
Bounds contentBounds,
|
||||
int sourceOffsetX
|
||||
) {
|
||||
this(
|
||||
source,
|
||||
bounds,
|
||||
key,
|
||||
signal,
|
||||
overflowDot,
|
||||
Color.WHITE,
|
||||
heldSignal,
|
||||
contentBounds,
|
||||
sourceOffsetX);
|
||||
}
|
||||
|
||||
SnapshotPlacement(
|
||||
SnapshotSource source,
|
||||
Bounds bounds,
|
||||
String key,
|
||||
boolean signal,
|
||||
boolean overflowDot,
|
||||
int overflowDotColor,
|
||||
HeldSignal heldSignal,
|
||||
Bounds contentBounds,
|
||||
int sourceOffsetX
|
||||
) {
|
||||
this.source = source;
|
||||
this.bounds = bounds;
|
||||
this.key = key;
|
||||
this.signal = signal;
|
||||
this.overflowDot = overflowDot;
|
||||
this.overflowDotColor = overflowDotColor;
|
||||
this.heldSignal = heldSignal;
|
||||
this.contentBounds = contentBounds;
|
||||
this.sourceOffsetX = sourceOffsetX;
|
||||
@@ -78,6 +104,10 @@ final class SnapshotPlacement {
|
||||
return overflowDot;
|
||||
}
|
||||
|
||||
int overflowDotColor() {
|
||||
return overflowDotColor;
|
||||
}
|
||||
|
||||
HeldSignal heldSignal() {
|
||||
return heldSignal;
|
||||
}
|
||||
@@ -102,6 +132,7 @@ record SnapshotRenderState(
|
||||
int height,
|
||||
boolean signal,
|
||||
boolean overflowDot,
|
||||
int overflowDotColor,
|
||||
int sourceOffsetX,
|
||||
String heldSignalKey,
|
||||
int heldBitmapId,
|
||||
|
||||
@@ -176,7 +176,7 @@ final class SnapshotRenderer {
|
||||
|| !desiredState.equals(statesByProxy.get(proxy));
|
||||
if (bitmapChanged) {
|
||||
if (placement.overflowDot()) {
|
||||
drawOverflowDot(bitmap);
|
||||
drawOverflowDot(bitmap, placement.overflowDotColor());
|
||||
} else if (placement.heldSignal() != null) {
|
||||
drawHeldSignal(placement.heldSignal(), bitmap);
|
||||
} else if (placement.source() != null) {
|
||||
@@ -471,6 +471,7 @@ final class SnapshotRenderer {
|
||||
bounds.height,
|
||||
placement.signal(),
|
||||
placement.overflowDot(),
|
||||
placement.overflowDotColor(),
|
||||
placement.sourceOffsetX(),
|
||||
placement.heldSignal() != null ? placement.heldSignal().key : "",
|
||||
placement.heldSignal() != null ? System.identityHashCode(placement.heldSignal().bitmap) : 0,
|
||||
@@ -493,6 +494,7 @@ final class SnapshotRenderer {
|
||||
CharSequence contentDescription = view.getContentDescription();
|
||||
result = 31 * result + (contentDescription != null ? contentDescription.toString().hashCode() : 0);
|
||||
result = 31 * result + java.util.Arrays.hashCode(view.getDrawableState());
|
||||
result = 31 * result + SnapshotAppearanceSignature.view(view);
|
||||
if (view instanceof TextView textView) {
|
||||
CharSequence text = textView.getText();
|
||||
result = 31 * result + (text != null ? text.toString().hashCode() : 0);
|
||||
@@ -500,7 +502,7 @@ final class SnapshotRenderer {
|
||||
result = 31 * result + Float.floatToIntBits(textView.getTextSize());
|
||||
}
|
||||
if (view instanceof ImageView imageView) {
|
||||
result = 31 * result + drawableSignature(imageView.getDrawable());
|
||||
result = 31 * result + SnapshotAppearanceSignature.drawable(imageView.getDrawable());
|
||||
}
|
||||
if (view instanceof ViewGroup group) {
|
||||
result = 31 * result + group.getChildCount();
|
||||
@@ -516,10 +518,7 @@ final class SnapshotRenderer {
|
||||
return 0;
|
||||
}
|
||||
int result = 17;
|
||||
result = 31 * result + System.identityHashCode(drawable);
|
||||
result = 31 * result + drawable.getLevel();
|
||||
result = 31 * result + drawable.getAlpha();
|
||||
result = 31 * result + java.util.Arrays.hashCode(drawable.getState());
|
||||
result = 31 * result + SnapshotAppearanceSignature.drawable(drawable);
|
||||
Rect bounds = drawable.getBounds();
|
||||
result = 31 * result + bounds.left;
|
||||
result = 31 * result + bounds.top;
|
||||
@@ -570,7 +569,7 @@ final class SnapshotRenderer {
|
||||
canvas.drawBitmap(heldSignal.bitmap, src, dst, null);
|
||||
}
|
||||
|
||||
private void drawOverflowDot(Bitmap bitmap) {
|
||||
private void drawOverflowDot(Bitmap bitmap, int color) {
|
||||
bitmap.eraseColor(Color.TRANSPARENT);
|
||||
int base = Math.min(bitmap.getWidth(), bitmap.getHeight());
|
||||
if (base <= 0) {
|
||||
@@ -578,7 +577,7 @@ final class SnapshotRenderer {
|
||||
}
|
||||
float radius = Math.max(1f, base * 0.16f);
|
||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setColor(Color.WHITE);
|
||||
paint.setColor(color);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
canvas.drawCircle(bitmap.getWidth() / 2f, bitmap.getHeight() / 2f, radius, paint);
|
||||
}
|
||||
|
||||
+2
@@ -190,6 +190,7 @@ final class UnlockedChipPlacementController {
|
||||
placement.key,
|
||||
false,
|
||||
false,
|
||||
placement.overflowDotColor,
|
||||
null,
|
||||
placement.contentBounds,
|
||||
placement.sourceOffsetX));
|
||||
@@ -211,6 +212,7 @@ final class UnlockedChipPlacementController {
|
||||
placement.key,
|
||||
placement.signal,
|
||||
placement.overflowDot,
|
||||
placement.overflowDotColor,
|
||||
placement.heldSignal,
|
||||
placement.contentBounds,
|
||||
placement.sourceOffsetX));
|
||||
|
||||
+234
-1
@@ -34,6 +34,7 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
private final WeakHashMap<View, LayoutPlan> lastLayoutPlanByRoot = new WeakHashMap<>();
|
||||
private final WeakHashMap<View, Integer> lastClockGeometryByRoot = new WeakHashMap<>();
|
||||
private final WeakHashMap<View, Integer> lastClockSourceGeometryByRoot = new WeakHashMap<>();
|
||||
private final WeakHashMap<View, Integer> lastClockAppearanceByRoot = new WeakHashMap<>();
|
||||
|
||||
public UnlockedIconSnapshotRenderController() {
|
||||
statusRenderer = new SnapshotRenderer(true, true, false);
|
||||
@@ -164,6 +165,8 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
lastLayoutPlanByRoot.put(root, layoutPlan);
|
||||
lastClockGeometryByRoot.put(root, currentClockGeometry != null ? currentClockGeometry : 0);
|
||||
lastClockSourceGeometryByRoot.put(root, currentClockSourceGeometry);
|
||||
layoutPlan = withCurrentDotColors(layoutPlan, collectedIcons);
|
||||
lastLayoutPlanByRoot.put(root, layoutPlan);
|
||||
if (settings.clockEnabledUnlocked && layoutPlan.clockPlacement != null) {
|
||||
clockRenderer.render(clockHost, layoutPlan.clockPlacement);
|
||||
} else {
|
||||
@@ -187,6 +190,47 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
return new RenderResult(true, stockSourcesChanged, chipSourcesChanged);
|
||||
}
|
||||
|
||||
public void refreshUnlockedAppearance(
|
||||
View root,
|
||||
ViewGroup clockHost,
|
||||
ViewGroup chipHost,
|
||||
ViewGroup statusHost,
|
||||
ViewGroup notificationHost,
|
||||
SceneKey scene
|
||||
) {
|
||||
if (root == null || scene == null || !scene.isUnlocked() || !root.isAttachedToWindow()) {
|
||||
return;
|
||||
}
|
||||
LayoutPlan layoutPlan = lastLayoutPlanByRoot.get(root);
|
||||
if (layoutPlan == null) {
|
||||
return;
|
||||
}
|
||||
SbtSettings settings = RuntimeSettingsCache.get(root.getContext());
|
||||
CollectedIcons collectedIcons = lastCollectedIconsByRoot.get(root);
|
||||
LayoutPlan updatedPlan = withCurrentDotColors(layoutPlan, collectedIcons);
|
||||
if (updatedPlan != layoutPlan) {
|
||||
lastLayoutPlanByRoot.put(root, updatedPlan);
|
||||
layoutPlan = updatedPlan;
|
||||
}
|
||||
if (settings.layoutChipEnabledUnlocked && layoutPlan.chipPlacements != null) {
|
||||
chipRenderer.renderPlacements(chipHost, layoutPlan.chipPlacements);
|
||||
}
|
||||
if (settings.layoutStatusEnabledUnlocked && layoutPlan.statusPlacements != null) {
|
||||
statusRenderer.renderPlacements(statusHost, layoutPlan.statusPlacements);
|
||||
}
|
||||
if (settings.layoutNotifEnabledUnlocked && layoutPlan.notificationPlacements != null) {
|
||||
notificationRenderer.renderPlacements(notificationHost, layoutPlan.notificationPlacements);
|
||||
}
|
||||
updatedPlan = withCurrentClockAppearance(root, layoutPlan, collectedIcons, settings);
|
||||
if (updatedPlan != layoutPlan) {
|
||||
lastLayoutPlanByRoot.put(root, updatedPlan);
|
||||
layoutPlan = updatedPlan;
|
||||
}
|
||||
if (settings.clockEnabledUnlocked && layoutPlan.clockPlacement != null) {
|
||||
clockRenderer.render(clockHost, layoutPlan.clockPlacement);
|
||||
}
|
||||
}
|
||||
|
||||
private void layoutHostToRoot(View root, ViewGroup host) {
|
||||
if (root == null || host == null || root.getWidth() <= 0 || root.getHeight() <= 0) {
|
||||
return;
|
||||
@@ -205,6 +249,180 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
host.layout(0, 0, root.getWidth(), root.getHeight());
|
||||
}
|
||||
|
||||
private LayoutPlan withCurrentDotColors(LayoutPlan plan, CollectedIcons icons) {
|
||||
if (plan == null) {
|
||||
return null;
|
||||
}
|
||||
ArrayList<SnapshotPlacement> status = withCurrentDotColors(
|
||||
plan.statusPlacements,
|
||||
icons != null ? icons.statusIcons : null);
|
||||
ArrayList<SnapshotPlacement> notifications = withCurrentDotColors(
|
||||
plan.notificationPlacements,
|
||||
icons != null ? icons.notificationIcons : null);
|
||||
if (status == plan.statusPlacements && notifications == plan.notificationPlacements) {
|
||||
return plan;
|
||||
}
|
||||
return new LayoutPlan(
|
||||
plan.clockPlacement,
|
||||
plan.chipPlacements,
|
||||
status,
|
||||
notifications);
|
||||
}
|
||||
|
||||
private ArrayList<SnapshotPlacement> withCurrentDotColors(
|
||||
ArrayList<SnapshotPlacement> placements,
|
||||
ArrayList<SnapshotSource> fallbackSources
|
||||
) {
|
||||
if (placements == null || placements.isEmpty()) {
|
||||
return placements;
|
||||
}
|
||||
int color = dotColor(placements, fallbackSources);
|
||||
if (color == 0) {
|
||||
return placements;
|
||||
}
|
||||
ArrayList<SnapshotPlacement> updated = null;
|
||||
for (int i = 0; i < placements.size(); i++) {
|
||||
SnapshotPlacement placement = placements.get(i);
|
||||
if (!placement.overflowDot || placement.overflowDotColor == color) {
|
||||
continue;
|
||||
}
|
||||
if (updated == null) {
|
||||
updated = new ArrayList<>(placements);
|
||||
}
|
||||
updated.set(i, new SnapshotPlacement(
|
||||
placement.source,
|
||||
placement.bounds,
|
||||
placement.key,
|
||||
placement.signal,
|
||||
placement.overflowDot,
|
||||
color,
|
||||
placement.heldSignal,
|
||||
placement.contentBounds,
|
||||
placement.sourceOffsetX));
|
||||
}
|
||||
return updated != null ? updated : placements;
|
||||
}
|
||||
|
||||
private int dotColor(
|
||||
ArrayList<SnapshotPlacement> placements,
|
||||
ArrayList<SnapshotSource> fallbackSources
|
||||
) {
|
||||
for (SnapshotPlacement placement : placements) {
|
||||
if (placement != null && placement.source != null) {
|
||||
int color = sourceColor(placement.source);
|
||||
if (color != 0) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fallbackSources != null) {
|
||||
for (SnapshotSource source : fallbackSources) {
|
||||
int color = sourceColor(source);
|
||||
if (color != 0) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int sourceColor(SnapshotSource source) {
|
||||
if (source == null || source.view() == null) {
|
||||
return 0;
|
||||
}
|
||||
int color = SnapshotAppearanceSignature.preferredColor(
|
||||
source.view(),
|
||||
android.graphics.Color.TRANSPARENT);
|
||||
return android.graphics.Color.alpha(color) != 0 ? color : 0;
|
||||
}
|
||||
|
||||
private LayoutPlan withCurrentClockAppearance(
|
||||
View root,
|
||||
LayoutPlan plan,
|
||||
CollectedIcons icons,
|
||||
SbtSettings settings
|
||||
) {
|
||||
if (root == null
|
||||
|| plan == null
|
||||
|| plan.clockPlacement == null
|
||||
|| !settings.clockEnabledUnlocked) {
|
||||
return plan;
|
||||
}
|
||||
ClockPlacement previous = plan.clockPlacement;
|
||||
int referenceColor = clockReferenceColor(previous, icons);
|
||||
int signature = clockAppearanceSignature(previous, referenceColor, settings);
|
||||
Integer lastSignature = lastClockAppearanceByRoot.get(root);
|
||||
if (lastSignature != null && lastSignature == signature) {
|
||||
return plan;
|
||||
}
|
||||
ClockPlacement updatedClock = clockPlacementWithTextFromModel(
|
||||
previous,
|
||||
previous.source,
|
||||
settings,
|
||||
referenceColor);
|
||||
lastClockAppearanceByRoot.put(root, signature);
|
||||
if (updatedClock == null) {
|
||||
return plan;
|
||||
}
|
||||
return plan.withClockPlacement(updatedClock);
|
||||
}
|
||||
|
||||
private int clockReferenceColor(ClockPlacement placement, CollectedIcons icons) {
|
||||
if (icons != null && icons.statusIcons != null) {
|
||||
for (SnapshotSource source : icons.statusIcons) {
|
||||
int color = sourceColor(source);
|
||||
if (color != 0) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (icons != null && icons.notificationIcons != null) {
|
||||
for (SnapshotSource source : icons.notificationIcons) {
|
||||
int color = sourceColor(source);
|
||||
if (color != 0) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (placement != null && placement.source != null) {
|
||||
return placement.source.getCurrentTextColor();
|
||||
}
|
||||
return android.graphics.Color.WHITE;
|
||||
}
|
||||
|
||||
private int clockAppearanceSignature(
|
||||
ClockPlacement placement,
|
||||
int referenceColor,
|
||||
SbtSettings settings
|
||||
) {
|
||||
int result = 17;
|
||||
result = 31 * result + referenceColor;
|
||||
result = 31 * result + clockTextSettingsSignature(settings);
|
||||
if (placement != null && placement.source != null) {
|
||||
result = 31 * result + placement.source.getCurrentTextColor();
|
||||
}
|
||||
if (placement != null && placement.rows != null) {
|
||||
result = 31 * result + placement.rows.size();
|
||||
for (ClockRow row : placement.rows) {
|
||||
result = 31 * result + row.rowIndex;
|
||||
result = 31 * result + row.segment.ordinal();
|
||||
result = 31 * result + (row.text != null ? row.text.toString().hashCode() : 0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int clockTextSettingsSignature(SbtSettings settings) {
|
||||
if (settings == null) {
|
||||
return 0;
|
||||
}
|
||||
return java.util.Objects.hash(
|
||||
settings.clockShowSeconds,
|
||||
settings.clockShowDatePrefix,
|
||||
settings.clockCustomFormatEnabled,
|
||||
settings.clockCustomFormat);
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
clockRenderer.clearAll();
|
||||
statusRenderer.clearAll();
|
||||
@@ -218,6 +436,7 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
lastLayoutPlanByRoot.clear();
|
||||
lastClockGeometryByRoot.clear();
|
||||
lastClockSourceGeometryByRoot.clear();
|
||||
lastClockAppearanceByRoot.clear();
|
||||
chipPlacementController.clear();
|
||||
}
|
||||
|
||||
@@ -228,6 +447,7 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
lastCollectedIconsByRoot.clear();
|
||||
lastLayoutPlanByRoot.clear();
|
||||
lastClockGeometryByRoot.clear();
|
||||
lastClockAppearanceByRoot.clear();
|
||||
}
|
||||
|
||||
private boolean isClockOnlySignatureChange(
|
||||
@@ -368,6 +588,19 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
ClockPlacement previousPlacement,
|
||||
TextView source,
|
||||
SbtSettings settings
|
||||
) {
|
||||
return clockPlacementWithTextFromModel(
|
||||
previousPlacement,
|
||||
source,
|
||||
settings,
|
||||
source != null ? source.getCurrentTextColor() : 0);
|
||||
}
|
||||
|
||||
private ClockPlacement clockPlacementWithTextFromModel(
|
||||
ClockPlacement previousPlacement,
|
||||
TextView source,
|
||||
SbtSettings settings,
|
||||
int referenceColor
|
||||
) {
|
||||
if (previousPlacement == null
|
||||
|| previousPlacement.rows == null
|
||||
@@ -375,7 +608,7 @@ public final class UnlockedIconSnapshotRenderController {
|
||||
|| settings == null) {
|
||||
return null;
|
||||
}
|
||||
ClockLayoutTextFactory.Model model = ClockLayoutTextFactory.build(source, settings);
|
||||
ClockLayoutTextFactory.Model model = ClockLayoutTextFactory.build(source, settings, referenceColor);
|
||||
if (model == null || model.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -493,11 +493,40 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
||||
SnapshotKeys.OVERFLOW_DOT + ":" + kind.name().toLowerCase(java.util.Locale.ROOT),
|
||||
false,
|
||||
true,
|
||||
dotColor(),
|
||||
null,
|
||||
new Bounds(0, 0, Math.max(1, width), Math.max(1, height)),
|
||||
0);
|
||||
}
|
||||
|
||||
private int dotColor() {
|
||||
for (SnapshotPlacement placement : activePlacements()) {
|
||||
int color = sourceColor(placement);
|
||||
if (color != 0) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
if (rawPlacements != null) {
|
||||
for (SnapshotPlacement placement : rawPlacements) {
|
||||
int color = sourceColor(placement);
|
||||
if (color != 0) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
return android.graphics.Color.WHITE;
|
||||
}
|
||||
|
||||
private int sourceColor(SnapshotPlacement placement) {
|
||||
if (placement == null || placement.source == null || placement.source.view() == null) {
|
||||
return 0;
|
||||
}
|
||||
int color = SnapshotAppearanceSignature.preferredColor(
|
||||
placement.source.view(),
|
||||
android.graphics.Color.TRANSPARENT);
|
||||
return android.graphics.Color.alpha(color) != 0 ? color : 0;
|
||||
}
|
||||
|
||||
private SnapshotPlacement emptyIconContainerPlacement() {
|
||||
int height = Math.max(1, dotHeight(activePlacements()));
|
||||
return new SnapshotPlacement(
|
||||
@@ -548,6 +577,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
||||
placement.key,
|
||||
placement.signal,
|
||||
placement.overflowDot,
|
||||
placement.overflowDotColor,
|
||||
placement.heldSignal,
|
||||
clippedContent,
|
||||
placement.sourceOffsetX + removeLeft);
|
||||
|
||||
@@ -218,6 +218,7 @@ final class UnlockedLayoutPlanner {
|
||||
placement.key,
|
||||
placement.signal,
|
||||
placement.overflowDot,
|
||||
placement.overflowDotColor,
|
||||
placement.heldSignal,
|
||||
placement.contentBounds,
|
||||
placement.sourceOffsetX));
|
||||
|
||||
+2
-4
@@ -2,7 +2,6 @@ package se.ajpanton.statusbartweak.runtime.render;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
@@ -636,19 +635,18 @@ final class UnlockedStockSourceCollector {
|
||||
: 0);
|
||||
}
|
||||
if (view instanceof ImageView imageView) {
|
||||
result = 31 * result + drawableSignature(imageView.getDrawable());
|
||||
result = 31 * result + drawableLayoutSignature(imageView.getDrawable());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int drawableSignature(Drawable drawable) {
|
||||
private static int drawableLayoutSignature(android.graphics.drawable.Drawable drawable) {
|
||||
if (drawable == null) {
|
||||
return 0;
|
||||
}
|
||||
int result = 17;
|
||||
result = 31 * result + System.identityHashCode(drawable);
|
||||
result = 31 * result + drawable.getLevel();
|
||||
result = 31 * result + drawable.getAlpha();
|
||||
result = 31 * result + java.util.Arrays.hashCode(drawable.getState());
|
||||
Rect bounds = drawable.getBounds();
|
||||
result = 31 * result + bounds.left;
|
||||
|
||||
Reference in New Issue
Block a user