Skip to content

Commit 790e396

Browse files
committed
android: add material 3 expressive theme
All of the new UI was written by hand! also fixed upgraded being set to false in FOSS builds when opening App settings. should've been a different commit, but ¯\_(ツ)_/¯
1 parent 633d036 commit 790e396

74 files changed

Lines changed: 10428 additions & 9690 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

android/app/build.gradle.kts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import java.util.Properties
22

3-
val appVersionName = "0.3.0"
3+
val appVersionName = "1.0.0-rc1"
44

55
plugins {
66
alias(libs.plugins.android.application)
@@ -24,6 +24,14 @@ val releaseSigningAvailable = listOf(
2424
"RELEASE_KEY_PASSWORD"
2525
).all { props[it]?.toString()?.isNotBlank() == true }
2626

27+
kotlin {
28+
compilerOptions {
29+
optIn.add(
30+
"androidx.compose.material3.ExperimentalMaterial3ExpressiveApi"
31+
)
32+
}
33+
}
34+
2735
android {
2836
signingConfigs {
2937
if (releaseSigningAvailable) {
@@ -41,7 +49,7 @@ android {
4149
defaultConfig {
4250
applicationId = "me.kavishdevar.librepods"
4351
targetSdk = 37
44-
versionCode = 56
52+
versionCode = 61
4553
versionName = appVersionName
4654
}
4755
buildTypes {
@@ -117,6 +125,7 @@ android {
117125
dependencies {
118126
implementation(platform(libs.androidx.compose.bom))
119127
implementation(libs.accompanist.permissions)
128+
implementation(libs.androidx.compose.ui.text.google.fonts)
120129
implementation(libs.androidx.core.ktx)
121130
implementation(libs.androidx.lifecycle.process)
122131
implementation(libs.androidx.lifecycle.runtime.ktx)
@@ -145,6 +154,10 @@ dependencies {
145154
implementation(libs.libxposed.service)
146155
implementation(libs.play.review)
147156
implementation(libs.play.review.ktx)
157+
implementation(libs.androidx.navigation3.ui)
158+
implementation(libs.androidx.navigation3.runtime)
159+
implementation(libs.androidx.lifecycle.viewmodel.navigation3)
160+
implementation(libs.androidx.navigationevent)
148161
}
149162

150163
aboutLibraries {

android/app/src/main/java/me/kavishdevar/librepods/MainActivity.kt

Lines changed: 78 additions & 717 deletions
Large diffs are not rendered by default.

android/app/src/main/java/me/kavishdevar/librepods/bluetooth/AACPManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,7 @@ class AACPManager {
11591159
)
11601160
}
11611161

1162-
val socket = BluetoothConnectionManager.getAACPSocket() ?: return false
1162+
val socket = BluetoothConnectionManager.aacpSocket ?: return false
11631163

11641164
if (socket.isConnected) {
11651165
socket.outputStream?.write(packet)

android/app/src/main/java/me/kavishdevar/librepods/bluetooth/ATTManager.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ enum class ATTHandles(val value: Int) {
3434

3535
enum class ATTCCCDHandles(val value: Int) {
3636
TRANSPARENCY(ATTHandles.TRANSPARENCY.value + 1),
37-
// LOUD_SOUND_REDUCTION(ATTHandles.LOUD_SOUND_REDUCTION.value + 1), // doesn't work
37+
// LOUD_SOUND_REDUCTION(ATTHandles.LOUD_SOUND_REDUCTION.value + 1), // doesn't work
3838
HEARING_AID(ATTHandles.HEARING_AID.value + 1)
3939
}
4040

@@ -86,7 +86,7 @@ class ATTManagerv2 {
8686
}
8787

8888
fun readCharacteristic(handle: ATTHandles, timeoutMillis: Long = 2000): ByteArray? {
89-
val socket = BluetoothConnectionManager.getATTSocket() ?: return null
89+
val socket = BluetoothConnectionManager.attSocket ?: return null
9090
try {
9191
val output = socket.outputStream
9292
val pdu = byteArrayOf(0x0A, handle.value.toByte(), 0x00)
@@ -117,7 +117,7 @@ class ATTManagerv2 {
117117
}
118118

119119
fun writeCharacteristic(handle: Byte, data: ByteArray, timeoutMillis: Long = 2000) {
120-
val socket = BluetoothConnectionManager.getATTSocket() ?: return
120+
val socket = BluetoothConnectionManager.attSocket ?: return
121121
try {
122122
val output = socket.outputStream
123123
val pdu = byteArrayOf(0x12, handle, 0x00) + data // 0x00 for LE
@@ -141,7 +141,7 @@ class ATTManagerv2 {
141141
fun disconnected() {
142142
characteristicList.clear()
143143
stopReader()
144-
val socket = BluetoothConnectionManager.getATTSocket() ?: return
144+
val socket = BluetoothConnectionManager.attSocket?: return
145145
try {
146146
socket.close()
147147
} catch (e: Exception) {
@@ -151,7 +151,7 @@ class ATTManagerv2 {
151151
}
152152

153153
private fun runReaderLoop() {
154-
val socket = BluetoothConnectionManager.getATTSocket() ?: run {
154+
val socket = BluetoothConnectionManager.attSocket ?: run {
155155
Log.w(TAG, "ATT socket not available. stopping reader")
156156
readerRunning.set(false)
157157
return

android/app/src/main/java/me/kavishdevar/librepods/bluetooth/BluetoothConnectionManager.kt

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,59 @@
1818

1919
package me.kavishdevar.librepods.bluetooth
2020

21+
import android.bluetooth.BluetoothAdapter
22+
import android.bluetooth.BluetoothDevice
2123
import android.bluetooth.BluetoothSocket
24+
import android.os.ParcelUuid
25+
import android.util.Log
2226

2327
object BluetoothConnectionManager {
24-
private var aacpSocket: BluetoothSocket? = null
25-
private var attSocket: BluetoothSocket? = null
28+
var aacpSocket: BluetoothSocket? = null
29+
var attSocket: BluetoothSocket? = null
30+
}
2631

27-
fun setCurrentConnection(aacpSocket: BluetoothSocket?, attSocket: BluetoothSocket?) {
28-
BluetoothConnectionManager.aacpSocket = aacpSocket
29-
BluetoothConnectionManager.attSocket = attSocket
30-
}
32+
fun createBluetoothSocket(
33+
adapter: BluetoothAdapter, device: BluetoothDevice, uuid: ParcelUuid, psm: Int
34+
): BluetoothSocket {
35+
val type = 3 // L2CAP
36+
val constructorSpecs = listOf(
37+
arrayOf(adapter, device, type, true, true, psm, uuid), // A16QPR3
38+
arrayOf(device, type, true, true, psm, uuid),
39+
arrayOf(device, type, 1, true, true, psm, uuid),
40+
arrayOf(type, 1, true, true, device, psm, uuid),
41+
arrayOf(type, true, true, device, psm, uuid)
42+
)
3143

32-
fun getAACPSocket(): BluetoothSocket? {
33-
return aacpSocket
44+
val constructors = BluetoothSocket::class.java.declaredConstructors
45+
Log.d("createSocket<psm>", "BluetoothSocket has ${constructors.size} constructors:")
46+
47+
constructors.forEachIndexed { index, constructor ->
48+
val params = constructor.parameterTypes.joinToString(", ") { it.simpleName }
49+
Log.d("createSocket<psm>", "Constructor $index: ($params)")
3450
}
3551

36-
fun getATTSocket(): BluetoothSocket? {
37-
return attSocket
52+
var lastException: Exception? = null
53+
var attemptedConstructors = 0
54+
55+
for ((index, params) in constructorSpecs.withIndex()) {
56+
try {
57+
Log.d("createSocket<psm>", "Trying constructor signature #${index + 1}")
58+
attemptedConstructors++
59+
60+
val paramTypes =
61+
params.map { it::class.javaPrimitiveType ?: it::class.java }.toTypedArray()
62+
val constructor = BluetoothSocket::class.java.getDeclaredConstructor(*paramTypes)
63+
constructor.isAccessible = true
64+
return constructor.newInstance(*params) as BluetoothSocket
65+
66+
} catch (e: Exception) {
67+
Log.e("createSocket<psm>", "Constructor signature #${index + 1} failed: ${e.message}")
68+
lastException = e
69+
}
3870
}
71+
72+
val errorMessage =
73+
"Failed to create BluetoothSocket after trying $attemptedConstructors constructor signatures"
74+
Log.e("createSocket<psm>", errorMessage)
75+
throw lastException ?: IllegalStateException(errorMessage)
3976
}

android/app/src/main/java/me/kavishdevar/librepods/data/HearingAid.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import me.kavishdevar.librepods.bluetooth.ATTHandles
2929
import java.io.IOException
3030
import java.nio.ByteBuffer
3131
import java.nio.ByteOrder
32+
import kotlin.time.Duration.Companion.milliseconds
3233

3334
private const val TAG = "HearingAidUtils"
3435

@@ -144,7 +145,7 @@ fun sendHearingAidSettings(
144145
) {
145146
debounceJob.value?.cancel()
146147
debounceJob.value = CoroutineScope(Dispatchers.IO).launch {
147-
delay(100)
148+
delay(100.milliseconds)
148149
try {
149150
Log.d(TAG, "Current data before update: ${currentData.joinToString(" ") { String.format("%02X", it) }}")
150151
if (currentData.size < 104) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package me.kavishdevar.librepods.data.updates
2+
3+
import androidx.compose.runtime.Composable
4+
5+
data class UpdateItem(
6+
val titleRes: Int,
7+
val descriptionRes: Int,
8+
val demoComposeable: @Composable () -> Unit
9+
)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package me.kavishdevar.librepods.data.updates
2+
3+
import androidx.compose.runtime.Composable
4+
import me.kavishdevar.librepods.R
5+
import me.kavishdevar.librepods.presentation.screens.AirPodsSettingsScreenPreviewMaterial
6+
import me.kavishdevar.librepods.presentation.screens.EqualizerScreenPreviewApple
7+
import me.kavishdevar.librepods.presentation.screens.EqualizerScreenPreviewMaterial
8+
import me.kavishdevar.librepods.presentation.theme.DesignSystem
9+
import me.kavishdevar.librepods.presentation.theme.LocalDesignSystem
10+
11+
val update0_3_1 = listOf(
12+
UpdateItem(
13+
titleRes = R.string.material3e,
14+
descriptionRes = R.string.update_m3e_description,
15+
demoComposeable = @Composable {
16+
AirPodsSettingsScreenPreviewMaterial()
17+
}
18+
),
19+
UpdateItem(
20+
titleRes = R.string.equalizer,
21+
descriptionRes = R.string.update_equalizer_description,
22+
demoComposeable = @Composable {
23+
when (LocalDesignSystem.current) {
24+
DesignSystem.Apple -> {
25+
EqualizerScreenPreviewApple()
26+
}
27+
DesignSystem.Material -> {
28+
EqualizerScreenPreviewMaterial()
29+
}
30+
}
31+
}
32+
),
33+
)
34+
35+
val updates = update0_3_1

0 commit comments

Comments
 (0)