mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-05-16 13:35:37 +00:00
Compare commits
6 Commits
nightly-46
...
nightly-b0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b06d780eee | ||
|
|
70f420dedb | ||
|
|
23193ceb39 | ||
|
|
cb246d1287 | ||
|
|
95cd677da9 | ||
|
|
0d049d93fb |
16
.github/workflows/ci-android.yml
vendored
16
.github/workflows/ci-android.yml
vendored
@@ -87,7 +87,9 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
fetch-tags: true
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: apk-release
|
name: apk-release
|
||||||
@@ -107,12 +109,16 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: root-module-debug
|
name: root-module-debug
|
||||||
path: artifacts/root-module-debug
|
path: artifacts/root-module-debug
|
||||||
|
|
||||||
- id: prev
|
- id: prev
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
TAG=$(gh release list \
|
||||||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
--limit 1 \
|
||||||
|
--json tagName \
|
||||||
|
--jq '.[0].tagName')
|
||||||
|
|
||||||
|
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||||
- id: changelog
|
- id: changelog
|
||||||
run: |
|
run: |
|
||||||
if [ -z "${{ steps.prev.outputs.tag }}" ]; then
|
if [ -z "${{ steps.prev.outputs.tag }}" ]; then
|
||||||
@@ -134,4 +140,4 @@ jobs:
|
|||||||
artifacts/**/* \
|
artifacts/**/* \
|
||||||
-t "Nightly ${{ needs.build.outputs.short_sha }}" \
|
-t "Nightly ${{ needs.build.outputs.short_sha }}" \
|
||||||
--notes "${{ steps.changelog.outputs.notes }}" \
|
--notes "${{ steps.changelog.outputs.notes }}" \
|
||||||
--prerelease
|
--prerelease
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
|
|
||||||
val appVersionName = "0.2.4"
|
val appVersionName = "0.2.6"
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application)
|
alias(libs.plugins.android.application)
|
||||||
@@ -30,7 +30,7 @@ android {
|
|||||||
applicationId = "me.kavishdevar.librepods"
|
applicationId = "me.kavishdevar.librepods"
|
||||||
minSdk = 33
|
minSdk = 33
|
||||||
targetSdk = 37
|
targetSdk = 37
|
||||||
versionCode = 40
|
versionCode = 43
|
||||||
versionName = appVersionName
|
versionName = appVersionName
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
|||||||
import dev.chrisbanes.haze.rememberHazeState
|
import dev.chrisbanes.haze.rememberHazeState
|
||||||
import me.kavishdevar.librepods.data.AirPodsNotifications
|
import me.kavishdevar.librepods.data.AirPodsNotifications
|
||||||
import me.kavishdevar.librepods.data.ControlCommandRepository
|
import me.kavishdevar.librepods.data.ControlCommandRepository
|
||||||
|
import me.kavishdevar.librepods.presentation.components.AppInfoCard
|
||||||
import me.kavishdevar.librepods.presentation.components.ConfirmationDialog
|
import me.kavishdevar.librepods.presentation.components.ConfirmationDialog
|
||||||
import me.kavishdevar.librepods.presentation.components.DeviceInfoCard
|
import me.kavishdevar.librepods.presentation.components.DeviceInfoCard
|
||||||
import me.kavishdevar.librepods.presentation.components.SelectItem
|
import me.kavishdevar.librepods.presentation.components.SelectItem
|
||||||
@@ -223,7 +224,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
fun Main() {
|
fun Main() {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val sharedPreferences = context.getSharedPreferences("settings", MODE_PRIVATE)
|
val sharedPreferences = context.getSharedPreferences("settings", MODE_PRIVATE)
|
||||||
if (!isSupported(sharedPreferences)) {
|
if (!isSupported(sharedPreferences) && !XposedState.bluetoothScopeEnabled) {
|
||||||
val showDialog = remember { mutableStateOf(false) }
|
val showDialog = remember { mutableStateOf(false) }
|
||||||
val showPlayBypassVisible = remember { mutableStateOf(false) }
|
val showPlayBypassVisible = remember { mutableStateOf(false) }
|
||||||
val hazeState = rememberHazeState()
|
val hazeState = rememberHazeState()
|
||||||
@@ -249,27 +250,25 @@ fun Main() {
|
|||||||
verticalArrangement = Arrangement
|
verticalArrangement = Arrangement
|
||||||
.spacedBy(16.dp)
|
.spacedBy(16.dp)
|
||||||
) {
|
) {
|
||||||
val innerBackdrop = rememberLayerBackdrop()
|
|
||||||
Spacer(modifier = Modifier.height(48.dp))
|
Spacer(modifier = Modifier.height(48.dp))
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.layerBackdrop(innerBackdrop),
|
modifier = Modifier,
|
||||||
verticalArrangement = Arrangement
|
verticalArrangement = Arrangement
|
||||||
.spacedBy(16.dp)
|
.spacedBy(16.dp)
|
||||||
) {
|
) {
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.not_supported),
|
text = stringResource(R.string.not_supported),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
color = textColor,
|
color = textColor,
|
||||||
fontSize = 20.sp,
|
fontSize = 28.sp,
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
),
|
),
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
|
|
||||||
DeviceInfoCard()
|
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -281,7 +280,7 @@ fun Main() {
|
|||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
color = if (isSystemInDarkTheme()) Color.White else Color.Black,
|
color = if (isDarkTheme) Color.White else Color.Black,
|
||||||
fontSize = 16.sp
|
fontSize = 16.sp
|
||||||
),
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -289,22 +288,27 @@ fun Main() {
|
|||||||
.padding(horizontal = 12.dp, vertical = 16.dp)
|
.padding(horizontal = 12.dp, vertical = 16.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
StyledButton(
|
||||||
StyledButton(
|
onClick = { showDialog.value = true },
|
||||||
onClick = { showDialog.value = true },
|
backdrop = rememberLayerBackdrop(),
|
||||||
backdrop = innerBackdrop,
|
modifier = Modifier
|
||||||
modifier = Modifier
|
.fillMaxWidth(),
|
||||||
.fillMaxWidth()
|
isInteractive = false,
|
||||||
) {
|
surfaceColor = if (isDarkTheme) Color(0xFF862424) else Color(0xFFC94646)
|
||||||
Text(
|
) {
|
||||||
text = stringResource(R.string.bypass_compatibility_check),
|
Text(
|
||||||
style = TextStyle(
|
text = stringResource(R.string.bypass_compatibility_check),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
style = TextStyle(
|
||||||
fontWeight = FontWeight.Medium,
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
color = if (isSystemInDarkTheme()) Color.White else Color.Black,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 16.sp
|
color = Color.White,
|
||||||
),
|
fontSize = 16.sp
|
||||||
)
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
DeviceInfoCard()
|
||||||
|
AppInfoCard()
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(48.dp))
|
Spacer(modifier = Modifier.height(48.dp))
|
||||||
}
|
}
|
||||||
@@ -323,16 +327,17 @@ fun Main() {
|
|||||||
} else {
|
} else {
|
||||||
sharedPreferences.edit {
|
sharedPreferences.edit {
|
||||||
putBoolean("bypass_device_check.v2", true)
|
putBoolean("bypass_device_check.v2", true)
|
||||||
val intent = Intent(context, MainActivity::class.java)
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
|
||||||
context.startActivity(intent)
|
|
||||||
}
|
}
|
||||||
|
val intent = Intent(context, MainActivity::class.java)
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||||
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
showDialog.value = false
|
showDialog.value = false
|
||||||
},
|
},
|
||||||
hazeState = hazeState
|
backdrop = backdrop
|
||||||
|
// hazeState = hazeState
|
||||||
)
|
)
|
||||||
|
|
||||||
if (BuildConfig.PLAY_BUILD) {
|
if (BuildConfig.PLAY_BUILD) {
|
||||||
|
|||||||
@@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
LibrePods - AirPods liberated from Apple’s ecosystem
|
||||||
|
Copyright (C) 2025 LibrePods contributors
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.kavishdevar.librepods.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.Font
|
||||||
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import me.kavishdevar.librepods.BuildConfig
|
||||||
|
import me.kavishdevar.librepods.R
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AppInfoCard() {
|
||||||
|
val rowHeight = remember { mutableStateOf(0.dp) }
|
||||||
|
val density = LocalDensity.current
|
||||||
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
|
val backgroundColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFFFFFFF)
|
||||||
|
val textColor = if (isDarkTheme) Color.White else Color.Black
|
||||||
|
|
||||||
|
Column {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(if (isDarkTheme) Color.Black else Color(0xFFF2F2F7))
|
||||||
|
.padding(start = 16.dp, bottom = 8.dp, end = 4.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.about), style = TextStyle(
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = textColor.copy(alpha = 0.6f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(28.dp))
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(backgroundColor, RoundedCornerShape(28.dp))
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp)
|
||||||
|
.onGloballyPositioned { coordinates ->
|
||||||
|
rowHeight.value = with(density) { coordinates.size.height.toDp() }
|
||||||
|
},
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.version), style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = textColor,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = BuildConfig.VERSION_NAME, style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(
|
||||||
|
alpha = 0.8f
|
||||||
|
),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
HorizontalDivider(
|
||||||
|
thickness = 1.dp,
|
||||||
|
color = Color(0x40888888),
|
||||||
|
modifier = Modifier.padding(horizontal = 12.dp)
|
||||||
|
)
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.version_code), style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = textColor,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = BuildConfig.VERSION_CODE.toString(), style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(
|
||||||
|
alpha = 0.8f
|
||||||
|
),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
HorizontalDivider(
|
||||||
|
thickness = 1.dp,
|
||||||
|
color = Color(0x40888888),
|
||||||
|
modifier = Modifier.padding(horizontal = 12.dp)
|
||||||
|
)
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.flavor), style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = textColor,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = BuildConfig.FLAVOR, style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(
|
||||||
|
alpha = 0.8f
|
||||||
|
),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
HorizontalDivider(
|
||||||
|
thickness = 1.dp,
|
||||||
|
color = Color(0x40888888),
|
||||||
|
modifier = Modifier.padding(horizontal = 12.dp)
|
||||||
|
)
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.build_type), style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = textColor,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = BuildConfig.BUILD_TYPE,
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(
|
||||||
|
alpha = 0.8f
|
||||||
|
),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,37 +18,32 @@
|
|||||||
|
|
||||||
package me.kavishdevar.librepods.presentation.components
|
package me.kavishdevar.librepods.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.scaleIn
|
||||||
|
import androidx.compose.animation.scaleOut
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.requiredWidthIn
|
import androidx.compose.foundation.layout.requiredWidthIn
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.HorizontalDivider
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
|
||||||
import androidx.compose.ui.input.pointer.PointerEventType
|
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.Font
|
import androidx.compose.ui.text.font.Font
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
@@ -56,13 +51,13 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.compose.ui.window.Dialog
|
import com.kyant.backdrop.backdrops.LayerBackdrop
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||||
import dev.chrisbanes.haze.HazeState
|
import com.kyant.backdrop.drawBackdrop
|
||||||
import dev.chrisbanes.haze.hazeEffect
|
import com.kyant.backdrop.effects.blur
|
||||||
import dev.chrisbanes.haze.materials.CupertinoMaterials
|
import com.kyant.backdrop.effects.lens
|
||||||
|
import com.kyant.backdrop.effects.vibrancy
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import me.kavishdevar.librepods.R
|
import me.kavishdevar.librepods.R
|
||||||
|
|
||||||
@ExperimentalHazeMaterialsApi
|
@ExperimentalHazeMaterialsApi
|
||||||
@@ -75,162 +70,107 @@ fun ConfirmationDialog(
|
|||||||
dismissText: String = "Cancel",
|
dismissText: String = "Cancel",
|
||||||
onConfirm: () -> Unit,
|
onConfirm: () -> Unit,
|
||||||
onDismiss: () -> Unit = { showDialog.value = false },
|
onDismiss: () -> Unit = { showDialog.value = false },
|
||||||
hazeState: HazeState,
|
backdrop: LayerBackdrop,
|
||||||
) {
|
) {
|
||||||
val isDarkTheme = isSystemInDarkTheme()
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
val textColor = if (isDarkTheme) Color.White else Color.Black
|
val textColor = if (isDarkTheme) Color.White else Color.Black
|
||||||
val accentColor = if (isDarkTheme) Color(0xFF007AFF) else Color(0xFF3C6DF5)
|
val accentColor = if (isDarkTheme) Color(0xFF0091FF) else Color(0xFF0088FF)
|
||||||
|
|
||||||
val haptics = LocalHapticFeedback.current
|
AnimatedVisibility(
|
||||||
val scope = rememberCoroutineScope()
|
visible = showDialog.value,
|
||||||
|
enter = scaleIn(initialScale = 1.05f) + fadeIn(),
|
||||||
if (showDialog.value) {
|
exit = scaleOut(targetScale = 1.05f) + fadeOut()
|
||||||
Dialog(
|
) {
|
||||||
onDismissRequest = { showDialog.value = false },
|
Box(
|
||||||
properties = DialogProperties(
|
modifier = Modifier.fillMaxSize(),
|
||||||
dismissOnBackPress = false,
|
contentAlignment = Alignment.Center
|
||||||
dismissOnClickOutside = false
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
|
val innerBackdrop = rememberLayerBackdrop()
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
// .fillMaxWidth(0.75f)
|
.fillMaxSize()
|
||||||
.requiredWidthIn(min = 200.dp, max = 360.dp)
|
.background(Color.Black.copy(alpha = 0.4f))
|
||||||
.background(Color.Transparent, RoundedCornerShape(14.dp))
|
.clickable(enabled = false, onClick = {}),
|
||||||
.clip(RoundedCornerShape(14.dp))
|
contentAlignment = Alignment.Center
|
||||||
.hazeEffect(
|
|
||||||
hazeState,
|
|
||||||
style = CupertinoMaterials.regular(
|
|
||||||
containerColor = if (isDarkTheme) Color(0xFF1C1C1E).copy(alpha = 0.95f) else Color.White.copy(alpha = 0.95f)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
Box(
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
modifier = Modifier
|
||||||
Text(
|
.requiredWidthIn(min = 200.dp, max = 360.dp)
|
||||||
title,
|
.clip(RoundedCornerShape(48.dp))
|
||||||
style = TextStyle(
|
.drawBackdrop(
|
||||||
fontSize = 16.sp,
|
backdrop = backdrop,
|
||||||
fontWeight = FontWeight.Bold,
|
exportedBackdrop = innerBackdrop,
|
||||||
color = textColor,
|
shape = { RoundedCornerShape(48.dp) },
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
effects = {
|
||||||
),
|
vibrancy()
|
||||||
textAlign = TextAlign.Center,
|
blur(4f.dp.toPx())
|
||||||
modifier = Modifier.padding(horizontal = 16.dp)
|
lens(12f.dp.toPx(), 48f.dp.toPx(), true)
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
|
||||||
Text(
|
|
||||||
message,
|
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 14.sp,
|
|
||||||
color = textColor.copy(alpha = 0.8f),
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
),
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.padding(horizontal = 16.dp)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
HorizontalDivider(
|
|
||||||
thickness = 1.dp,
|
|
||||||
color = Color(0x40888888),
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
)
|
|
||||||
var leftPressed by remember { mutableStateOf(false) }
|
|
||||||
var rightPressed by remember { mutableStateOf(false) }
|
|
||||||
val pressedColor = if (isDarkTheme) Color(0x40888888) else Color(0x40D9D9D9)
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(48.dp)
|
|
||||||
.pointerInput(Unit) {
|
|
||||||
awaitPointerEventScope {
|
|
||||||
while (true) {
|
|
||||||
val event = awaitPointerEvent()
|
|
||||||
val position = event.changes.first().position
|
|
||||||
val width = size.width.toFloat()
|
|
||||||
val height = size.height.toFloat()
|
|
||||||
val isWithinBounds = position.y >= 0 && position.y <= height
|
|
||||||
val isLeft = position.x < width / 2
|
|
||||||
event.changes.first().consume()
|
|
||||||
when (event.type) {
|
|
||||||
PointerEventType.Press -> {
|
|
||||||
if (isWithinBounds) {
|
|
||||||
leftPressed = isLeft
|
|
||||||
rightPressed = !isLeft
|
|
||||||
} else {
|
|
||||||
leftPressed = false
|
|
||||||
rightPressed = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PointerEventType.Move -> {
|
|
||||||
if (isWithinBounds) {
|
|
||||||
if (leftPressed != isLeft) scope.launch { haptics.performHapticFeedback(
|
|
||||||
HapticFeedbackType.SegmentTick) }
|
|
||||||
leftPressed = isLeft
|
|
||||||
rightPressed = !isLeft
|
|
||||||
} else {
|
|
||||||
leftPressed = false
|
|
||||||
rightPressed = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PointerEventType.Release -> {
|
|
||||||
if (isWithinBounds) {
|
|
||||||
if (leftPressed) {
|
|
||||||
scope.launch { haptics.performHapticFeedback(
|
|
||||||
HapticFeedbackType.Reject) }
|
|
||||||
onDismiss()
|
|
||||||
} else if (rightPressed) {
|
|
||||||
scope.launch { haptics.performHapticFeedback(
|
|
||||||
HapticFeedbackType.Confirm) }
|
|
||||||
onConfirm()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
leftPressed = false
|
|
||||||
rightPressed = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
horizontalArrangement = Arrangement.Start,
|
onDrawSurface = {
|
||||||
verticalAlignment = Alignment.CenterVertically
|
drawRect(
|
||||||
) {
|
if (isDarkTheme) Color(0xFF1F1F1F).copy(alpha = 0.35f) else Color(0xFFE0E0E0).copy(alpha = 0.7f)
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.fillMaxHeight()
|
|
||||||
.background(if (leftPressed) pressedColor else Color.Transparent),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = dismissText,
|
|
||||||
style = TextStyle(
|
|
||||||
color = accentColor,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
)
|
)
|
||||||
)
|
})) {
|
||||||
}
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
Box(
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
modifier = Modifier
|
Text(
|
||||||
.width(1.dp)
|
title,
|
||||||
.fillMaxHeight()
|
style = TextStyle(
|
||||||
.background(Color(0x40888888))
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = textColor,
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp)
|
||||||
)
|
)
|
||||||
Box(
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
modifier = Modifier
|
Text(
|
||||||
.weight(1f)
|
message,
|
||||||
.fillMaxHeight()
|
style = TextStyle(
|
||||||
.background(if (rightPressed) pressedColor else Color.Transparent),
|
fontSize = 14.sp,
|
||||||
contentAlignment = Alignment.Center
|
color = textColor.copy(alpha = 0.8f),
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro))
|
||||||
|
),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(0.9f),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(24.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
StyledButton(
|
||||||
text = confirmText,
|
onClick = onDismiss,
|
||||||
style = TextStyle(
|
backdrop = innerBackdrop,
|
||||||
color = accentColor,
|
modifier = Modifier.weight(1f),
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
) {
|
||||||
|
Text(
|
||||||
|
text = dismissText, style = TextStyle(
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = textColor
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
|
StyledButton(
|
||||||
|
onClick = onConfirm,
|
||||||
|
backdrop = innerBackdrop,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
surfaceColor = accentColor
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = confirmText, style = TextStyle(
|
||||||
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ fun DeviceInfoCard() {
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(if (isDarkTheme) Color.Black else Color(0xFFF2F2F7))
|
.background(if (isDarkTheme) Color.Black else Color(0xFFF2F2F7))
|
||||||
.padding(start = 16.dp, bottom = 2.dp, top = 24.dp, end = 4.dp)
|
.padding(start = 16.dp, top = 24.dp, end = 4.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.device_info), style = TextStyle(
|
text = stringResource(R.string.device_info), style = TextStyle(
|
||||||
|
|||||||
@@ -58,9 +58,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.Font
|
import androidx.compose.ui.text.font.Font
|
||||||
@@ -80,6 +78,7 @@ import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
|||||||
import dev.chrisbanes.haze.hazeSource
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import me.kavishdevar.librepods.BuildConfig
|
import me.kavishdevar.librepods.BuildConfig
|
||||||
import me.kavishdevar.librepods.R
|
import me.kavishdevar.librepods.R
|
||||||
|
import me.kavishdevar.librepods.presentation.components.AppInfoCard
|
||||||
import me.kavishdevar.librepods.presentation.components.DeviceInfoCard
|
import me.kavishdevar.librepods.presentation.components.DeviceInfoCard
|
||||||
import me.kavishdevar.librepods.presentation.components.NavigationButton
|
import me.kavishdevar.librepods.presentation.components.NavigationButton
|
||||||
import me.kavishdevar.librepods.presentation.components.StyledBottomSheet
|
import me.kavishdevar.librepods.presentation.components.StyledBottomSheet
|
||||||
@@ -513,145 +512,8 @@ fun AppSettingsScreen(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
DeviceInfoCard()
|
DeviceInfoCard()
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Box(
|
AppInfoCard()
|
||||||
modifier = Modifier
|
|
||||||
.background(if (isDarkTheme) Color.Black else Color(0xFFF2F2F7))
|
|
||||||
.padding(start = 16.dp, bottom = 2.dp, top = 24.dp, end = 4.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.about), style = TextStyle(
|
|
||||||
fontSize = 14.sp,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
color = textColor.copy(alpha = 0.6f),
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val rowHeight = remember { mutableStateOf(0.dp) }
|
|
||||||
val density = LocalDensity.current
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.clip(RoundedCornerShape(28.dp))
|
|
||||||
.fillMaxWidth()
|
|
||||||
.background(backgroundColor, RoundedCornerShape(28.dp))
|
|
||||||
.padding(top = 2.dp)
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(16.dp)
|
|
||||||
.onGloballyPositioned { coordinates ->
|
|
||||||
rowHeight.value = with(density) { coordinates.size.height.toDp() }
|
|
||||||
},
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.version), style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = BuildConfig.VERSION_NAME, style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(
|
|
||||||
alpha = 0.8f
|
|
||||||
),
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
HorizontalDivider(
|
|
||||||
thickness = 1.dp,
|
|
||||||
color = Color(0x40888888),
|
|
||||||
modifier = Modifier.padding(horizontal = 12.dp)
|
|
||||||
)
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(16.dp),
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.version_code), style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = BuildConfig.VERSION_CODE.toString(), style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(
|
|
||||||
alpha = 0.8f
|
|
||||||
),
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
HorizontalDivider(
|
|
||||||
thickness = 1.dp,
|
|
||||||
color = Color(0x40888888),
|
|
||||||
modifier = Modifier.padding(horizontal = 12.dp)
|
|
||||||
)
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(16.dp),
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.flavor), style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = BuildConfig.FLAVOR, style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(
|
|
||||||
alpha = 0.8f
|
|
||||||
),
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
HorizontalDivider(
|
|
||||||
thickness = 1.dp,
|
|
||||||
color = Color(0x40888888),
|
|
||||||
modifier = Modifier.padding(horizontal = 12.dp)
|
|
||||||
)
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(16.dp),
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.build_type), style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor,
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = BuildConfig.BUILD_TYPE,
|
|
||||||
style = TextStyle(
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = if (isDarkTheme) Color.White.copy(alpha = 0.6f) else Color.Black.copy(
|
|
||||||
alpha = 0.8f
|
|
||||||
),
|
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
@@ -763,7 +625,8 @@ fun AppSettingsScreen(
|
|||||||
fontSize = 18.sp,
|
fontSize = 18.sp,
|
||||||
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
fontFamily = FontFamily(Font(R.font.sf_pro)),
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center,
|
||||||
|
color = if (isSystemInDarkTheme()) Color.White else Color.Black
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
StyledIconButton(
|
StyledIconButton(
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ fun HearingAidScreen(viewModel: AirPodsViewModel, navController: NavController)
|
|||||||
hearingAidEnabled.value = false
|
hearingAidEnabled.value = false
|
||||||
showDialog.value = false
|
showDialog.value = false
|
||||||
},
|
},
|
||||||
hazeState = hazeStateS.value,
|
// hazeState = hazeStateS.value,
|
||||||
// backdrop = backdrop
|
backdrop = backdrop
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class LibrePodsApplication: Application(), XposedServiceHelper.OnServiceListener
|
|||||||
|
|
||||||
override fun onResume(owner: LifecycleOwner) {
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
BillingManager.provider.queryPurchases()
|
BillingManager.provider.queryPurchases()
|
||||||
XposedState.isAvailable = true
|
XposedState.isAvailable = XposedServiceHolder.service != null
|
||||||
XposedState.bluetoothScopeEnabled = XposedServiceHolder.service?.scope?.contains("com.google.android.bluetooth") == true || XposedServiceHolder.service?.scope?.contains("com.android.bluetooth") == true
|
XposedState.bluetoothScopeEnabled = XposedServiceHolder.service?.scope?.contains("com.google.android.bluetooth") == true || XposedServiceHolder.service?.scope?.contains("com.android.bluetooth") == true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class KotlinModule: XposedModule() {
|
|||||||
log(Log.INFO, TAG, "framework: $frameworkName($frameworkVersionCode) API $apiVersion")
|
log(Log.INFO, TAG, "framework: $frameworkName($frameworkVersionCode) API $apiVersion")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeDynamicallyLoadedCode")
|
||||||
override fun onPackageLoaded(param: PackageLoadedParam) {
|
override fun onPackageLoaded(param: PackageLoadedParam) {
|
||||||
log(Log.INFO, TAG, "onPackageLoaded :: ${param.packageName}")
|
log(Log.INFO, TAG, "onPackageLoaded :: ${param.packageName}")
|
||||||
|
|
||||||
@@ -27,8 +28,36 @@ class KotlinModule: XposedModule() {
|
|||||||
log(Log.INFO, TAG, "Bluetooth app detected, hooking l2c_fcr_chk_chan_modes")
|
log(Log.INFO, TAG, "Bluetooth app detected, hooking l2c_fcr_chk_chan_modes")
|
||||||
try {
|
try {
|
||||||
if (param.isFirstPackage) {
|
if (param.isFirstPackage) {
|
||||||
log(Log.INFO, TAG, "Loading native library for Bluetooth hook")
|
val abi = android.os.Build.SUPPORTED_ABIS.first()
|
||||||
System.loadLibrary("l2c_fcr_hook")
|
val soName = "libl2c_fcr_hook.so"
|
||||||
|
|
||||||
|
val candidates = buildList {
|
||||||
|
add("${moduleApplicationInfo.sourceDir}!/lib/$abi/$soName")
|
||||||
|
|
||||||
|
moduleApplicationInfo.splitSourceDirs?.forEach { split ->
|
||||||
|
add("$split!/lib/$abi/$soName")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var loaded = false
|
||||||
|
|
||||||
|
for (path in candidates) {
|
||||||
|
try {
|
||||||
|
log(Log.INFO, TAG, "Trying to load native lib from $path")
|
||||||
|
System.load(path)
|
||||||
|
log(Log.INFO, TAG, "Loaded native lib from $path")
|
||||||
|
loaded = true
|
||||||
|
break
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
log(Log.WARN, TAG, "Failed to load from $path: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loaded) {
|
||||||
|
log(Log.ERROR, TAG, "Could not load $soName from base or splits")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val remotePrefValue = getRemotePreferences("me.kavishdevar.librepods").getBoolean("vendor_id_hook", false)
|
val remotePrefValue = getRemotePreferences("me.kavishdevar.librepods").getBoolean("vendor_id_hook", false)
|
||||||
log(Log.INFO, TAG, "sdp hook enabled (remote pref): $remotePrefValue")
|
log(Log.INFO, TAG, "sdp hook enabled (remote pref): $remotePrefValue")
|
||||||
NativeBridge.setSdpHook(remotePrefValue)
|
NativeBridge.setSdpHook(remotePrefValue)
|
||||||
|
|||||||
Reference in New Issue
Block a user