diff --git a/android/app/src/main/java/me/kavishdevar/librepods/composables/IndependentToggle.kt b/android/app/src/main/java/me/kavishdevar/librepods/composables/IndependentToggle.kt index c83cc34..25e142c 100644 --- a/android/app/src/main/java/me/kavishdevar/librepods/composables/IndependentToggle.kt +++ b/android/app/src/main/java/me/kavishdevar/librepods/composables/IndependentToggle.kt @@ -146,7 +146,16 @@ fun IndependentToggle(name: String, service: AirPodsService? = null, functionNam .padding(horizontal = 12.dp), verticalAlignment = Alignment.CenterVertically ) { - Text(text = name, modifier = Modifier.weight(1f), fontSize = 16.sp, color = textColor) + Text( + text = name, + modifier = Modifier.weight(1f), + style = TextStyle( + fontSize = 16.sp, + fontFamily = FontFamily(Font(R.font.sf_pro)), + fontWeight = FontWeight.Normal, + color = textColor + ) + ) StyledSwitch( checked = checked, onCheckedChange = { diff --git a/android/app/src/main/java/me/kavishdevar/librepods/screens/AccessibilitySettingsScreen.kt b/android/app/src/main/java/me/kavishdevar/librepods/screens/AccessibilitySettingsScreen.kt index 193d162..3715c9d 100644 --- a/android/app/src/main/java/me/kavishdevar/librepods/screens/AccessibilitySettingsScreen.kt +++ b/android/app/src/main/java/me/kavishdevar/librepods/screens/AccessibilitySettingsScreen.kt @@ -1055,7 +1055,7 @@ fun AccessibilitySettingsScreen() { @Composable -fun AccessibilityToggle(text: String, mutableState: MutableState, independent: Boolean = false, description: String? = null) { +fun AccessibilityToggle(text: String, mutableState: MutableState, independent: Boolean = false, description: String? = null, title: String? = null) { val isDarkTheme = isSystemInDarkTheme() var backgroundColor by remember { mutableStateOf(if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) } val animatedBackgroundColor by animateColorAsState(targetValue = backgroundColor, animationSpec = tween(durationMillis = 500)) @@ -1065,7 +1065,20 @@ fun AccessibilityToggle(text: String, mutableState: MutableState, indep Column( modifier = Modifier .padding(vertical = 8.dp) - ) { + ) { + if (title != null) { + Text( + text = title, + style = TextStyle( + fontSize = 14.sp, + fontWeight = FontWeight.Light, + color = textColor.copy(alpha = 0.6f), + fontFamily = FontFamily(Font(R.font.sf_pro)) + ), + modifier = Modifier.padding(8.dp, bottom = 2.dp) + ) + Spacer(modifier = Modifier.height(4.dp)) + } Box ( modifier = Modifier .background(animatedBackgroundColor, cornerShape) diff --git a/android/app/src/main/java/me/kavishdevar/librepods/screens/HearingAidScreen.kt b/android/app/src/main/java/me/kavishdevar/librepods/screens/HearingAidScreen.kt index e7d6084..0557e16 100644 --- a/android/app/src/main/java/me/kavishdevar/librepods/screens/HearingAidScreen.kt +++ b/android/app/src/main/java/me/kavishdevar/librepods/screens/HearingAidScreen.kt @@ -221,6 +221,10 @@ fun HearingAidScreen(navController: NavController) { } } + val mediaAssistEnabled = remember { mutableStateOf(false) } + val adjustMediaEnabled = remember { mutableStateOf(false) } + val adjustPhoneEnabled = remember { mutableStateOf(false) } + LaunchedEffect(Unit) { aacpManager?.registerControlCommandListener(AACPManager.Companion.ControlCommandIdentifiers.HEARING_AID, hearingAidListener) aacpManager?.registerControlCommandListener(AACPManager.Companion.ControlCommandIdentifiers.HEARING_ASSIST_CONFIG, hearingAidListener) @@ -256,7 +260,8 @@ fun HearingAidScreen(navController: NavController) { style = TextStyle( fontSize = 14.sp, fontWeight = FontWeight.Light, - color = textColor.copy(alpha = 0.6f) + color = textColor.copy(alpha = 0.6f), + fontFamily = FontFamily(Font(R.font.sf_pro)) ), modifier = Modifier.padding(8.dp, bottom = 2.dp) ) @@ -336,6 +341,108 @@ fun HearingAidScreen(navController: NavController) { ), modifier = Modifier.padding(horizontal = 8.dp) ) + + Spacer(modifier = Modifier.height(16.dp)) + + AccessibilityToggle( + text = stringResource(R.string.media_assist), + mutableState = mediaAssistEnabled, + independent = true, + description = stringResource(R.string.media_assist_description), + title = stringResource(R.string.media_assist).uppercase() + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Column ( + modifier = Modifier + .fillMaxWidth() + .background(backgroundColor, RoundedCornerShape(14.dp)) + ) { + val isDarkThemeLocal = isSystemInDarkTheme() + var backgroundColorAdjustMedia by remember { mutableStateOf(if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) } + val animatedBackgroundColorAdjustMedia by animateColorAsState(targetValue = backgroundColorAdjustMedia, animationSpec = tween(durationMillis = 500)) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(12.dp) + .pointerInput(Unit) { + detectTapGestures( + onPress = { + backgroundColorAdjustMedia = if (isDarkThemeLocal) Color(0x40888888) else Color(0x40D9D9D9) + tryAwaitRelease() + backgroundColorAdjustMedia = if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF) + }, + onTap = { + adjustMediaEnabled.value = !adjustMediaEnabled.value + } + ) + }, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(R.string.adjust_media), + modifier = Modifier.weight(1f), + style = TextStyle( + fontSize = 16.sp, + fontFamily = FontFamily(Font(R.font.sf_pro)), + fontWeight = FontWeight.Normal, + color = textColor + ) + ) + StyledSwitch( + checked = adjustMediaEnabled.value, + onCheckedChange = { + adjustMediaEnabled.value = it + }, + ) + } + + HorizontalDivider( + thickness = 1.5.dp, + color = Color(0x40888888), + modifier = Modifier + .padding(start = 12.dp, end = 0.dp) + ) + + var backgroundColorAdjustPhone by remember { mutableStateOf(if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)) } + val animatedBackgroundColorAdjustPhone by animateColorAsState(targetValue = backgroundColorAdjustPhone, animationSpec = tween(durationMillis = 500)) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(12.dp) + .pointerInput(Unit) { + detectTapGestures( + onPress = { + backgroundColorAdjustPhone = if (isDarkThemeLocal) Color(0x40888888) else Color(0x40D9D9D9) + tryAwaitRelease() + backgroundColorAdjustPhone = if (isDarkThemeLocal) Color(0xFF1C1C1E) else Color(0xFFFFFFFF) + }, + onTap = { + adjustPhoneEnabled.value = !adjustPhoneEnabled.value + } + ) + }, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(R.string.adjust_calls), + modifier = Modifier.weight(1f), + style = TextStyle( + fontSize = 16.sp, + fontFamily = FontFamily(Font(R.font.sf_pro)), + fontWeight = FontWeight.Normal, + color = textColor + ) + ) + StyledSwitch( + checked = adjustPhoneEnabled.value, + onCheckedChange = { + adjustPhoneEnabled.value = it + }, + ) + } + } } } } \ No newline at end of file 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 76e31e1..b5fe15b 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 @@ -1856,7 +1856,6 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList } private lateinit var connectionReceiver: BroadcastReceiver - private lateinit var disconnectionReceiver: BroadcastReceiver private fun resToUri(resId: Int): Uri? { return try { @@ -2581,11 +2580,6 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList } catch (e: Exception) { e.printStackTrace() } - try { - unregisterReceiver(disconnectionReceiver) - } catch (e: Exception) { - e.printStackTrace() - } try { unregisterReceiver(earReceiver) } catch (e: Exception) { diff --git a/android/app/src/main/java/me/kavishdevar/librepods/utils/ATTManager.kt b/android/app/src/main/java/me/kavishdevar/librepods/utils/ATTManager.kt index 09fceff..3312217 100644 --- a/android/app/src/main/java/me/kavishdevar/librepods/utils/ATTManager.kt +++ b/android/app/src/main/java/me/kavishdevar/librepods/utils/ATTManager.kt @@ -173,7 +173,10 @@ class ATTManager(private val device: BluetoothDevice) { val inp = input ?: throw IllegalStateException("Not connected") val buffer = ByteArray(512) val len = inp.read(buffer) - if (len <= 0) throw IllegalStateException("No data read from ATT socket") + if (len == -1) { + disconnect() + throw IllegalStateException("End of stream reached") + } val data = buffer.copyOfRange(0, len) Log.wtf(TAG, "Read ${data.size} bytes from ATT") Log.d(TAG, "readPDU: ${data.joinToString(" ") { String.format("%02X", it) }}") diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index a9825cb..83960d0 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -130,4 +130,8 @@ Conversation Boost Conversation Boost focuses your AirPods Pro on the person talking in front of you, making it easier to hear in a face-to-face conversation. AirPods can use the results of a hearing test to make adjustments that improve the clarity of voices and sounds around you. \n\n Hearing Aid is only intended for people with perceived mild to moderate hearing loss. + Media Assist + AirPods Pro can use the results of a hearing test to make adjustments that improve the clarity of music, video, and calls. + Adjust Music and Video + Adjust Calls