mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-14 18:26:11 -04:00
feat(reactions): Move reaction settings to per-device profiles
Migrate reaction toggles (auto-play, auto-pause, auto-connect, popups) from global ReactionSettings singleton to per-profile fields on AppleDeviceProfile. Each paired device can now have independent reaction behavior. Extract ReactionConfig snapshot to decouple PodDevice from AppleDeviceProfile — reaction consumers read device.reactions instead of device.profile. Remove auto-connect from upgrade benefits (now free). Add LegacyReactionSettingsReader for one-shot DataStore migration.
This commit is contained in:
@@ -20,8 +20,6 @@ import eu.darken.capod.common.compose.preview.MockPodDataProvider
|
||||
import eu.darken.capod.common.theming.CapodTheme
|
||||
import eu.darken.capod.main.ui.overview.OverviewScreen
|
||||
import eu.darken.capod.main.ui.overview.OverviewViewModel
|
||||
import eu.darken.capod.main.ui.settings.SettingsScreen
|
||||
import eu.darken.capod.main.ui.settings.SettingsViewModel
|
||||
import eu.darken.capod.main.ui.widget.ComposeWidgetPreview
|
||||
import eu.darken.capod.main.ui.widget.WidgetConfigurationScreen
|
||||
import eu.darken.capod.main.ui.widget.WidgetConfigurationViewModel
|
||||
@@ -32,9 +30,8 @@ import eu.darken.capod.profiles.ui.DeviceManagerScreen
|
||||
import eu.darken.capod.profiles.ui.DeviceManagerViewModel
|
||||
import eu.darken.capod.profiles.ui.creation.DeviceProfileCreationScreen
|
||||
import eu.darken.capod.profiles.ui.creation.DeviceProfileCreationViewModel
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
import eu.darken.capod.reaction.ui.ReactionSettingsScreen
|
||||
import eu.darken.capod.reaction.ui.ReactionSettingsViewModel
|
||||
import eu.darken.capod.main.ui.devicesettings.DeviceSettingsScreen
|
||||
import eu.darken.capod.main.ui.devicesettings.DeviceSettingsViewModel
|
||||
import eu.darken.capod.reaction.ui.popup.PopUpContent as PopUpCard
|
||||
|
||||
internal const val DS = "spec:width=1080px,height=2400px,dpi=428"
|
||||
@@ -113,44 +110,15 @@ internal fun AddProfileContent() = PreviewWrapper {
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun SettingsIndexContent() = PreviewWrapper {
|
||||
SettingsScreen(
|
||||
state = SettingsViewModel.State(isPro = true, sponsorUrl = "https://example.com"),
|
||||
onNavigateUp = {},
|
||||
onGeneralSettings = {},
|
||||
onDeviceManager = {},
|
||||
onReactions = {},
|
||||
onSupport = {},
|
||||
onWiki = {},
|
||||
onChangelog = {},
|
||||
onHelpTranslate = {},
|
||||
onAcknowledgements = {},
|
||||
onPrivacyPolicy = {},
|
||||
onSponsor = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun ReactionSettingsContent() = PreviewWrapper {
|
||||
ReactionSettingsScreen(
|
||||
state = ReactionSettingsViewModel.State(
|
||||
internal fun DeviceSettingsReactionsContent() = PreviewWrapper {
|
||||
DeviceSettingsScreen(
|
||||
state = DeviceSettingsViewModel.State(
|
||||
device = MockPodDataProvider.dualPodMonitoredWithReactions(),
|
||||
now = MOCK_NOW,
|
||||
isPro = true,
|
||||
onePodMode = false,
|
||||
autoPlay = true,
|
||||
autoPause = true,
|
||||
autoConnect = false,
|
||||
autoConnectCondition = AutoConnectCondition.WHEN_SEEN,
|
||||
showPopUpOnCaseOpen = true,
|
||||
showPopUpOnConnection = false,
|
||||
isNudgeAvailable = true,
|
||||
),
|
||||
onNavigateUp = {},
|
||||
onOnePodModeChanged = {},
|
||||
onAutoPlayChanged = {},
|
||||
onAutoPauseChanged = {},
|
||||
onAutoConnectChanged = {},
|
||||
onAutoConnectConditionSelected = {},
|
||||
onShowPopUpOnCaseOpenChanged = {},
|
||||
onShowPopUpOnConnectionChanged = {},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -260,14 +228,10 @@ private fun PreviewDeviceProfiles() = DeviceProfilesContent()
|
||||
@Composable
|
||||
private fun PreviewAddProfile() = AddProfileContent()
|
||||
|
||||
@Preview(name = "7 - Settings", locale = "en", device = DS, showSystemUi = true)
|
||||
@Preview(name = "7 - Device Settings Reactions", locale = "en", device = DS, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewSettingsIndex() = SettingsIndexContent()
|
||||
private fun PreviewDeviceSettingsReactions() = DeviceSettingsReactionsContent()
|
||||
|
||||
@Preview(name = "8 - Reaction Settings", locale = "en", device = DS, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewReactionSettings() = ReactionSettingsContent()
|
||||
|
||||
@Preview(name = "9 - Homescreen Widget", device = DS, showSystemUi = true)
|
||||
@Preview(name = "8 - Homescreen Widget", device = DS, showSystemUi = true)
|
||||
@Composable
|
||||
private fun PreviewHomescreenWidget() = HomescreenWidgetContent()
|
||||
|
||||
@@ -23,6 +23,7 @@ import eu.darken.capod.pods.core.apple.ble.protocol.ProximityPayload
|
||||
import eu.darken.capod.pods.core.unknown.UnknownSnapshotBle
|
||||
import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
import eu.darken.capod.profiles.core.ReactionConfig
|
||||
import java.time.Instant
|
||||
|
||||
/** Fixed timestamp for deterministic preview/screenshot rendering. */
|
||||
@@ -64,6 +65,7 @@ object MockPodDataProvider {
|
||||
leftPodIcon = R.drawable.device_airpods_pro2_left,
|
||||
rightPodIcon = R.drawable.device_airpods_pro2_right,
|
||||
_caseIcon = R.drawable.device_airpods_pro2_case,
|
||||
_address = "AA:BB:CC:DD:EE:FF",
|
||||
)
|
||||
|
||||
fun airPodsProLowBattery(): DualBlePodSnapshot = MockDualBlePodSnapshot(
|
||||
@@ -120,6 +122,7 @@ object MockPodDataProvider {
|
||||
_label = "AirPods Max",
|
||||
batteryHeadsetPercent = 0.85f,
|
||||
_isBeingWorn = true,
|
||||
_address = "AA:BB:CC:DD:EE:FF",
|
||||
)
|
||||
|
||||
fun airPodsMaxCharging(): SingleBlePodSnapshot = MockSingleAppleBlePodSnapshot(
|
||||
@@ -206,6 +209,22 @@ object MockPodDataProvider {
|
||||
),
|
||||
)
|
||||
|
||||
/** Dual pods with a profile that has reaction toggles set — used for the Reactions screenshot. */
|
||||
fun dualPodMonitoredWithReactions(): PodDevice = PodDevice(
|
||||
profileId = "preview-dual-reactions",
|
||||
label = "My AirPods Pro",
|
||||
ble = airPodsProWithKeys(),
|
||||
aap = null,
|
||||
reactions = ReactionConfig(
|
||||
autoPause = true,
|
||||
autoPlay = true,
|
||||
onePodMode = false,
|
||||
autoConnect = true,
|
||||
showPopUpOnCaseOpen = true,
|
||||
showPopUpOnConnection = false,
|
||||
),
|
||||
)
|
||||
|
||||
fun singlePodMonitored(): PodDevice = PodDevice(
|
||||
profileId = "preview-single",
|
||||
ble = airPodsMax(),
|
||||
@@ -379,6 +398,7 @@ private class MockSingleBlePodSnapshot(
|
||||
override val batteryHeadsetPercent: Float?,
|
||||
private val _isHeadsetBeingCharged: Boolean = false,
|
||||
private val _isBeingWorn: Boolean = false,
|
||||
private val _address: String? = null,
|
||||
rssi: Int = -50,
|
||||
) : SingleBlePodSnapshot, HasChargeDetection, HasEarDetection {
|
||||
override val identifier: BlePodSnapshot.Id = BlePodSnapshot.Id()
|
||||
@@ -391,7 +411,7 @@ private class MockSingleBlePodSnapshot(
|
||||
override val signalQuality: Float = 0.80f
|
||||
override val iconRes: Int = _model.iconRes
|
||||
override val meta: BlePodSnapshot.Meta = object : BlePodSnapshot.Meta {
|
||||
override val profile: DeviceProfile = AppleDeviceProfile(label = _label, model = _model)
|
||||
override val profile: DeviceProfile = AppleDeviceProfile(label = _label, model = _model, address = _address)
|
||||
}
|
||||
|
||||
override fun getLabel(context: Context): String = _model.label
|
||||
|
||||
@@ -23,7 +23,7 @@ object Nav {
|
||||
data object Upgrade : Main
|
||||
|
||||
@Serializable
|
||||
data class DeviceSettings(val address: String) : Main
|
||||
data class DeviceSettings(val profileId: String) : Main
|
||||
|
||||
@Serializable
|
||||
data object StemActionConfig : Main
|
||||
@@ -36,9 +36,6 @@ object Nav {
|
||||
@Serializable
|
||||
data object General : Settings
|
||||
|
||||
@Serializable
|
||||
data object Reactions : Settings
|
||||
|
||||
@Serializable
|
||||
data object Debug : Settings
|
||||
|
||||
|
||||
@@ -6,10 +6,12 @@ import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.common.permissions.Permission
|
||||
import eu.darken.capod.common.permissions.isRequired
|
||||
import eu.darken.capod.reaction.core.ReactionSettings
|
||||
import eu.darken.capod.profiles.core.toReactionConfig
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesRepo
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import java.util.UUID
|
||||
@@ -20,7 +22,7 @@ import javax.inject.Singleton
|
||||
class PermissionTool @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val generalSettings: GeneralSettings,
|
||||
private val reactionSettings: ReactionSettings,
|
||||
private val profilesRepo: DeviceProfilesRepo,
|
||||
) {
|
||||
private val permissionCheckTrigger = MutableStateFlow(UUID.randomUUID())
|
||||
|
||||
@@ -29,12 +31,20 @@ class PermissionTool @Inject constructor(
|
||||
permissionCheckTrigger.value = UUID.randomUUID()
|
||||
}
|
||||
|
||||
private val anyPopupEnabled: Flow<Boolean> = profilesRepo.profiles
|
||||
.map { profiles ->
|
||||
profiles.any { profile ->
|
||||
profile.toReactionConfig().let { it.showPopUpOnCaseOpen || it.showPopUpOnConnection }
|
||||
}
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
|
||||
val missingPermissions: Flow<Set<Permission>> = combine(
|
||||
permissionCheckTrigger,
|
||||
generalSettings.monitorMode.flow,
|
||||
reactionSettings.showPopUpOnCaseOpen.flow
|
||||
anyPopupEnabled,
|
||||
) { _, monitorMode, showPopUp ->
|
||||
Permission.values()
|
||||
Permission.entries
|
||||
.filter { it != Permission.IGNORE_BATTERY_OPTIMIZATION || monitorMode == MonitorMode.ALWAYS }
|
||||
.filter { it != Permission.ACCESS_BACKGROUND_LOCATION || monitorMode == MonitorMode.ALWAYS }
|
||||
.filter { it != Permission.SYSTEM_ALERT_WINDOW || showPopUp }
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import javax.inject.Inject
|
||||
class DeviceSettingsNavigation @Inject constructor() : NavigationEntry {
|
||||
override fun EntryProviderScope<NavKey>.setup() {
|
||||
entry<Nav.Main.DeviceSettings> { key ->
|
||||
DeviceSettingsScreenHost(address = key.address)
|
||||
DeviceSettingsScreenHost(profileId = key.profileId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,21 +18,29 @@ import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.twotone.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.twotone.Message
|
||||
import androidx.compose.material.icons.automirrored.twotone.VolumeUp
|
||||
import androidx.compose.material.icons.twotone.BluetoothConnected
|
||||
import androidx.compose.material.icons.twotone.DevicesOther
|
||||
import androidx.compose.material.icons.twotone.Edit
|
||||
import androidx.compose.material.icons.twotone.GraphicEq
|
||||
import androidx.compose.material.icons.twotone.Headphones
|
||||
import androidx.compose.material.icons.twotone.Hearing
|
||||
import androidx.compose.material.icons.twotone.LooksOne
|
||||
import androidx.compose.material.icons.twotone.Loop
|
||||
import androidx.compose.material.icons.twotone.Mic
|
||||
import androidx.compose.material.icons.twotone.Nightlight
|
||||
import androidx.compose.material.icons.twotone.PauseCircle
|
||||
import androidx.compose.material.icons.twotone.PlayCircle
|
||||
import androidx.compose.material.icons.twotone.QuestionMark
|
||||
import androidx.compose.material.icons.twotone.Speed
|
||||
import androidx.compose.material.icons.twotone.Swipe
|
||||
import androidx.compose.material.icons.twotone.Timer
|
||||
import androidx.compose.material.icons.twotone.TouchApp
|
||||
import androidx.compose.material.icons.twotone.Visibility
|
||||
import androidx.compose.material.icons.twotone.VisibilityOff
|
||||
import androidx.compose.material.icons.twotone.Workspaces
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
@@ -48,7 +56,9 @@ import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -86,17 +96,18 @@ import eu.darken.capod.pods.core.apple.aap.AapPodState
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapDeviceInfo
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapSetting
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasStateDetection
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
import java.time.Duration
|
||||
|
||||
@Composable
|
||||
fun DeviceSettingsScreenHost(
|
||||
address: String,
|
||||
profileId: String,
|
||||
vm: DeviceSettingsViewModel = hiltViewModel(),
|
||||
) {
|
||||
ErrorEventHandler(vm)
|
||||
NavigationEventHandler(vm)
|
||||
|
||||
LaunchedEffect(address) { vm.initialize(address) }
|
||||
LaunchedEffect(profileId) { vm.initialize(profileId) }
|
||||
|
||||
val context = LocalContext.current
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
@@ -140,7 +151,6 @@ fun DeviceSettingsScreenHost(
|
||||
onVolumeSwipeLengthChange = { vm.setVolumeSwipeLength(it) },
|
||||
onEndCallMuteMicChange = { muteMic, endCall -> vm.setEndCallMuteMic(muteMic, endCall) },
|
||||
onMicrophoneModeChange = { vm.setMicrophoneMode(it) },
|
||||
onEarDetectionEnabledChange = { vm.setEarDetectionEnabled(it) },
|
||||
onListeningModeCycleChange = { vm.setListeningModeCycle(it) },
|
||||
onAllowOffOptionChange = { vm.setAllowOffOption(it) },
|
||||
onSleepDetectionChange = { vm.setSleepDetection(it) },
|
||||
@@ -148,6 +158,13 @@ fun DeviceSettingsScreenHost(
|
||||
onStemActionsClick = { vm.navToStemConfig() },
|
||||
onForceConnect = { vm.forceConnect() },
|
||||
onUpgrade = { vm.launchUpgrade() },
|
||||
onOnePodModeChange = { vm.setOnePodMode(it) },
|
||||
onAutoPlayChange = { vm.setAutoPlay(it) },
|
||||
onAutoPauseChange = { vm.setAutoPause(it) },
|
||||
onAutoConnectChange = { vm.setAutoConnect(it) },
|
||||
onAutoConnectConditionChange = { vm.setAutoConnectCondition(it) },
|
||||
onShowPopUpOnCaseOpenChange = { vm.setShowPopUpOnCaseOpen(it) },
|
||||
onShowPopUpOnConnectionChange = { vm.setShowPopUpOnConnection(it) },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -169,7 +186,6 @@ fun DeviceSettingsScreen(
|
||||
onVolumeSwipeLengthChange: (AapSetting.VolumeSwipeLength.Value) -> Unit = {},
|
||||
onEndCallMuteMicChange: (AapSetting.EndCallMuteMic.MuteMicMode, AapSetting.EndCallMuteMic.EndCallMode) -> Unit = { _, _ -> },
|
||||
onMicrophoneModeChange: (AapSetting.MicrophoneMode.Mode) -> Unit = {},
|
||||
onEarDetectionEnabledChange: (Boolean) -> Unit = {},
|
||||
onListeningModeCycleChange: (Int) -> Unit = {},
|
||||
onAllowOffOptionChange: (Boolean) -> Unit = {},
|
||||
onSleepDetectionChange: (Boolean) -> Unit = {},
|
||||
@@ -177,11 +193,21 @@ fun DeviceSettingsScreen(
|
||||
onStemActionsClick: () -> Unit = {},
|
||||
onForceConnect: () -> Unit = {},
|
||||
onUpgrade: () -> Unit = {},
|
||||
onOnePodModeChange: (Boolean) -> Unit = {},
|
||||
onAutoPlayChange: (Boolean) -> Unit = {},
|
||||
onAutoPauseChange: (Boolean) -> Unit = {},
|
||||
onAutoConnectChange: (Boolean) -> Unit = {},
|
||||
onAutoConnectConditionChange: (AutoConnectCondition) -> Unit = {},
|
||||
onShowPopUpOnCaseOpenChange: (Boolean) -> Unit = {},
|
||||
onShowPopUpOnConnectionChange: (Boolean) -> Unit = {},
|
||||
) {
|
||||
val device = state.device
|
||||
val features = device?.model?.features
|
||||
val enabled = device?.isAapReady == true
|
||||
val isPro = state.isPro
|
||||
val reactions = state.reactions
|
||||
|
||||
var showAutoConnectConditionDialog by remember { mutableStateOf(false) }
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
@@ -254,6 +280,105 @@ fun DeviceSettingsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
// ── Reactions (per-profile, not gated on AAP) ─────────────────
|
||||
if (device != null && features != null) {
|
||||
item("reactions_header") {
|
||||
SettingsCategoryHeader(text = stringResource(R.string.settings_reaction_label))
|
||||
}
|
||||
|
||||
if (features.hasEarDetection) {
|
||||
item("reaction_auto_play") {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.TwoTone.PlayCircle,
|
||||
title = stringResource(R.string.settings_autopplay_label),
|
||||
subtitle = stringResource(R.string.settings_autoplay_description),
|
||||
checked = reactions.autoPlay,
|
||||
onCheckedChange = onAutoPlayChange,
|
||||
requiresUpgrade = !isPro,
|
||||
)
|
||||
}
|
||||
item("reaction_auto_pause") {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.TwoTone.PauseCircle,
|
||||
title = stringResource(R.string.settings_autopause_label),
|
||||
subtitle = stringResource(R.string.settings_autopause_description),
|
||||
checked = reactions.autoPause,
|
||||
onCheckedChange = onAutoPauseChange,
|
||||
requiresUpgrade = !isPro,
|
||||
)
|
||||
}
|
||||
if (features.hasDualPods) {
|
||||
val earDetectionActive = reactions.autoPlay || reactions.autoPause
|
||||
item("reaction_one_pod_mode") {
|
||||
SettingsBaseItem(
|
||||
title = stringResource(R.string.settings_onepod_mode_label),
|
||||
subtitle = stringResource(R.string.settings_onepod_mode_description),
|
||||
icon = Icons.TwoTone.LooksOne,
|
||||
onClick = { if (earDetectionActive) onOnePodModeChange(!reactions.onePodMode) },
|
||||
enabled = earDetectionActive,
|
||||
trailingContent = {
|
||||
Switch(
|
||||
checked = reactions.onePodMode,
|
||||
onCheckedChange = onOnePodModeChange,
|
||||
enabled = earDetectionActive,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
item("reaction_ear_detection_info") {
|
||||
SettingsBaseItem(
|
||||
title = stringResource(R.string.settings_eardetection_info_label),
|
||||
subtitle = stringResource(R.string.settings_eardetection_info_description),
|
||||
icon = Icons.TwoTone.QuestionMark,
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
item("reaction_auto_connect") {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.TwoTone.BluetoothConnected,
|
||||
title = stringResource(R.string.settings_autoconnect_label),
|
||||
subtitle = stringResource(R.string.settings_autoconnect_description),
|
||||
checked = reactions.autoConnect,
|
||||
onCheckedChange = onAutoConnectChange,
|
||||
)
|
||||
}
|
||||
item("reaction_auto_connect_condition") {
|
||||
SettingsBaseItem(
|
||||
title = stringResource(R.string.settings_autoconnect_condition_label),
|
||||
subtitle = stringResource(reactions.autoConnectCondition.labelRes),
|
||||
icon = Icons.TwoTone.Workspaces,
|
||||
onClick = { if (reactions.autoConnect) showAutoConnectConditionDialog = true },
|
||||
enabled = reactions.autoConnect,
|
||||
)
|
||||
}
|
||||
if (features.hasCase) {
|
||||
item("reaction_popup_caseopen") {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.AutoMirrored.TwoTone.Message,
|
||||
title = stringResource(R.string.settings_popup_caseopen_label),
|
||||
subtitle = stringResource(R.string.settings_popup_caseopen_description),
|
||||
checked = reactions.showPopUpOnCaseOpen,
|
||||
onCheckedChange = onShowPopUpOnCaseOpenChange,
|
||||
requiresUpgrade = !isPro,
|
||||
)
|
||||
}
|
||||
}
|
||||
item("reaction_popup_connection") {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.AutoMirrored.TwoTone.Message,
|
||||
title = stringResource(R.string.settings_popup_connected_label),
|
||||
subtitle = stringResource(R.string.settings_popup_connected_description),
|
||||
checked = reactions.showPopUpOnConnection,
|
||||
onCheckedChange = onShowPopUpOnConnectionChange,
|
||||
requiresUpgrade = !isPro,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Settings — only show when AAP is connected
|
||||
if (features != null && device.isAapConnected) {
|
||||
|
||||
@@ -490,21 +615,6 @@ fun DeviceSettingsScreen(
|
||||
SettingsCategoryHeader(text = stringResource(R.string.device_settings_category_general_label))
|
||||
}
|
||||
|
||||
if (features.hasEarDetectionToggle) {
|
||||
val earDetection = device.earDetectionEnabled
|
||||
?: AapSetting.EarDetectionEnabled(enabled = true)
|
||||
item("ear_detection_toggle") {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.TwoTone.Hearing,
|
||||
title = stringResource(R.string.device_settings_ear_detection_label),
|
||||
subtitle = stringResource(R.string.device_settings_ear_detection_description),
|
||||
checked = earDetection.enabled,
|
||||
onCheckedChange = onEarDetectionEnabledChange,
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (features.hasSleepDetection) {
|
||||
val sleepDet = device.sleepDetection
|
||||
?: AapSetting.SleepDetection(enabled = true)
|
||||
@@ -554,9 +664,73 @@ fun DeviceSettingsScreen(
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
|
||||
if (showAutoConnectConditionDialog && device != null) {
|
||||
AutoConnectConditionDialog(
|
||||
current = reactions.autoConnectCondition,
|
||||
hasEarDetection = features?.hasEarDetection == true,
|
||||
hasCase = features?.hasCase == true,
|
||||
onSelect = {
|
||||
onAutoConnectConditionChange(it)
|
||||
showAutoConnectConditionDialog = false
|
||||
},
|
||||
onDismiss = { showAutoConnectConditionDialog = false },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AutoConnectConditionDialog(
|
||||
current: AutoConnectCondition,
|
||||
hasEarDetection: Boolean,
|
||||
hasCase: Boolean,
|
||||
onSelect: (AutoConnectCondition) -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
val options = AutoConnectCondition.entries.filter { condition ->
|
||||
when (condition) {
|
||||
AutoConnectCondition.IN_EAR -> hasEarDetection
|
||||
AutoConnectCondition.CASE_OPEN -> hasCase
|
||||
AutoConnectCondition.WHEN_SEEN -> true
|
||||
}
|
||||
}
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = { Text(text = stringResource(R.string.settings_autoconnect_condition_label)) },
|
||||
text = {
|
||||
Column(Modifier.selectableGroup()) {
|
||||
options.forEach { condition ->
|
||||
val isSelected = condition == current
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.selectable(
|
||||
selected = isSelected,
|
||||
onClick = { onSelect(condition) },
|
||||
role = Role.RadioButton,
|
||||
)
|
||||
.padding(vertical = 12.dp, horizontal = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
RadioButton(selected = isSelected, onClick = null)
|
||||
Text(
|
||||
text = stringResource(condition.labelRes),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = onDismiss) {
|
||||
Text(text = stringResource(android.R.string.cancel))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DeviceInfoCard(
|
||||
deviceInfo: AapDeviceInfo?,
|
||||
|
||||
+102
-23
@@ -1,14 +1,16 @@
|
||||
package eu.darken.capod.main.ui.devicesettings
|
||||
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import eu.darken.capod.common.bluetooth.BluetoothAddress
|
||||
import eu.darken.capod.common.bluetooth.BluetoothManager2
|
||||
import eu.darken.capod.common.coroutine.DispatcherProvider
|
||||
import eu.darken.capod.common.datastore.value
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.WARN
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.common.flow.SingleEventFlow
|
||||
import eu.darken.capod.common.uix.ViewModel4
|
||||
import eu.darken.capod.main.core.GeneralSettings
|
||||
import eu.darken.capod.main.core.MonitorMode
|
||||
import eu.darken.capod.monitor.core.DeviceMonitor
|
||||
import eu.darken.capod.monitor.core.PodDevice
|
||||
import eu.darken.capod.common.navigation.Nav
|
||||
@@ -17,12 +19,18 @@ import eu.darken.capod.common.upgrade.isPro
|
||||
import eu.darken.capod.pods.core.apple.aap.AapConnectionManager
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapCommand
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapSetting
|
||||
import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesRepo
|
||||
import eu.darken.capod.profiles.core.ReactionConfig
|
||||
import eu.darken.capod.profiles.core.ProfileId
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.isActive
|
||||
import java.time.Instant
|
||||
@@ -35,15 +43,17 @@ class DeviceSettingsViewModel @Inject constructor(
|
||||
private val aapManager: AapConnectionManager,
|
||||
private val upgradeRepo: UpgradeRepo,
|
||||
private val bluetoothManager: BluetoothManager2,
|
||||
private val profilesRepo: DeviceProfilesRepo,
|
||||
private val generalSettings: GeneralSettings,
|
||||
) : ViewModel4(dispatcherProvider) {
|
||||
|
||||
private val targetAddress = MutableStateFlow<BluetoothAddress?>(null)
|
||||
private val targetProfileId = MutableStateFlow<ProfileId?>(null)
|
||||
private var initialized = false
|
||||
|
||||
fun initialize(address: BluetoothAddress) {
|
||||
if (initialized && targetAddress.value == address) return
|
||||
fun initialize(profileId: ProfileId) {
|
||||
if (initialized && targetProfileId.value == profileId) return
|
||||
initialized = true
|
||||
targetAddress.value = address
|
||||
targetProfileId.value = profileId
|
||||
}
|
||||
|
||||
private val updateTicker = channelFlow<Unit> {
|
||||
@@ -63,16 +73,16 @@ class DeviceSettingsViewModel @Inject constructor(
|
||||
|
||||
val events = SingleEventFlow<Event>()
|
||||
|
||||
val state = targetAddress.flatMapLatest { address ->
|
||||
if (address == null) return@flatMapLatest flowOf(State(device = null))
|
||||
val state = targetProfileId.flatMapLatest { profileId ->
|
||||
if (profileId == null) return@flatMapLatest flowOf(State(device = null))
|
||||
combine(
|
||||
updateTicker,
|
||||
deviceMonitor.devices,
|
||||
deviceForProfile(profileId),
|
||||
upgradeRepo.upgradeInfo,
|
||||
isForceConnecting,
|
||||
) { _, devices, upgrade, forcing ->
|
||||
) { _, device, upgrade, forcing ->
|
||||
State(
|
||||
device = devices.firstOrNull { it.address == address },
|
||||
device = device,
|
||||
now = Instant.now(),
|
||||
isPro = upgrade.isPro,
|
||||
isNudgeAvailable = bluetoothManager.isNudgeAvailable,
|
||||
@@ -81,13 +91,31 @@ class DeviceSettingsViewModel @Inject constructor(
|
||||
}
|
||||
}.asLiveState()
|
||||
|
||||
/**
|
||||
* Returns the [PodDevice] for [profileId] reactively. Falls back to a synthesized bare
|
||||
* device when the profile exists but isn't currently visible (no BLE / cache / AAP),
|
||||
* so the Reactions section can still be edited for pristine profiles.
|
||||
*/
|
||||
private fun deviceForProfile(profileId: ProfileId): kotlinx.coroutines.flow.Flow<PodDevice?> =
|
||||
deviceMonitor.devices.flatMapLatest { devices ->
|
||||
val live = devices.firstOrNull { it.profileId == profileId }
|
||||
flow<PodDevice?> { emit(live ?: deviceMonitor.getDeviceForProfile(profileId)) }
|
||||
}
|
||||
|
||||
data class State(
|
||||
val device: PodDevice?,
|
||||
val now: Instant = Instant.now(),
|
||||
val isPro: Boolean = false,
|
||||
val isNudgeAvailable: Boolean = true,
|
||||
val isForceConnecting: Boolean = false,
|
||||
)
|
||||
) {
|
||||
val reactions: ReactionConfig get() = device?.reactions ?: ReactionConfig()
|
||||
}
|
||||
|
||||
private suspend fun currentAddress(): String? {
|
||||
val profileId = targetProfileId.value ?: return null
|
||||
return deviceMonitor.getDeviceForProfile(profileId)?.address
|
||||
}
|
||||
|
||||
fun forceConnect() = launch {
|
||||
if (!isForceConnecting.compareAndSet(expect = false, update = true)) {
|
||||
@@ -95,7 +123,7 @@ class DeviceSettingsViewModel @Inject constructor(
|
||||
return@launch
|
||||
}
|
||||
try {
|
||||
val address = targetAddress.value ?: run {
|
||||
val address = currentAddress() ?: run {
|
||||
events.tryEmit(Event.OpenBluetoothSettings)
|
||||
return@launch
|
||||
}
|
||||
@@ -124,23 +152,18 @@ class DeviceSettingsViewModel @Inject constructor(
|
||||
if (!accepted) {
|
||||
events.tryEmit(Event.OpenBluetoothSettings)
|
||||
}
|
||||
// On accepted=true, AapAutoConnect.initialConnect() will pick up the new
|
||||
// connectedDevices entry and trigger the AAP handshake. The card disappears
|
||||
// when device.isAapConnected becomes true.
|
||||
} finally {
|
||||
isForceConnecting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun sendInternal(command: AapCommand) {
|
||||
val address = targetAddress.value ?: return
|
||||
val address = currentAddress() ?: return
|
||||
try {
|
||||
aapManager.sendCommand(address, command)
|
||||
log(TAG) { "Sent $command to $address" }
|
||||
} catch (e: Exception) {
|
||||
log(TAG, WARN) { "Failed to send $command: ${e.message}" }
|
||||
// SingleEventFlow is backed by a BUFFERED Channel — use the suspending emit to avoid
|
||||
// dropping the event under momentary backpressure.
|
||||
events.emit(Event.SendFailed(command, e.message))
|
||||
}
|
||||
}
|
||||
@@ -193,12 +216,15 @@ class DeviceSettingsViewModel @Inject constructor(
|
||||
fun setSleepDetection(enabled: Boolean) = sendProGated(AapCommand.SetSleepDetection(enabled))
|
||||
|
||||
fun setDeviceName(name: String) = launch {
|
||||
val address = targetAddress.value ?: return@launch
|
||||
sendInternal(AapCommand.SetDeviceName(name))
|
||||
val address = currentAddress() ?: return@launch
|
||||
try {
|
||||
aapManager.sendCommand(address, AapCommand.SetDeviceName(name))
|
||||
log(TAG) { "Sent SetDeviceName to $address" }
|
||||
} catch (e: Exception) {
|
||||
log(TAG, WARN) { "Failed to send SetDeviceName: ${e.message}" }
|
||||
events.emit(Event.SendFailed(AapCommand.SetDeviceName(name), e.message))
|
||||
}
|
||||
|
||||
// Also try to update the Android-local bond alias so the new name shows in Android's
|
||||
// Bluetooth settings too. The AAP rename only changes what the AirPods themselves report;
|
||||
// Android's system display reads from the bond database and needs a separate update.
|
||||
val bonded = try {
|
||||
bluetoothManager.bondedDevices().first().firstOrNull { it.address == address }
|
||||
} catch (e: Exception) {
|
||||
@@ -212,6 +238,59 @@ class DeviceSettingsViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
// ── Reaction toggles (per-profile) ───────────────────────────────────────
|
||||
|
||||
private suspend fun updateProfileNow(transform: (AppleDeviceProfile) -> AppleDeviceProfile) {
|
||||
val profileId = targetProfileId.value ?: return
|
||||
try {
|
||||
profilesRepo.updateAppleProfile(profileId, transform)
|
||||
} catch (e: Exception) {
|
||||
log(TAG, WARN) { "Failed to update profile $profileId: ${e.message}" }
|
||||
errorEvents.emit(e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun proGatedReaction(
|
||||
enabled: Boolean,
|
||||
transform: (AppleDeviceProfile) -> AppleDeviceProfile,
|
||||
) = launch {
|
||||
// Disabling never requires pro; enabling does.
|
||||
if (enabled && !upgradeRepo.isPro()) {
|
||||
navTo(Nav.Main.Upgrade)
|
||||
return@launch
|
||||
}
|
||||
updateProfileNow(transform)
|
||||
}
|
||||
|
||||
fun setOnePodMode(enabled: Boolean) = launch { updateProfileNow { it.copy(onePodMode = enabled) } }
|
||||
|
||||
fun setAutoPlay(enabled: Boolean) = proGatedReaction(enabled) { it.copy(autoPlay = enabled) }
|
||||
|
||||
fun setAutoPause(enabled: Boolean) = proGatedReaction(enabled) { it.copy(autoPause = enabled) }
|
||||
|
||||
fun setAutoConnect(enabled: Boolean) = launch {
|
||||
updateProfileNow { it.copy(autoConnect = enabled) }
|
||||
if (enabled) {
|
||||
// Auto-connect requires ALWAYS mode to react to BLE/case/ear events when
|
||||
// nothing is connected. We intentionally do NOT revert on disable — the user
|
||||
// may have set ALWAYS manually, or another profile may still need it.
|
||||
if (generalSettings.monitorMode.value() != MonitorMode.ALWAYS) {
|
||||
log(TAG) { "Forcing monitorMode to ALWAYS because autoConnect was enabled" }
|
||||
generalSettings.monitorMode.value(MonitorMode.ALWAYS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setAutoConnectCondition(condition: AutoConnectCondition) = launch {
|
||||
updateProfileNow { it.copy(autoConnectCondition = condition) }
|
||||
}
|
||||
|
||||
fun setShowPopUpOnCaseOpen(enabled: Boolean) =
|
||||
proGatedReaction(enabled) { it.copy(showPopUpOnCaseOpen = enabled) }
|
||||
|
||||
fun setShowPopUpOnConnection(enabled: Boolean) =
|
||||
proGatedReaction(enabled) { it.copy(showPopUpOnConnection = enabled) }
|
||||
|
||||
fun navToStemConfig() = launch {
|
||||
if (upgradeRepo.isPro()) {
|
||||
navTo(Nav.Main.StemActionConfig)
|
||||
|
||||
@@ -154,8 +154,8 @@ class OverviewViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun goToDeviceSettings(device: PodDevice) {
|
||||
val address = device.address ?: return
|
||||
navTo(Nav.Main.DeviceSettings(address))
|
||||
val profileId = device.profileId ?: return
|
||||
navTo(Nav.Main.DeviceSettings(profileId))
|
||||
}
|
||||
|
||||
fun goToEditProfile(device: PodDevice) {
|
||||
|
||||
@@ -141,7 +141,7 @@ fun DualPodsCard(
|
||||
}
|
||||
}
|
||||
|
||||
if (device.address != null && onDeviceSettings != null) {
|
||||
if (device.profileId != null && onDeviceSettings != null) {
|
||||
IconButton(onClick = onDeviceSettings) {
|
||||
Icon(
|
||||
imageVector = Icons.TwoTone.Tune,
|
||||
@@ -149,7 +149,8 @@ fun DualPodsCard(
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
} else if (device.profileId != null && device.address == null && onEditProfile != null) {
|
||||
}
|
||||
if (device.profileId != null && device.address == null && onEditProfile != null) {
|
||||
IconButton(onClick = onEditProfile) {
|
||||
Icon(
|
||||
imageVector = Icons.TwoTone.Warning,
|
||||
|
||||
@@ -140,7 +140,7 @@ fun SinglePodsCard(
|
||||
}
|
||||
}
|
||||
|
||||
if (device.address != null && onDeviceSettings != null) {
|
||||
if (device.profileId != null && onDeviceSettings != null) {
|
||||
IconButton(onClick = onDeviceSettings) {
|
||||
Icon(
|
||||
imageVector = Icons.TwoTone.Tune,
|
||||
@@ -148,7 +148,8 @@ fun SinglePodsCard(
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
} else if (device.profileId != null && device.address == null && onEditProfile != null) {
|
||||
}
|
||||
if (device.profileId != null && device.address == null && onEditProfile != null) {
|
||||
IconButton(onClick = onEditProfile) {
|
||||
Icon(
|
||||
imageVector = Icons.TwoTone.Warning,
|
||||
|
||||
@@ -11,7 +11,6 @@ import androidx.compose.material.icons.twotone.Favorite
|
||||
import androidx.compose.material.icons.twotone.Settings
|
||||
import androidx.compose.material.icons.twotone.SupportAgent
|
||||
import androidx.compose.material.icons.twotone.Translate
|
||||
import androidx.compose.material.icons.twotone.Widgets
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
@@ -47,7 +46,6 @@ fun SettingsScreenHost(vm: SettingsViewModel = hiltViewModel()) {
|
||||
onNavigateUp = { vm.navUp() },
|
||||
onGeneralSettings = { vm.navTo(Nav.Settings.General) },
|
||||
onDeviceManager = { vm.navTo(Nav.Main.DeviceManager) },
|
||||
onReactions = { vm.navTo(Nav.Settings.Reactions) },
|
||||
onSupport = { vm.navTo(Nav.Settings.Support) },
|
||||
onWiki = { vm.openUrl("https://github.com/d4rken-org/capod/wiki") },
|
||||
onChangelog = { vm.openUrl("https://capod.darken.eu/changelog") },
|
||||
@@ -65,7 +63,6 @@ fun SettingsScreen(
|
||||
onNavigateUp: () -> Unit,
|
||||
onGeneralSettings: () -> Unit,
|
||||
onDeviceManager: () -> Unit,
|
||||
onReactions: () -> Unit,
|
||||
onSupport: () -> Unit,
|
||||
onWiki: () -> Unit,
|
||||
onChangelog: () -> Unit,
|
||||
@@ -121,14 +118,6 @@ fun SettingsScreen(
|
||||
onClick = onDeviceManager,
|
||||
)
|
||||
}
|
||||
item {
|
||||
SettingsBaseItem(
|
||||
title = stringResource(R.string.settings_reaction_label),
|
||||
subtitle = stringResource(R.string.settings_reaction_description),
|
||||
icon = Icons.TwoTone.Widgets,
|
||||
onClick = onReactions,
|
||||
)
|
||||
}
|
||||
item {
|
||||
SettingsCategoryHeader(text = stringResource(R.string.settings_category_other_label))
|
||||
}
|
||||
@@ -192,7 +181,6 @@ private fun SettingsScreenPreview() = PreviewWrapper {
|
||||
onNavigateUp = {},
|
||||
onGeneralSettings = {},
|
||||
onDeviceManager = {},
|
||||
onReactions = {},
|
||||
onSupport = {},
|
||||
onWiki = {},
|
||||
onChangelog = {},
|
||||
|
||||
@@ -15,6 +15,7 @@ import eu.darken.capod.pods.core.apple.aap.AapConnectionManager
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.ApplePods
|
||||
import eu.darken.capod.pods.core.apple.aap.AapPodState
|
||||
import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import eu.darken.capod.profiles.core.toReactionConfig
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesRepo
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -64,6 +65,7 @@ class DeviceMonitor @Inject constructor(
|
||||
profileAddress = profile?.address,
|
||||
profileModel = profile?.model,
|
||||
profileKeyState = profile.toBleKeyState(),
|
||||
reactions = profile.toReactionConfig(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -114,6 +116,7 @@ class DeviceMonitor @Inject constructor(
|
||||
profileAddress = profile.address,
|
||||
profileModel = profile.model,
|
||||
profileKeyState = profile.toBleKeyState(),
|
||||
reactions = profile.toReactionConfig(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -167,24 +170,26 @@ class DeviceMonitor @Inject constructor(
|
||||
}
|
||||
|
||||
val profile = profilesRepo.profiles.firstOrNull()?.firstOrNull { it.id == profileId }
|
||||
val cached = deviceStateCache.load(profileId)
|
||||
val aap = profile?.let { aapManager.allStates.value.forProfile(it) }
|
||||
|
||||
if (cached == null && aap == null) {
|
||||
log(TAG) { "No device found for profile $profileId" }
|
||||
if (profile == null) {
|
||||
log(TAG) { "No profile with id $profileId" }
|
||||
return null
|
||||
}
|
||||
val cached = deviceStateCache.load(profileId)
|
||||
val aap = aapManager.allStates.value.forProfile(profile)
|
||||
|
||||
log(TAG) { "Found fallback device for profile $profileId (cached=${cached != null}, aap=${aap != null})" }
|
||||
log(TAG) {
|
||||
"Synthesizing device for profile $profileId (cached=${cached != null}, aap=${aap != null})"
|
||||
}
|
||||
return PodDevice(
|
||||
profileId = profileId,
|
||||
label = profile?.label,
|
||||
label = profile.label,
|
||||
ble = null,
|
||||
aap = aap,
|
||||
cached = cached,
|
||||
profileAddress = profile?.address,
|
||||
profileModel = profile?.model,
|
||||
profileAddress = profile.address,
|
||||
profileModel = profile.model,
|
||||
profileKeyState = profile.toBleKeyState(),
|
||||
reactions = profile.toReactionConfig(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import eu.darken.capod.pods.core.apple.ble.devices.HasChargeDetectionDual
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasDualMicrophone
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasEarDetection
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasEarDetectionDual
|
||||
import eu.darken.capod.profiles.core.ReactionConfig
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
|
||||
@@ -45,6 +46,8 @@ data class PodDevice(
|
||||
* every time the BLE scanner misses the next advertisement batch.
|
||||
*/
|
||||
internal val profileKeyState: BleKeyState = BleKeyState.NONE,
|
||||
/** Reaction toggle snapshot from the profile. Defaults to all-off when no profile is matched. */
|
||||
val reactions: ReactionConfig = ReactionConfig(),
|
||||
) {
|
||||
val model: PodModel get() = ble?.model ?: profileModel ?: cached?.model ?: PodModel.UNKNOWN
|
||||
/** Bonded BR/EDR address (from profile). Used for AAP commands. */
|
||||
|
||||
@@ -4,6 +4,7 @@ import eu.darken.capod.common.serialization.ByteArrayBase64Serializer
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.protocol.IdentityResolvingKey
|
||||
import eu.darken.capod.pods.core.apple.ble.protocol.ProximityEncryptionKey
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -21,4 +22,23 @@ data class AppleDeviceProfile(
|
||||
@SerialName("identityKey") @Serializable(with = ByteArrayBase64Serializer::class) val identityKey: IdentityResolvingKey? = null,
|
||||
@SerialName("encryptionKey") @Serializable(with = ByteArrayBase64Serializer::class) val encryptionKey: ProximityEncryptionKey? = null,
|
||||
@SerialName("address") override val address: String? = null,
|
||||
) : DeviceProfile
|
||||
@SerialName("reactionAutoPause") val autoPause: Boolean = false,
|
||||
@SerialName("reactionAutoPlay") val autoPlay: Boolean = false,
|
||||
@SerialName("reactionOnePodMode") val onePodMode: Boolean = false,
|
||||
@SerialName("reactionAutoConnect") val autoConnect: Boolean = false,
|
||||
@SerialName("reactionAutoConnectCondition") val autoConnectCondition: AutoConnectCondition = AutoConnectCondition.WHEN_SEEN,
|
||||
@SerialName("reactionShowPopUpOnCaseOpen") val showPopUpOnCaseOpen: Boolean = false,
|
||||
@SerialName("reactionShowPopUpOnConnection") val showPopUpOnConnection: Boolean = false,
|
||||
) : DeviceProfile, HasReactionConfig {
|
||||
|
||||
override val reactionConfig: ReactionConfig
|
||||
get() = ReactionConfig(
|
||||
autoPause = autoPause,
|
||||
autoPlay = autoPlay,
|
||||
onePodMode = onePodMode,
|
||||
autoConnect = autoConnect,
|
||||
autoConnectCondition = autoConnectCondition,
|
||||
showPopUpOnCaseOpen = showPopUpOnCaseOpen,
|
||||
showPopUpOnConnection = showPopUpOnConnection,
|
||||
)
|
||||
}
|
||||
@@ -6,10 +6,14 @@ import eu.darken.capod.R
|
||||
import eu.darken.capod.common.coroutine.AppScope
|
||||
import eu.darken.capod.common.datastore.valueBlocking
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.WARN
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.common.serialization.SerializationCapod
|
||||
import eu.darken.capod.main.core.GeneralSettings
|
||||
import eu.darken.capod.monitor.core.cache.DeviceStateCache
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
@@ -26,37 +30,80 @@ class DeviceProfilesRepo @Inject constructor(
|
||||
private val generalSettings: GeneralSettings,
|
||||
private val settings: DeviceProfilesSettings,
|
||||
private val deviceStateCache: DeviceStateCache,
|
||||
@SerializationCapod private val json: Json,
|
||||
) {
|
||||
|
||||
private val mutex = Mutex()
|
||||
|
||||
init {
|
||||
scope.launch {
|
||||
if (settings.defaultProfileCreated.valueBlocking) return@launch
|
||||
|
||||
|
||||
log(TAG) { "Creating default profile" }
|
||||
var defaultProfile = AppleDeviceProfile(
|
||||
label = context.getString(R.string.profiles_name_default),
|
||||
)
|
||||
if (!settings.singleToMultiMigrationDone.valueBlocking) {
|
||||
log(TAG) { "Migrating settings default profile" }
|
||||
defaultProfile = defaultProfile.copy(
|
||||
minimumSignalQuality = generalSettings.oldMinimumSignalQuality.valueBlocking,
|
||||
model = generalSettings.oldMainDeviceModel.valueBlocking,
|
||||
address = generalSettings.oldMainDeviceAddress.valueBlocking,
|
||||
identityKey = generalSettings.oldMainDeviceIdentityKey.valueBlocking,
|
||||
encryptionKey = generalSettings.oldMainDeviceEncryptionKey.valueBlocking,
|
||||
if (!settings.defaultProfileCreated.valueBlocking) {
|
||||
log(TAG) { "Creating default profile" }
|
||||
var defaultProfile = AppleDeviceProfile(
|
||||
label = context.getString(R.string.profiles_name_default),
|
||||
)
|
||||
settings.singleToMultiMigrationDone.valueBlocking = true
|
||||
if (!settings.singleToMultiMigrationDone.valueBlocking) {
|
||||
log(TAG) { "Migrating settings default profile" }
|
||||
defaultProfile = defaultProfile.copy(
|
||||
minimumSignalQuality = generalSettings.oldMinimumSignalQuality.valueBlocking,
|
||||
model = generalSettings.oldMainDeviceModel.valueBlocking,
|
||||
address = generalSettings.oldMainDeviceAddress.valueBlocking,
|
||||
identityKey = generalSettings.oldMainDeviceIdentityKey.valueBlocking,
|
||||
encryptionKey = generalSettings.oldMainDeviceEncryptionKey.valueBlocking,
|
||||
)
|
||||
settings.singleToMultiMigrationDone.valueBlocking = true
|
||||
}
|
||||
|
||||
log(TAG) { "Default profile: $defaultProfile" }
|
||||
addProfile(defaultProfile)
|
||||
settings.defaultProfileCreated.valueBlocking = true
|
||||
}
|
||||
|
||||
log(TAG) { "Default profile: $defaultProfile" }
|
||||
addProfile(defaultProfile)
|
||||
settings.defaultProfileCreated.valueBlocking = true
|
||||
// Reaction migration runs INDEPENDENTLY of defaultProfileCreated. Existing
|
||||
// installs already have defaultProfileCreated=true, so nesting this inside the
|
||||
// block above would silently swallow the migration on upgrade.
|
||||
if (!settings.reactionMigrationDone.valueBlocking) {
|
||||
migrateLegacyReactions()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun migrateLegacyReactions() {
|
||||
log(TAG) { "Migrating legacy global reaction settings onto profiles" }
|
||||
mutex.withLock {
|
||||
val legacy = try {
|
||||
LegacyReactionSettingsReader(context, json).read()
|
||||
} catch (e: Exception) {
|
||||
log(TAG, WARN) { "Failed to read legacy reactions, defaulting all profiles: ${e.message}" }
|
||||
null
|
||||
}
|
||||
val current = settings.profiles.valueBlocking.profiles
|
||||
val migrated = current.map { p ->
|
||||
if (p !is AppleDeviceProfile || legacy == null) return@map p
|
||||
val features = p.model.features
|
||||
val coercedCondition = when {
|
||||
legacy.autoConnectCondition == AutoConnectCondition.IN_EAR && !features.hasEarDetection ->
|
||||
AutoConnectCondition.WHEN_SEEN
|
||||
legacy.autoConnectCondition == AutoConnectCondition.CASE_OPEN && !features.hasCase ->
|
||||
AutoConnectCondition.WHEN_SEEN
|
||||
else -> legacy.autoConnectCondition
|
||||
}
|
||||
p.copy(
|
||||
autoPause = legacy.autoPause,
|
||||
autoPlay = legacy.autoPlay,
|
||||
onePodMode = legacy.onePodMode && features.hasDualPods && features.hasEarDetection,
|
||||
autoConnect = legacy.autoConnect,
|
||||
autoConnectCondition = coercedCondition,
|
||||
showPopUpOnCaseOpen = legacy.showPopUpOnCaseOpen,
|
||||
showPopUpOnConnection = legacy.showPopUpOnConnection,
|
||||
)
|
||||
}
|
||||
settings.profiles.valueBlocking = DeviceProfilesContainer(migrated)
|
||||
settings.reactionMigrationDone.valueBlocking = true
|
||||
}
|
||||
log(TAG) { "Legacy reaction migration complete" }
|
||||
}
|
||||
|
||||
val profiles: Flow<List<DeviceProfile>> = settings.profiles.flow.map { it.profiles }
|
||||
|
||||
suspend fun addProfile(profile: DeviceProfile, addFirst: Boolean = false) = mutex.withLock {
|
||||
@@ -80,6 +127,30 @@ class DeviceProfilesRepo @Inject constructor(
|
||||
log(VERBOSE) { "Updated device profile: ${profile.label}" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Read-modify-write helper that preserves every field the caller doesn't touch.
|
||||
* Prevents callers that only know a subset of fields (e.g. the profile editor holding
|
||||
* name/model/keys/address/signalQuality) from silently wiping fields the user set
|
||||
* elsewhere — notably the reaction toggles edited from Device Settings.
|
||||
*/
|
||||
suspend fun updateAppleProfile(
|
||||
id: ProfileId,
|
||||
transform: (AppleDeviceProfile) -> AppleDeviceProfile,
|
||||
) = mutex.withLock {
|
||||
val currentContainer = settings.profiles.valueBlocking
|
||||
val existing = currentContainer.profiles.firstOrNull { it.id == id } as? AppleDeviceProfile
|
||||
if (existing == null) {
|
||||
log(TAG, WARN) { "updateAppleProfile($id): profile not found or not AppleDeviceProfile" }
|
||||
return@withLock
|
||||
}
|
||||
val updated = transform(existing)
|
||||
val otherProfiles = currentContainer.profiles.filter { it.id != id }
|
||||
checkAddressUniqueness(updated, otherProfiles)
|
||||
val updatedProfiles = currentContainer.profiles.map { if (it.id == id) updated else it }
|
||||
settings.profiles.valueBlocking = DeviceProfilesContainer(updatedProfiles)
|
||||
log(VERBOSE) { "Updated apple device profile: ${updated.label}" }
|
||||
}
|
||||
|
||||
suspend fun removeProfile(profileId: ProfileId) = mutex.withLock {
|
||||
val currentContainer = settings.profiles.valueBlocking
|
||||
val updatedProfiles = currentContainer.profiles.filter { it.id != profileId }
|
||||
|
||||
@@ -33,5 +33,6 @@ class DeviceProfilesSettings @Inject constructor(
|
||||
)
|
||||
val singleToMultiMigrationDone = dataStore.createValue("profiles.migration.v2.done", false)
|
||||
val defaultProfileCreated = dataStore.createValue("profiles.default.v2.created", false)
|
||||
val reactionMigrationDone = dataStore.createValue("profiles.reactions.migration.done", false)
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package eu.darken.capod.profiles.core
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.WARN
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
/**
|
||||
* One-shot reader for the legacy global `settings_reaction` DataStore. Used by the reaction
|
||||
* migration in [DeviceProfilesRepo] to copy the old global values onto every profile. Does
|
||||
* not depend on the old `ReactionSettings` class (deleted in the same change), so the
|
||||
* migration can still run after that class is gone.
|
||||
*/
|
||||
class LegacyReactionSettingsReader(context: Context, private val json: Json) {
|
||||
|
||||
private val Context.legacyStore: DataStore<Preferences> by preferencesDataStore(
|
||||
name = LEGACY_STORE_NAME,
|
||||
)
|
||||
|
||||
private val dataStore: DataStore<Preferences> = context.applicationContext.legacyStore
|
||||
|
||||
suspend fun read(): LegacyReactionValues {
|
||||
val prefs = dataStore.data.first()
|
||||
val conditionRaw = prefs[CONDITION_KEY]
|
||||
val condition = conditionRaw?.let {
|
||||
try {
|
||||
json.decodeFromString<AutoConnectCondition>(it)
|
||||
} catch (e: Exception) {
|
||||
log(TAG, WARN) { "Failed to decode legacy auto-connect condition: ${e.message}" }
|
||||
null
|
||||
}
|
||||
} ?: AutoConnectCondition.WHEN_SEEN
|
||||
|
||||
return LegacyReactionValues(
|
||||
autoPause = prefs[AUTO_PAUSE_KEY] ?: false,
|
||||
autoPlay = prefs[AUTO_PLAY_KEY] ?: false,
|
||||
autoConnect = prefs[AUTO_CONNECT_KEY] ?: false,
|
||||
autoConnectCondition = condition,
|
||||
showPopUpOnCaseOpen = prefs[POPUP_CASE_OPEN_KEY] ?: false,
|
||||
showPopUpOnConnection = prefs[POPUP_CONNECTED_KEY] ?: false,
|
||||
onePodMode = prefs[ONE_POD_KEY] ?: false,
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = logTag("LegacyReactionReader")
|
||||
private const val LEGACY_STORE_NAME = "settings_reaction"
|
||||
|
||||
internal val AUTO_PAUSE_KEY = booleanPreferencesKey("reaction.autopause.enabled")
|
||||
internal val AUTO_PLAY_KEY = booleanPreferencesKey("reaction.autoplay.enabled")
|
||||
internal val AUTO_CONNECT_KEY = booleanPreferencesKey("reaction.autoconnect.enabled")
|
||||
internal val CONDITION_KEY = stringPreferencesKey("reaction.autoconnect.condition")
|
||||
internal val POPUP_CASE_OPEN_KEY = booleanPreferencesKey("reaction.popup.caseopen")
|
||||
internal val POPUP_CONNECTED_KEY = booleanPreferencesKey("reaction.popup.connected")
|
||||
internal val ONE_POD_KEY = booleanPreferencesKey("reaction.onepod.enabled")
|
||||
}
|
||||
}
|
||||
|
||||
data class LegacyReactionValues(
|
||||
val autoPause: Boolean,
|
||||
val autoPlay: Boolean,
|
||||
val autoConnect: Boolean,
|
||||
val autoConnectCondition: AutoConnectCondition,
|
||||
val showPopUpOnCaseOpen: Boolean,
|
||||
val showPopUpOnConnection: Boolean,
|
||||
val onePodMode: Boolean,
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
package eu.darken.capod.profiles.core
|
||||
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
|
||||
data class ReactionConfig(
|
||||
val autoPause: Boolean = false,
|
||||
val autoPlay: Boolean = false,
|
||||
val onePodMode: Boolean = false,
|
||||
val autoConnect: Boolean = false,
|
||||
val autoConnectCondition: AutoConnectCondition = AutoConnectCondition.WHEN_SEEN,
|
||||
val showPopUpOnCaseOpen: Boolean = false,
|
||||
val showPopUpOnConnection: Boolean = false,
|
||||
)
|
||||
|
||||
interface HasReactionConfig {
|
||||
val reactionConfig: ReactionConfig
|
||||
}
|
||||
|
||||
fun DeviceProfile?.toReactionConfig(): ReactionConfig =
|
||||
(this as? HasReactionConfig)?.reactionConfig ?: ReactionConfig()
|
||||
@@ -19,6 +19,7 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.twotone.ArrowBack
|
||||
import androidx.compose.material.icons.twotone.Add
|
||||
import androidx.compose.material.icons.twotone.DragHandle
|
||||
import androidx.compose.material.icons.twotone.Tune
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -63,6 +64,7 @@ fun DeviceManagerScreenHost(vm: DeviceManagerViewModel = hiltViewModel()) {
|
||||
onBack = { vm.navUp() },
|
||||
onAddDevice = { vm.onAddDevice() },
|
||||
onEditProfile = { profile -> vm.onEditProfile(profile) },
|
||||
onDeviceSettings = { profile -> vm.onDeviceSettings(profile) },
|
||||
onReorder = { ids -> vm.onReorder(ids) },
|
||||
)
|
||||
}
|
||||
@@ -74,6 +76,7 @@ fun DeviceManagerScreen(
|
||||
onBack: () -> Unit,
|
||||
onAddDevice: () -> Unit,
|
||||
onEditProfile: (DeviceProfile) -> Unit,
|
||||
onDeviceSettings: (DeviceProfile) -> Unit = {},
|
||||
onReorder: (List<ProfileId>) -> Unit = {},
|
||||
) {
|
||||
val lazyListState = rememberLazyListState()
|
||||
@@ -142,6 +145,7 @@ fun DeviceManagerScreen(
|
||||
),
|
||||
profile = profile,
|
||||
onClick = { if (!reorderableState.isDragging) onEditProfile(profile) },
|
||||
onDeviceSettings = { onDeviceSettings(profile) },
|
||||
showDragHandle = showDragHandles,
|
||||
)
|
||||
}
|
||||
@@ -230,13 +234,14 @@ private fun ProfileRow(
|
||||
modifier: Modifier = Modifier,
|
||||
profile: DeviceProfile,
|
||||
onClick: () -> Unit,
|
||||
onDeviceSettings: () -> Unit = {},
|
||||
showDragHandle: Boolean = false,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onClick)
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
.padding(start = 16.dp, end = 4.dp, top = 12.dp, bottom = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Image(
|
||||
@@ -256,6 +261,13 @@ private fun ProfileRow(
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
IconButton(onClick = onDeviceSettings) {
|
||||
Icon(
|
||||
imageVector = Icons.TwoTone.Tune,
|
||||
contentDescription = stringResource(R.string.device_settings_open_cd),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
if (showDragHandle) {
|
||||
Icon(
|
||||
imageVector = Icons.TwoTone.DragHandle,
|
||||
|
||||
@@ -37,6 +37,11 @@ class DeviceManagerViewModel @Inject constructor(
|
||||
navTo(Nav.Main.DeviceProfileCreation(profileId = profile.id))
|
||||
}
|
||||
|
||||
fun onDeviceSettings(profile: DeviceProfile) {
|
||||
log(TAG) { "onDeviceSettings(): $profile" }
|
||||
navTo(Nav.Main.DeviceSettings(profileId = profile.id))
|
||||
}
|
||||
|
||||
fun onReorder(profileIds: List<ProfileId>) = launch {
|
||||
log(TAG) { "onReorder(): ${profileIds.size} profiles" }
|
||||
deviceProfilesRepo.reorderProfilesById(profileIds)
|
||||
|
||||
+22
-12
@@ -219,20 +219,30 @@ class DeviceProfileCreationViewModel @Inject constructor(
|
||||
|
||||
launch {
|
||||
try {
|
||||
val profile = AppleDeviceProfile(
|
||||
id = if (isEditMode) profileId!! else UUID.randomUUID().toString(),
|
||||
label = name,
|
||||
model = editorState.selectedModel,
|
||||
minimumSignalQuality = editorState.minimumSignalQuality,
|
||||
identityKey = editorState.identityKeyHex?.fromHex(),
|
||||
encryptionKey = editorState.encryptionKeyHex?.fromHex(),
|
||||
address = editorState.selectedDeviceAddress,
|
||||
)
|
||||
|
||||
if (isEditMode) {
|
||||
deviceProfilesRepo.updateProfile(profile)
|
||||
log(TAG) { "Profile updated: $profile" }
|
||||
// Read-modify-write so reaction toggles (and any other fields this editor
|
||||
// doesn't know about) survive a rename or key-refresh.
|
||||
deviceProfilesRepo.updateAppleProfile(profileId!!) { existing ->
|
||||
existing.copy(
|
||||
label = name,
|
||||
model = editorState.selectedModel,
|
||||
minimumSignalQuality = editorState.minimumSignalQuality,
|
||||
identityKey = editorState.identityKeyHex?.fromHex(),
|
||||
encryptionKey = editorState.encryptionKeyHex?.fromHex(),
|
||||
address = editorState.selectedDeviceAddress,
|
||||
)
|
||||
}
|
||||
log(TAG) { "Profile updated: $profileId" }
|
||||
} else {
|
||||
val profile = AppleDeviceProfile(
|
||||
id = UUID.randomUUID().toString(),
|
||||
label = name,
|
||||
model = editorState.selectedModel,
|
||||
minimumSignalQuality = editorState.minimumSignalQuality,
|
||||
identityKey = editorState.identityKeyHex?.fromHex(),
|
||||
encryptionKey = editorState.encryptionKeyHex?.fromHex(),
|
||||
address = editorState.selectedDeviceAddress,
|
||||
)
|
||||
deviceProfilesRepo.addProfile(profile)
|
||||
log(TAG) { "Profile created: $profile" }
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package eu.darken.capod.reaction.core
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.SharedPreferencesMigration
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import eu.darken.capod.common.datastore.createValue
|
||||
import eu.darken.capod.common.serialization.SerializationCapod
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
import kotlinx.serialization.json.Json
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ReactionSettings @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
@SerializationCapod json: Json,
|
||||
) {
|
||||
|
||||
private val Context.dataStore by preferencesDataStore(
|
||||
name = "settings_reaction",
|
||||
produceMigrations = { ctx -> listOf(SharedPreferencesMigration(ctx, "settings_reaction")) }
|
||||
)
|
||||
|
||||
private val dataStore: DataStore<Preferences> get() = context.dataStore
|
||||
|
||||
val autoPause = dataStore.createValue("reaction.autopause.enabled", false)
|
||||
|
||||
val autoPlay = dataStore.createValue("reaction.autoplay.enabled", false)
|
||||
|
||||
val autoConnect = dataStore.createValue("reaction.autoconnect.enabled", false)
|
||||
|
||||
val autoConnectCondition = dataStore.createValue(
|
||||
"reaction.autoconnect.condition",
|
||||
AutoConnectCondition.WHEN_SEEN,
|
||||
json,
|
||||
onErrorFallbackToDefault = true,
|
||||
)
|
||||
|
||||
val showPopUpOnCaseOpen = dataStore.createValue("reaction.popup.caseopen", false)
|
||||
|
||||
val showPopUpOnConnection = dataStore.createValue("reaction.popup.connected", false)
|
||||
|
||||
val onePodMode = dataStore.createValue("reaction.onepod.enabled", false)
|
||||
|
||||
}
|
||||
@@ -10,10 +10,9 @@ import eu.darken.capod.main.core.GeneralSettings
|
||||
import eu.darken.capod.monitor.core.DeviceMonitor
|
||||
import eu.darken.capod.monitor.core.primaryDevice
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesRepo
|
||||
import eu.darken.capod.reaction.core.ReactionSettings
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.distinctUntilChangedBy
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
@@ -22,23 +21,23 @@ import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import eu.darken.capod.common.datastore.valueBlocking
|
||||
|
||||
@Singleton
|
||||
class AutoConnect @Inject constructor(
|
||||
private val bluetoothManager: BluetoothManager2,
|
||||
private val deviceMonitor: DeviceMonitor,
|
||||
private val generalSettings: GeneralSettings,
|
||||
private val reactionSettings: ReactionSettings,
|
||||
private val deviceProfilesRepo: DeviceProfilesRepo,
|
||||
) {
|
||||
|
||||
fun monitor(): Flow<Unit> = reactionSettings.autoConnect.flow
|
||||
fun monitor(): Flow<Unit> = deviceMonitor.primaryDevice()
|
||||
.map { it?.reactions?.autoConnect == true }
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest { isAutoConnectEnabled ->
|
||||
if (isAutoConnectEnabled) {
|
||||
combine(
|
||||
bluetoothManager.connectedDevices,
|
||||
deviceMonitor.primaryDevice().filterNotNull().distinctUntilChangedBy { it.rawDataHex },
|
||||
deviceMonitor.primaryDevice().filterNotNull().distinctUntilChangedBy {
|
||||
Triple(it.rawDataHex, it.reactions.autoConnectCondition, it.reactions.onePodMode)
|
||||
},
|
||||
) { connectedDevices, mainDevice ->
|
||||
connectedDevices to mainDevice
|
||||
}
|
||||
@@ -73,13 +72,14 @@ class AutoConnect @Inject constructor(
|
||||
return@map
|
||||
}
|
||||
|
||||
val condition = reactionSettings.autoConnectCondition.valueBlocking
|
||||
val reactions = mainDevice.reactions
|
||||
val condition = reactions.autoConnectCondition
|
||||
log(TAG) { "Checking condition $condition" }
|
||||
|
||||
val lidState = mainDevice.caseLidState
|
||||
val isBeingWorn = mainDevice.isBeingWorn ?: false
|
||||
val isEitherPodInEar = mainDevice.isEitherPodInEar ?: false
|
||||
val onePodMode = reactionSettings.onePodMode.valueBlocking
|
||||
val onePodMode = reactions.onePodMode
|
||||
|
||||
val decision = evaluateAutoConnect(
|
||||
mainDeviceAddr = mainDeviceAddr,
|
||||
|
||||
@@ -2,7 +2,6 @@ package eu.darken.capod.reaction.core.playpause
|
||||
|
||||
import eu.darken.capod.common.MediaControl
|
||||
import eu.darken.capod.common.bluetooth.BluetoothManager2
|
||||
import eu.darken.capod.common.datastore.valueBlocking
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.WARN
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
@@ -11,12 +10,11 @@ import eu.darken.capod.common.flow.setupCommonEventHandlers
|
||||
import eu.darken.capod.common.flow.withPrevious
|
||||
import eu.darken.capod.monitor.core.DeviceMonitor
|
||||
import eu.darken.capod.monitor.core.primaryDevice
|
||||
import eu.darken.capod.reaction.core.ReactionSettings
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@@ -25,22 +23,21 @@ import javax.inject.Singleton
|
||||
class PlayPause @Inject constructor(
|
||||
private val deviceMonitor: DeviceMonitor,
|
||||
private val bluetoothManager: BluetoothManager2,
|
||||
private val reactionSettings: ReactionSettings,
|
||||
private val mediaControl: MediaControl,
|
||||
) {
|
||||
|
||||
fun monitor() = combine(
|
||||
reactionSettings.autoPlay.flow,
|
||||
reactionSettings.autoPause.flow,
|
||||
reactionSettings.onePodMode.flow, // Included to restart pipeline when toggled; value read at decision time
|
||||
) { play, pause, _ -> play || pause }
|
||||
.flatMapLatest { if (it) bluetoothManager.connectedDevices else emptyFlow() }
|
||||
.flatMapLatest {
|
||||
if (it.isEmpty()) {
|
||||
fun monitor() = deviceMonitor.primaryDevice()
|
||||
.map { device -> device?.reactions?.let { it.autoPlay || it.autoPause } == true }
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest { shouldMonitor ->
|
||||
if (shouldMonitor) bluetoothManager.connectedDevices else emptyFlow()
|
||||
}
|
||||
.flatMapLatest { connected ->
|
||||
if (connected.isEmpty()) {
|
||||
log(TAG) { "No known devices connected." }
|
||||
emptyFlow()
|
||||
} else {
|
||||
log(TAG) { "Known devices connected: $it" }
|
||||
log(TAG) { "Known devices connected: $connected" }
|
||||
deviceMonitor.primaryDevice()
|
||||
}
|
||||
}
|
||||
@@ -48,21 +45,28 @@ class PlayPause @Inject constructor(
|
||||
.withPrevious()
|
||||
.filter { (previous, current) ->
|
||||
if (previous == null || current == null) return@filter false
|
||||
log(TAG, VERBOSE) { "previous-id=${previous.identifier}, current-id=${current.identifier}" }
|
||||
val match = previous.identifier == current.identifier
|
||||
// Use profileId (stable across BLE address rotations) rather than BLE identifier.
|
||||
// Only profiled devices reach this point (outer gate requires profile.autoPlay/autoPause).
|
||||
val match = previous.profileId != null && previous.profileId == current.profileId
|
||||
if (!match) log(TAG, WARN) { "Main device switched, skipping reaction." }
|
||||
match
|
||||
}
|
||||
.onEach { (previous, current) ->
|
||||
log(TAG, VERBOSE) { "Checking\nprevious=$previous\ncurrent=$current" }
|
||||
|
||||
val reactions = current?.reactions
|
||||
if (reactions == null) {
|
||||
log(TAG, VERBOSE) { "No reactions on current device, skipping reaction" }
|
||||
return@onEach
|
||||
}
|
||||
|
||||
// Convert to EarDetectionState based on device capabilities
|
||||
val prevState: EarDetectionState
|
||||
val currState: EarDetectionState
|
||||
|
||||
when {
|
||||
previous!!.hasEarDetection && previous.hasDualPods &&
|
||||
current!!.hasEarDetection && current.hasDualPods -> {
|
||||
current.hasEarDetection && current.hasDualPods -> {
|
||||
// Dual pod devices (AirPods, AirPods Pro, etc.)
|
||||
log(TAG, VERBOSE) {
|
||||
"Dual-pod device: left=${current.isLeftInEar}, right=${current.isRightInEar}"
|
||||
@@ -77,7 +81,7 @@ class PlayPause @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
previous!!.hasEarDetection && current!!.hasEarDetection -> {
|
||||
previous.hasEarDetection && current.hasEarDetection -> {
|
||||
// Single pod devices (AirPods Max, etc.)
|
||||
log(TAG, VERBOSE) { "Single-pod device: worn=${current.isBeingWorn}" }
|
||||
prevState = EarDetectionState.fromSinglePod(worn = previous.isBeingWorn ?: false)
|
||||
@@ -94,7 +98,7 @@ class PlayPause @Inject constructor(
|
||||
val decision = evaluatePlayPauseAction(
|
||||
previous = prevState,
|
||||
current = currState,
|
||||
onePodMode = reactionSettings.onePodMode.valueBlocking,
|
||||
onePodMode = reactions.onePodMode,
|
||||
isCurrentlyPlaying = mediaControl.isPlaying
|
||||
)
|
||||
|
||||
@@ -102,21 +106,21 @@ class PlayPause @Inject constructor(
|
||||
|
||||
// Execute the decision
|
||||
when {
|
||||
decision.shouldPlay && reactionSettings.autoPlay.valueBlocking -> {
|
||||
decision.shouldPlay && reactions.autoPlay -> {
|
||||
log(TAG) { "autoPlay is triggered, sendPlay() - ${decision.reason}" }
|
||||
mediaControl.sendPlay()
|
||||
}
|
||||
|
||||
decision.shouldPlay && !reactionSettings.autoPlay.valueBlocking -> {
|
||||
decision.shouldPlay && !reactions.autoPlay -> {
|
||||
log(TAG, VERBOSE) { "autoPlay is disabled" }
|
||||
}
|
||||
|
||||
decision.shouldPause && reactionSettings.autoPause.valueBlocking -> {
|
||||
decision.shouldPause && reactions.autoPause -> {
|
||||
log(TAG) { "autoPause is triggered, sendPause() - ${decision.reason}" }
|
||||
mediaControl.sendPause()
|
||||
}
|
||||
|
||||
decision.shouldPause && !reactionSettings.autoPause.valueBlocking -> {
|
||||
decision.shouldPause && !reactions.autoPause -> {
|
||||
log(TAG, VERBOSE) { "autoPause is disabled" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package eu.darken.capod.reaction.core.popup
|
||||
|
||||
import eu.darken.capod.common.bluetooth.BluetoothAddress
|
||||
import eu.darken.capod.common.bluetooth.BluetoothDevice2
|
||||
import eu.darken.capod.common.bluetooth.BluetoothManager2
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
@@ -11,12 +12,9 @@ import eu.darken.capod.monitor.core.DeviceMonitor
|
||||
import eu.darken.capod.monitor.core.PodDevice
|
||||
import eu.darken.capod.monitor.core.primaryDevice
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
import eu.darken.capod.reaction.core.ReactionSettings
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChangedBy
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import java.time.Duration
|
||||
@@ -27,35 +25,41 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class PopUpReaction @Inject constructor(
|
||||
private val deviceMonitor: DeviceMonitor,
|
||||
private val reactionSettings: ReactionSettings,
|
||||
private val bluetoothManager: BluetoothManager2,
|
||||
) {
|
||||
|
||||
private val caseCoolDowns = mutableMapOf<String, Instant>()
|
||||
private val caseCoolDowns = java.util.concurrent.ConcurrentHashMap<String, Instant>()
|
||||
|
||||
private fun monitorCase(): Flow<Event> = reactionSettings.showPopUpOnCaseOpen.flow
|
||||
.flatMapLatest { isEnabled ->
|
||||
if (isEnabled) {
|
||||
deviceMonitor.primaryDevice().distinctUntilChangedBy { it?.rawDataHex }
|
||||
} else {
|
||||
emptyFlow()
|
||||
}
|
||||
private fun monitorCase(): Flow<Event> = deviceMonitor.primaryDevice()
|
||||
.distinctUntilChangedBy {
|
||||
// Re-emit on profile changes (eligibility) AND on raw BLE state changes (lid).
|
||||
Triple(it?.profileId, it?.reactions?.showPopUpOnCaseOpen, it?.rawDataHex)
|
||||
}
|
||||
.withPrevious()
|
||||
.setupCommonEventHandlers(TAG) { "popUpCase" }
|
||||
.mapNotNull { (previous, current) ->
|
||||
if (current?.caseLidState == null) {
|
||||
return@mapNotNull null
|
||||
val wasEligible = previous?.reactions?.showPopUpOnCaseOpen == true
|
||||
val isEligible = current?.reactions?.showPopUpOnCaseOpen == true
|
||||
|
||||
// Eligibility transition: just lost it (toggled off, or switched to a profile
|
||||
// with the toggle off). Dismiss any visible overlay immediately.
|
||||
if (wasEligible && !isEligible) {
|
||||
log(TAG) { "Case popup eligibility lost, emitting Hide" }
|
||||
return@mapNotNull Event.PopupHide()
|
||||
}
|
||||
|
||||
if (!isEligible) return@mapNotNull null
|
||||
if (current.caseLidState == null) return@mapNotNull null
|
||||
|
||||
log(TAG, VERBOSE) {
|
||||
"previous=${previous?.caseLidState}, current=${current.caseLidState}"
|
||||
}
|
||||
log(TAG, VERBOSE) { "previous-id=${previous?.identifier}, current-id=${current.identifier}" }
|
||||
|
||||
val isSameDeviceOrProfile = previous?.identifier == current.identifier ||
|
||||
(previous?.profileId != null && previous.profileId == current.profileId)
|
||||
val isSameDeviceOrProfile = previous?.profileId != null && previous.profileId == current.profileId
|
||||
val isSameDeviceWithCaseNowOpen = isSameDeviceOrProfile && previous?.caseLidState != current.caseLidState
|
||||
val isNewDeviceWithJustOpenedCase = !isSameDeviceOrProfile && previous?.caseLidState != current.caseLidState
|
||||
val isNewDeviceWithJustOpenedCase = !isSameDeviceOrProfile
|
||||
&& previous != null
|
||||
&& previous.caseLidState != null
|
||||
&& previous.caseLidState != current.caseLidState
|
||||
|
||||
if (!isSameDeviceWithCaseNowOpen && !isNewDeviceWithJustOpenedCase) {
|
||||
return@mapNotNull null
|
||||
@@ -66,7 +70,7 @@ class PopUpReaction @Inject constructor(
|
||||
}
|
||||
|
||||
private fun throttleCasePopUps(current: PodDevice): Event? {
|
||||
val cooldownKey = current.profileId ?: current.identifier.toString()
|
||||
val cooldownKey = current.profileId ?: current.identifier?.toString() ?: return null
|
||||
val now = Instant.now()
|
||||
val lastShown = caseCoolDowns[cooldownKey]
|
||||
|
||||
@@ -99,38 +103,57 @@ class PopUpReaction @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private val connectionCoolDowns = mutableMapOf<BluetoothAddress, Instant>()
|
||||
private val connectionCoolDowns = java.util.concurrent.ConcurrentHashMap<BluetoothAddress, Instant>()
|
||||
|
||||
private fun monitorConnection(): Flow<Event> = reactionSettings.showPopUpOnConnection.flow
|
||||
.flatMapLatest { isEnabled ->
|
||||
if (!isEnabled) return@flatMapLatest emptyFlow()
|
||||
private data class ConnectionWindow(
|
||||
val direct: BluetoothDevice2?,
|
||||
val broadcast: PodDevice?,
|
||||
val eligible: Boolean,
|
||||
)
|
||||
|
||||
combine(
|
||||
bluetoothManager.connectedDevices,
|
||||
deviceMonitor.primaryDevice().distinctUntilChangedBy { it?.rawDataHex },
|
||||
) { devices, broadcast ->
|
||||
log(TAG) { "$broadcast $devices " }
|
||||
val primaryAddr = broadcast?.address
|
||||
val direct = devices.singleOrNull { it.address == primaryAddr }.also {
|
||||
log(TAG, VERBOSE) { "Connected main device is $it" }
|
||||
}
|
||||
if (direct == null) {
|
||||
connectionCoolDowns.remove(primaryAddr).also {
|
||||
if (it != null) log(TAG) { "Cleared connection cooldown for $primaryAddr due to disconect" }
|
||||
}
|
||||
}
|
||||
if (direct != null && broadcast != null) direct to broadcast else null
|
||||
private fun monitorConnection(): Flow<Event> = combine(
|
||||
bluetoothManager.connectedDevices,
|
||||
deviceMonitor.primaryDevice().distinctUntilChangedBy {
|
||||
Triple(it?.profileId, it?.reactions?.showPopUpOnConnection, it?.rawDataHex)
|
||||
},
|
||||
) { devices, broadcast ->
|
||||
val eligible = broadcast?.reactions?.showPopUpOnConnection == true
|
||||
if (!eligible) {
|
||||
ConnectionWindow(direct = null, broadcast = null, eligible = false)
|
||||
} else {
|
||||
val primaryAddr = broadcast.address
|
||||
?: return@combine ConnectionWindow(direct = null, broadcast = null, eligible = false)
|
||||
val direct = devices.singleOrNull { it.address == primaryAddr }.also {
|
||||
log(TAG, VERBOSE) { "Connected main device is $it" }
|
||||
}
|
||||
if (direct == null) {
|
||||
connectionCoolDowns.remove(primaryAddr).also {
|
||||
if (it != null) log(TAG) { "Cleared connection cooldown for $primaryAddr due to disconnect" }
|
||||
}
|
||||
}
|
||||
ConnectionWindow(direct = direct, broadcast = broadcast, eligible = true)
|
||||
}
|
||||
}
|
||||
.withPrevious()
|
||||
.mapNotNull { (previouss, currents) ->
|
||||
val previousConnected = previouss?.first
|
||||
.mapNotNull { (previous, current) ->
|
||||
val wasEligible = previous?.eligible == true
|
||||
val isEligible = current.eligible
|
||||
|
||||
// Eligibility transition: dismiss any visible overlay immediately.
|
||||
if (wasEligible && !isEligible) {
|
||||
log(TAG) { "Connection popup eligibility lost, emitting Hide" }
|
||||
return@mapNotNull Event.PopupHide()
|
||||
}
|
||||
|
||||
if (!isEligible) return@mapNotNull null
|
||||
|
||||
val previousConnected = previous?.direct
|
||||
log(TAG, VERBOSE) { "previousConnected: $previousConnected" }
|
||||
val previousBroadcasted = previouss?.second
|
||||
val previousBroadcasted = previous?.broadcast
|
||||
log(TAG, VERBOSE) { "previousBroadcasted: $previousBroadcasted" }
|
||||
val currentConnected = currents?.first
|
||||
val currentConnected = current.direct
|
||||
log(TAG, VERBOSE) { "currentConnected: $currentConnected" }
|
||||
val currentBroadcasted = currents?.second
|
||||
val currentBroadcasted = current.broadcast
|
||||
log(TAG, VERBOSE) { "currentBroadcasted: $currentBroadcasted" }
|
||||
|
||||
if (previousConnected != null && previousBroadcasted != null && currentConnected == null) {
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package eu.darken.capod.reaction.ui
|
||||
|
||||
import androidx.navigation3.runtime.EntryProviderScope
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import dagger.multibindings.IntoSet
|
||||
import eu.darken.capod.common.navigation.Nav
|
||||
import eu.darken.capod.common.navigation.NavigationEntry
|
||||
import javax.inject.Inject
|
||||
|
||||
class ReactionSettingsNavigation @Inject constructor() : NavigationEntry {
|
||||
override fun EntryProviderScope<NavKey>.setup() {
|
||||
entry<Nav.Settings.Reactions> { ReactionSettingsScreenHost() }
|
||||
}
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
abstract class Mod {
|
||||
@Binds
|
||||
@IntoSet
|
||||
abstract fun bind(entry: ReactionSettingsNavigation): NavigationEntry
|
||||
}
|
||||
}
|
||||
@@ -1,292 +0,0 @@
|
||||
package eu.darken.capod.reaction.ui
|
||||
|
||||
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.lazy.LazyColumn
|
||||
import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.foundation.selection.selectableGroup
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.twotone.ArrowBack
|
||||
import androidx.compose.material.icons.twotone.BluetoothConnected
|
||||
import androidx.compose.material.icons.twotone.LooksOne
|
||||
import androidx.compose.material.icons.automirrored.twotone.Message
|
||||
import androidx.compose.material.icons.twotone.PauseCircle
|
||||
import androidx.compose.material.icons.twotone.PlayCircle
|
||||
import androidx.compose.material.icons.twotone.QuestionMark
|
||||
import androidx.compose.material.icons.twotone.Workspaces
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.compose.Preview2
|
||||
import eu.darken.capod.common.compose.PreviewWrapper
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import eu.darken.capod.common.error.ErrorEventHandler
|
||||
import eu.darken.capod.common.navigation.NavigationEventHandler
|
||||
import eu.darken.capod.common.settings.SettingsBaseItem
|
||||
import eu.darken.capod.common.settings.SettingsCategoryHeader
|
||||
import eu.darken.capod.common.settings.SettingsSwitchItem
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
|
||||
@Composable
|
||||
fun ReactionSettingsScreenHost(vm: ReactionSettingsViewModel = hiltViewModel()) {
|
||||
ErrorEventHandler(vm)
|
||||
NavigationEventHandler(vm)
|
||||
|
||||
val state by vm.state.collectAsStateWithLifecycle(initialValue = null)
|
||||
|
||||
state?.let {
|
||||
ReactionSettingsScreen(
|
||||
state = it,
|
||||
onNavigateUp = { vm.navUp() },
|
||||
onOnePodModeChanged = { enabled -> vm.setOnePodMode(enabled) },
|
||||
onAutoPlayChanged = { enabled -> vm.setAutoPlay(enabled) },
|
||||
onAutoPauseChanged = { enabled -> vm.setAutoPause(enabled) },
|
||||
onAutoConnectChanged = { enabled -> vm.setAutoConnect(enabled) },
|
||||
onAutoConnectConditionSelected = { condition -> vm.setAutoConnectCondition(condition) },
|
||||
onShowPopUpOnCaseOpenChanged = { enabled -> vm.setShowPopUpOnCaseOpen(enabled) },
|
||||
onShowPopUpOnConnectionChanged = { enabled -> vm.setShowPopUpOnConnection(enabled) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ReactionSettingsScreen(
|
||||
state: ReactionSettingsViewModel.State,
|
||||
onNavigateUp: () -> Unit,
|
||||
onOnePodModeChanged: (Boolean) -> Unit,
|
||||
onAutoPlayChanged: (Boolean) -> Unit,
|
||||
onAutoPauseChanged: (Boolean) -> Unit,
|
||||
onAutoConnectChanged: (Boolean) -> Unit,
|
||||
onAutoConnectConditionSelected: (AutoConnectCondition) -> Unit,
|
||||
onShowPopUpOnCaseOpenChanged: (Boolean) -> Unit,
|
||||
onShowPopUpOnConnectionChanged: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var showAutoConnectConditionDialog by remember { mutableStateOf(false) }
|
||||
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text(text = stringResource(R.string.settings_reaction_label)) },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onNavigateUp) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.TwoTone.ArrowBack,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
) { innerPadding ->
|
||||
LazyColumn(modifier = Modifier.padding(innerPadding)) {
|
||||
item {
|
||||
SettingsCategoryHeader(text = stringResource(R.string.settings_autopplay_label))
|
||||
}
|
||||
item {
|
||||
SettingsBaseItem(
|
||||
title = stringResource(R.string.settings_onepod_mode_label),
|
||||
subtitle = stringResource(R.string.settings_onepod_mode_description),
|
||||
icon = Icons.TwoTone.LooksOne,
|
||||
onClick = { onOnePodModeChanged(!state.onePodMode) },
|
||||
trailingContent = {
|
||||
Switch(
|
||||
checked = state.onePodMode,
|
||||
onCheckedChange = onOnePodModeChanged,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
item {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.TwoTone.PlayCircle,
|
||||
title = stringResource(R.string.settings_autopplay_label),
|
||||
subtitle = stringResource(R.string.settings_autoplay_description),
|
||||
checked = state.autoPlay,
|
||||
onCheckedChange = onAutoPlayChanged,
|
||||
requiresUpgrade = !state.isPro,
|
||||
)
|
||||
}
|
||||
item {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.TwoTone.PauseCircle,
|
||||
title = stringResource(R.string.settings_autopause_label),
|
||||
subtitle = stringResource(R.string.settings_autopause_description),
|
||||
checked = state.autoPause,
|
||||
onCheckedChange = onAutoPauseChanged,
|
||||
requiresUpgrade = !state.isPro,
|
||||
)
|
||||
}
|
||||
item {
|
||||
SettingsBaseItem(
|
||||
title = stringResource(R.string.settings_eardetection_info_label),
|
||||
subtitle = stringResource(R.string.settings_eardetection_info_description),
|
||||
icon = Icons.TwoTone.QuestionMark,
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
)
|
||||
}
|
||||
item {
|
||||
SettingsCategoryHeader(text = stringResource(R.string.settings_autoconnect_label))
|
||||
}
|
||||
item {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.TwoTone.BluetoothConnected,
|
||||
title = stringResource(R.string.settings_autoconnect_label),
|
||||
subtitle = stringResource(R.string.settings_autoconnect_description),
|
||||
checked = state.autoConnect,
|
||||
onCheckedChange = onAutoConnectChanged,
|
||||
requiresUpgrade = !state.isPro,
|
||||
)
|
||||
}
|
||||
item {
|
||||
SettingsBaseItem(
|
||||
title = stringResource(R.string.settings_autoconnect_condition_label),
|
||||
subtitle = stringResource(state.autoConnectCondition.labelRes),
|
||||
icon = Icons.TwoTone.Workspaces,
|
||||
onClick = { if (state.autoConnect) showAutoConnectConditionDialog = true },
|
||||
enabled = state.autoConnect,
|
||||
)
|
||||
}
|
||||
item {
|
||||
SettingsCategoryHeader(text = stringResource(R.string.settings_category_other_label))
|
||||
}
|
||||
item {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.AutoMirrored.TwoTone.Message,
|
||||
title = stringResource(R.string.settings_popup_caseopen_label),
|
||||
subtitle = stringResource(R.string.settings_popup_caseopen_description),
|
||||
checked = state.showPopUpOnCaseOpen,
|
||||
onCheckedChange = onShowPopUpOnCaseOpenChanged,
|
||||
requiresUpgrade = !state.isPro,
|
||||
)
|
||||
}
|
||||
item {
|
||||
SettingsSwitchItem(
|
||||
icon = Icons.AutoMirrored.TwoTone.Message,
|
||||
title = stringResource(R.string.settings_popup_connected_label),
|
||||
subtitle = stringResource(R.string.settings_popup_connected_description),
|
||||
checked = state.showPopUpOnConnection,
|
||||
onCheckedChange = onShowPopUpOnConnectionChanged,
|
||||
requiresUpgrade = !state.isPro,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showAutoConnectConditionDialog) {
|
||||
AlertDialog(
|
||||
onDismissRequest = { showAutoConnectConditionDialog = false },
|
||||
title = { Text(text = stringResource(R.string.settings_autoconnect_condition_label)) },
|
||||
text = {
|
||||
Column(Modifier.selectableGroup()) {
|
||||
AutoConnectCondition.entries.forEach { condition ->
|
||||
val isSelected = condition == state.autoConnectCondition
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.selectable(
|
||||
selected = isSelected,
|
||||
onClick = {
|
||||
onAutoConnectConditionSelected(condition)
|
||||
showAutoConnectConditionDialog = false
|
||||
},
|
||||
role = Role.RadioButton,
|
||||
)
|
||||
.padding(vertical = 12.dp, horizontal = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
RadioButton(
|
||||
selected = isSelected,
|
||||
onClick = null,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(condition.labelRes),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = { showAutoConnectConditionDialog = false }) {
|
||||
Text(text = stringResource(android.R.string.cancel))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun ReactionSettingsScreenPreview() = PreviewWrapper {
|
||||
ReactionSettingsScreen(
|
||||
state = ReactionSettingsViewModel.State(
|
||||
isPro = true,
|
||||
onePodMode = false,
|
||||
autoPlay = true,
|
||||
autoPause = true,
|
||||
autoConnect = false,
|
||||
autoConnectCondition = AutoConnectCondition.WHEN_SEEN,
|
||||
showPopUpOnCaseOpen = true,
|
||||
showPopUpOnConnection = false,
|
||||
),
|
||||
onNavigateUp = {},
|
||||
onOnePodModeChanged = {},
|
||||
onAutoPlayChanged = {},
|
||||
onAutoPauseChanged = {},
|
||||
onAutoConnectChanged = {},
|
||||
onAutoConnectConditionSelected = {},
|
||||
onShowPopUpOnCaseOpenChanged = {},
|
||||
onShowPopUpOnConnectionChanged = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Preview2
|
||||
@Composable
|
||||
private fun ReactionSettingsScreenNonProPreview() = PreviewWrapper {
|
||||
ReactionSettingsScreen(
|
||||
state = ReactionSettingsViewModel.State(
|
||||
isPro = false,
|
||||
onePodMode = false,
|
||||
autoPlay = false,
|
||||
autoPause = false,
|
||||
autoConnect = false,
|
||||
autoConnectCondition = AutoConnectCondition.WHEN_SEEN,
|
||||
showPopUpOnCaseOpen = false,
|
||||
showPopUpOnConnection = false,
|
||||
),
|
||||
onNavigateUp = {},
|
||||
onOnePodModeChanged = {},
|
||||
onAutoPlayChanged = {},
|
||||
onAutoPauseChanged = {},
|
||||
onAutoConnectChanged = {},
|
||||
onAutoConnectConditionSelected = {},
|
||||
onShowPopUpOnCaseOpenChanged = {},
|
||||
onShowPopUpOnConnectionChanged = {},
|
||||
)
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
package eu.darken.capod.reaction.ui
|
||||
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import eu.darken.capod.common.coroutine.DispatcherProvider
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.common.navigation.Nav
|
||||
import eu.darken.capod.common.uix.ViewModel4
|
||||
import eu.darken.capod.common.upgrade.UpgradeRepo
|
||||
import eu.darken.capod.main.core.GeneralSettings
|
||||
import eu.darken.capod.main.core.MonitorMode
|
||||
import eu.darken.capod.reaction.core.ReactionSettings
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
import eu.darken.capod.common.datastore.valueBlocking
|
||||
|
||||
@HiltViewModel
|
||||
class ReactionSettingsViewModel @Inject constructor(
|
||||
dispatcherProvider: DispatcherProvider,
|
||||
private val reactionSettings: ReactionSettings,
|
||||
private val generalSettings: GeneralSettings,
|
||||
private val upgradeRepo: UpgradeRepo,
|
||||
) : ViewModel4(dispatcherProvider) {
|
||||
|
||||
data class State(
|
||||
val isPro: Boolean,
|
||||
val onePodMode: Boolean,
|
||||
val autoPlay: Boolean,
|
||||
val autoPause: Boolean,
|
||||
val autoConnect: Boolean,
|
||||
val autoConnectCondition: AutoConnectCondition,
|
||||
val showPopUpOnCaseOpen: Boolean,
|
||||
val showPopUpOnConnection: Boolean,
|
||||
)
|
||||
|
||||
private val isPro = upgradeRepo.upgradeInfo.map { it.isPro }.asLiveState()
|
||||
|
||||
val state = combine(
|
||||
isPro,
|
||||
reactionSettings.onePodMode.flow,
|
||||
reactionSettings.autoPlay.flow,
|
||||
reactionSettings.autoPause.flow,
|
||||
reactionSettings.autoConnect.flow,
|
||||
reactionSettings.autoConnectCondition.flow,
|
||||
reactionSettings.showPopUpOnCaseOpen.flow,
|
||||
reactionSettings.showPopUpOnConnection.flow,
|
||||
) { values ->
|
||||
State(
|
||||
isPro = values[0] as Boolean,
|
||||
onePodMode = values[1] as Boolean,
|
||||
autoPlay = values[2] as Boolean,
|
||||
autoPause = values[3] as Boolean,
|
||||
autoConnect = values[4] as Boolean,
|
||||
autoConnectCondition = values[5] as AutoConnectCondition,
|
||||
showPopUpOnCaseOpen = values[6] as Boolean,
|
||||
showPopUpOnConnection = values[7] as Boolean,
|
||||
)
|
||||
}.asLiveState()
|
||||
|
||||
fun setOnePodMode(enabled: Boolean) {
|
||||
reactionSettings.onePodMode.valueBlocking = enabled
|
||||
}
|
||||
|
||||
fun setAutoPlay(enabled: Boolean) = launch {
|
||||
if (!enabled) {
|
||||
reactionSettings.autoPlay.valueBlocking = false
|
||||
return@launch
|
||||
}
|
||||
if (isPro.first()) {
|
||||
reactionSettings.autoPlay.valueBlocking = true
|
||||
} else {
|
||||
navTo(Nav.Main.Upgrade)
|
||||
}
|
||||
}
|
||||
|
||||
fun setAutoPause(enabled: Boolean) = launch {
|
||||
if (!enabled) {
|
||||
reactionSettings.autoPause.valueBlocking = false
|
||||
return@launch
|
||||
}
|
||||
if (isPro.first()) {
|
||||
reactionSettings.autoPause.valueBlocking = true
|
||||
} else {
|
||||
navTo(Nav.Main.Upgrade)
|
||||
}
|
||||
}
|
||||
|
||||
fun setAutoConnect(enabled: Boolean) = launch {
|
||||
if (!enabled) {
|
||||
reactionSettings.autoConnect.valueBlocking = false
|
||||
return@launch
|
||||
}
|
||||
if (isPro.first()) {
|
||||
reactionSettings.autoConnect.valueBlocking = true
|
||||
generalSettings.monitorMode.valueBlocking = MonitorMode.ALWAYS
|
||||
} else {
|
||||
navTo(Nav.Main.Upgrade)
|
||||
}
|
||||
}
|
||||
|
||||
fun setAutoConnectCondition(condition: AutoConnectCondition) {
|
||||
reactionSettings.autoConnectCondition.valueBlocking = condition
|
||||
}
|
||||
|
||||
fun setShowPopUpOnCaseOpen(enabled: Boolean) = launch {
|
||||
if (!enabled) {
|
||||
reactionSettings.showPopUpOnCaseOpen.valueBlocking = false
|
||||
return@launch
|
||||
}
|
||||
if (isPro.first()) {
|
||||
reactionSettings.showPopUpOnCaseOpen.valueBlocking = true
|
||||
} else {
|
||||
navTo(Nav.Main.Upgrade)
|
||||
}
|
||||
}
|
||||
|
||||
fun setShowPopUpOnConnection(enabled: Boolean) = launch {
|
||||
if (!enabled) {
|
||||
reactionSettings.showPopUpOnConnection.valueBlocking = false
|
||||
return@launch
|
||||
}
|
||||
if (isPro.first()) {
|
||||
reactionSettings.showPopUpOnConnection.valueBlocking = true
|
||||
} else {
|
||||
navTo(Nav.Main.Upgrade)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = logTag("Settings", "Reaction", "VM")
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod word deur een persoon ontwikkel. Opgradering ontsluit ekstra funksies en help om die app aan die lewe te hou.</string>
|
||||
<string name="upgrade_benefit_themes">Tema-aanpassing</string>
|
||||
<string name="upgrade_benefit_autoplay">Outo-speel & outo-pouseer</string>
|
||||
<string name="upgrade_benefit_autoconnect">Outo-koppel</string>
|
||||
<string name="upgrade_benefit_popups">Opspringvenster by kas oop & verbinding</string>
|
||||
<string name="upgrade_benefit_widgets">Tuisskerm-widgets</string>
|
||||
<string name="upgrade_benefit_device_settings">Gevorderde toestel-instellings</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Toestelle</string>
|
||||
<string name="settings_devices_description">Bestuur jou toestelle.</string>
|
||||
<string name="settings_reaction_label">Reaksies</string>
|
||||
<string name="settings_reaction_description">Reageer op gebeure en gedrag.</string>
|
||||
<string name="settings_category_yourdevice_label">Jou toestel</string>
|
||||
<string name="settings_category_compatibility_options_title">Verenigbaarheidsopsies</string>
|
||||
<string name="settings_category_compatibility_options_description">Moenie aanraak as alles werk nie ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod በአንድ ሰው ብቻ ተዘጋጅቷል። ማሻሻያ ተጨማሪ ባህሪያትን ያስከፍትና መተግበሪያውን ህያው ለማቆየት ይረዳል።</string>
|
||||
<string name="upgrade_benefit_themes">ጭብጥ ብጁ አሰናዳ</string>
|
||||
<string name="upgrade_benefit_autoplay">ራስ-ሰር አጫውት & ራስ-ሰር አቁም</string>
|
||||
<string name="upgrade_benefit_autoconnect">ራስ-ሰር ግንኙነት</string>
|
||||
<string name="upgrade_benefit_popups">ቴሌ ሲከፈት & ሲገናኝ ፖፕ-አፕ</string>
|
||||
<string name="upgrade_benefit_widgets">የመነሻ ስክሪን ዊጀቶች</string>
|
||||
<string name="upgrade_benefit_device_settings">የተሻሻሉ የመሣሪያ ቅንብሮች</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">መሳሪያዎች</string>
|
||||
<string name="settings_devices_description">መሳሪያዎችዎን ያስተዳድሩ።</string>
|
||||
<string name="settings_reaction_label">ግብረመልሶች</string>
|
||||
<string name="settings_reaction_description">ለክስተቶች እና ባህሪዎች ምላሽ ይስጡ።</string>
|
||||
<string name="settings_category_yourdevice_label">የእርስዎ መሣሪያ</string>
|
||||
<string name="settings_category_compatibility_options_title">የተኳኋኝነት አማራጮች</string>
|
||||
<string name="settings_category_compatibility_options_description">ሁሉም ነገር የሚሰራ ከሆነ አይንኩ ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">تم تطوير CAPod من قِبل شخص واحد. الترقية تفتح ميزات إضافية وتساعد في إبقاء التطبيق حياً.</string>
|
||||
<string name="upgrade_benefit_themes">تخصيص السمة</string>
|
||||
<string name="upgrade_benefit_autoplay">تشغيل تلقائي وإيقاف مؤقت تلقائي</string>
|
||||
<string name="upgrade_benefit_autoconnect">اتصال تلقائي</string>
|
||||
<string name="upgrade_benefit_popups">نافذة منبثقة عند فتح الغطاء والاتصال</string>
|
||||
<string name="upgrade_benefit_widgets">عناصر واجهة الشاشة الرئيسية</string>
|
||||
<string name="upgrade_benefit_device_settings">إعدادات الجهاز المتقدمة</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">الأجهزة</string>
|
||||
<string name="settings_devices_description">إدارة أجهزتك.</string>
|
||||
<string name="settings_reaction_label">ردود الفعل</string>
|
||||
<string name="settings_reaction_description">التفاعل مع الأحداث والسلوكيات.</string>
|
||||
<string name="settings_category_yourdevice_label">جهازك</string>
|
||||
<string name="settings_category_compatibility_options_title">خيارات التوافق</string>
|
||||
<string name="settings_category_compatibility_options_description">لا تلمس إذا كان كل شيء يعمل ؛)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod tək bir şəxs tərəfindən hazırlanıb. Yüksəltmə əlavə funksiyaları açır və tətbiqin yaşamasına kömək edir.</string>
|
||||
<string name="upgrade_benefit_themes">Tema fərdiləşdirməsi</string>
|
||||
<string name="upgrade_benefit_autoplay">Avtomatik oynat və avtomatik dayandır</string>
|
||||
<string name="upgrade_benefit_autoconnect">Avtomatik qoşulma</string>
|
||||
<string name="upgrade_benefit_popups">Qutunu açarkən və qoşulduqda açılan pəncərə</string>
|
||||
<string name="upgrade_benefit_widgets">Ana ekran vidcetləri</string>
|
||||
<string name="upgrade_benefit_device_settings">Qabaqcıl cihaz parametrləri</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Cihazlar</string>
|
||||
<string name="settings_devices_description">Cihazlarınızı idarə edin.</string>
|
||||
<string name="settings_reaction_label">Reaksiyalar</string>
|
||||
<string name="settings_reaction_description">Hadisələrə və davranışlara reaksiya verin.</string>
|
||||
<string name="settings_category_yourdevice_label">Sizin cihazınız</string>
|
||||
<string name="settings_category_compatibility_options_title">Uyğunluq seçimləri</string>
|
||||
<string name="settings_category_compatibility_options_description">Hər şey işləyirsə toxunmayın ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod распрацаваны адным чалавекам. Абнаўленне разблакоўвае дадатковыя функцыі і дапамагае трымаць праграму ў жывых.</string>
|
||||
<string name="upgrade_benefit_themes">Наладка тэм</string>
|
||||
<string name="upgrade_benefit_autoplay">Аўтаматычнае прайграванне і паўза</string>
|
||||
<string name="upgrade_benefit_autoconnect">Аўтаматычнае падключэнне</string>
|
||||
<string name="upgrade_benefit_popups">Усплывальнае акно пры адкрыцці скрынкі і падключэнні</string>
|
||||
<string name="upgrade_benefit_widgets">Віджэты галоўнага экрана</string>
|
||||
<string name="upgrade_benefit_device_settings">Пашыраныя налады прылады</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Прылады</string>
|
||||
<string name="settings_devices_description">Кіруйце вашымі прыладамі.</string>
|
||||
<string name="settings_reaction_label">Рэакцыі</string>
|
||||
<string name="settings_reaction_description">Рэагаваць на падзеі і паводзіны.</string>
|
||||
<string name="settings_category_yourdevice_label">Ваша прылада</string>
|
||||
<string name="settings_category_compatibility_options_title">Параметры сумяшчальнасці</string>
|
||||
<string name="settings_category_compatibility_options_description">Не чапайце, калі ўсё працуе ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod е разработен от един човек. Надграждането отключва допълнителни функции и помага да поддържате приложението живо.</string>
|
||||
<string name="upgrade_benefit_themes">Персонализиране на тема</string>
|
||||
<string name="upgrade_benefit_autoplay">Автоматично възпроизвеждане и пауза</string>
|
||||
<string name="upgrade_benefit_autoconnect">Автоматично свързване</string>
|
||||
<string name="upgrade_benefit_popups">Изскачащ прозорец при отваряне на калъфа и свързване</string>
|
||||
<string name="upgrade_benefit_widgets">Джаджи на началния екран</string>
|
||||
<string name="upgrade_benefit_device_settings">Разширени настройки на устройството</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Устройства</string>
|
||||
<string name="settings_devices_description">Управлявайте устройствата си.</string>
|
||||
<string name="settings_reaction_label">Реакции</string>
|
||||
<string name="settings_reaction_description">Реагирайте на събития и поведения.</string>
|
||||
<string name="settings_category_yourdevice_label">Вашето устройство</string>
|
||||
<string name="settings_category_compatibility_options_title">Опции за съвместимост</string>
|
||||
<string name="settings_category_compatibility_options_description">Не пипайте, ако всичко работи ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod একজন একক ব্যক্তি দ্বারা তৈরি। আপগ্রেড করলে অতিরিক্ত বৈশিষ্ট্য আনলক হয় এবং অ্যাপটি বাঁচিয়ে রাখতে সহায়তা করে।</string>
|
||||
<string name="upgrade_benefit_themes">থিম কাস্টমাইজেশন</string>
|
||||
<string name="upgrade_benefit_autoplay">স্বয়ংক্রিয় প্লে এবং স্বয়ংক্রিয় পজ</string>
|
||||
<string name="upgrade_benefit_autoconnect">স্বয়ংক্রিয় সংযোগ</string>
|
||||
<string name="upgrade_benefit_popups">কেস খোলা ও সংযোগের সময় পপআপ</string>
|
||||
<string name="upgrade_benefit_widgets">হোম স্ক্রিন উইজেট</string>
|
||||
<string name="upgrade_benefit_device_settings">উন্নত ডিভাইস সেটিংস</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">ডিভাইস</string>
|
||||
<string name="settings_devices_description">আপনার ডিভাইসগুলি পরিচালনা করুন।</string>
|
||||
<string name="settings_reaction_label">প্রতিক্রিয়া</string>
|
||||
<string name="settings_reaction_description">ঘটনা এবং আচরণের প্রতি প্রতিক্রিয়া জানান।</string>
|
||||
<string name="settings_category_yourdevice_label">আপনার ডিভাইস</string>
|
||||
<string name="settings_category_compatibility_options_title">সামঞ্জস্যতার বিকল্প</string>
|
||||
<string name="settings_category_compatibility_options_description">সবকিছু কাজ করলে স্পর্শ করবেন না ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">El CAPod està desenvolupat per una sola persona. La millora desbloqueja funcions addicionals i ajuda a mantenir l\'aplicació activa.</string>
|
||||
<string name="upgrade_benefit_themes">Personalització de temes</string>
|
||||
<string name="upgrade_benefit_autoplay">Reproducció i pausa automàtica</string>
|
||||
<string name="upgrade_benefit_autoconnect">Connexió automàtica</string>
|
||||
<string name="upgrade_benefit_popups">Finestra emergent en obrir la funda i en connectar</string>
|
||||
<string name="upgrade_benefit_widgets">Ginys de la pantalla d\'inici</string>
|
||||
<string name="upgrade_benefit_device_settings">Configuració avançada del dispositiu</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Dispositius</string>
|
||||
<string name="settings_devices_description">Gestioneu els dispositius.</string>
|
||||
<string name="settings_reaction_label">Reaccions</string>
|
||||
<string name="settings_reaction_description">Reacció davant esdeveniments i comportaments.</string>
|
||||
<string name="settings_category_yourdevice_label">El vostre dispositiu</string>
|
||||
<string name="settings_category_compatibility_options_title">Opcions de compatibilitat</string>
|
||||
<string name="settings_category_compatibility_options_description">No ho toqueu si tot funciona ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod vyvíjí jediná osoba. Upgrade odemkne další funkce a pomůže udržet aplikaci naživu.</string>
|
||||
<string name="upgrade_benefit_themes">Přizpůsobení motivu</string>
|
||||
<string name="upgrade_benefit_autoplay">Automatické přehrávání a pozastavení</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automatické připojení</string>
|
||||
<string name="upgrade_benefit_popups">Vyskakovací okno při otevření a připojení</string>
|
||||
<string name="upgrade_benefit_widgets">Widgety domovské obrazovky</string>
|
||||
<string name="upgrade_benefit_device_settings">Pokročilá nastavení zařízení</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Zařízení</string>
|
||||
<string name="settings_devices_description">Správa zařízení.</string>
|
||||
<string name="settings_reaction_label">Reakce</string>
|
||||
<string name="settings_reaction_description">Reakce na události a chování.</string>
|
||||
<string name="settings_category_yourdevice_label">Vaše zařízení</string>
|
||||
<string name="settings_category_compatibility_options_title">Možnosti kompatibility</string>
|
||||
<string name="settings_category_compatibility_options_description">Nedotýkejte se, pokud vše funguje ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod er udviklet af én person. Opgradering låser ekstra funktioner op og hjælper med at holde appen i live.</string>
|
||||
<string name="upgrade_benefit_themes">Tema-tilpasning</string>
|
||||
<string name="upgrade_benefit_autoplay">Auto-afspilning & auto-pause</string>
|
||||
<string name="upgrade_benefit_autoconnect">Auto-tilslut</string>
|
||||
<string name="upgrade_benefit_popups">Popup ved åbning af etui & tilslutning</string>
|
||||
<string name="upgrade_benefit_widgets">Startskærm-widgets</string>
|
||||
<string name="upgrade_benefit_device_settings">Avancerede enhedsindstillinger</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Enheder</string>
|
||||
<string name="settings_devices_description">Administrer dine enheder.</string>
|
||||
<string name="settings_reaction_label">Reaktioner</string>
|
||||
<string name="settings_reaction_description">Reager på begivenheder og adfærd.</string>
|
||||
<string name="settings_category_yourdevice_label">Din enhed</string>
|
||||
<string name="settings_category_compatibility_options_title">Kompatibilitetsindstillinger</string>
|
||||
<string name="settings_category_compatibility_options_description">Rør ikke, hvis alt virker ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod wird von einer einzelnen Person entwickelt. Ein Upgrade schaltet zusätzliche Funktionen frei und hilft, die App am Leben zu erhalten.</string>
|
||||
<string name="upgrade_benefit_themes">Design-Anpassung</string>
|
||||
<string name="upgrade_benefit_autoplay">Automatische Wiedergabe & automatisches Pausieren</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automatisch verbinden</string>
|
||||
<string name="upgrade_benefit_popups">Popup beim Öffnen des Cases & bei Verbindung</string>
|
||||
<string name="upgrade_benefit_widgets">Startbildschirm-Widgets</string>
|
||||
<string name="upgrade_benefit_device_settings">Erweiterte Geräteeinstellungen</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Geräte</string>
|
||||
<string name="settings_devices_description">Verwalte Deine Geräte.</string>
|
||||
<string name="settings_reaction_label">Reaktionen</string>
|
||||
<string name="settings_reaction_description">Reagier auf Ereignisse und Verhaltensweisen.</string>
|
||||
<string name="settings_category_yourdevice_label">Dein Gerät</string>
|
||||
<string name="settings_category_compatibility_options_title">Kompatibilitätsoptionen</string>
|
||||
<string name="settings_category_compatibility_options_description">Nicht anfassen, wenn alles funktioniert ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">Το CAPod αναπτύσσεται από ένα μόνο άτομο. Η αναβάθμιση ξεκλειδώνει επιπλέον λειτουργίες και βοηθά στη συνέχεια της εφαρμογής.</string>
|
||||
<string name="upgrade_benefit_themes">Προσαρμογή θέματος</string>
|
||||
<string name="upgrade_benefit_autoplay">Αυτόματη αναπαραγωγή & αυτόματη παύση</string>
|
||||
<string name="upgrade_benefit_autoconnect">Αυτόματη σύνδεση</string>
|
||||
<string name="upgrade_benefit_popups">Αναδυόμενο παράθυρο κατά το άνοιγμα θήκης & σύνδεση</string>
|
||||
<string name="upgrade_benefit_widgets">Γραφικά στοιχεία αρχικής οθόνης</string>
|
||||
<string name="upgrade_benefit_device_settings">Προηγμένες ρυθμίσεις συσκευής</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Συσκευές</string>
|
||||
<string name="settings_devices_description">Διαχειριστείτε τις συσκευές σας.</string>
|
||||
<string name="settings_reaction_label">Αντιδράσεις</string>
|
||||
<string name="settings_reaction_description">Αντίδραση σε συμβάντα και συμπεριφορές.</string>
|
||||
<string name="settings_category_yourdevice_label">Η συσκευή σας</string>
|
||||
<string name="settings_category_compatibility_options_title">Επιλογές συμβατότητας</string>
|
||||
<string name="settings_category_compatibility_options_description">Μην αγγίζετε αν όλα λειτουργούν ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod es desarrollado por una sola persona. Actualizar desbloquea funciones extra y ayuda a mantener la app viva.</string>
|
||||
<string name="upgrade_benefit_themes">Personalización de tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Reproducción automática y pausa automática</string>
|
||||
<string name="upgrade_benefit_autoconnect">Conexión automática</string>
|
||||
<string name="upgrade_benefit_popups">Ventana emergente al abrir el estuche y al conectar</string>
|
||||
<string name="upgrade_benefit_widgets">Widgets de pantalla de inicio</string>
|
||||
<string name="upgrade_benefit_device_settings">Configuración avanzada del dispositivo</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Dispositivos</string>
|
||||
<string name="settings_devices_description">Gestionar tus dispositivos.</string>
|
||||
<string name="settings_reaction_label">Reacciones</string>
|
||||
<string name="settings_reaction_description">Reaccionar a eventos y comportamientos.</string>
|
||||
<string name="settings_category_yourdevice_label">Tu dispositivo</string>
|
||||
<string name="settings_category_compatibility_options_title">Opciones de compatibilidad</string>
|
||||
<string name="settings_category_compatibility_options_description">No tocar si todo funciona ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod es desarrollado por una sola persona. Actualizar desbloquea funciones adicionales y ayuda a mantener la aplicación activa.</string>
|
||||
<string name="upgrade_benefit_themes">Personalización de temas</string>
|
||||
<string name="upgrade_benefit_autoplay">Reproducción automática y pausa automática</string>
|
||||
<string name="upgrade_benefit_autoconnect">Conexión automática</string>
|
||||
<string name="upgrade_benefit_popups">Popup al abrir la funda y conexión</string>
|
||||
<string name="upgrade_benefit_widgets">Widgets de pantalla de inicio</string>
|
||||
<string name="upgrade_benefit_device_settings">Ajustes avanzados del dispositivo</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Dispositivos</string>
|
||||
<string name="settings_devices_description">Gestionar tus dispositivos.</string>
|
||||
<string name="settings_reaction_label">Reacciones</string>
|
||||
<string name="settings_reaction_description">Reaccionar a eventos y comportamientos.</string>
|
||||
<string name="settings_category_yourdevice_label">Tu dispositivo</string>
|
||||
<string name="settings_category_compatibility_options_title">Opciones de compatibilidad</string>
|
||||
<string name="settings_category_compatibility_options_description">No tocar si todo funciona ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod es desarrollado por una sola persona. Actualizar desbloquea funciones adicionales y ayuda a mantener la app viva.</string>
|
||||
<string name="upgrade_benefit_themes">Personalización de tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Reproducción automática y pausa automática</string>
|
||||
<string name="upgrade_benefit_autoconnect">Conexión automática</string>
|
||||
<string name="upgrade_benefit_popups">Ventana emergente al abrir el estuche y al conectar</string>
|
||||
<string name="upgrade_benefit_widgets">Widgets de pantalla de inicio</string>
|
||||
<string name="upgrade_benefit_device_settings">Configuración avanzada del dispositivo</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Dispositivos</string>
|
||||
<string name="settings_devices_description">Gestionar tus dispositivos.</string>
|
||||
<string name="settings_reaction_label">Reacciones</string>
|
||||
<string name="settings_reaction_description">Reaccionar a eventos y comportamientos.</string>
|
||||
<string name="settings_category_yourdevice_label">Tu dispositivo</string>
|
||||
<string name="settings_category_compatibility_options_title">Opciones de compatibilidad</string>
|
||||
<string name="settings_category_compatibility_options_description">No toques si todo funciona ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPodi arendab üks inimene. Uuendamine avab lisavõimalused ja aitab rakendust arendada.</string>
|
||||
<string name="upgrade_benefit_themes">Teema kohandamine</string>
|
||||
<string name="upgrade_benefit_autoplay">Automaatesitus ja automaatne paus</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automaatne ühendamine</string>
|
||||
<string name="upgrade_benefit_popups">Hüpikaken korpuse avamisel ja ühendamisel</string>
|
||||
<string name="upgrade_benefit_widgets">Avakuva vidinad</string>
|
||||
<string name="upgrade_benefit_device_settings">Täpsemad seadme sätted</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Seadmed</string>
|
||||
<string name="settings_devices_description">Seadmete haldamine.</string>
|
||||
<string name="settings_reaction_label">Reaktsioonid</string>
|
||||
<string name="settings_reaction_description">Reageerige sündmustele ja tegevustele.</string>
|
||||
<string name="settings_category_yourdevice_label">Teie seade</string>
|
||||
<string name="settings_category_compatibility_options_title">Ühilduvuse valikud</string>
|
||||
<string name="settings_category_compatibility_options_description">Las jääda, kui kõik toimib ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod pertsona bakar batek garatzen du. Berrituz gero, funtzio gehigarriak desblokeatzen dira eta aplikazioa bizirik mantentzen laguntzen duzu.</string>
|
||||
<string name="upgrade_benefit_themes">Gai pertsonalizazioa</string>
|
||||
<string name="upgrade_benefit_autoplay">Erreprodukzio automatikoa eta eten automatikoa</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automatikoki konektatu</string>
|
||||
<string name="upgrade_benefit_popups">Leiho gainerakorra kutxako irekieran eta konexioan</string>
|
||||
<string name="upgrade_benefit_widgets">Hasierako pantailako widgetak</string>
|
||||
<string name="upgrade_benefit_device_settings">Gailuaren ezarpen aurreratuak</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Gailuak</string>
|
||||
<string name="settings_devices_description">Kudeatu zure gailuak.</string>
|
||||
<string name="settings_reaction_label">Erreakzioak</string>
|
||||
<string name="settings_reaction_description">Erreakzionatu gertaera eta portaerei.</string>
|
||||
<string name="settings_category_yourdevice_label">Zure gailua</string>
|
||||
<string name="settings_category_compatibility_options_title">Bateragarritasun aukerak</string>
|
||||
<string name="settings_category_compatibility_options_description">Ez ukitu dena ondo badabil ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod توسط یک نفر توسعه داده میشود. ارتقا دادن ویژگیهای اضافی را باز میکند و به زنده نگه داشتن برنامه کمک میکند.</string>
|
||||
<string name="upgrade_benefit_themes">سفارشیسازی پوسته</string>
|
||||
<string name="upgrade_benefit_autoplay">پخش خودکار و توقف خودکار</string>
|
||||
<string name="upgrade_benefit_autoconnect">اتصال خودکار</string>
|
||||
<string name="upgrade_benefit_popups">پنجرهی بازشو هنگام باز کردن جعبه و اتصال</string>
|
||||
<string name="upgrade_benefit_widgets">ابزارکهای صفحهی اصلی</string>
|
||||
<string name="upgrade_benefit_device_settings">تنظیمات پیشرفته دستگاه</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">دستگاهها</string>
|
||||
<string name="settings_devices_description">مدیریت دستگاههای شما.</string>
|
||||
<string name="settings_reaction_label">واکنشها</string>
|
||||
<string name="settings_reaction_description">به رویدادها و رفتارها واکنش نشان دهید.</string>
|
||||
<string name="settings_category_yourdevice_label">دستگاه شما</string>
|
||||
<string name="settings_category_compatibility_options_title">گزینههای سازگاری</string>
|
||||
<string name="settings_category_compatibility_options_description">اگر همه چیز کار میکند، دست نزنید ؛)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod on yhden henkilön kehittämä. Päivittäminen avaa lisäominaisuuksia ja auttaa pitämään sovelluksen hengissä.</string>
|
||||
<string name="upgrade_benefit_themes">Teeman mukauttaminen</string>
|
||||
<string name="upgrade_benefit_autoplay">Automaattinen toisto & tauko</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automaattinen yhdistäminen</string>
|
||||
<string name="upgrade_benefit_popups">Ponnahdusikkuna koteloa avattaessa & yhdistettäessä</string>
|
||||
<string name="upgrade_benefit_widgets">Aloitusnäytön widgetit</string>
|
||||
<string name="upgrade_benefit_device_settings">Laitteiden lisäasetukset</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Laitteet</string>
|
||||
<string name="settings_devices_description">Hallitse laitteitasi.</string>
|
||||
<string name="settings_reaction_label">Reaktiot</string>
|
||||
<string name="settings_reaction_description">Reagoi tapahtumiin ja käyttäytymiseen.</string>
|
||||
<string name="settings_category_yourdevice_label">Laitteesi</string>
|
||||
<string name="settings_category_compatibility_options_title">Yhteensopivuusasetukset</string>
|
||||
<string name="settings_category_compatibility_options_description">Älä koske, jos kaikki toimii ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">Ang CAPod ay ginawa ng isang tao. Ang pag-upgrade ay nagbubukas ng mga karagdagang feature at tumutulong na mapanatiling buhay ang app.</string>
|
||||
<string name="upgrade_benefit_themes">Pag-customize ng tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Auto-play & auto-pause</string>
|
||||
<string name="upgrade_benefit_autoconnect">Auto-connect</string>
|
||||
<string name="upgrade_benefit_popups">Popup sa pagbubukas ng case & koneksyon</string>
|
||||
<string name="upgrade_benefit_widgets">Mga widget ng home screen</string>
|
||||
<string name="upgrade_benefit_device_settings">Mga advanced na setting ng device</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Mga Device</string>
|
||||
<string name="settings_devices_description">Pamahalaan ang iyong mga device.</string>
|
||||
<string name="settings_reaction_label">Mga Reaksyon</string>
|
||||
<string name="settings_reaction_description">Mag-react sa mga kaganapan at pag-uugali.</string>
|
||||
<string name="settings_category_yourdevice_label">Iyong device</string>
|
||||
<string name="settings_category_compatibility_options_title">Mga opsyon sa compatibility</string>
|
||||
<string name="settings_category_compatibility_options_description">Huwag galawin kung gumagana ang lahat ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod est développée par une seule personne. Passer à la version Pro déverrouille des fonctions supplémentaires et contribue à la pérennité de l’appli.</string>
|
||||
<string name="upgrade_benefit_themes">Personnalisation du thème</string>
|
||||
<string name="upgrade_benefit_autoplay">Lecture et pause automatiques</string>
|
||||
<string name="upgrade_benefit_autoconnect">Connexion automatique</string>
|
||||
<string name="upgrade_benefit_popups">Fenêtre de notification à l\'ouverture de l\'étui et à la connexion</string>
|
||||
<string name="upgrade_benefit_widgets">Widgets sur l’écran d’accueil</string>
|
||||
<string name="upgrade_benefit_device_settings">Paramètres avancés de l’appareil</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Appareils</string>
|
||||
<string name="settings_devices_description">Gérez vos appareils.</string>
|
||||
<string name="settings_reaction_label">Réactions</string>
|
||||
<string name="settings_reaction_description">Réagir à des événements et à des comportements.</string>
|
||||
<string name="settings_category_yourdevice_label">Votre appareil</string>
|
||||
<string name="settings_category_compatibility_options_title">Options de compatibilité</string>
|
||||
<string name="settings_category_compatibility_options_description">Ne rien changer rien si tout fonctionne ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod está desenvolvido por unha soa persoa. Actualizar desbloquea funcionalidades adicionais e axuda a manter a aplicación viva.</string>
|
||||
<string name="upgrade_benefit_themes">Personalización de temas</string>
|
||||
<string name="upgrade_benefit_autoplay">Reprodución automática e pausa automática</string>
|
||||
<string name="upgrade_benefit_autoconnect">Conexión automática</string>
|
||||
<string name="upgrade_benefit_popups">Ventá emerxente ao abrir a funda e ao conectar</string>
|
||||
<string name="upgrade_benefit_widgets">Widgets da pantalla de inicio</string>
|
||||
<string name="upgrade_benefit_device_settings">Configuración avanzada do dispositivo</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Dispositivos</string>
|
||||
<string name="settings_devices_description">Xestiona os teus dispositivos.</string>
|
||||
<string name="settings_reaction_label">Reaccións</string>
|
||||
<string name="settings_reaction_description">Reaccionar a eventos e comportamentos.</string>
|
||||
<string name="settings_category_yourdevice_label">O teu dispositivo</string>
|
||||
<string name="settings_category_compatibility_options_title">Opcións de compatibilidade</string>
|
||||
<string name="settings_category_compatibility_options_description">Non tocar se todo funciona ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod एक अकेले व्यक्ति द्वारा विकसित किया गया है। अपग्रेड करने से अतिरिक्त सुविधाएं अनलॉक होती हैं और ऐप को जीवित रखने में मदद मिलती है।</string>
|
||||
<string name="upgrade_benefit_themes">थीम अनुकूलन</string>
|
||||
<string name="upgrade_benefit_autoplay">ऑटो-प्ले और ऑटो-पॉज़</string>
|
||||
<string name="upgrade_benefit_autoconnect">ऑटो-कनेक्ट</string>
|
||||
<string name="upgrade_benefit_popups">केस खोलने और कनेक्शन पर पॉपअप</string>
|
||||
<string name="upgrade_benefit_widgets">होम स्क्रीन विजेट</string>
|
||||
<string name="upgrade_benefit_device_settings">उन्नत डिवाइस सेटिंग्स</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">डिवाइस</string>
|
||||
<string name="settings_devices_description">अपने डिवाइस प्रबंधित करें।</string>
|
||||
<string name="settings_reaction_label">प्रतिक्रियाएँ</string>
|
||||
<string name="settings_reaction_description">घटनाओं और व्यवहारों पर प्रतिक्रिया दें।</string>
|
||||
<string name="settings_category_yourdevice_label">आपका डिवाइस</string>
|
||||
<string name="settings_category_compatibility_options_title">संगतता विकल्प</string>
|
||||
<string name="settings_category_compatibility_options_description">अगर सब कुछ काम कर रहा है तो स्पर्श न करें ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod razvija jedna osoba. Nadogradnja otključava dodatne značajke i pomaže da aplikacija ostane aktivna.</string>
|
||||
<string name="upgrade_benefit_themes">Prilagodba tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Automatska reprodukcija i pauza</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automatsko povezivanje</string>
|
||||
<string name="upgrade_benefit_popups">Skočni prozor pri otvaranju kutije i spajanju</string>
|
||||
<string name="upgrade_benefit_widgets">Widgeti početnog zaslona</string>
|
||||
<string name="upgrade_benefit_device_settings">Napredne postavke uređaja</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Uređaji</string>
|
||||
<string name="settings_devices_description">Upravljajte svojim uređajima.</string>
|
||||
<string name="settings_reaction_label">Reakcije</string>
|
||||
<string name="settings_reaction_description">Reagirajte na događaje i ponašanja.</string>
|
||||
<string name="settings_category_yourdevice_label">Vaš uređaj</string>
|
||||
<string name="settings_category_compatibility_options_title">Opcije kompatibilnosti</string>
|
||||
<string name="settings_category_compatibility_options_description">Ne dirajte ako sve radi ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">A CAPod-ot egyetlen fejlesztő készíti. A frissítéssel extra funkciókat érhetsz el, és segíted az alkalmazás életben tartását.</string>
|
||||
<string name="upgrade_benefit_themes">Téma testreszabás</string>
|
||||
<string name="upgrade_benefit_autoplay">Automatikus lejátszás és szüneteltetés</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automatikus csatlakozás</string>
|
||||
<string name="upgrade_benefit_popups">Felugró ablak tok megnyitásakor és csatlakozáskor</string>
|
||||
<string name="upgrade_benefit_widgets">Kezdőképernyő-widgetek</string>
|
||||
<string name="upgrade_benefit_device_settings">Speciális eszközbeállítások</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Eszközök</string>
|
||||
<string name="settings_devices_description">Eszközök kezelése.</string>
|
||||
<string name="settings_reaction_label">Reakciók</string>
|
||||
<string name="settings_reaction_description">Reagáljon az eseményekre és viselkedésekre.</string>
|
||||
<string name="settings_category_yourdevice_label">Eszközei</string>
|
||||
<string name="settings_category_compatibility_options_title">Kompatibilitási opciók</string>
|
||||
<string name="settings_category_compatibility_options_description">Ezekhez ne nyúljon, ha minden jól műkődik ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod-ը մշակվում է մեկ անձի կողմից: Բարելավելը բացում է լրացուցիչ հնարավորություններ եւ օգնում է հավելվածը կենդանի պահել:</string>
|
||||
<string name="upgrade_benefit_themes">Թեմայի հարմարեցում</string>
|
||||
<string name="upgrade_benefit_autoplay">Ավտոնվագում & ավտոդադար</string>
|
||||
<string name="upgrade_benefit_autoconnect">Ինքնամիացում</string>
|
||||
<string name="upgrade_benefit_popups">Թռուցիկ՝ պատյան բացելիս & կապվելիս</string>
|
||||
<string name="upgrade_benefit_widgets">Գլխավոր էկրանի վիջեթներ</string>
|
||||
<string name="upgrade_benefit_device_settings">Սառքի լրացկին կառավարումներ</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Սարքեր</string>
|
||||
<string name="settings_devices_description">Կառավարեք ձեր սարքերը։</string>
|
||||
<string name="settings_reaction_label">Արձագանքներ</string>
|
||||
<string name="settings_reaction_description">Արձագանքեք իրադարձություններին և վարքագծերին։</string>
|
||||
<string name="settings_category_yourdevice_label">Ձեր սարքը</string>
|
||||
<string name="settings_category_compatibility_options_title">Համատեղելիության ընտրանքներ</string>
|
||||
<string name="settings_category_compatibility_options_description">Մի դիպչեք, եթե ամեն ինչ աշխատում է ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod dikembangkan oleh satu orang. Meningkatkan versi membuka fitur tambahan dan membantu menjaga aplikasi tetap berjalan.</string>
|
||||
<string name="upgrade_benefit_themes">Kustomisasi tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Putar otomatis & jeda otomatis</string>
|
||||
<string name="upgrade_benefit_autoconnect">Sambungkan otomatis</string>
|
||||
<string name="upgrade_benefit_popups">Popup saat kotak dibuka & dihubungkan</string>
|
||||
<string name="upgrade_benefit_widgets">Widget layar beranda</string>
|
||||
<string name="upgrade_benefit_device_settings">Pengaturan perangkat lanjutan</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Perangkat</string>
|
||||
<string name="settings_devices_description">Kelola perangkat Anda.</string>
|
||||
<string name="settings_reaction_label">Reaksi</string>
|
||||
<string name="settings_reaction_description">Bereaksi terhadap peristiwa dan perilaku.</string>
|
||||
<string name="settings_category_yourdevice_label">Perangkat Anda</string>
|
||||
<string name="settings_category_compatibility_options_title">Opsi kompatibilitas</string>
|
||||
<string name="settings_category_compatibility_options_description">Jangan sentuh jika semuanya berfungsi ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod er þróað af einum einstaklingi. Uppfærsla opnar aukaeiginleika og hjálpar til við að halda forritinu lifandi.</string>
|
||||
<string name="upgrade_benefit_themes">Sérsniðið þema</string>
|
||||
<string name="upgrade_benefit_autoplay">Sjálfvirk spilun og hlé</string>
|
||||
<string name="upgrade_benefit_autoconnect">Sjálfvirk tenging</string>
|
||||
<string name="upgrade_benefit_popups">Sprettigluggi við opnun hulsins og tengingu</string>
|
||||
<string name="upgrade_benefit_widgets">Heimaskjáviðbætur</string>
|
||||
<string name="upgrade_benefit_device_settings">Tæki stillingar (avanó)</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Tæki</string>
|
||||
<string name="settings_devices_description">Hafa umsjón með tækjunum þínum.</string>
|
||||
<string name="settings_reaction_label">Viðbrögð</string>
|
||||
<string name="settings_reaction_description">Bregðast við atburðum og hegðun.</string>
|
||||
<string name="settings_category_yourdevice_label">Tækið þitt</string>
|
||||
<string name="settings_category_compatibility_options_title">Samhæfisvalkostir</string>
|
||||
<string name="settings_category_compatibility_options_description">Ekki snerta ef allt virkar ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod è sviluppato da una singola persona. Aggiornare sblocca funzionalità extra e aiuta a mantenere l\'app in vita.</string>
|
||||
<string name="upgrade_benefit_themes">Personalizzazione tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Riproduzione automatica e pausa automatica</string>
|
||||
<string name="upgrade_benefit_autoconnect">Connessione automatica</string>
|
||||
<string name="upgrade_benefit_popups">Popup all\'apertura della custodia e alla connessione</string>
|
||||
<string name="upgrade_benefit_widgets">Widget della schermata home</string>
|
||||
<string name="upgrade_benefit_device_settings">Impostazioni avanzate dispositivo</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Dispositivi</string>
|
||||
<string name="settings_devices_description">Gestisci i tuoi dispositivi.</string>
|
||||
<string name="settings_reaction_label">Reazioni</string>
|
||||
<string name="settings_reaction_description">Reagisci a eventi e comportamenti.</string>
|
||||
<string name="settings_category_yourdevice_label">Il tuo dispositivo</string>
|
||||
<string name="settings_category_compatibility_options_title">Opzioni di compatibilità</string>
|
||||
<string name="settings_category_compatibility_options_description">Non toccare se tutto funziona ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod פותחה על ידי אדם אחד. שדרוג פותח תכונות נוספות ועוזר לשמור על האפליקציה בחיים.</string>
|
||||
<string name="upgrade_benefit_themes">התאמה אישית של ערכת נושא</string>
|
||||
<string name="upgrade_benefit_autoplay">השמעה אוטומטית והשהיה אוטומטית</string>
|
||||
<string name="upgrade_benefit_autoconnect">חיבור אוטומטי</string>
|
||||
<string name="upgrade_benefit_popups">חלון קופץ בפתיחת הנרתיק וחיבור</string>
|
||||
<string name="upgrade_benefit_widgets">ווידג\'טים למסך הבית</string>
|
||||
<string name="upgrade_benefit_device_settings">הגדרות מכשיר מתקדמות</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">מכשירים</string>
|
||||
<string name="settings_devices_description">ניהול המכשירים שלך.</string>
|
||||
<string name="settings_reaction_label">תגובות</string>
|
||||
<string name="settings_reaction_description">להגיב לאירועים והתנהגויות.</string>
|
||||
<string name="settings_category_yourdevice_label">המכשיר שלך</string>
|
||||
<string name="settings_category_compatibility_options_title">מצב תאימות</string>
|
||||
<string name="settings_category_compatibility_options_description">אל תיגע אם הכל עובד ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPodは一人の開発者によって作られています。アップグレードすると追加機能がアンロックされ、アプリの存続を支援できます。</string>
|
||||
<string name="upgrade_benefit_themes">テーマのカスタマイズ</string>
|
||||
<string name="upgrade_benefit_autoplay">自動再生 & 自動一時停止</string>
|
||||
<string name="upgrade_benefit_autoconnect">自動接続</string>
|
||||
<string name="upgrade_benefit_popups">ケースオープン & 接続時のポップアップ</string>
|
||||
<string name="upgrade_benefit_widgets">ホーム画面ウィジェット</string>
|
||||
<string name="upgrade_benefit_device_settings">詳細なデバイス設定</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">デバイス</string>
|
||||
<string name="settings_devices_description">デバイスを管理します。</string>
|
||||
<string name="settings_reaction_label">リアクション</string>
|
||||
<string name="settings_reaction_description">イベントや行動に反応します。</string>
|
||||
<string name="settings_category_yourdevice_label">あなたのデバイス</string>
|
||||
<string name="settings_category_compatibility_options_title">互換性オプション</string>
|
||||
<string name="settings_category_compatibility_options_description">すべてが機能する場合は触れないでください ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod შემუშავებულია ერთი ადამიანის მიერ. განახლება ხსნის დამატებით ფუნქციებს და ეხმარება აპს გადარჩენაში.</string>
|
||||
<string name="upgrade_benefit_themes">თემის მორგება</string>
|
||||
<string name="upgrade_benefit_autoplay">ავტო-დაკვრა და ავტო-პაუზა</string>
|
||||
<string name="upgrade_benefit_autoconnect">ავტომატური დაკავშირება</string>
|
||||
<string name="upgrade_benefit_popups">Popup ქეისის გახსნისა და დაკავშირებისას</string>
|
||||
<string name="upgrade_benefit_widgets">მთავარი ეკრანის ვიჯეტები</string>
|
||||
<string name="upgrade_benefit_device_settings">მოწყობილობის გაფართოებული პარამეტრები</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">მოწყობილობები</string>
|
||||
<string name="settings_devices_description">მართეთ თქვენი მოწყობილობები.</string>
|
||||
<string name="settings_reaction_label">რეაქციები</string>
|
||||
<string name="settings_reaction_description">რეაგირება მოვლენებსა და ქცევებზე.</string>
|
||||
<string name="settings_category_yourdevice_label">თქვენი მოწყობილობა</string>
|
||||
<string name="settings_category_compatibility_options_title">თავსებადობის პარამეტრები</string>
|
||||
<string name="settings_category_compatibility_options_description">არ შეეხოთ, თუ ყველაფერი მუშაობს ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod ត្រូវបានអភិវឌ្ឍដោយបុគ្គលម្នាក់។ ការតម្លើងកំណែថ្មីដោះសោមុខងារបន្ថែម ហើយជួយឱ្យកម្មវិធីនៅតែដំណើរការ។</string>
|
||||
<string name="upgrade_benefit_themes">ការប្ដូរទ្រង់ទ្រាយតាមបំណង</string>
|
||||
<string name="upgrade_benefit_autoplay">ចាក់ដោយស្វ័យប្រវត្តិ & ផ្អាកដោយស្វ័យប្រវត្តិ</string>
|
||||
<string name="upgrade_benefit_autoconnect">ភ្ជាប់ដោយស្វ័យប្រវត្តិ</string>
|
||||
<string name="upgrade_benefit_popups">Popup នៅពេលបើកប្រអប់ & ការភ្ជាប់</string>
|
||||
<string name="upgrade_benefit_widgets">វិជេតអេក្រង់ដើម</string>
|
||||
<string name="upgrade_benefit_device_settings">ការកំណត់ឧបករណ៍កម្រិតខ្ពស់</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">ឧបករណ៍</string>
|
||||
<string name="settings_devices_description">គ្រប់គ្រងឧបករណ៍របស់អ្នក។</string>
|
||||
<string name="settings_reaction_label">ប្រតិកម្ម</string>
|
||||
<string name="settings_reaction_description">ប្រតិកម្មចំពោះព្រឹត្តិការណ៍ និងអាកប្បកិរិយា។</string>
|
||||
<string name="settings_category_yourdevice_label">ឧបករណ៍របស់អ្នក</string>
|
||||
<string name="settings_category_compatibility_options_title">ជម្រើសភាពឆបគ្នា</string>
|
||||
<string name="settings_category_compatibility_options_description">កុំប៉ះប្រសិនបើអ្វីៗដំណើរការបានល្អ ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod ji aliyê kesekî yekane ve tê pêşxistin. Nûvekirina sepanê taybetmendiyên zêde vedike û dibe alîkar ku sepan sax bimîne.</string>
|
||||
<string name="upgrade_benefit_themes">Xweşandina temayê</string>
|
||||
<string name="upgrade_benefit_autoplay">Otomatîk lêdan & otomatîk rawestin</string>
|
||||
<string name="upgrade_benefit_autoconnect">Girêdana otomatîk</string>
|
||||
<string name="upgrade_benefit_popups">Popup dema vekirina qutiyê & girêdanê</string>
|
||||
<string name="upgrade_benefit_widgets">Widgetên ekrana malê</string>
|
||||
<string name="upgrade_benefit_device_settings">Mîhengen pêşkertî yên cîhazê</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Amûr</string>
|
||||
<string name="settings_devices_description">Amûrên xwe birêve bibin.</string>
|
||||
<string name="settings_reaction_label">Bertek</string>
|
||||
<string name="settings_reaction_description">Bertek nîşanî bûyer û tevgeran bide.</string>
|
||||
<string name="settings_category_yourdevice_label">Amûra we</string>
|
||||
<string name="settings_category_compatibility_options_title">Vebijarkên lihevhatinê</string>
|
||||
<string name="settings_category_compatibility_options_description">Heke her tişt baş dixebite dest nedin ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod ಅನ್ನು ಒಬ್ಬ ವ್ಯಕ್ತಿ ಅಭಿವೃದ್ಧಿಪಡಿಸಿದ್ದಾರೆ. ಅಪ್ಗ್ರೇಡ್ ಮಾಡುವುದರಿಂದ ಹೆಚ್ಚುವರಿ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಲಾಗುತ್ತದೆ ಮತ್ತು ಅ್ಯಾಪ್ ಅನ್ನು ಜೀವಂತವಾಗಿಡಲು ಸಹಾಯ ಮಾಡುತ್ತದೆ.</string>
|
||||
<string name="upgrade_benefit_themes">ಥೀಮ್ ಕಸ್ಟಮೈಸೇಶನ್</string>
|
||||
<string name="upgrade_benefit_autoplay">ಆಟೋ-ಪ್ಲೇ ಮತ್ತು ಆಟೋ-ಪಾಸ್</string>
|
||||
<string name="upgrade_benefit_autoconnect">ಸ್ವಯಂ-ಸಂಪರ್ಕ</string>
|
||||
<string name="upgrade_benefit_popups">ಕೇಸ್ ತೆರೆದಾಗ ಮತ್ತು ಸಂಪರ್ಕದ ಸಮಯದಲ್ಲಿ ಪಾಪಪ್</string>
|
||||
<string name="upgrade_benefit_widgets">ಹೋಮ್ ಸ್ಕ್ರೀನ್ ವಿಜೆಟ್ಗಳು</string>
|
||||
<string name="upgrade_benefit_device_settings">ಸುಧಾರಿತ ಸಾಧನ ಸೆಟ್ಟಿಂಗ್ಸ್</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">ಸಾಧನಗಳು</string>
|
||||
<string name="settings_devices_description">ನಿಮ್ಮ ಸಾಧನಗಳನ್ನು ನಿರ್ವಹಿಸಿ.</string>
|
||||
<string name="settings_reaction_label">ಪ್ರತಿಕ್ರಿಯೆಗಳು</string>
|
||||
<string name="settings_reaction_description">ಘಟನೆಗಳು ಮತ್ತು ನಡವಳಿಕೆಗಳಿಗೆ ಪ್ರತಿಕ್ರಿಯಿಸಿ.</string>
|
||||
<string name="settings_category_yourdevice_label">ನಿಮ್ಮ ಸಾಧನ</string>
|
||||
<string name="settings_category_compatibility_options_title">ಹೊಂದಾಣಿಕೆ ಆಯ್ಕೆಗಳು</string>
|
||||
<string name="settings_category_compatibility_options_description">ಎಲ್ಲವೂ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತಿದ್ದರೆ ಮುಟ್ಟಬೇಡಿ ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod는 한 명이 개발합니다. 업그레이드하면 추가 기능이 잠금 해제되고 앱 유지에 도움이 됩니다.</string>
|
||||
<string name="upgrade_benefit_themes">테마 사용자 지정</string>
|
||||
<string name="upgrade_benefit_autoplay">자동 재생 & 자동 일시정지</string>
|
||||
<string name="upgrade_benefit_autoconnect">자동 연결</string>
|
||||
<string name="upgrade_benefit_popups">케이스 열기 & 연결 시 팝업</string>
|
||||
<string name="upgrade_benefit_widgets">홈 화면 위젯</string>
|
||||
<string name="upgrade_benefit_device_settings">고급 기기 설정</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">장치</string>
|
||||
<string name="settings_devices_description">당신의 장치를 관리하세요.</string>
|
||||
<string name="settings_reaction_label">반응</string>
|
||||
<string name="settings_reaction_description">이벤트 및 행동에 반응합니다.</string>
|
||||
<string name="settings_category_yourdevice_label">내 기기</string>
|
||||
<string name="settings_category_compatibility_options_title">호환성 옵션</string>
|
||||
<string name="settings_category_compatibility_options_description">모든 것이 작동하면 건드리지 마세요 ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod бир адам тарабынан иштелип чыгат. Жаңыртуу кошумча функцияларды ачып, колдонмонун тирүү калуусуна жардам берет.</string>
|
||||
<string name="upgrade_benefit_themes">Темаларды ыңгайлаштыруу</string>
|
||||
<string name="upgrade_benefit_autoplay">Авто-ойнотуу & авто-токтотуу</string>
|
||||
<string name="upgrade_benefit_autoconnect">Авто туташуу</string>
|
||||
<string name="upgrade_benefit_popups">Кутуча ачылганда & туташканда калкыма терезе</string>
|
||||
<string name="upgrade_benefit_widgets">Башкы экран виджеттери</string>
|
||||
<string name="upgrade_benefit_device_settings">Өнүккөн түзмөк жөндөөлөрү</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Түзмөктөр</string>
|
||||
<string name="settings_devices_description">Түзмөктөрүңүздү башкаруу.</string>
|
||||
<string name="settings_reaction_label">Реакциялар</string>
|
||||
<string name="settings_reaction_description">Окуяларга жана жүрүм-турумдарга реакция кылыңыз.</string>
|
||||
<string name="settings_category_yourdevice_label">Сиздин түзмөгүңүз</string>
|
||||
<string name="settings_category_compatibility_options_title">Шайкештик опциялары</string>
|
||||
<string name="settings_category_compatibility_options_description">Эгер баары иштесе тийбеңиз ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod ຖືກພັດທະນາໂດຍຄົນດຽວ. ການອັບເກຣດຈະປົດລັອກຟີເຈີເພີ່ມເຕີມ ແລະ ຊ່ວຍຮັກສາແອັບໃຫ້ດຳເນີນຕໍ່ໄປ.</string>
|
||||
<string name="upgrade_benefit_themes">ປັບແຕ່ງຮູບແບບ</string>
|
||||
<string name="upgrade_benefit_autoplay">ຫຼິ້ນອັດຕະໂນມັດ & ຢຸດຊົ່ວຄາວອັດຕະໂນມັດ</string>
|
||||
<string name="upgrade_benefit_autoconnect">ເຊື່ອມຕໍ່ອັດຕະໂນມັດ</string>
|
||||
<string name="upgrade_benefit_popups">ປັອບອັບເມື່ອເປີດກ່ອງ & ເຊື່ອມຕໍ່</string>
|
||||
<string name="upgrade_benefit_widgets">ວິດເຈັດໜ້າຈໍຫຼັກ</string>
|
||||
<string name="upgrade_benefit_device_settings">ການຕັ້ງຄ່າອຸປະກອນຂັ້ນສູງ</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">ອຸປະກອນ</string>
|
||||
<string name="settings_devices_description">ຈັດການອຸປະກອນຂອງທ່ານ.</string>
|
||||
<string name="settings_reaction_label">ປະຕິກິລິຍາ</string>
|
||||
<string name="settings_reaction_description">ປະຕິກິລິຍາຕໍ່ເຫດການ ແລະ ພຶດຕິກຳ.</string>
|
||||
<string name="settings_category_yourdevice_label">ອຸປະກອນຂອງທ່ານ</string>
|
||||
<string name="settings_category_compatibility_options_title">ຕົວເລືອກຄວາມເຂົ້າກັນໄດ້</string>
|
||||
<string name="settings_category_compatibility_options_description">ຢ່າແຕະຕ້ອງຖ້າທຸກຢ່າງເຮັດວຽກ ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod sukūrė vienas žmogus. Atnaujinimas atrakins papildomas funkcijas ir padės išlaikyti programėlę gyvą.</string>
|
||||
<string name="upgrade_benefit_themes">Temos pritaikymas</string>
|
||||
<string name="upgrade_benefit_autoplay">Automatinis grojimas ir pauzė</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automatinis prisijungimas</string>
|
||||
<string name="upgrade_benefit_popups">Iššokantis langas atidarius dėklą ir prisijungus</string>
|
||||
<string name="upgrade_benefit_widgets">Pradinio ekrano valdikliai</string>
|
||||
<string name="upgrade_benefit_device_settings">Išplėstiniai įrenginio nustatymai</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Įrenginiai</string>
|
||||
<string name="settings_devices_description">Tvarkykite savo įrenginius.</string>
|
||||
<string name="settings_reaction_label">Reakcijos</string>
|
||||
<string name="settings_reaction_description">Reaguoti į įvykius ir elgseną.</string>
|
||||
<string name="settings_category_yourdevice_label">Jūsų įrenginys</string>
|
||||
<string name="settings_category_compatibility_options_title">Suderinamumo parinktys</string>
|
||||
<string name="settings_category_compatibility_options_description">Nelieskite, jei viskas veikia ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod ir izstrādājusi viena persona. Jaunināšana atbloķē papildu funkcijas un palīdz uzturēt lietotni pie dzīvības.</string>
|
||||
<string name="upgrade_benefit_themes">Tēmu pielāgošana</string>
|
||||
<string name="upgrade_benefit_autoplay">Automātiska atskaņošana un pauze</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automātiska savienošana</string>
|
||||
<string name="upgrade_benefit_popups">Uznirstošs logs, atverot futrāli un savienojoties</string>
|
||||
<string name="upgrade_benefit_widgets">Sākuma ekrāna logrīki</string>
|
||||
<string name="upgrade_benefit_device_settings">Papildu ierīces iestatījumi</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Ierīces</string>
|
||||
<string name="settings_devices_description">Pārvaldiet savas ierīces.</string>
|
||||
<string name="settings_reaction_label">Reakcijas</string>
|
||||
<string name="settings_reaction_description">Reaģēt uz notikumiem un uzvedību.</string>
|
||||
<string name="settings_category_yourdevice_label">Jūsu ierīce</string>
|
||||
<string name="settings_category_compatibility_options_title">Saderības opcijas</string>
|
||||
<string name="settings_category_compatibility_options_description">Neaiztieciet, ja viss darbojas ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod е развиен од една личност. Надградувањето отклучува дополнителни функции и помага да се одржи апликацијата жива.</string>
|
||||
<string name="upgrade_benefit_themes">Прилагодување на теми</string>
|
||||
<string name="upgrade_benefit_autoplay">Автоматско пуштање & автоматска пауза</string>
|
||||
<string name="upgrade_benefit_autoconnect">Автоматско поврзување</string>
|
||||
<string name="upgrade_benefit_popups">Исскочувачки прозорец при отворање на куќиштето & поврзување</string>
|
||||
<string name="upgrade_benefit_widgets">Виџети на почетниот екран</string>
|
||||
<string name="upgrade_benefit_device_settings">Напредни поставки на уредот</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Уреди</string>
|
||||
<string name="settings_devices_description">Управувајте со вашите уреди.</string>
|
||||
<string name="settings_reaction_label">Реакции</string>
|
||||
<string name="settings_reaction_description">Реагирајте на настани и однесувања.</string>
|
||||
<string name="settings_category_yourdevice_label">Вашиот уред</string>
|
||||
<string name="settings_category_compatibility_options_title">Опции за компатибилност</string>
|
||||
<string name="settings_category_compatibility_options_description">Не допирајте ако сè работи ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod ഒരൊറ്റ വ്യക്തി വികസിപ്പിച്ചതാണ്. അപ്ഗ്രേഡ് ചെയ്യുന്നത് അധിക സവിശേഷതകൾ അൺലോക്ക് ചെയ്യുകയും ആപ്പ് നിലനിർത്താൻ സഹായിക്കുകയും ചെയ്യുന്നു.</string>
|
||||
<string name="upgrade_benefit_themes">തീം ഇഷ്ടാനുസൃതമാക്കൽ</string>
|
||||
<string name="upgrade_benefit_autoplay">ഓട്ടോ-പ്ലേ & ഓട്ടോ-പോസ്</string>
|
||||
<string name="upgrade_benefit_autoconnect">ഓട്ടോ-കണക്റ്റ്</string>
|
||||
<string name="upgrade_benefit_popups">കേസ് തുറക്കുമ്പോഴും കണക്ഷൻ സമയത്തും പോപ്പ്അപ്പ്</string>
|
||||
<string name="upgrade_benefit_widgets">ഹോം സ്ക്രീൻ വിജറ്റുകൾ</string>
|
||||
<string name="upgrade_benefit_device_settings">വിപുലമായ ഉപകരണ ക്രമീകരണങ്ങൾ</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">ഉപകരണങ്ങൾ</string>
|
||||
<string name="settings_devices_description">നിങ്ങളുടെ ഉപകരണങ്ങൾ നിയന്ത്രിക്കുക.</string>
|
||||
<string name="settings_reaction_label">പ്രতিকകരണങ്ങൾ</string>
|
||||
<string name="settings_reaction_description">സംഭവങ്ങളോടും പെരുമാറ്റങ്ങളോടും പ്രതികരിക്കുക.</string>
|
||||
<string name="settings_category_yourdevice_label">നിങ്ങളുടെ ഉപകരണം</string>
|
||||
<string name="settings_category_compatibility_options_title">അനുയോജ്യത ഓപ്ഷനുകൾ</string>
|
||||
<string name="settings_category_compatibility_options_description">എല്ലാം ശരിയായി പ്രവർത്തിക്കുന്നുണ്ടെങ്കിൽ തൊടരുത് ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod-ийг нэг хүн боловсруулсан. Шинэчлэх нь нэмэлт функцуудыг нээж, аппликейшнийг амьд байлгахад тусалдаг.</string>
|
||||
<string name="upgrade_benefit_themes">Загварын тохиргоо</string>
|
||||
<string name="upgrade_benefit_autoplay">Автомат тоглуулах & автомат зогсоох</string>
|
||||
<string name="upgrade_benefit_autoconnect">Автомат холболт</string>
|
||||
<string name="upgrade_benefit_popups">Тохиолдол нээх & холбогдох үед popup</string>
|
||||
<string name="upgrade_benefit_widgets">Нүүр дэлгэцийн виджетүүд</string>
|
||||
<string name="upgrade_benefit_device_settings">Төхөөрөмжийн нарийнчилсан тохиргоо</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Төхөөрөмжүүд</string>
|
||||
<string name="settings_devices_description">Төхөөрөмжүүдээ удирдах.</string>
|
||||
<string name="settings_reaction_label">Урвалууд</string>
|
||||
<string name="settings_reaction_description">Үйл явдал, зан үйлд хариу үйлдэл үзүүлнэ.</string>
|
||||
<string name="settings_category_yourdevice_label">Таны төхөөрөмж</string>
|
||||
<string name="settings_category_compatibility_options_title">Тохиромжтой байдлын сонголтууд</string>
|
||||
<string name="settings_category_compatibility_options_description">Хэрэв бүх зүйл ажиллаж байвал бүү хүр ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod एका व्यक्तीने विकसित केला आहे. अपग्रेड केल्यास अतिरिक्त वैशिष्ट्ये मिळतात आणि अॅप सुरू ठेवण्यास मदत होते.</string>
|
||||
<string name="upgrade_benefit_themes">थीम सानुकूलन</string>
|
||||
<string name="upgrade_benefit_autoplay">ऑटो-प्ले आणि ऑटो-पॉज</string>
|
||||
<string name="upgrade_benefit_autoconnect">ऑटो-कनेक्ट</string>
|
||||
<string name="upgrade_benefit_popups">केस उघडताना आणि कनेक्शनवर पॉपअप</string>
|
||||
<string name="upgrade_benefit_widgets">होम स्क्रीन विजेट</string>
|
||||
<string name="upgrade_benefit_device_settings">प्रगत डिव्हाइस सेटिंग्ज</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">डिव्हाइस</string>
|
||||
<string name="settings_devices_description">आपल्या डिव्हाइसचे व्यवस्थापन करा.</string>
|
||||
<string name="settings_reaction_label">प्रतिक्रिया</string>
|
||||
<string name="settings_reaction_description">घटना आणि वर्तनांवर प्रतिक्रिया द्या.</string>
|
||||
<string name="settings_category_yourdevice_label">तुमचे डिव्हाइस</string>
|
||||
<string name="settings_category_compatibility_options_title">सुसंगतता पर्याय</string>
|
||||
<string name="settings_category_compatibility_options_description">सर्व काही ठीक चालत असल्यास स्पर्श करू नका ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod dibangunkan oleh seorang individu. Menaik taraf membuka kunci ciri-ciri tambahan dan membantu mengekalkan aplikasi ini.</string>
|
||||
<string name="upgrade_benefit_themes">Penyesuaian tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Main automatik & jeda automatik</string>
|
||||
<string name="upgrade_benefit_autoconnect">Sambung automatik</string>
|
||||
<string name="upgrade_benefit_popups">Popup semasa buka kotak & sambungan</string>
|
||||
<string name="upgrade_benefit_widgets">Widget skrin utama</string>
|
||||
<string name="upgrade_benefit_device_settings">Tetapan peranti lanjutan</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Peranti</string>
|
||||
<string name="settings_devices_description">Urus peranti anda.</string>
|
||||
<string name="settings_reaction_label">Reaksi</string>
|
||||
<string name="settings_reaction_description">Bertindak balas terhadap peristiwa dan tingkah laku.</string>
|
||||
<string name="settings_category_yourdevice_label">Peranti anda</string>
|
||||
<string name="settings_category_compatibility_options_title">Pilihan keserasian</string>
|
||||
<string name="settings_category_compatibility_options_description">Jangan sentuh jika semuanya berfungsi ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod ကို တစ်ဦးတည်းသောသူက တည်ဆောက်ထားသည်။ အဆင့်မြှင့်ခြင်းဖြင့် အပိုဝန်ဆောင်မှုများကို ရယူနိုင်ပြီး အက်ပ်ကို ဆက်လက်ရှင်သန်စေရန် ကူညီပေးသည်။</string>
|
||||
<string name="upgrade_benefit_themes">အပြင်အဆင် စိတ်ကြိုက်ပြင်ဆင်မှု</string>
|
||||
<string name="upgrade_benefit_autoplay">အလိုအလျောက် ဖွင့်ခြင်း & ခေတ္တရပ်ခြင်း</string>
|
||||
<string name="upgrade_benefit_autoconnect">အလိုအလျောက် ချိတ်ဆက်ခြင်း</string>
|
||||
<string name="upgrade_benefit_popups">ဖွင့်သောအခါ & ချိတ်ဆက်သောအခါ Popup ပေါ်လာခြင်း</string>
|
||||
<string name="upgrade_benefit_widgets">ပင်မစခရင် Widget များ</string>
|
||||
<string name="upgrade_benefit_device_settings">အဆင့်မြင့့်် ကိရိယာ ဆက်တင်များ</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">စက်ပစ္စည်းများ</string>
|
||||
<string name="settings_devices_description">သင့်စက်ပစ္စည်းများကို စီမံခန့်ခွဲပါ။</string>
|
||||
<string name="settings_reaction_label">တုံ့ပြန်မှုများ</string>
|
||||
<string name="settings_reaction_description">ဖြစ်ရပ်များနှင့် အပြုအမူများအပေါ် တုံ့ပြန်ပါ။</string>
|
||||
<string name="settings_category_yourdevice_label">သင့်စက်ပစ္စည်း</string>
|
||||
<string name="settings_category_compatibility_options_title">လိုက်ဖက်ညီမှုရွေးချယ်စရာများ</string>
|
||||
<string name="settings_category_compatibility_options_description">အရာအားလုံးအဆင်ပြေနေပါက မထိပါနှင့် ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod er utviklet av én person. Oppgradering låser opp ekstra funksjoner og bidrar til å holde appen i live.</string>
|
||||
<string name="upgrade_benefit_themes">Tematilpasning</string>
|
||||
<string name="upgrade_benefit_autoplay">Autoavspilling & autopause</string>
|
||||
<string name="upgrade_benefit_autoconnect">Autotilkobling</string>
|
||||
<string name="upgrade_benefit_popups">Popup ved åpning av etui & tilkobling</string>
|
||||
<string name="upgrade_benefit_widgets">Hjemmeskjerm-widgeter</string>
|
||||
<string name="upgrade_benefit_device_settings">Avanserte enhetsinnstillinger</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Enheter</string>
|
||||
<string name="settings_devices_description">Administrer enhetene dine.</string>
|
||||
<string name="settings_reaction_label">Reaksjoner</string>
|
||||
<string name="settings_reaction_description">Reager på hendelser og oppførsel.</string>
|
||||
<string name="settings_category_yourdevice_label">Enheten din</string>
|
||||
<string name="settings_category_compatibility_options_title">Kompatibilitets-alternativer</string>
|
||||
<string name="settings_category_compatibility_options_description">Ikke rør hvis alt virker ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod एकल व्यक्तिद्वारा विकास गरिएको छ। अपग्रेड गर्दा थप सुविधाहरू अनलक हुन्छन् र एपलाई जीवित राख्न मद्दत गर्छ।</string>
|
||||
<string name="upgrade_benefit_themes">थिम अनुकूलन</string>
|
||||
<string name="upgrade_benefit_autoplay">स्वत: प्ले र स्वत: पज</string>
|
||||
<string name="upgrade_benefit_autoconnect">स्वत: जडान</string>
|
||||
<string name="upgrade_benefit_popups">केस खोल्दा र जडान हुँदा पपअप</string>
|
||||
<string name="upgrade_benefit_widgets">होम स्क्रिन विजेटहरू</string>
|
||||
<string name="upgrade_benefit_device_settings">उन्नत उपकरण सेटिङहरू</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">उपकरणहरू</string>
|
||||
<string name="settings_devices_description">आफ्ना उपकरणहरू व्यवस्थापन गर्नुहोस्।</string>
|
||||
<string name="settings_reaction_label">प्रतिक्रियाहरू</string>
|
||||
<string name="settings_reaction_description">घटनाहरू र व्यवहारहरूमा प्रतिक्रिया दिनुहोस्।</string>
|
||||
<string name="settings_category_yourdevice_label">तपाईंको उपकरण</string>
|
||||
<string name="settings_category_compatibility_options_title">अनुकूलता विकल्पहरू</string>
|
||||
<string name="settings_category_compatibility_options_description">सबै कुरा ठीकठाक चलिरहेको छ भने नचलाउनुहोस् ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod wordt ontwikkeld door één persoon. Upgraden ontgrendelt extra functies en helpt de app in leven te houden.</string>
|
||||
<string name="upgrade_benefit_themes">Thema-aanpassing</string>
|
||||
<string name="upgrade_benefit_autoplay">Automatisch afspelen & pauzeren</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automatisch verbinden</string>
|
||||
<string name="upgrade_benefit_popups">Popup bij openen van hoesje & verbinding</string>
|
||||
<string name="upgrade_benefit_widgets">Startscherm-widgets</string>
|
||||
<string name="upgrade_benefit_device_settings">Geavanceerde apparaatinstellingen</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Apparaten</string>
|
||||
<string name="settings_devices_description">Beheer je apparaten.</string>
|
||||
<string name="settings_reaction_label">Reacties</string>
|
||||
<string name="settings_reaction_description">Reageren op gebeurtenissen en gedragingen.</string>
|
||||
<string name="settings_category_yourdevice_label">Uw apparaat</string>
|
||||
<string name="settings_category_compatibility_options_title">Compatibiliteitsopties</string>
|
||||
<string name="settings_category_compatibility_options_description">Niet aankomen als alles werkt ;-)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod jest rozwijany przez jedną osobę. Uaktualnienie odblokowuje dodatkowe funkcje i pomaga utrzymać aplikację przy życiu.</string>
|
||||
<string name="upgrade_benefit_themes">Personalizacja motywu</string>
|
||||
<string name="upgrade_benefit_autoplay">Automatyczne odtwarzanie i automatyczna pauza</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automatyczne połączenie</string>
|
||||
<string name="upgrade_benefit_popups">Wyskakujące okienko po otwarciu etui i połączeniu</string>
|
||||
<string name="upgrade_benefit_widgets">Widżety ekranu głównego</string>
|
||||
<string name="upgrade_benefit_device_settings">Zaawansowane ustawienia urządzenia</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Urządzenia</string>
|
||||
<string name="settings_devices_description">Zarządzaj swoimi urządzeniami.</string>
|
||||
<string name="settings_reaction_label">Reakcje</string>
|
||||
<string name="settings_reaction_description">Reakcje na wydarzenia lub zachowania.</string>
|
||||
<string name="settings_category_yourdevice_label">Twoje urządzenie</string>
|
||||
<string name="settings_category_compatibility_options_title">Opcje kompatybilności</string>
|
||||
<string name="settings_category_compatibility_options_description">Nie dotykaj, jeżeli wszystko działa ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">O CAPod é desenvolvido por uma única pessoa. Fazer upgrade desbloqueia recursos extras e ajuda a manter o aplicativo ativo.</string>
|
||||
<string name="upgrade_benefit_themes">Personalização de tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Reprodução automática & pausa automática</string>
|
||||
<string name="upgrade_benefit_autoconnect">Conexão automática</string>
|
||||
<string name="upgrade_benefit_popups">Popup ao abrir o estojo & conexão</string>
|
||||
<string name="upgrade_benefit_widgets">Widgets da tela inicial</string>
|
||||
<string name="upgrade_benefit_device_settings">Configurações avançadas do dispositivo</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Dispositivos</string>
|
||||
<string name="settings_devices_description">Gerenciar seus dispositivos</string>
|
||||
<string name="settings_reaction_label">Reações</string>
|
||||
<string name="settings_reaction_description">Reaja a eventos e comportamentos.</string>
|
||||
<string name="settings_category_yourdevice_label">Seu dispositivo</string>
|
||||
<string name="settings_category_compatibility_options_title">Opções de compatibilidade</string>
|
||||
<string name="settings_category_compatibility_options_description">Não toque se tudo funcionar ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">O CAPod é desenvolvido por uma única pessoa. Atualizar desbloqueia funcionalidades extra e ajuda a manter a aplicação ativa.</string>
|
||||
<string name="upgrade_benefit_themes">Personalização de tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Reprodução automática & pausa automática</string>
|
||||
<string name="upgrade_benefit_autoconnect">Ligar automaticamente</string>
|
||||
<string name="upgrade_benefit_popups">Pop-up ao abrir a caixa & ao ligar</string>
|
||||
<string name="upgrade_benefit_widgets">Widgets do ecrã principal</string>
|
||||
<string name="upgrade_benefit_device_settings">Definições avançadas do dispositivo</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Dispositivos</string>
|
||||
<string name="settings_devices_description">Gerir os seus dispositivos.</string>
|
||||
<string name="settings_reaction_label">Reações</string>
|
||||
<string name="settings_reaction_description">Reagir a eventos e comportamentos.</string>
|
||||
<string name="settings_category_yourdevice_label">O seu dispositivo</string>
|
||||
<string name="settings_category_compatibility_options_title">Opções de compatibilidade</string>
|
||||
<string name="settings_category_compatibility_options_description">Não mexa se tudo estiver a funcionar ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod è sviluppà da ina singula persuna. Actualisar sblucca funcziuns supplementaras ed agida a mantegnair l\'app viva.</string>
|
||||
<string name="upgrade_benefit_themes">Persunalisaziun dal tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Start automatic & pausa automatica</string>
|
||||
<string name="upgrade_benefit_autoconnect">Connectar automaticamain</string>
|
||||
<string name="upgrade_benefit_popups">Popup sin avrir il cais & connexiun</string>
|
||||
<string name="upgrade_benefit_widgets">Widgets sin l\'ècran principal</string>
|
||||
<string name="upgrade_benefit_device_settings">Parameters avanzads da l\'apparat</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Apparats</string>
|
||||
<string name="settings_devices_description">Administrar Voss apparats.</string>
|
||||
<string name="settings_reaction_label">Reacziuns</string>
|
||||
<string name="settings_reaction_description">Reagir sin eveniments e cumportaments.</string>
|
||||
<string name="settings_category_yourdevice_label">Voss apparat</string>
|
||||
<string name="settings_category_compatibility_options_title">Opziuns da cumpatibilitad</string>
|
||||
<string name="settings_category_compatibility_options_description">Betg tuccar sche tut funcziuna ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod este dezvoltat de o singură persoană. Actualizarea deblochează funcții extra și ajută la menținerea aplicației în viață.</string>
|
||||
<string name="upgrade_benefit_themes">Personalizare temă</string>
|
||||
<string name="upgrade_benefit_autoplay">Redare automată și pauză automată</string>
|
||||
<string name="upgrade_benefit_autoconnect">Conectare automată</string>
|
||||
<string name="upgrade_benefit_popups">Fereastră pop-up la deschiderea husă și conectare</string>
|
||||
<string name="upgrade_benefit_widgets">Widgeturi ecran principal</string>
|
||||
<string name="upgrade_benefit_device_settings">Setări avansate dispozitiv</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Dispozitive</string>
|
||||
<string name="settings_devices_description">Gestionați dispozitivele dvs.</string>
|
||||
<string name="settings_reaction_label">Reacții</string>
|
||||
<string name="settings_reaction_description">Reacționați la evenimente și comportamente.</string>
|
||||
<string name="settings_category_yourdevice_label">Dispozitivul tău</string>
|
||||
<string name="settings_category_compatibility_options_title">Opțiuni de compatibilitate</string>
|
||||
<string name="settings_category_compatibility_options_description">Nu atingeți dacă totul funcționează ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod разработан одним человеком. Обновление открывает дополнительные функции и помогает поддерживать приложение.</string>
|
||||
<string name="upgrade_benefit_themes">Настройка темы</string>
|
||||
<string name="upgrade_benefit_autoplay">Авто-воспроизведение и авто-пауза</string>
|
||||
<string name="upgrade_benefit_autoconnect">Автоподключение</string>
|
||||
<string name="upgrade_benefit_popups">Всплывающее окно при открытии чехла и подключении</string>
|
||||
<string name="upgrade_benefit_widgets">Виджеты главного экрана</string>
|
||||
<string name="upgrade_benefit_device_settings">Расширенные настройки устройства</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Устройства</string>
|
||||
<string name="settings_devices_description">Управление устройствами.</string>
|
||||
<string name="settings_reaction_label">Реакции</string>
|
||||
<string name="settings_reaction_description">Реакции на события и действия.</string>
|
||||
<string name="settings_category_yourdevice_label">Ваше устройство</string>
|
||||
<string name="settings_category_compatibility_options_title">Настройки совместимости</string>
|
||||
<string name="settings_category_compatibility_options_description">Не трогать, если всё работает :)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod est isvilupadu dae una sola persona. Aggiornar isbloca funtzionalidades in prus e agiudat a mantènnere s\'app in vita.</string>
|
||||
<string name="upgrade_benefit_themes">Personalizzatzione de su tema</string>
|
||||
<string name="upgrade_benefit_autoplay">Reprodutzione autom. e pausa autom.</string>
|
||||
<string name="upgrade_benefit_autoconnect">Cullegamentu automàticu</string>
|
||||
<string name="upgrade_benefit_popups">Popup a s\'apertùra de sa custodia e cullegamentu</string>
|
||||
<string name="upgrade_benefit_widgets">Widget de sa pantalla printzipale</string>
|
||||
<string name="upgrade_benefit_device_settings">Impostatziones avanzadas de su dispositivo</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Dispositivos</string>
|
||||
<string name="settings_devices_description">Gestisci is dispositivos tuos.</string>
|
||||
<string name="settings_reaction_label">Reatziones</string>
|
||||
<string name="settings_reaction_description">Reaghit a eventos e cumportamentos.</string>
|
||||
<string name="settings_category_yourdevice_label">Su dispositivu tuo</string>
|
||||
<string name="settings_category_compatibility_options_title">Opsiones de cumpatibilidade</string>
|
||||
<string name="settings_category_compatibility_options_description">Non toches si totu funtzionat ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod සකසා ඇත්තේ එක් කෙනෙකු විසිනි. යාවත්කාලීන කිරීම අමතර විශේෂාංග විවෘත කරන අතර යෙදුම ක්රියාත්මකව තබා ගැනීමට උපකාරී වේ.</string>
|
||||
<string name="upgrade_benefit_themes">තේමා අභිරුචිකරණය</string>
|
||||
<string name="upgrade_benefit_autoplay">ස්වයංක්රීය ධාවනය සහ ස්වයංක්රීය විරාමය</string>
|
||||
<string name="upgrade_benefit_autoconnect">ස්වයංක්රීයව සම්බන්ධ වන්න</string>
|
||||
<string name="upgrade_benefit_popups">කේස් විවෘත කිරීමේ සහ සම්බන්ධතාවයේ පොප්අප්</string>
|
||||
<string name="upgrade_benefit_widgets">මුල් පිටු තිර විජට්</string>
|
||||
<string name="upgrade_benefit_device_settings">උසස් උපාංග සැකසුම්</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">උපාංග</string>
|
||||
<string name="settings_devices_description">ඔබගේ උපාංග කළමනාකරණය කරන්න.</string>
|
||||
<string name="settings_reaction_label">ප්රතික්රියා</string>
|
||||
<string name="settings_reaction_description">සිදුවීම් සහ හැසිරීම් වලට ප්රතිචාර දක්වන්න.</string>
|
||||
<string name="settings_category_yourdevice_label">ඔබගේ උපාංගය</string>
|
||||
<string name="settings_category_compatibility_options_title">ගැළපුම් විකල්ප</string>
|
||||
<string name="settings_category_compatibility_options_description">සියල්ල ක්රියාත්මක නම් අත නොගසන්න ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod vyvíja jedna osoba. Aktualizácia odomkne extra funkcie a pomáha udržiavať aplikáciu v prevádzke.</string>
|
||||
<string name="upgrade_benefit_themes">Prispôsobenie tém</string>
|
||||
<string name="upgrade_benefit_autoplay">Automatické prehrávanie & pauza</string>
|
||||
<string name="upgrade_benefit_autoconnect">Automatické pripojenie</string>
|
||||
<string name="upgrade_benefit_popups">Vyskakovacie okno pri otvorení puzdra & pripojení</string>
|
||||
<string name="upgrade_benefit_widgets">Widgety domovskej obrazovky</string>
|
||||
<string name="upgrade_benefit_device_settings">Pokročilé nastavenia zariadenia</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Zariadenia</string>
|
||||
<string name="settings_devices_description">Spravujte svoje zariadenia.</string>
|
||||
<string name="settings_reaction_label">Reakcie</string>
|
||||
<string name="settings_reaction_description">Reakcia na udalosti a správanie.</string>
|
||||
<string name="settings_category_yourdevice_label">Vaše zariadenie</string>
|
||||
<string name="settings_category_compatibility_options_title">Možnosti kompatibility</string>
|
||||
<string name="settings_category_compatibility_options_description">Nedotýkajte sa, ak všetko funguje ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod je razvila ena sama oseba. Z nadgradnjo odklenete dodatne funkcije in pomagate ohranjati aplikacijo.</string>
|
||||
<string name="upgrade_benefit_themes">Prilagajanje teme</string>
|
||||
<string name="upgrade_benefit_autoplay">Samodejno predvajanje in zaustavitev</string>
|
||||
<string name="upgrade_benefit_autoconnect">Samodejna povezava</string>
|
||||
<string name="upgrade_benefit_popups">Pojavno okno ob odprtju ohišja in povezavi</string>
|
||||
<string name="upgrade_benefit_widgets">Gradniki na začetnem zaslonu</string>
|
||||
<string name="upgrade_benefit_device_settings">Napredne nastavitve naprave</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Naprave</string>
|
||||
<string name="settings_devices_description">Upravljajte svoje naprave.</string>
|
||||
<string name="settings_reaction_label">Reakcije</string>
|
||||
<string name="settings_reaction_description">Odzovite se na dogodke in vedenja.</string>
|
||||
<string name="settings_category_yourdevice_label">Vaša naprava</string>
|
||||
<string name="settings_category_compatibility_options_title">Možnosti združljivosti</string>
|
||||
<string name="settings_category_compatibility_options_description">Ne dotikajte se, če vse deluje ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod është zhvilluar nga një person i vetëm. Përmirësimi zhbllokon veçori shtesë dhe ndihmon të mbajë aplikacionin gjallë.</string>
|
||||
<string name="upgrade_benefit_themes">Personalizimi i temës</string>
|
||||
<string name="upgrade_benefit_autoplay">Auto-luaj & auto-pauzë</string>
|
||||
<string name="upgrade_benefit_autoconnect">Lidhje automatike</string>
|
||||
<string name="upgrade_benefit_popups">Dritare kërcyese kur hapet kuti & lidhja</string>
|
||||
<string name="upgrade_benefit_widgets">Miniaplikacionet e ekranit kryesor</string>
|
||||
<string name="upgrade_benefit_device_settings">Cilësimet e avancuara të pajisjes</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Pajisjet</string>
|
||||
<string name="settings_devices_description">Menaxhoni pajisjet tuaja.</string>
|
||||
<string name="settings_reaction_label">Reagimet</string>
|
||||
<string name="settings_reaction_description">Reago ndaj ngjarjeve dhe sjelljeve.</string>
|
||||
<string name="settings_category_yourdevice_label">Pajisja juaj</string>
|
||||
<string name="settings_category_compatibility_options_title">Opsionet e përputhshmërisë</string>
|
||||
<string name="settings_category_compatibility_options_description">Mos i prekni nëse gjithçka funksionon ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod је развила једна особа. Надоградњом откључавате додатне функције и помажете да апликација опстане.</string>
|
||||
<string name="upgrade_benefit_themes">Прилагођавање теме</string>
|
||||
<string name="upgrade_benefit_autoplay">Аутоматско репродуковање и паузирање</string>
|
||||
<string name="upgrade_benefit_autoconnect">Аутоматско повезивање</string>
|
||||
<string name="upgrade_benefit_popups">Искачући прозор при отварању кућишта и повезивању</string>
|
||||
<string name="upgrade_benefit_widgets">Виџети почетног екрана</string>
|
||||
<string name="upgrade_benefit_device_settings">Напредна подешавања уређаја</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Уређаји</string>
|
||||
<string name="settings_devices_description">Управљајте својим уређајима.</string>
|
||||
<string name="settings_reaction_label">Реакције</string>
|
||||
<string name="settings_reaction_description">Реагујте на догађаје и понашања.</string>
|
||||
<string name="settings_category_yourdevice_label">Ваш уређај</string>
|
||||
<string name="settings_category_compatibility_options_title">Опције компатибилности</string>
|
||||
<string name="settings_category_compatibility_options_description">Не дирајте ако све ради ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod är utvecklad av en enda person. Uppgraderingen låser upp extra funktioner och hjälper till att hålla appen vid liv.</string>
|
||||
<string name="upgrade_benefit_themes">Temoanpassning</string>
|
||||
<string name="upgrade_benefit_autoplay">Uppspelning automatiskt & automatisk paus</string>
|
||||
<string name="upgrade_benefit_autoconnect">Anslut automatiskt</string>
|
||||
<string name="upgrade_benefit_popups">Popup vid öppning av fodral & anslutning</string>
|
||||
<string name="upgrade_benefit_widgets">Hemskärmswidgetar</string>
|
||||
<string name="upgrade_benefit_device_settings">Avancerade enhetsinställningar</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Enheter</string>
|
||||
<string name="settings_devices_description">Hantera dina enheter.</string>
|
||||
<string name="settings_reaction_label">Reaktioner</string>
|
||||
<string name="settings_reaction_description">Reagera på händelser och beteenden.</string>
|
||||
<string name="settings_category_yourdevice_label">Din enhet</string>
|
||||
<string name="settings_category_compatibility_options_title">Kompatibilitetsalternativ</string>
|
||||
<string name="settings_category_compatibility_options_description">Rör inte om allt fungerar ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod inaendelezwa na mtu mmoja. Kuboresha kunafungua vipengele vya ziada na husaidia kuweka programu iwe hai.</string>
|
||||
<string name="upgrade_benefit_themes">Ubinafsishaji wa mandhari</string>
|
||||
<string name="upgrade_benefit_autoplay">Cheza kiotomatiki & simama kiotomatiki</string>
|
||||
<string name="upgrade_benefit_autoconnect">Unganisha kiotomatiki</string>
|
||||
<string name="upgrade_benefit_popups">Dirisha la kuibuka wakati wa kufungua kifuniko & muunganiko</string>
|
||||
<string name="upgrade_benefit_widgets">Wijeti za skrini ya nyumbani</string>
|
||||
<string name="upgrade_benefit_device_settings">Mipangilio ya kifaa ya hali ya juu</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Vifaa</string>
|
||||
<string name="settings_devices_description">Simamia vifaa vyako.</string>
|
||||
<string name="settings_reaction_label">Matendo</string>
|
||||
<string name="settings_reaction_description">Jibu kwa matukio na tabia.</string>
|
||||
<string name="settings_category_yourdevice_label">Kifaa chako</string>
|
||||
<string name="settings_category_compatibility_options_title">Chaguo za uoanifu</string>
|
||||
<string name="settings_category_compatibility_options_description">Usiguse ikiwa kila kitu kinafanya kazi ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod ஒரு நபரால் உருவாக்கப்பட்டது. மேம்படுத்துவது கூடுதல் அம்சங்களை திறக்கிறது மற்றும் பயன்பாட்டை உயிருடன் வைத்திருக்க உதவுகிறது.</string>
|
||||
<string name="upgrade_benefit_themes">தீம் தனிப்பயனாக்கம்</string>
|
||||
<string name="upgrade_benefit_autoplay">தானியங்கு இயக்கம் மற்றும் தானியங்கு இடைநிறுத்தம்</string>
|
||||
<string name="upgrade_benefit_autoconnect">தானியங்கு இணைப்பு</string>
|
||||
<string name="upgrade_benefit_popups">கேஸ் திறக்கும்போது மற்றும் இணைப்பின்போது பாப்அப்</string>
|
||||
<string name="upgrade_benefit_widgets">முகப்புத் திரை விட்ஜெட்கள்</string>
|
||||
<string name="upgrade_benefit_device_settings">மேம்பட்ட சாதன அமைப்புகள்</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">சாதனங்கள்</string>
|
||||
<string name="settings_devices_description">உங்கள் சாதனங்களை நிர்வகிக்கவும்.</string>
|
||||
<string name="settings_reaction_label">எதிர்வினைகள்</string>
|
||||
<string name="settings_reaction_description">நிகழ்வுகள் மற்றும் நடத்தைகளுக்கு எதிர்வினையாற்று.</string>
|
||||
<string name="settings_category_yourdevice_label">உங்கள் சாதனம்</string>
|
||||
<string name="settings_category_compatibility_options_title">இணக்கத்தன்மை விருப்பங்கள்</string>
|
||||
<string name="settings_category_compatibility_options_description">எல்லாம் வேலை செய்தால் தொடாதே ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod ఒక వ్యక్తిచే అభివృద్ధి చేయబడింది. అప్గ్రేడ్ చేయడం అదనపు ఫీచర్లను అన్లాక్ చేస్తుంది మరియు యాప్ను సజీవంగా ఉంచడానికి సహాయపడుతుంది.</string>
|
||||
<string name="upgrade_benefit_themes">థీమ్ కస్టమైజేషన్</string>
|
||||
<string name="upgrade_benefit_autoplay">ఆటో-ప్లే & ఆటో-పాజ్</string>
|
||||
<string name="upgrade_benefit_autoconnect">ఆటో-కనెక్ట్</string>
|
||||
<string name="upgrade_benefit_popups">కేస్ తెరిచినప్పుడు & కనెక్షన్పై పాప్అప్</string>
|
||||
<string name="upgrade_benefit_widgets">హోమ్ స్క్రీన్ విడ్జెట్లు</string>
|
||||
<string name="upgrade_benefit_device_settings">అధునాతన పరికర సెట్టింగ్లు</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">పరికరాలు</string>
|
||||
<string name="settings_devices_description">మీ పరికరాలను నిర్వహించండి.</string>
|
||||
<string name="settings_reaction_label">ప్రతిచర్యలు</string>
|
||||
<string name="settings_reaction_description">ఈవెంట్లు మరియు ప్రవర్తనలకు ప్రతిస్పందించండి.</string>
|
||||
<string name="settings_category_yourdevice_label">మీ పరికరం</string>
|
||||
<string name="settings_category_compatibility_options_title">అనుకూలత ఎంపికలు</string>
|
||||
<string name="settings_category_compatibility_options_description">అన్నీ పని చేస్తే తాకవద్దు ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod พัฒนาโดยบุคคลเพียงคนเดียว การอัปเกรดจะปลดล็อกฟีเจอร์เพิ่มเติมและช่วยให้แอปนี้ดำเนินต่อไปได้</string>
|
||||
<string name="upgrade_benefit_themes">การปรับแต่งธีม</string>
|
||||
<string name="upgrade_benefit_autoplay">เล่นอัตโนมัติและหยุดชั่วคราวอัตโนมัติ</string>
|
||||
<string name="upgrade_benefit_autoconnect">เชื่อมต่ออัตโนมัติ</string>
|
||||
<string name="upgrade_benefit_popups">ป๊อปอัปเมื่อเปิดเคสและเชื่อมต่อ</string>
|
||||
<string name="upgrade_benefit_widgets">วิดเจ็ตหน้าจอหลัก</string>
|
||||
<string name="upgrade_benefit_device_settings">การตั้งค่าอุปกรณ์ขั้นสูง</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">อุปกรณ์</string>
|
||||
<string name="settings_devices_description">จัดการอุปกรณ์ของคุณ</string>
|
||||
<string name="settings_reaction_label">ปฏิกิริยา</string>
|
||||
<string name="settings_reaction_description">ตอบสนองต่อเหตุการณ์และพฤติกรรม</string>
|
||||
<string name="settings_category_yourdevice_label">อุปกรณ์ของคุณ</string>
|
||||
<string name="settings_category_compatibility_options_title">ตัวเลือกความเข้ากันได้</string>
|
||||
<string name="settings_category_compatibility_options_description">อย่าแตะต้องหากทุกอย่างทำงานได้ดี ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod bir kişi tarafından geliştirilmiştir. Yükseltme ekstra özelliklerin kilidini açar ve uygulamanın canlı kalabilmesine yardımcı olur.</string>
|
||||
<string name="upgrade_benefit_themes">Tema özelleştirmesi</string>
|
||||
<string name="upgrade_benefit_autoplay">Oto-oynatma & oto-duraklatma</string>
|
||||
<string name="upgrade_benefit_autoconnect">Oto-bağlanma</string>
|
||||
<string name="upgrade_benefit_popups">Kutu açıldığında & bağlandığında popup</string>
|
||||
<string name="upgrade_benefit_widgets">Ana ekran widgetleri</string>
|
||||
<string name="upgrade_benefit_device_settings">Gelişmiş cihaz ayarları</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Cihazlar</string>
|
||||
<string name="settings_devices_description">Cihazlarınızı yönetin.</string>
|
||||
<string name="settings_reaction_label">Tepkiler</string>
|
||||
<string name="settings_reaction_description">Olaylar ve etkileşimlere verilen tepkiler.</string>
|
||||
<string name="settings_category_yourdevice_label">Aygıtınız</string>
|
||||
<string name="settings_category_compatibility_options_title">Uyumluluk seçenekleri</string>
|
||||
<string name="settings_category_compatibility_options_description">Eğer her şey düzgün çalışıyorsa lütfen dokunma ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod розробляється однією людиною. Оновлення розблоковує додаткові функції та допомагає підтримувати застосунок.</string>
|
||||
<string name="upgrade_benefit_themes">Налаштування теми</string>
|
||||
<string name="upgrade_benefit_autoplay">Автовідтворення та автопауза</string>
|
||||
<string name="upgrade_benefit_autoconnect">Автопід\'єднання</string>
|
||||
<string name="upgrade_benefit_popups">Спливаюче вікно при відкритті футляра та підключенні</string>
|
||||
<string name="upgrade_benefit_widgets">Віджети головного екрана</string>
|
||||
<string name="upgrade_benefit_device_settings">Розширені налаштування пристрою</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Пристрої</string>
|
||||
<string name="settings_devices_description">Керування вашими пристроями.</string>
|
||||
<string name="settings_reaction_label">Реакції</string>
|
||||
<string name="settings_reaction_description">Реагування на події та дії.</string>
|
||||
<string name="settings_category_yourdevice_label">Ваш пристрій</string>
|
||||
<string name="settings_category_compatibility_options_title">Опції сумісності</string>
|
||||
<string name="settings_category_compatibility_options_description">Не чіпай, якщо все працює ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod ایک اکیلے شخص نے بنائی ہے۔ اپگریڈ کرنے سے اضافی خصوصیات ملتی ہیں اور ایپ کو زندہ رکھنے میں مدد ملتی ہے۔</string>
|
||||
<string name="upgrade_benefit_themes">تھیم کی تخصیص</string>
|
||||
<string name="upgrade_benefit_autoplay">خودکار چلائیں اور خودکار رکیں</string>
|
||||
<string name="upgrade_benefit_autoconnect">خودکار کنیکٹ</string>
|
||||
<string name="upgrade_benefit_popups">کیس کھلنے اور کنیکشن پر پاپ اپ</string>
|
||||
<string name="upgrade_benefit_widgets">ہوم اسکرین ویجٹس</string>
|
||||
<string name="upgrade_benefit_device_settings">ڈیوائس کی اعلی ترتیبات</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">آلات</string>
|
||||
<string name="settings_devices_description">اپنے آلات کا نظم کریں۔</string>
|
||||
<string name="settings_reaction_label">رد عمل</string>
|
||||
<string name="settings_reaction_description">واقعات اور رویوں پر رد عمل ظاہر کریں۔</string>
|
||||
<string name="settings_category_yourdevice_label">آپ کا آلہ</string>
|
||||
<string name="settings_category_compatibility_options_title">مطابقت کے اختیارات</string>
|
||||
<string name="settings_category_compatibility_options_description">اگر سب کچھ کام کر رہا ہو تو ہاتھ نہ لگائیں ؛)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod bitta shaxs tomonidan ishlab chiqilgan. Yangilash qo\'shimcha funksiyalarni ochadi va ilovani tirik saqlashga yordam beradi.</string>
|
||||
<string name="upgrade_benefit_themes">Mavzu sozlamalari</string>
|
||||
<string name="upgrade_benefit_autoplay">Avtomatik ijro & avtomatik to\'xtatish</string>
|
||||
<string name="upgrade_benefit_autoconnect">Avtomatik ulanish</string>
|
||||
<string name="upgrade_benefit_popups">Quti ochilganda & ulanishda qalqib chiquvchi oyna</string>
|
||||
<string name="upgrade_benefit_widgets">Asosiy ekran vidjetlari</string>
|
||||
<string name="upgrade_benefit_device_settings">Qurilmaning kengaytirilgan sozlamalari</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Qurilmalar</string>
|
||||
<string name="settings_devices_description">Qurilmalaringizni boshqaring.</string>
|
||||
<string name="settings_reaction_label">Reaksiyalar</string>
|
||||
<string name="settings_reaction_description">Voqealar va xatti-harakatlarga munosabat bildiring.</string>
|
||||
<string name="settings_category_yourdevice_label">Sizning qurilmangiz</string>
|
||||
<string name="settings_category_compatibility_options_title">Moslik parametrlari</string>
|
||||
<string name="settings_category_compatibility_options_description">Agar hamma narsa ishlayotgan bo\'lsa, tegmang ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod được phát triển bởi một người duy nhất. Việc nâng cấp sẽ mở khóa các tính năng bổ sung và giúp duy trì ứng dụng.</string>
|
||||
<string name="upgrade_benefit_themes">Tùy chỉnh giao diện</string>
|
||||
<string name="upgrade_benefit_autoplay">Tự động phát & tự động tạm dừng</string>
|
||||
<string name="upgrade_benefit_autoconnect">Tự động kết nối</string>
|
||||
<string name="upgrade_benefit_popups">Cửa sổ bật lên khi mở hộp & kết nối</string>
|
||||
<string name="upgrade_benefit_widgets">Widget màn hình chính</string>
|
||||
<string name="upgrade_benefit_device_settings">Cài đặt thiết bị nâng cao</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">Thiết bị</string>
|
||||
<string name="settings_devices_description">Quản lý thiết bị của bạn.</string>
|
||||
<string name="settings_reaction_label">Phản ứng</string>
|
||||
<string name="settings_reaction_description">Phản ứng với các sự kiện và hành vi.</string>
|
||||
<string name="settings_category_yourdevice_label">Thiết bị của bạn</string>
|
||||
<string name="settings_category_compatibility_options_title">Tùy chọn tương thích</string>
|
||||
<string name="settings_category_compatibility_options_description">Đừng chạm vào nếu mọi thứ hoạt động ;)</string>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<string name="upgrade_preamble">CAPod 由一个人开发。升级可解锁额外功能,并帮助应用持续运营。</string>
|
||||
<string name="upgrade_benefit_themes">主题定制</string>
|
||||
<string name="upgrade_benefit_autoplay">自动播放 & 自动暂停</string>
|
||||
<string name="upgrade_benefit_autoconnect">自动连接</string>
|
||||
<string name="upgrade_benefit_popups">打开耳机盒 & 连接时弹出提示</string>
|
||||
<string name="upgrade_benefit_widgets">主屏幕小组件</string>
|
||||
<string name="upgrade_benefit_device_settings">高级设备设置</string>
|
||||
@@ -66,7 +65,6 @@
|
||||
<string name="settings_devices_label">设备</string>
|
||||
<string name="settings_devices_description">管理您的设备。</string>
|
||||
<string name="settings_reaction_label">动作</string>
|
||||
<string name="settings_reaction_description">响应事件和行为的动作。</string>
|
||||
<string name="settings_category_yourdevice_label">您的设备</string>
|
||||
<string name="settings_category_compatibility_options_title">兼容性选项</string>
|
||||
<string name="settings_category_compatibility_options_description">如果一切正常,请不要修改 ;)</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user