mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-09-01 16:59:35 +02:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 53679cc902 | |||
| b4cacb89f1 | |||
| cf6d226fca | |||
| 4c7a3cb203 | |||
| 1783bb742e | |||
| 3cc4d92d62 | |||
| 95ecc0eb3d | |||
| a7537f2361 | |||
| 21babd819f | |||
| b5a3eaee8f | |||
| c3f537b0e9 |
@@ -224,11 +224,11 @@ A huge thank you to everyone supporting the project!
|
||||
|
||||
# Star History
|
||||
|
||||
<a href="https://www.star-history.com/#kavishdevar/librepods&type=date&legend=top-left">
|
||||
<a href="https://www.star-history.com/?repos=librepods-org%2Flibrepods&type=date&legend=top-left">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=kavishdevar/librepods&type=date&theme=dark&legend=top-left" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=kavishdevar/librepods&type=date&legend=top-left" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=kavishdevar/librepods&type=date&legend=top-left" />
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=librepods-org/librepods&type=date&theme=dark&legend=top-left&sealed_token=CS9QF2Wcx-_EN6M7lBhwvTa2WBd5eB8FbQa5FWt3SV14v1OcQdy2aCGsXxHoytVaoylP_pTxj1h2U-odoXDV_EwTqMxM-MQwG_WpvV_1g_yH-Jh3ux2BuWCmS98LxLqfox2ibLOlFDHu_-geTLFsTmqTc1SjX6-NYxVHXF5DaqnxFOAyjLPL5_WtXVew" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=librepods-org/librepods&type=date&legend=top-left&sealed_token=CS9QF2Wcx-_EN6M7lBhwvTa2WBd5eB8FbQa5FWt3SV14v1OcQdy2aCGsXxHoytVaoylP_pTxj1h2U-odoXDV_EwTqMxM-MQwG_WpvV_1g_yH-Jh3ux2BuWCmS98LxLqfox2ibLOlFDHu_-geTLFsTmqTc1SjX6-NYxVHXF5DaqnxFOAyjLPL5_WtXVew" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=librepods-org/librepods&type=date&legend=top-left&sealed_token=CS9QF2Wcx-_EN6M7lBhwvTa2WBd5eB8FbQa5FWt3SV14v1OcQdy2aCGsXxHoytVaoylP_pTxj1h2U-odoXDV_EwTqMxM-MQwG_WpvV_1g_yH-Jh3ux2BuWCmS98LxLqfox2ibLOlFDHu_-geTLFsTmqTc1SjX6-NYxVHXF5DaqnxFOAyjLPL5_WtXVew" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
@@ -258,4 +258,4 @@ If you see any misuse of the LibrePods name or logo, please report it to [me@kav
|
||||
|
||||
The SF Pro font used in the Android app is the property of Apple Inc.. This will be removed in future versions of the app and replaced with an open alternative soon.
|
||||
|
||||
AirPods, AirPods Pro, AirPods Max, and the AirPods logo are trademarks of Apple Inc. The LibrePods project is not affiliated with or endorsed by Apple Inc. in any way.
|
||||
AirPods, AirPods Pro, AirPods Max, and the AirPods logo are trademarks of Apple Inc. The LibrePods project is not affiliated with or endorsed by Apple Inc. in any way.
|
||||
|
||||
+96
-76
@@ -736,96 +736,116 @@ fun AirPodsSettingsScreen(
|
||||
|
||||
val animatedShapeColor by animateColorAsState(if (reconnecting) primaryContainerColor else secondaryContainerColor)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(240.dp)
|
||||
.background(
|
||||
MaterialTheme.colorScheme.surfaceBright,
|
||||
CircleShape
|
||||
)
|
||||
.clickable(
|
||||
interactionSource = null,
|
||||
indication = ripple(
|
||||
bounded = false,
|
||||
radius = 120.dp
|
||||
),
|
||||
enabled = !reconnecting,
|
||||
onClick = {}
|
||||
)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onTap = {
|
||||
if (!reconnecting) {
|
||||
currentMorphIndex = 1
|
||||
reconnecting = true
|
||||
reconnectFromSavedMac()
|
||||
}
|
||||
},
|
||||
onPress = {
|
||||
if (!reconnecting) {
|
||||
morphProgress.animateTo(
|
||||
targetValue = 1f,
|
||||
animationSpec = spring(
|
||||
dampingRatio = Spring.DampingRatioMediumBouncy,
|
||||
stiffness = Spring.StiffnessLow
|
||||
if (state.connectionSuccessful) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(240.dp)
|
||||
.background(
|
||||
MaterialTheme.colorScheme.surfaceBright,
|
||||
CircleShape
|
||||
)
|
||||
.clickable(
|
||||
interactionSource = null,
|
||||
indication = ripple(
|
||||
bounded = false,
|
||||
radius = 120.dp
|
||||
),
|
||||
enabled = !reconnecting,
|
||||
onClick = {}
|
||||
)
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures(
|
||||
onTap = {
|
||||
if (!reconnecting) {
|
||||
currentMorphIndex = 1
|
||||
reconnecting = true
|
||||
reconnectFromSavedMac()
|
||||
}
|
||||
},
|
||||
onPress = {
|
||||
if (!reconnecting) {
|
||||
morphProgress.animateTo(
|
||||
targetValue = 1f,
|
||||
animationSpec = spring(
|
||||
dampingRatio = Spring.DampingRatioMediumBouncy,
|
||||
stiffness = Spring.StiffnessLow
|
||||
)
|
||||
)
|
||||
)
|
||||
tryAwaitRelease()
|
||||
morphProgress.animateTo(
|
||||
targetValue = 0f,
|
||||
animationSpec = spring(
|
||||
dampingRatio = Spring.DampingRatioMediumBouncy,
|
||||
stiffness = Spring.StiffnessLow
|
||||
tryAwaitRelease()
|
||||
morphProgress.animateTo(
|
||||
targetValue = 0f,
|
||||
animationSpec = spring(
|
||||
dampingRatio = Spring.DampingRatioMediumBouncy,
|
||||
stiffness = Spring.StiffnessLow
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
.drawWithContent {
|
||||
val activeMorph = morphs[currentMorphIndex]
|
||||
)
|
||||
}
|
||||
.drawWithContent {
|
||||
val activeMorph = morphs[currentMorphIndex]
|
||||
|
||||
val shapePath = activeMorph.toPath(
|
||||
progress = morphProgress.value,
|
||||
path = path
|
||||
)
|
||||
val shapePath = activeMorph.toPath(
|
||||
progress = morphProgress.value,
|
||||
path = path
|
||||
)
|
||||
|
||||
val bounds = shapePath.getBounds()
|
||||
val bounds = shapePath.getBounds()
|
||||
|
||||
val scale = min(size.width/bounds.width, size.height/bounds.height) * 0.8f
|
||||
val scale = min(
|
||||
size.width / bounds.width,
|
||||
size.height / bounds.height
|
||||
) * 0.8f
|
||||
|
||||
scaleMatrix.reset()
|
||||
scaleMatrix.reset()
|
||||
|
||||
scaleMatrix.scale(x = scale, y = scale)
|
||||
scaleMatrix.scale(x = scale, y = scale)
|
||||
|
||||
shapePath.transform(scaleMatrix)
|
||||
shapePath.transform(scaleMatrix)
|
||||
|
||||
shapePath.translate(size.center - shapePath.getBounds().center)
|
||||
shapePath.translate(size.center - shapePath.getBounds().center)
|
||||
|
||||
drawPath(
|
||||
path = shapePath,
|
||||
color = animatedShapeColor
|
||||
)
|
||||
drawPath(
|
||||
path = shapePath,
|
||||
color = animatedShapeColor
|
||||
)
|
||||
|
||||
drawContent()
|
||||
},
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (reconnecting) MaterialIcons.bluetooth_searching else MaterialIcons.headset_off,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(84.dp),
|
||||
tint = if (reconnecting) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSecondaryContainer
|
||||
drawContent()
|
||||
},
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (reconnecting) MaterialIcons.bluetooth_searching else MaterialIcons.headset_off,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(84.dp),
|
||||
tint = if (reconnecting) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSecondaryContainer
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(40.dp))
|
||||
|
||||
Text(
|
||||
text = if (reconnecting) stringResource(R.string.reconnecting) else stringResource(R.string.tap_to_reconnect),
|
||||
style = MaterialTheme.typography.labelSmallEmphasized,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
text = stringResource(R.string.airpods_not_connected),
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
if (sharedPreferences.getBoolean("bypass_device_check.v2", false)) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.compatibility_check_bypassed),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(40.dp))
|
||||
|
||||
Text(
|
||||
text = if (reconnecting) stringResource(R.string.reconnecting) else stringResource(R.string.tap_to_reconnect),
|
||||
style = MaterialTheme.typography.labelSmallEmphasized,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
|
||||
if (!BuildConfig.PLAY_BUILD) {
|
||||
|
||||
+7
@@ -47,6 +47,7 @@ import me.kavishdevar.librepods.presentation.theme.LibrePodsTheme
|
||||
import me.kavishdevar.librepods.utils.XposedState
|
||||
import me.kavishdevar.librepods.utils.bypassDeviceCheck
|
||||
import me.kavishdevar.librepods.utils.isSupported
|
||||
import me.kavishdevar.librepods.utils.removeDeviceCheckBypass
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class, ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -191,6 +192,9 @@ fun OnboardingScreen(
|
||||
NotSupportedPage(
|
||||
bypassCompatibilityCheck = {
|
||||
bypassDeviceCheck(sharedPreferences)
|
||||
animationScope.launch {
|
||||
state.animateScrollToItem(3)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -199,6 +203,9 @@ fun OnboardingScreen(
|
||||
onBackward = {
|
||||
animationScope.launch {
|
||||
if (state.canScrollBackward) state.animateScrollToItem(if (isSupported) 1 else 2)
|
||||
if (!isSupported) {
|
||||
removeDeviceCheckBypass(sharedPreferences)
|
||||
}
|
||||
}
|
||||
},
|
||||
onForward = onOnboardingComplete
|
||||
|
||||
+1
-3
@@ -105,7 +105,7 @@ data class AirPodsUiState(
|
||||
)
|
||||
|
||||
val demoInstance = AirPodsInstance(
|
||||
name = "AirPods Pro",
|
||||
name = "[DEMO] AirPods Pro",
|
||||
model = AirPodsModels.getModelByModelNumber("A3064")!!,
|
||||
actualModelNumber = "A3064",
|
||||
serialNumber = "JXF9Q94A40",
|
||||
@@ -160,8 +160,6 @@ val demoState = AirPodsUiState(
|
||||
|
||||
dynamicEndOfCharge = true,
|
||||
|
||||
connectionSuccessful = true,
|
||||
|
||||
customEq = CustomEq(state = 2, low = 65, mid = 50, high = 70),
|
||||
|
||||
controlStates = mapOf(
|
||||
|
||||
@@ -42,3 +42,7 @@ fun isSupported(sharedPreferences: SharedPreferences): Boolean {
|
||||
fun bypassDeviceCheck(sharedPreferences: SharedPreferences) {
|
||||
sharedPreferences.edit{ putBoolean("bypass_device_check.v2", true) }
|
||||
}
|
||||
|
||||
fun removeDeviceCheckBypass(sharedPreferences: SharedPreferences) {
|
||||
sharedPreferences.edit{ putBoolean("bypass_device_check.v2", false) }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -290,4 +290,5 @@
|
||||
<string name="permissions">Permissions</string>
|
||||
<string name="privacy_policy">Privacy Policy</string>
|
||||
<string name="i_agree">I agree</string>
|
||||
<string name="compatibility_check_bypassed">Compatibility check bypassed. Are you sure your device is compatible?</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user