diff --git a/android/app/src/main/java/me/kavishdevar/librepods/bluetooth/AACPManager.kt b/android/app/src/main/java/me/kavishdevar/librepods/bluetooth/AACPManager.kt index 726430ea1..22288c4fc 100644 --- a/android/app/src/main/java/me/kavishdevar/librepods/bluetooth/AACPManager.kt +++ b/android/app/src/main/java/me/kavishdevar/librepods/bluetooth/AACPManager.kt @@ -207,7 +207,7 @@ class AACPManager { identifier: ControlCommandIdentifiers, value: ByteArray ) { val existingStatus = getControlCommandStatus(identifier) - if (existingStatus?.value.contentEquals(value)) { + if (existingStatus != null) { controlCommandStatusList.remove(existingStatus) } controlCommandListeners[identifier]?.forEach { listener -> diff --git a/android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt b/android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt index 464edddea..f163acc39 100644 --- a/android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt +++ b/android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt @@ -1462,6 +1462,7 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList preferences.getBoolean(key, true) "head_gestures" -> config.headGestures = preferences.getBoolean(key, true) + "off_listening_mode" -> updateNoiseControlWidget() "disconnect_when_not_wearing" -> config.disconnectWhenNotWearing = preferences.getBoolean(key, false) @@ -1957,54 +1958,97 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList val appWidgetManager = AppWidgetManager.getInstance(this) val componentName = ComponentName(this, NoiseControlWidget::class.java) val widgetIds = appWidgetManager.getAppWidgetIds(componentName) - val remoteViews = RemoteViews(packageName, R.layout.noise_control_widget).also { it -> - val ancStatus = ancNotification.status - val allowOffModeValue = - aacpManager.controlCommandStatusList.find { it.identifier == AACPManager.Companion.ControlCommandIdentifiers.ALLOW_OFF_OPTION } - val allowOffMode = - allowOffModeValue?.value?.takeIf { it.isNotEmpty() }?.get(0) == 0x01.toByte() || sharedPreferences.getBoolean("off_listening_mode", true) - it.setInt( - R.id.widget_off_button, - "setBackgroundResource", - if (ancStatus == 1) R.drawable.widget_button_checked_shape_start else R.drawable.widget_button_shape_start - ) - it.setInt( - R.id.widget_transparency_button, - "setBackgroundResource", - if (ancStatus == 3) (if (allowOffMode) R.drawable.widget_button_checked_shape_middle else R.drawable.widget_button_checked_shape_start) else (if (allowOffMode) R.drawable.widget_button_shape_middle else R.drawable.widget_button_shape_start) - ) - it.setInt( - R.id.widget_adaptive_button, - "setBackgroundResource", - if (ancStatus == 4) R.drawable.widget_button_checked_shape_middle else R.drawable.widget_button_shape_middle - ) - it.setInt( - R.id.widget_anc_button, - "setBackgroundResource", - if (ancStatus == 2) R.drawable.widget_button_checked_shape_end else R.drawable.widget_button_shape_end - ) - it.setViewVisibility( - R.id.widget_off_button, if (allowOffMode) View.VISIBLE else View.GONE - ) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - it.setViewLayoutMargin( - R.id.widget_transparency_button, - RemoteViews.MARGIN_START, - if (allowOffMode) 2f else 12f, - TypedValue.COMPLEX_UNIT_DIP + + val ancStatus = ancNotification.status + val allowOffModeValue = + aacpManager.controlCommandStatusList.find { it.identifier == AACPManager.Companion.ControlCommandIdentifiers.ALLOW_OFF_OPTION } + val allowOffMode = + allowOffModeValue?.value?.takeIf { it.isNotEmpty() }?.get(0) == 0x01.toByte() || sharedPreferences.getBoolean("off_listening_mode", true) + + val visibleLabels = buildList { + if (allowOffMode) add(getString(R.string.off)) + add(getString(R.string.transparency)) + add(getString(R.string.adaptive)) + add(getString(R.string.widget_noise_cancellation)) + } + + for (widgetId in widgetIds) { + val widgetWidthDp = appWidgetManager.getAppWidgetOptions(widgetId) + .getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 180) + val uniformTextSizeSp = computeUniformWidgetTextSizeSp(widgetWidthDp, visibleLabels.size, visibleLabels) + + val remoteViews = RemoteViews(packageName, R.layout.noise_control_widget).also { it -> + it.setInt( + R.id.widget_off_button, + "setBackgroundResource", + if (ancStatus == 1) R.drawable.widget_button_checked_shape_start else R.drawable.widget_button_shape_start ) - } else { - it.setViewPadding( + it.setInt( R.id.widget_transparency_button, - if (allowOffMode) 2.dpToPx() else 12.dpToPx(), - 12.dpToPx(), - 2.dpToPx(), - 12.dpToPx() + "setBackgroundResource", + if (ancStatus == 3) (if (allowOffMode) R.drawable.widget_button_checked_shape_middle else R.drawable.widget_button_checked_shape_start) else (if (allowOffMode) R.drawable.widget_button_shape_middle else R.drawable.widget_button_shape_start) ) + it.setInt( + R.id.widget_adaptive_button, + "setBackgroundResource", + if (ancStatus == 4) R.drawable.widget_button_checked_shape_middle else R.drawable.widget_button_shape_middle + ) + it.setInt( + R.id.widget_anc_button, + "setBackgroundResource", + if (ancStatus == 2) R.drawable.widget_button_checked_shape_end else R.drawable.widget_button_shape_end + ) + it.setViewVisibility( + R.id.widget_off_button, if (allowOffMode) View.VISIBLE else View.GONE + ) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + it.setViewLayoutMargin( + R.id.widget_transparency_button, + RemoteViews.MARGIN_START, + if (allowOffMode) 2f else 12f, + TypedValue.COMPLEX_UNIT_DIP + ) + } else { + it.setViewPadding( + R.id.widget_transparency_button, + if (allowOffMode) 2.dpToPx() else 12.dpToPx(), + 12.dpToPx(), + 2.dpToPx(), + 12.dpToPx() + ) + } + it.setTextViewTextSize(R.id.widget_off_button_label, TypedValue.COMPLEX_UNIT_SP, uniformTextSizeSp) + it.setTextViewTextSize(R.id.widget_transparency_button_label, TypedValue.COMPLEX_UNIT_SP, uniformTextSizeSp) + it.setTextViewTextSize(R.id.widget_adaptive_button_label, TypedValue.COMPLEX_UNIT_SP, uniformTextSizeSp) + it.setTextViewTextSize(R.id.widget_anc_button_label, TypedValue.COMPLEX_UNIT_SP, uniformTextSizeSp) } + + appWidgetManager.updateAppWidget(widgetId, remoteViews) } + } - appWidgetManager.updateAppWidget(widgetIds, remoteViews) + private fun computeUniformWidgetTextSizeSp( + widgetWidthDp: Int, + buttonCount: Int, + labels: List + ): Float { + val displayMetrics = resources.displayMetrics + val widgetWidthPx = widgetWidthDp * displayMetrics.density + val outerMarginsPx = 24f * displayMetrics.density + val gapsPx = (buttonCount - 1) * 4f * displayMetrics.density + val perButtonPaddingPx = 8f * displayMetrics.density + val availablePerButtonPx = (widgetWidthPx - outerMarginsPx - gapsPx) / buttonCount - perButtonPaddingPx + + val paint = android.text.TextPaint() + var size = 11f + while (size >= 7f) { + paint.textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, displayMetrics) + if (labels.all { paint.measureText(it) <= availablePerButtonPx }) { + return size + } + size -= 0.5f + } + return 7f } @OptIn(ExperimentalMaterial3Api::class) diff --git a/android/app/src/main/res/layout/noise_control_widget.xml b/android/app/src/main/res/layout/noise_control_widget.xml index baa2f4bdd..e1981838b 100644 --- a/android/app/src/main/res/layout/noise_control_widget.xml +++ b/android/app/src/main/res/layout/noise_control_widget.xml @@ -18,61 +18,73 @@ android:id="@+id/widget_off_button" android:layout_width="0dp" android:layout_height="match_parent" - android:layout_marginVertical="12dp" + android:layout_marginVertical="6dp" android:layout_marginStart="12dp" android:layout_marginEnd="2dp" android:layout_weight="1" android:background="@drawable/widget_button_shape_start" android:clickable="true" android:gravity="center" - android:orientation="vertical"> + android:orientation="vertical" + android:padding="4dp"> + android:textSize="11sp" /> + android:orientation="vertical" + android:padding="4dp"> @@ -80,32 +92,37 @@ android:id="@+id/widget_adaptive_button" android:layout_width="0dp" android:layout_height="match_parent" - android:layout_marginVertical="12dp" + android:layout_marginVertical="6dp" android:layout_marginStart="2dp" android:layout_marginEnd="2dp" android:layout_weight="1" android:background="@drawable/widget_button_shape_middle" android:clickable="true" android:gravity="center" - android:orientation="vertical"> + android:orientation="vertical" + android:padding="4dp"> @@ -113,31 +130,37 @@ android:id="@+id/widget_anc_button" android:layout_width="0dp" android:layout_height="match_parent" - android:layout_marginVertical="12dp" + android:layout_marginVertical="6dp" android:layout_marginStart="2dp" android:layout_marginEnd="12dp" android:layout_weight="1" android:background="@drawable/widget_button_shape_end" android:clickable="true" android:gravity="center" - android:orientation="vertical"> + android:orientation="vertical" + android:padding="4dp"> diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 3a1db0b77..6fa31a8a8 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -267,4 +267,5 @@ App enabled in Xposed Subject Describe your issue + ANC