mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-14 18:26:11 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78ccddf87c | ||
|
|
df1bc48e84 | ||
|
|
3b48d61571 | ||
|
|
92d5e2a40d | ||
|
|
234857c414 | ||
|
|
b1bbe785ea | ||
|
|
487fb49bff | ||
|
|
b14b7fa926 | ||
|
|
4cc1ab143d | ||
|
|
c23de67cd2 | ||
|
|
e9bb4868c8 | ||
|
|
ae6fd0eabd | ||
|
|
f4f73906bc | ||
|
|
c437decbbf | ||
|
|
1d36677ead | ||
|
|
542b69ca92 | ||
|
|
8547c9c396 | ||
|
|
4e258e65c1 | ||
|
|
9f49b470fe | ||
|
|
4a71cfe65a | ||
|
|
d06959f964 | ||
|
|
8c339ca2eb | ||
|
|
3aab53566d | ||
|
|
749cfed137 | ||
|
|
ce25ad6711 | ||
|
|
568aeec0d5 | ||
|
|
6b02fd66e6 |
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
.idea
|
.idea
|
||||||
.gradle
|
.gradle
|
||||||
build/
|
build/
|
||||||
|
/fastlane/report.xml
|
||||||
|
|||||||
+218
@@ -0,0 +1,218 @@
|
|||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
CFPropertyList (3.0.5)
|
||||||
|
rexml
|
||||||
|
addressable (2.8.0)
|
||||||
|
public_suffix (>= 2.0.2, < 5.0)
|
||||||
|
artifactory (3.0.15)
|
||||||
|
atomos (0.1.3)
|
||||||
|
aws-eventstream (1.2.0)
|
||||||
|
aws-partitions (1.554.0)
|
||||||
|
aws-sdk-core (3.126.0)
|
||||||
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
|
aws-partitions (~> 1, >= 1.525.0)
|
||||||
|
aws-sigv4 (~> 1.1)
|
||||||
|
jmespath (~> 1.0)
|
||||||
|
aws-sdk-kms (1.54.0)
|
||||||
|
aws-sdk-core (~> 3, >= 3.126.0)
|
||||||
|
aws-sigv4 (~> 1.1)
|
||||||
|
aws-sdk-s3 (1.112.0)
|
||||||
|
aws-sdk-core (~> 3, >= 3.126.0)
|
||||||
|
aws-sdk-kms (~> 1)
|
||||||
|
aws-sigv4 (~> 1.4)
|
||||||
|
aws-sigv4 (1.4.0)
|
||||||
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
|
babosa (1.0.4)
|
||||||
|
claide (1.1.0)
|
||||||
|
colored (1.2)
|
||||||
|
colored2 (3.1.2)
|
||||||
|
commander (4.6.0)
|
||||||
|
highline (~> 2.0.0)
|
||||||
|
declarative (0.0.20)
|
||||||
|
digest-crc (0.6.4)
|
||||||
|
rake (>= 12.0.0, < 14.0.0)
|
||||||
|
domain_name (0.5.20190701)
|
||||||
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
|
dotenv (2.7.6)
|
||||||
|
emoji_regex (3.2.3)
|
||||||
|
excon (0.91.0)
|
||||||
|
faraday (1.9.3)
|
||||||
|
faraday-em_http (~> 1.0)
|
||||||
|
faraday-em_synchrony (~> 1.0)
|
||||||
|
faraday-excon (~> 1.1)
|
||||||
|
faraday-httpclient (~> 1.0)
|
||||||
|
faraday-multipart (~> 1.0)
|
||||||
|
faraday-net_http (~> 1.0)
|
||||||
|
faraday-net_http_persistent (~> 1.0)
|
||||||
|
faraday-patron (~> 1.0)
|
||||||
|
faraday-rack (~> 1.0)
|
||||||
|
faraday-retry (~> 1.0)
|
||||||
|
ruby2_keywords (>= 0.0.4)
|
||||||
|
faraday-cookie_jar (0.0.7)
|
||||||
|
faraday (>= 0.8.0)
|
||||||
|
http-cookie (~> 1.0.0)
|
||||||
|
faraday-em_http (1.0.0)
|
||||||
|
faraday-em_synchrony (1.0.0)
|
||||||
|
faraday-excon (1.1.0)
|
||||||
|
faraday-httpclient (1.0.1)
|
||||||
|
faraday-multipart (1.0.3)
|
||||||
|
multipart-post (>= 1.2, < 3)
|
||||||
|
faraday-net_http (1.0.1)
|
||||||
|
faraday-net_http_persistent (1.2.0)
|
||||||
|
faraday-patron (1.0.0)
|
||||||
|
faraday-rack (1.0.0)
|
||||||
|
faraday-retry (1.0.3)
|
||||||
|
faraday_middleware (1.2.0)
|
||||||
|
faraday (~> 1.0)
|
||||||
|
fastimage (2.2.6)
|
||||||
|
fastlane (2.204.3)
|
||||||
|
CFPropertyList (>= 2.3, < 4.0.0)
|
||||||
|
addressable (>= 2.8, < 3.0.0)
|
||||||
|
artifactory (~> 3.0)
|
||||||
|
aws-sdk-s3 (~> 1.0)
|
||||||
|
babosa (>= 1.0.3, < 2.0.0)
|
||||||
|
bundler (>= 1.12.0, < 3.0.0)
|
||||||
|
colored
|
||||||
|
commander (~> 4.6)
|
||||||
|
dotenv (>= 2.1.1, < 3.0.0)
|
||||||
|
emoji_regex (>= 0.1, < 4.0)
|
||||||
|
excon (>= 0.71.0, < 1.0.0)
|
||||||
|
faraday (~> 1.0)
|
||||||
|
faraday-cookie_jar (~> 0.0.6)
|
||||||
|
faraday_middleware (~> 1.0)
|
||||||
|
fastimage (>= 2.1.0, < 3.0.0)
|
||||||
|
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||||
|
google-apis-androidpublisher_v3 (~> 0.3)
|
||||||
|
google-apis-playcustomapp_v1 (~> 0.1)
|
||||||
|
google-cloud-storage (~> 1.31)
|
||||||
|
highline (~> 2.0)
|
||||||
|
json (< 3.0.0)
|
||||||
|
jwt (>= 2.1.0, < 3)
|
||||||
|
mini_magick (>= 4.9.4, < 5.0.0)
|
||||||
|
multipart-post (~> 2.0.0)
|
||||||
|
naturally (~> 2.2)
|
||||||
|
optparse (~> 0.1.1)
|
||||||
|
plist (>= 3.1.0, < 4.0.0)
|
||||||
|
rubyzip (>= 2.0.0, < 3.0.0)
|
||||||
|
security (= 0.1.3)
|
||||||
|
simctl (~> 1.6.3)
|
||||||
|
terminal-notifier (>= 2.0.0, < 3.0.0)
|
||||||
|
terminal-table (>= 1.4.5, < 2.0.0)
|
||||||
|
tty-screen (>= 0.6.3, < 1.0.0)
|
||||||
|
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||||
|
word_wrap (~> 1.0.0)
|
||||||
|
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||||
|
xcpretty (~> 0.3.0)
|
||||||
|
xcpretty-travis-formatter (>= 0.0.3)
|
||||||
|
gh_inspector (1.1.3)
|
||||||
|
google-apis-androidpublisher_v3 (0.16.0)
|
||||||
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
|
google-apis-core (0.4.2)
|
||||||
|
addressable (~> 2.5, >= 2.5.1)
|
||||||
|
googleauth (>= 0.16.2, < 2.a)
|
||||||
|
httpclient (>= 2.8.1, < 3.a)
|
||||||
|
mini_mime (~> 1.0)
|
||||||
|
representable (~> 3.0)
|
||||||
|
retriable (>= 2.0, < 4.a)
|
||||||
|
rexml
|
||||||
|
webrick
|
||||||
|
google-apis-iamcredentials_v1 (0.10.0)
|
||||||
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
|
google-apis-playcustomapp_v1 (0.7.0)
|
||||||
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
|
google-apis-storage_v1 (0.11.0)
|
||||||
|
google-apis-core (>= 0.4, < 2.a)
|
||||||
|
google-cloud-core (1.6.0)
|
||||||
|
google-cloud-env (~> 1.0)
|
||||||
|
google-cloud-errors (~> 1.0)
|
||||||
|
google-cloud-env (1.5.0)
|
||||||
|
faraday (>= 0.17.3, < 2.0)
|
||||||
|
google-cloud-errors (1.2.0)
|
||||||
|
google-cloud-storage (1.36.1)
|
||||||
|
addressable (~> 2.8)
|
||||||
|
digest-crc (~> 0.4)
|
||||||
|
google-apis-iamcredentials_v1 (~> 0.1)
|
||||||
|
google-apis-storage_v1 (~> 0.1)
|
||||||
|
google-cloud-core (~> 1.6)
|
||||||
|
googleauth (>= 0.16.2, < 2.a)
|
||||||
|
mini_mime (~> 1.0)
|
||||||
|
googleauth (1.1.0)
|
||||||
|
faraday (>= 0.17.3, < 2.0)
|
||||||
|
jwt (>= 1.4, < 3.0)
|
||||||
|
memoist (~> 0.16)
|
||||||
|
multi_json (~> 1.11)
|
||||||
|
os (>= 0.9, < 2.0)
|
||||||
|
signet (>= 0.16, < 2.a)
|
||||||
|
highline (2.0.3)
|
||||||
|
http-cookie (1.0.4)
|
||||||
|
domain_name (~> 0.5)
|
||||||
|
httpclient (2.8.3)
|
||||||
|
jmespath (1.5.0)
|
||||||
|
json (2.6.1)
|
||||||
|
jwt (2.3.0)
|
||||||
|
memoist (0.16.2)
|
||||||
|
mini_magick (4.11.0)
|
||||||
|
mini_mime (1.1.2)
|
||||||
|
multi_json (1.15.0)
|
||||||
|
multipart-post (2.0.0)
|
||||||
|
nanaimo (0.3.0)
|
||||||
|
naturally (2.2.1)
|
||||||
|
optparse (0.1.1)
|
||||||
|
os (1.1.4)
|
||||||
|
plist (3.6.0)
|
||||||
|
public_suffix (4.0.6)
|
||||||
|
rake (13.0.6)
|
||||||
|
representable (3.1.1)
|
||||||
|
declarative (< 0.1.0)
|
||||||
|
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||||
|
uber (< 0.2.0)
|
||||||
|
retriable (3.1.2)
|
||||||
|
rexml (3.2.5)
|
||||||
|
rouge (2.0.7)
|
||||||
|
ruby2_keywords (0.0.5)
|
||||||
|
rubyzip (2.3.2)
|
||||||
|
security (0.1.3)
|
||||||
|
signet (0.16.0)
|
||||||
|
addressable (~> 2.8)
|
||||||
|
faraday (>= 0.17.3, < 2.0)
|
||||||
|
jwt (>= 1.5, < 3.0)
|
||||||
|
multi_json (~> 1.10)
|
||||||
|
simctl (1.6.8)
|
||||||
|
CFPropertyList
|
||||||
|
naturally
|
||||||
|
terminal-notifier (2.0.0)
|
||||||
|
terminal-table (1.8.0)
|
||||||
|
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||||
|
trailblazer-option (0.1.2)
|
||||||
|
tty-cursor (0.7.1)
|
||||||
|
tty-screen (0.8.1)
|
||||||
|
tty-spinner (0.9.3)
|
||||||
|
tty-cursor (~> 0.7)
|
||||||
|
uber (0.1.0)
|
||||||
|
unf (0.1.4)
|
||||||
|
unf_ext
|
||||||
|
unf_ext (0.0.8)
|
||||||
|
unicode-display_width (1.8.0)
|
||||||
|
webrick (1.7.0)
|
||||||
|
word_wrap (1.0.0)
|
||||||
|
xcodeproj (1.21.0)
|
||||||
|
CFPropertyList (>= 2.3.3, < 4.0)
|
||||||
|
atomos (~> 0.1.3)
|
||||||
|
claide (>= 1.0.2, < 2.0)
|
||||||
|
colored2 (~> 3.1)
|
||||||
|
nanaimo (~> 0.3.0)
|
||||||
|
rexml (~> 3.2.4)
|
||||||
|
xcpretty (0.3.0)
|
||||||
|
rouge (~> 2.0.7)
|
||||||
|
xcpretty-travis-formatter (1.0.1)
|
||||||
|
xcpretty (~> 0.2, >= 0.0.7)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
x86_64-linux
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
fastlane
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
2.2.8
|
||||||
@@ -1,2 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="foss_upgrade_donate_label">Donar</string>
|
||||||
|
<string name="foss_upgrade_alreadydonated_label">Ya doné</string>
|
||||||
|
<string name="foss_upgrade_no_money_label">Gasto todo mi dinero en AirPods</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="foss_upgrade_donate_label">दान करना</string>
|
||||||
|
<string name="foss_upgrade_alreadydonated_label">मैंने पहले ही दान कर दिया है</string>
|
||||||
|
<string name="foss_upgrade_no_money_label">मैं अपना सारा पैसा AirPods पर खर्च करता हूं</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="foss_upgrade_donate_label">Dona</string>
|
||||||
|
<string name="foss_upgrade_alreadydonated_label">Ho già donato</string>
|
||||||
|
<string name="foss_upgrade_no_money_label">Spendo tutti i miei soldi per gli AirPods</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="foss_upgrade_donate_label">Doner</string>
|
||||||
|
<string name="foss_upgrade_alreadydonated_label">Jeg har allerede donert</string>
|
||||||
|
<string name="foss_upgrade_no_money_label">Jeg bruker alle pengene mine på AirPods</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="foss_upgrade_donate_label">Bağış</string>
|
||||||
|
<string name="foss_upgrade_alreadydonated_label">Ben zaten bağışladım</string>
|
||||||
|
<string name="foss_upgrade_no_money_label">Tüm paramı AirPod\'lara harcıyorum</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="upgrades_gplay_unavailable_error">Los servicios de Google Play no están disponibles.</string>
|
||||||
|
<string name="upgrades_no_purchases_found_check_account">No se han encontrado compras. ¿Estás usando la cuenta correcta?</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="upgrades_gplay_unavailable_error">Google Play सेवाएं अनुपलब्ध हैं।</string>
|
||||||
|
<string name="upgrades_no_purchases_found_check_account">कोई खरीदारी नहीं मिली. क्या आप सही खाते का उपयोग कर रहे हैं?</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="upgrades_gplay_unavailable_error">I servizi di Google Play non sono disponibili.</string>
|
||||||
|
<string name="upgrades_no_purchases_found_check_account">Nessun acquisto trovato. Stai usando l\'account giusto?</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="upgrades_gplay_unavailable_error">Google Play-tjenester er utilgjengelige.</string>
|
||||||
|
<string name="upgrades_no_purchases_found_check_account">Ingen kjøp funnet. Bruker du riktig konto?</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="upgrades_gplay_unavailable_error">Google Play hizmetleri kullanılamıyor.</string>
|
||||||
|
<string name="upgrades_no_purchases_found_check_account">Satın alma bulunamadı. Doğru hesabı mı kullanıyorsunuz?</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class BleScanner @Inject constructor(
|
|||||||
scannerMode: ScannerMode,
|
scannerMode: ScannerMode,
|
||||||
compatMode: Boolean,
|
compatMode: Boolean,
|
||||||
): Flow<List<BleScanResult>> = callbackFlow {
|
): Flow<List<BleScanResult>> = callbackFlow {
|
||||||
|
log(TAG, VERBOSE) { "scan(filters=$filters, scannerMode=$scannerMode, compatMode=$compatMode)" }
|
||||||
if (compatMode) log(TAG, WARN) { "Using compatibilityMode!" }
|
if (compatMode) log(TAG, WARN) { "Using compatibilityMode!" }
|
||||||
|
|
||||||
val adapter = bluetoothManager.adapter
|
val adapter = bluetoothManager.adapter
|
||||||
@@ -55,7 +56,11 @@ class BleScanner @Inject constructor(
|
|||||||
lastScanAt = System.currentTimeMillis()
|
lastScanAt = System.currentTimeMillis()
|
||||||
"onScanResult(delay=${delay}ms, callbackType=$callbackType, result=$result)"
|
"onScanResult(delay=${delay}ms, callbackType=$callbackType, result=$result)"
|
||||||
}
|
}
|
||||||
val toSend = if (supportsOffloadFiltering || filters.isEmpty() || filters.any { it.matches(result) }) {
|
val toSend = if (
|
||||||
|
supportsOffloadFiltering
|
||||||
|
|| filters.isEmpty()
|
||||||
|
|| filters.any { it.matchesSafe(result) }
|
||||||
|
) {
|
||||||
listOf(BleScanResult.fromScanResult(result))
|
listOf(BleScanResult.fromScanResult(result))
|
||||||
} else {
|
} else {
|
||||||
log(TAG, VERBOSE) { "Manual filtering: No match for $result" }
|
log(TAG, VERBOSE) { "Manual filtering: No match for $result" }
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
package eu.darken.capod.common.bluetooth
|
|
||||||
|
|
||||||
import android.bluetooth.BluetoothDevice
|
|
||||||
import android.os.ParcelUuid
|
|
||||||
|
|
||||||
fun BluetoothDevice.hasFeature(uuid: ParcelUuid): Boolean {
|
|
||||||
return uuids?.contains(uuid) ?: false
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package eu.darken.capod.common.bluetooth
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice
|
||||||
|
import android.bluetooth.le.ScanFilter
|
||||||
|
import android.bluetooth.le.ScanResult
|
||||||
|
import android.os.ParcelUuid
|
||||||
|
import eu.darken.capod.common.debug.logging.asLog
|
||||||
|
import eu.darken.capod.common.debug.logging.log
|
||||||
|
|
||||||
|
fun BluetoothDevice.hasFeature(uuid: ParcelUuid): Boolean {
|
||||||
|
return uuids?.contains(uuid) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.util.SparseArray.get(int)' on a null object reference
|
||||||
|
* at android.bluetooth.le.ScanRecord.getManufacturerSpecificData(ScanRecord.java:118)
|
||||||
|
* at android.bluetooth.le.ScanFilter.matches(ScanFilter.java:369)
|
||||||
|
* ZenFone Max Pro M1 (ZB602KL) (WW) / Max Pro M1 (ZB601KL) (IN) (ZB602KL), Android 9, PKQ1.WW_Phone-16.2017.2009.087-20200826
|
||||||
|
* Intel Gemini Lake Chromebook (octopus), Android 9, R99-14469.59.0 release-keys
|
||||||
|
*/
|
||||||
|
fun ScanFilter.matchesSafe(scanResult: ScanResult): Boolean = try {
|
||||||
|
matches(scanResult)
|
||||||
|
} catch (e: NullPointerException) {
|
||||||
|
log { "AOSP error: ${e.asLog()}" }
|
||||||
|
false
|
||||||
|
}
|
||||||
@@ -75,6 +75,19 @@ class FakeBleData @Inject constructor(
|
|||||||
fakeDevices.add(this)
|
fakeDevices.add(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tws i99999
|
||||||
|
BleScanResult(
|
||||||
|
address = "5E:9E:D1:29:D2:6D",
|
||||||
|
rssi = Random.nextInt(15, 75) * -1,
|
||||||
|
generatedAtNanos = SystemClockWrap.elapsedRealtimeNanos + 400,
|
||||||
|
manufacturerSpecificData = mapOf(76 to "07 13 01 02 20 71 AA 37 32 00 10 00 64 64 FF 00 00 00 00 00 00".hexToByteArray())
|
||||||
|
).run {
|
||||||
|
if (Random.nextBoolean()) {
|
||||||
|
fakeDevices.add(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Unknown Device
|
// Unknown Device
|
||||||
BleScanResult(
|
BleScanResult(
|
||||||
address = "6E:9E:D1:49:D2:6D",
|
address = "6E:9E:D1:49:D2:6D",
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class RecorderModule @Inject constructor(
|
|||||||
|
|
||||||
private fun createRecordingFilePath() = File(
|
private fun createRecordingFilePath() = File(
|
||||||
File(context.cacheDir, "debug/logs"),
|
File(context.cacheDir, "debug/logs"),
|
||||||
"bb_logfile_${System.currentTimeMillis()}.log"
|
"capod_logfile_${System.currentTimeMillis()}.log"
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun startRecorder(): File {
|
suspend fun startRecorder(): File {
|
||||||
@@ -123,6 +123,6 @@ class RecorderModule @Inject constructor(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
internal val TAG = logTag("Debug", "Log", "Recorder", "Module")
|
internal val TAG = logTag("Debug", "Log", "Recorder", "Module")
|
||||||
private const val FORCE_FILE = "bb_force_debug_run"
|
private const val FORCE_FILE = "capod_force_debug_run"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,9 +14,8 @@ import eu.darken.capod.common.lists.modular.mods.TypedVHCreatorMod
|
|||||||
import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH
|
import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH
|
||||||
import eu.darken.capod.main.ui.overview.cards.MissingMainDeviceVH
|
import eu.darken.capod.main.ui.overview.cards.MissingMainDeviceVH
|
||||||
import eu.darken.capod.main.ui.overview.cards.PermissionCardVH
|
import eu.darken.capod.main.ui.overview.cards.PermissionCardVH
|
||||||
import eu.darken.capod.main.ui.overview.cards.pods.BasicSingleApplePodsCardVH
|
import eu.darken.capod.main.ui.overview.cards.pods.DualPodsCardVH
|
||||||
import eu.darken.capod.main.ui.overview.cards.pods.DualApplePodsCardVH
|
import eu.darken.capod.main.ui.overview.cards.pods.SinglePodsCardVH
|
||||||
import eu.darken.capod.main.ui.overview.cards.pods.SingleApplePodsCardVH
|
|
||||||
import eu.darken.capod.main.ui.overview.cards.pods.UnknownPodDeviceCardVH
|
import eu.darken.capod.main.ui.overview.cards.pods.UnknownPodDeviceCardVH
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -29,9 +28,8 @@ class OverviewAdapter @Inject constructor() :
|
|||||||
init {
|
init {
|
||||||
modules.add(DataBinderMod(data))
|
modules.add(DataBinderMod(data))
|
||||||
modules.add(TypedVHCreatorMod({ data[it] is PermissionCardVH.Item }) { PermissionCardVH(it) })
|
modules.add(TypedVHCreatorMod({ data[it] is PermissionCardVH.Item }) { PermissionCardVH(it) })
|
||||||
modules.add(TypedVHCreatorMod({ data[it] is DualApplePodsCardVH.Item }) { DualApplePodsCardVH(it) })
|
modules.add(TypedVHCreatorMod({ data[it] is DualPodsCardVH.Item }) { DualPodsCardVH(it) })
|
||||||
modules.add(TypedVHCreatorMod({ data[it] is SingleApplePodsCardVH.Item }) { SingleApplePodsCardVH(it) })
|
modules.add(TypedVHCreatorMod({ data[it] is SinglePodsCardVH.Item }) { SinglePodsCardVH(it) })
|
||||||
modules.add(TypedVHCreatorMod({ data[it] is BasicSingleApplePodsCardVH.Item }) { BasicSingleApplePodsCardVH(it) })
|
|
||||||
modules.add(TypedVHCreatorMod({ data[it] is MissingMainDeviceVH.Item }) { MissingMainDeviceVH(it) })
|
modules.add(TypedVHCreatorMod({ data[it] is MissingMainDeviceVH.Item }) { MissingMainDeviceVH(it) })
|
||||||
modules.add(TypedVHCreatorMod({ data[it] is BluetoothDisabledVH.Item }) { BluetoothDisabledVH(it) })
|
modules.add(TypedVHCreatorMod({ data[it] is BluetoothDisabledVH.Item }) { BluetoothDisabledVH(it) })
|
||||||
modules.add(TypedVHCreatorMod({ data[it] is UnknownPodDeviceCardVH.Item }) { UnknownPodDeviceCardVH(it) })
|
modules.add(TypedVHCreatorMod({ data[it] is UnknownPodDeviceCardVH.Item }) { UnknownPodDeviceCardVH(it) })
|
||||||
|
|||||||
@@ -20,23 +20,23 @@ import eu.darken.capod.main.core.PermissionTool
|
|||||||
import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH
|
import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH
|
||||||
import eu.darken.capod.main.ui.overview.cards.MissingMainDeviceVH
|
import eu.darken.capod.main.ui.overview.cards.MissingMainDeviceVH
|
||||||
import eu.darken.capod.main.ui.overview.cards.PermissionCardVH
|
import eu.darken.capod.main.ui.overview.cards.PermissionCardVH
|
||||||
import eu.darken.capod.main.ui.overview.cards.pods.*
|
import eu.darken.capod.main.ui.overview.cards.pods.DualPodsCardVH
|
||||||
|
import eu.darken.capod.main.ui.overview.cards.pods.SinglePodsCardVH
|
||||||
|
import eu.darken.capod.main.ui.overview.cards.pods.UnknownPodDeviceCardVH
|
||||||
import eu.darken.capod.monitor.core.PodMonitor
|
import eu.darken.capod.monitor.core.PodMonitor
|
||||||
import eu.darken.capod.monitor.core.worker.MonitorControl
|
import eu.darken.capod.monitor.core.worker.MonitorControl
|
||||||
|
import eu.darken.capod.pods.core.DualPodDevice
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
import eu.darken.capod.pods.core.SinglePodDevice
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
|
||||||
import eu.darken.capod.pods.core.apple.SingleApplePods
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class OverviewFragmentVM @Inject constructor(
|
class OverviewFragmentVM @Inject constructor(
|
||||||
handle: SavedStateHandle,
|
@Suppress("UNUSED_PARAMETER") handle: SavedStateHandle,
|
||||||
dispatcherProvider: DispatcherProvider,
|
dispatcherProvider: DispatcherProvider,
|
||||||
private val monitorControl: MonitorControl,
|
private val monitorControl: MonitorControl,
|
||||||
private val podMonitor: PodMonitor,
|
private val podMonitor: PodMonitor,
|
||||||
@@ -74,7 +74,7 @@ class OverviewFragmentVM @Inject constructor(
|
|||||||
monitorControl.startMonitor()
|
monitorControl.startMonitor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map { Unit }
|
.map { }
|
||||||
.asLiveData2()
|
.asLiveData2()
|
||||||
|
|
||||||
val requestPermissionEvent = SingleLiveEvent<Permission>()
|
val requestPermissionEvent = SingleLiveEvent<Permission>()
|
||||||
@@ -129,19 +129,13 @@ class OverviewFragmentVM @Inject constructor(
|
|||||||
pods.map {
|
pods.map {
|
||||||
val now = Instant.now()
|
val now = Instant.now()
|
||||||
when (it) {
|
when (it) {
|
||||||
is DualApplePods -> DualApplePodsCardVH.Item(
|
is DualPodDevice -> DualPodsCardVH.Item(
|
||||||
now = now,
|
now = now,
|
||||||
device = it,
|
device = it,
|
||||||
showDebug = isDebugMode,
|
showDebug = isDebugMode,
|
||||||
isMainPod = it == mainPod,
|
isMainPod = it == mainPod,
|
||||||
)
|
)
|
||||||
is SingleApplePods -> SingleApplePodsCardVH.Item(
|
is SinglePodDevice -> SinglePodsCardVH.Item(
|
||||||
now = now,
|
|
||||||
device = it,
|
|
||||||
showDebug = isDebugMode,
|
|
||||||
isMainPod = it == mainPod,
|
|
||||||
)
|
|
||||||
is BasicSingleApplePods -> BasicSingleApplePodsCardVH.Item(
|
|
||||||
now = now,
|
now = now,
|
||||||
device = it,
|
device = it,
|
||||||
showDebug = isDebugMode,
|
showDebug = isDebugMode,
|
||||||
|
|||||||
-58
@@ -1,58 +0,0 @@
|
|||||||
package eu.darken.capod.main.ui.overview.cards.pods
|
|
||||||
|
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.core.view.isGone
|
|
||||||
import eu.darken.capod.R
|
|
||||||
import eu.darken.capod.common.lists.binding
|
|
||||||
import eu.darken.capod.databinding.OverviewPodsAppleSingleBasicItemBinding
|
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
|
||||||
import eu.darken.capod.pods.core.getBatteryDrawable
|
|
||||||
import eu.darken.capod.pods.core.getBatteryLevelHeadset
|
|
||||||
import eu.darken.capod.pods.core.lastSeenFormatted
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
class BasicSingleApplePodsCardVH(parent: ViewGroup) :
|
|
||||||
PodDeviceVH<BasicSingleApplePodsCardVH.Item, OverviewPodsAppleSingleBasicItemBinding>(
|
|
||||||
R.layout.overview_pods_apple_single_basic_item,
|
|
||||||
parent
|
|
||||||
) {
|
|
||||||
|
|
||||||
override val viewBinding = lazy { OverviewPodsAppleSingleBasicItemBinding.bind(itemView) }
|
|
||||||
|
|
||||||
override val onBindData = binding(payload = true) { item: Item ->
|
|
||||||
val device = item.device
|
|
||||||
|
|
||||||
name.apply {
|
|
||||||
text = device.getLabel(context)
|
|
||||||
if (item.isMainPod) setTypeface(typeface, Typeface.BOLD)
|
|
||||||
else setTypeface(typeface, Typeface.NORMAL)
|
|
||||||
}
|
|
||||||
|
|
||||||
deviceIcon.setImageResource(device.iconRes)
|
|
||||||
|
|
||||||
lastSeen.text = device.lastSeenFormatted(item.now)
|
|
||||||
|
|
||||||
reception.text = item.getReceptionText()
|
|
||||||
|
|
||||||
batteryLabel.text = device.getBatteryLevelHeadset(context)
|
|
||||||
batteryIcon.setImageResource(getBatteryDrawable(device.batteryHeadsetPercent))
|
|
||||||
|
|
||||||
status.apply {
|
|
||||||
val sb = StringBuilder()
|
|
||||||
if (item.showDebug) {
|
|
||||||
sb.append("--- Debug ---")
|
|
||||||
sb.append("\n").append(device.rawDataHex)
|
|
||||||
}
|
|
||||||
text = sb
|
|
||||||
isGone = !item.showDebug
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Item(
|
|
||||||
override val now: Instant,
|
|
||||||
override val device: BasicSingleApplePods,
|
|
||||||
override val showDebug: Boolean,
|
|
||||||
override val isMainPod: Boolean,
|
|
||||||
) : PodDeviceVH.Item
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
package eu.darken.capod.main.ui.overview.cards.pods
|
|
||||||
|
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.core.view.isGone
|
|
||||||
import androidx.core.view.isInvisible
|
|
||||||
import eu.darken.capod.R
|
|
||||||
import eu.darken.capod.common.lists.binding
|
|
||||||
import eu.darken.capod.databinding.OverviewPodsAppleDualItemBinding
|
|
||||||
import eu.darken.capod.pods.core.*
|
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods.DeviceColor
|
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods.LidState
|
|
||||||
import java.time.Duration
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
class DualApplePodsCardVH(parent: ViewGroup) :
|
|
||||||
PodDeviceVH<DualApplePodsCardVH.Item, OverviewPodsAppleDualItemBinding>(
|
|
||||||
R.layout.overview_pods_apple_dual_item,
|
|
||||||
parent
|
|
||||||
) {
|
|
||||||
|
|
||||||
override val viewBinding = lazy { OverviewPodsAppleDualItemBinding.bind(itemView) }
|
|
||||||
|
|
||||||
override val onBindData = binding(payload = true) { item: Item ->
|
|
||||||
val device = item.device
|
|
||||||
name.apply {
|
|
||||||
val sb = StringBuilder(device.getLabel(context))
|
|
||||||
if (!listOf(DeviceColor.WHITE, DeviceColor.UNKNOWN).contains(device.deviceColor)) {
|
|
||||||
sb.append(" (${device.deviceColor.name})")
|
|
||||||
}
|
|
||||||
text = sb
|
|
||||||
if (item.isMainPod) setTypeface(typeface, Typeface.BOLD)
|
|
||||||
else setTypeface(typeface, Typeface.NORMAL)
|
|
||||||
if (item.showDebug) {
|
|
||||||
append(" [${device.primaryPod.name}]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deviceIcon.setImageResource(device.iconRes)
|
|
||||||
|
|
||||||
lastSeen.text = context.getString(R.string.last_seen_x, device.lastSeenFormatted(item.now))
|
|
||||||
firstSeen.text = context.getString(R.string.first_seen_x, device.firstSeenFormatted(item.now))
|
|
||||||
firstSeen.isGone = Duration.between(device.seenFirstAt, device.seenLastAt).toMinutes() < 1
|
|
||||||
|
|
||||||
reception.text = item.getReceptionText()
|
|
||||||
|
|
||||||
// Left Pod
|
|
||||||
device.apply {
|
|
||||||
podLeftBatteryIcon.setImageResource(getBatteryDrawable(batteryLeftPodPercent))
|
|
||||||
podLeftBatteryLabel.text = getBatteryLevelLeftPod(context)
|
|
||||||
|
|
||||||
podLeftChargingIcon.isInvisible = !isLeftPodCharging
|
|
||||||
podLeftChargingLabel.isInvisible = !isLeftPodCharging
|
|
||||||
|
|
||||||
podLeftMicrophoneIcon.isInvisible = !isLeftPodMicrophone
|
|
||||||
podLeftMicrophoneLabel.isInvisible = !isLeftPodMicrophone
|
|
||||||
|
|
||||||
podLeftWearIcon.isInvisible = !isLeftPodInEar
|
|
||||||
podLeftWearLabel.isInvisible = !isLeftPodInEar
|
|
||||||
}
|
|
||||||
|
|
||||||
// Right Pod
|
|
||||||
device.apply {
|
|
||||||
podRightBatteryIcon.setImageResource(getBatteryDrawable(batteryRightPodPercent))
|
|
||||||
podRightBatteryLabel.text = getBatteryLevelRightPod(context)
|
|
||||||
|
|
||||||
podRightChargingIcon.isInvisible = !isRightPodCharging
|
|
||||||
podRightChargingLabel.isInvisible = !isRightPodCharging
|
|
||||||
|
|
||||||
podRightMicrophoneIcon.isInvisible = !isRightPodMicrophone
|
|
||||||
podRightMicrophoneLabel.isInvisible = !isRightPodMicrophone
|
|
||||||
|
|
||||||
podRightWearIcon.isInvisible = !isRightPodInEar
|
|
||||||
podRightWearLabel.isInvisible = !isRightPodInEar
|
|
||||||
}
|
|
||||||
|
|
||||||
// Case
|
|
||||||
device.apply {
|
|
||||||
podCaseBatteryIcon.setImageResource(getBatteryDrawable(batteryCasePercent))
|
|
||||||
podCaseBatteryLabel.text = getBatteryLevelCase(context)
|
|
||||||
|
|
||||||
podCaseChargingIcon.isInvisible = !isCaseCharging
|
|
||||||
podCaseChargingLabel.isInvisible = !isCaseCharging
|
|
||||||
|
|
||||||
podCaseLidLabel.text = when (caseLidState) {
|
|
||||||
LidState.OPEN -> context.getString(R.string.pods_case_status_open_label)
|
|
||||||
LidState.CLOSED -> context.getString(R.string.pods_case_status_closed_label)
|
|
||||||
else -> context.getString(R.string.pods_case_unknown_state)
|
|
||||||
}
|
|
||||||
|
|
||||||
val hideInfo = !listOf(LidState.OPEN, LidState.CLOSED).contains(caseLidState)
|
|
||||||
podCaseLidIcon.isInvisible = hideInfo
|
|
||||||
podCaseLidLabel.isInvisible = hideInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
status.apply {
|
|
||||||
val sb = StringBuilder(device.getConnectionStateLabel(context))
|
|
||||||
if (item.showDebug) {
|
|
||||||
sb.append("\n\n").append("---Debug---")
|
|
||||||
sb.append("\n").append(device.rawDataHex)
|
|
||||||
}
|
|
||||||
text = sb
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Item(
|
|
||||||
override val now: Instant,
|
|
||||||
override val device: DualApplePods,
|
|
||||||
override val showDebug: Boolean,
|
|
||||||
override val isMainPod: Boolean,
|
|
||||||
) : PodDeviceVH.Item
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
package eu.darken.capod.main.ui.overview.cards.pods
|
||||||
|
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isGone
|
||||||
|
import androidx.core.view.isInvisible
|
||||||
|
import eu.darken.capod.R
|
||||||
|
import eu.darken.capod.common.lists.binding
|
||||||
|
import eu.darken.capod.databinding.OverviewPodsDualItemBinding
|
||||||
|
import eu.darken.capod.pods.core.*
|
||||||
|
import eu.darken.capod.pods.core.apple.DualAirPods
|
||||||
|
import eu.darken.capod.pods.core.apple.DualAirPods.LidState
|
||||||
|
import java.time.Duration
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
class DualPodsCardVH(parent: ViewGroup) :
|
||||||
|
PodDeviceVH<DualPodsCardVH.Item, OverviewPodsDualItemBinding>(
|
||||||
|
R.layout.overview_pods_dual_item,
|
||||||
|
parent
|
||||||
|
) {
|
||||||
|
|
||||||
|
override val viewBinding = lazy { OverviewPodsDualItemBinding.bind(itemView) }
|
||||||
|
|
||||||
|
override val onBindData = binding(payload = true) { item: Item ->
|
||||||
|
val device = item.device
|
||||||
|
name.apply {
|
||||||
|
val sb = StringBuilder(device.getLabel(context))
|
||||||
|
if (device is HasPodStyle && item.showDebug) {
|
||||||
|
val style = device.podStyle
|
||||||
|
sb.append(" (${style.getColor(context)})")
|
||||||
|
}
|
||||||
|
text = sb
|
||||||
|
|
||||||
|
if (item.isMainPod) setTypeface(typeface, Typeface.BOLD)
|
||||||
|
else setTypeface(typeface, Typeface.NORMAL)
|
||||||
|
|
||||||
|
if (device is DualAirPods && item.showDebug) {
|
||||||
|
append(" [${device.primaryPod.name}]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deviceIcon.setImageResource(device.iconRes)
|
||||||
|
|
||||||
|
lastSeen.text = context.getString(R.string.last_seen_x, device.lastSeenFormatted(item.now))
|
||||||
|
firstSeen.text = context.getString(R.string.first_seen_x, device.firstSeenFormatted(item.now))
|
||||||
|
firstSeen.isGone = Duration.between(device.seenFirstAt, device.seenLastAt).toMinutes() < 1
|
||||||
|
|
||||||
|
reception.text = item.getReceptionText()
|
||||||
|
|
||||||
|
// Pods battery state
|
||||||
|
device.apply {
|
||||||
|
podLeftBatteryIcon.setImageResource(getBatteryDrawable(batteryLeftPodPercent))
|
||||||
|
podLeftBatteryLabel.text = getBatteryLevelLeftPod(context)
|
||||||
|
|
||||||
|
podRightBatteryIcon.setImageResource(getBatteryDrawable(batteryRightPodPercent))
|
||||||
|
podRightBatteryLabel.text = getBatteryLevelRightPod(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pods charging state
|
||||||
|
device.apply {
|
||||||
|
if (this is HasChargeDetectionDual) {
|
||||||
|
podLeftChargingIcon.isInvisible = !isLeftPodCharging
|
||||||
|
podLeftChargingLabel.isInvisible = !isLeftPodCharging
|
||||||
|
|
||||||
|
podRightChargingIcon.isInvisible = !isRightPodCharging
|
||||||
|
podRightChargingLabel.isInvisible = !isRightPodCharging
|
||||||
|
} else {
|
||||||
|
podLeftChargingIcon.isGone = true
|
||||||
|
podLeftChargingLabel.isGone = true
|
||||||
|
|
||||||
|
podRightChargingIcon.isGone = true
|
||||||
|
podRightChargingLabel.isGone = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Microphone state
|
||||||
|
device.apply {
|
||||||
|
if (this is HasDualMicrophone) {
|
||||||
|
podLeftMicrophoneIcon.isInvisible = !isLeftPodMicrophone
|
||||||
|
podLeftMicrophoneLabel.isInvisible = !isLeftPodMicrophone
|
||||||
|
|
||||||
|
podRightMicrophoneIcon.isInvisible = !isRightPodMicrophone
|
||||||
|
podRightMicrophoneLabel.isInvisible = !isRightPodMicrophone
|
||||||
|
} else {
|
||||||
|
podLeftMicrophoneIcon.isGone = true
|
||||||
|
podLeftMicrophoneLabel.isGone = true
|
||||||
|
|
||||||
|
podRightMicrophoneIcon.isGone = true
|
||||||
|
podRightMicrophoneLabel.isGone = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pods wear state
|
||||||
|
device.apply {
|
||||||
|
if (this is HasEarDetectionDual) {
|
||||||
|
podLeftWearIcon.isInvisible = !isLeftPodInEar
|
||||||
|
podLeftWearLabel.isInvisible = !isLeftPodInEar
|
||||||
|
|
||||||
|
podRightWearIcon.isInvisible = !isRightPodInEar
|
||||||
|
podRightWearLabel.isInvisible = !isRightPodInEar
|
||||||
|
} else {
|
||||||
|
podLeftWearIcon.isGone = true
|
||||||
|
podLeftWearLabel.isGone = true
|
||||||
|
|
||||||
|
podRightWearIcon.isGone = true
|
||||||
|
podRightWearLabel.isGone = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case charge state
|
||||||
|
device.apply {
|
||||||
|
if (this is HasCase) {
|
||||||
|
podCaseBatteryIcon.isGone = false
|
||||||
|
podCaseBatteryIcon.setImageResource(getBatteryDrawable(batteryCasePercent))
|
||||||
|
podCaseBatteryLabel.text = getBatteryLevelCase(context)
|
||||||
|
|
||||||
|
podCaseChargingIcon.isInvisible = !isCaseCharging
|
||||||
|
podCaseChargingLabel.isInvisible = !isCaseCharging
|
||||||
|
} else {
|
||||||
|
podCaseBatteryIcon.isGone = true
|
||||||
|
podCaseBatteryLabel.isGone = true
|
||||||
|
|
||||||
|
podCaseChargingIcon.isGone = true
|
||||||
|
podCaseChargingLabel.isGone = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case lid state
|
||||||
|
device.apply {
|
||||||
|
if (this is DualAirPods) {
|
||||||
|
podCaseLidLabel.text = when (caseLidState) {
|
||||||
|
LidState.OPEN -> context.getString(R.string.pods_case_status_open_label)
|
||||||
|
LidState.CLOSED -> context.getString(R.string.pods_case_status_closed_label)
|
||||||
|
else -> context.getString(R.string.pods_case_unknown_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
val hideInfo = !listOf(LidState.OPEN, LidState.CLOSED).contains(caseLidState)
|
||||||
|
podCaseLidIcon.isInvisible = hideInfo
|
||||||
|
podCaseLidLabel.isInvisible = hideInfo
|
||||||
|
} else {
|
||||||
|
podCaseLidIcon.isGone = true
|
||||||
|
podCaseLidLabel.isGone = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connection state
|
||||||
|
device.apply {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
if (this is HasStateDetection) {
|
||||||
|
sb.append(state.getLabel(context))
|
||||||
|
}
|
||||||
|
if (item.showDebug) {
|
||||||
|
sb.append("\n\n").append("---Debug---")
|
||||||
|
sb.append("\n").append(rawDataHex)
|
||||||
|
}
|
||||||
|
status.text = sb
|
||||||
|
status.isGone = sb.isEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Item(
|
||||||
|
override val now: Instant,
|
||||||
|
override val device: DualPodDevice,
|
||||||
|
override val showDebug: Boolean,
|
||||||
|
override val isMainPod: Boolean,
|
||||||
|
) : PodDeviceVH.Item
|
||||||
|
}
|
||||||
-65
@@ -1,65 +0,0 @@
|
|||||||
package eu.darken.capod.main.ui.overview.cards.pods
|
|
||||||
|
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.core.view.isGone
|
|
||||||
import androidx.core.view.isInvisible
|
|
||||||
import eu.darken.capod.R
|
|
||||||
import eu.darken.capod.common.lists.binding
|
|
||||||
import eu.darken.capod.databinding.OverviewPodsAppleSingleItemBinding
|
|
||||||
import eu.darken.capod.pods.core.apple.SingleApplePods
|
|
||||||
import eu.darken.capod.pods.core.getBatteryDrawable
|
|
||||||
import eu.darken.capod.pods.core.getBatteryLevelHeadset
|
|
||||||
import eu.darken.capod.pods.core.lastSeenFormatted
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
class SingleApplePodsCardVH(parent: ViewGroup) :
|
|
||||||
PodDeviceVH<SingleApplePodsCardVH.Item, OverviewPodsAppleSingleItemBinding>(
|
|
||||||
R.layout.overview_pods_apple_single_item,
|
|
||||||
parent
|
|
||||||
) {
|
|
||||||
|
|
||||||
override val viewBinding = lazy { OverviewPodsAppleSingleItemBinding.bind(itemView) }
|
|
||||||
|
|
||||||
override val onBindData = binding(payload = true) { item: Item ->
|
|
||||||
val device = item.device
|
|
||||||
|
|
||||||
name.apply {
|
|
||||||
text = device.getLabel(context)
|
|
||||||
if (item.isMainPod) setTypeface(typeface, Typeface.BOLD)
|
|
||||||
else setTypeface(typeface, Typeface.NORMAL)
|
|
||||||
}
|
|
||||||
|
|
||||||
deviceIcon.setImageResource(device.iconRes)
|
|
||||||
|
|
||||||
lastSeen.text = device.lastSeenFormatted(item.now)
|
|
||||||
|
|
||||||
reception.text = item.getReceptionText()
|
|
||||||
|
|
||||||
batteryLabel.text = device.getBatteryLevelHeadset(context)
|
|
||||||
batteryIcon.setImageResource(getBatteryDrawable(device.batteryHeadsetPercent))
|
|
||||||
|
|
||||||
chargingIcon.isInvisible = device.isHeadsetBeingCharged
|
|
||||||
chargingLabel.isInvisible = device.isHeadsetBeingCharged
|
|
||||||
|
|
||||||
wearIcon.isInvisible = device.isHeadphonesBeingWorn
|
|
||||||
wearLabel.isInvisible = device.isHeadphonesBeingWorn
|
|
||||||
|
|
||||||
status.apply {
|
|
||||||
val sb = StringBuilder()
|
|
||||||
if (item.showDebug) {
|
|
||||||
sb.append("--- Debug ---")
|
|
||||||
sb.append("\n").append(device.rawDataHex)
|
|
||||||
}
|
|
||||||
text = sb
|
|
||||||
isGone = !item.showDebug
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Item(
|
|
||||||
override val now: Instant,
|
|
||||||
override val device: SingleApplePods,
|
|
||||||
override val showDebug: Boolean,
|
|
||||||
override val isMainPod: Boolean,
|
|
||||||
) : PodDeviceVH.Item
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package eu.darken.capod.main.ui.overview.cards.pods
|
||||||
|
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isGone
|
||||||
|
import androidx.core.view.isInvisible
|
||||||
|
import eu.darken.capod.R
|
||||||
|
import eu.darken.capod.common.lists.binding
|
||||||
|
import eu.darken.capod.databinding.OverviewPodsSingleItemBinding
|
||||||
|
import eu.darken.capod.pods.core.*
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
class SinglePodsCardVH(parent: ViewGroup) :
|
||||||
|
PodDeviceVH<SinglePodsCardVH.Item, OverviewPodsSingleItemBinding>(
|
||||||
|
R.layout.overview_pods_single_item,
|
||||||
|
parent
|
||||||
|
) {
|
||||||
|
|
||||||
|
override val viewBinding = lazy { OverviewPodsSingleItemBinding.bind(itemView) }
|
||||||
|
|
||||||
|
override val onBindData = binding(payload = true) { item: Item ->
|
||||||
|
val device = item.device
|
||||||
|
|
||||||
|
name.apply {
|
||||||
|
text = device.getLabel(context)
|
||||||
|
if (item.isMainPod) setTypeface(typeface, Typeface.BOLD)
|
||||||
|
else setTypeface(typeface, Typeface.NORMAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceIcon.setImageResource(device.iconRes)
|
||||||
|
|
||||||
|
lastSeen.text = device.lastSeenFormatted(item.now)
|
||||||
|
|
||||||
|
reception.text = item.getReceptionText()
|
||||||
|
|
||||||
|
// Battery level
|
||||||
|
device.apply {
|
||||||
|
batteryLabel.text = getBatteryLevelHeadset(context)
|
||||||
|
batteryIcon.setImageResource(getBatteryDrawable(batteryHeadsetPercent))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Charge state
|
||||||
|
device.apply {
|
||||||
|
if (this is HasChargeDetection) {
|
||||||
|
chargingIcon.isInvisible = isHeadsetBeingCharged
|
||||||
|
chargingLabel.isInvisible = isHeadsetBeingCharged
|
||||||
|
} else {
|
||||||
|
chargingIcon.isGone = true
|
||||||
|
chargingLabel.isGone = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has ear detection
|
||||||
|
device.apply {
|
||||||
|
if (this is HasEarDetection) {
|
||||||
|
wearIcon.isInvisible = isBeingWorn
|
||||||
|
wearLabel.isInvisible = isBeingWorn
|
||||||
|
} else {
|
||||||
|
wearIcon.isGone = true
|
||||||
|
wearLabel.isGone = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status.apply {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
if (item.showDebug) {
|
||||||
|
sb.append("--- Debug ---")
|
||||||
|
sb.append("\n").append(device.rawDataHex)
|
||||||
|
}
|
||||||
|
text = sb
|
||||||
|
isGone = !item.showDebug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Item(
|
||||||
|
override val now: Instant,
|
||||||
|
override val device: SinglePodDevice,
|
||||||
|
override val showDebug: Boolean,
|
||||||
|
override val isMainPod: Boolean,
|
||||||
|
) : PodDeviceVH.Item
|
||||||
|
}
|
||||||
+1
@@ -34,6 +34,7 @@ class DebugSettingsFragment : PreferenceFragment2() {
|
|||||||
vm.toggleRecorder()
|
vm.toggleRecorder()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
@@ -3,10 +3,15 @@ package eu.darken.capod.main.ui.settings.general.debug
|
|||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import eu.darken.capod.common.coroutine.DispatcherProvider
|
import eu.darken.capod.common.coroutine.DispatcherProvider
|
||||||
|
import eu.darken.capod.common.debug.autoreport.DebugSettings
|
||||||
|
import eu.darken.capod.common.debug.logging.log
|
||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.common.debug.recording.core.RecorderModule
|
import eu.darken.capod.common.debug.recording.core.RecorderModule
|
||||||
import eu.darken.capod.common.uix.ViewModel3
|
import eu.darken.capod.common.uix.ViewModel3
|
||||||
|
import eu.darken.capod.main.core.GeneralSettings
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
@@ -14,10 +19,24 @@ class DebugSettingsFragmentVM @Inject constructor(
|
|||||||
private val handle: SavedStateHandle,
|
private val handle: SavedStateHandle,
|
||||||
dispatcherProvider: DispatcherProvider,
|
dispatcherProvider: DispatcherProvider,
|
||||||
private val recorderModule: RecorderModule,
|
private val recorderModule: RecorderModule,
|
||||||
|
private val generalSettings: GeneralSettings,
|
||||||
|
private val debugSettings: DebugSettings,
|
||||||
) : ViewModel3(dispatcherProvider) {
|
) : ViewModel3(dispatcherProvider) {
|
||||||
|
|
||||||
val state = recorderModule.state.asLiveData2()
|
val state = recorderModule.state.asLiveData2()
|
||||||
|
|
||||||
|
init {
|
||||||
|
debugSettings.showUnfiltered.flow
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.onEach { showUnfiltered ->
|
||||||
|
if (showUnfiltered) {
|
||||||
|
log(TAG) { "Enabling 'show all' due to debug setting 'show unfiltered' enabled" }
|
||||||
|
generalSettings.showAll.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.launchInViewModel()
|
||||||
|
}
|
||||||
|
|
||||||
fun toggleRecorder() = launch {
|
fun toggleRecorder() = launch {
|
||||||
if (recorderModule.state.first().isRecording) {
|
if (recorderModule.state.first().isRecording) {
|
||||||
recorderModule.stopRecorder()
|
recorderModule.stopRecorder()
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ class PodMonitor @Inject constructor(
|
|||||||
) { scannerMode, compatMode, unfiltered ->
|
) { scannerMode, compatMode, unfiltered ->
|
||||||
Triple(scannerMode, compatMode, unfiltered)
|
Triple(scannerMode, compatMode, unfiltered)
|
||||||
}.flatMapLatest { (mode, compat, unfiltered) ->
|
}.flatMapLatest { (mode, compat, unfiltered) ->
|
||||||
|
log(TAG, VERBOSE) { "Starting BLEScanner mode=$mode, compat=$compat, unfiltered=$unfiltered" }
|
||||||
val filters = if (unfiltered) {
|
val filters = if (unfiltered) {
|
||||||
setOf(getUnfilteredFilter())
|
setOf(getUnfilteredFilter())
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import android.widget.RemoteViews
|
|||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import eu.darken.capod.R
|
import eu.darken.capod.R
|
||||||
import eu.darken.capod.pods.core.*
|
import eu.darken.capod.pods.core.*
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
import eu.darken.capod.pods.core.apple.DualAirPods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
|
||||||
import eu.darken.capod.pods.core.apple.SingleApplePods
|
import eu.darken.capod.pods.core.apple.SingleApplePods
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -17,13 +16,12 @@ class MonitorNotificationViewFactory @Inject constructor(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun createContentView(device: PodDevice): RemoteViews = when (device) {
|
fun createContentView(device: PodDevice): RemoteViews = when (device) {
|
||||||
is DualApplePods -> createDualApplePods(device)
|
is DualAirPods -> createDualApplePods(device)
|
||||||
is SingleApplePods -> createSingleApplePods(device)
|
is SingleApplePods -> createSingleApplePods(device)
|
||||||
is BasicSingleApplePods -> createSingleBasicApplePods(device)
|
|
||||||
else -> createUnknownDevice(device)
|
else -> createUnknownDevice(device)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createDualApplePods(device: DualApplePods): RemoteViews = RemoteViews(
|
private fun createDualApplePods(device: DualAirPods): RemoteViews = RemoteViews(
|
||||||
context.packageName,
|
context.packageName,
|
||||||
R.layout.monitor_notification_dual_pods_small
|
R.layout.monitor_notification_dual_pods_small
|
||||||
).apply {
|
).apply {
|
||||||
@@ -52,19 +50,12 @@ class MonitorNotificationViewFactory @Inject constructor(
|
|||||||
setTextViewText(R.id.headphones_label, getLabel(context))
|
setTextViewText(R.id.headphones_label, getLabel(context))
|
||||||
setImageViewResource(R.id.headphones_battery_icon, getBatteryDrawable(batteryHeadsetPercent))
|
setImageViewResource(R.id.headphones_battery_icon, getBatteryDrawable(batteryHeadsetPercent))
|
||||||
setTextViewText(R.id.headphones_battery_label, getBatteryLevelHeadset(context))
|
setTextViewText(R.id.headphones_battery_label, getBatteryLevelHeadset(context))
|
||||||
setViewVisibility(R.id.headphones_charging, if (isHeadsetBeingCharged) View.VISIBLE else View.GONE)
|
if (this is HasEarDetection) {
|
||||||
setViewVisibility(R.id.headphones_worn, if (isHeadphonesBeingWorn) View.VISIBLE else View.GONE)
|
setViewVisibility(R.id.headphones_worn, if (isBeingWorn) View.VISIBLE else View.GONE)
|
||||||
}
|
}
|
||||||
}
|
if (this is HasChargeDetectionDual) {
|
||||||
|
setViewVisibility(R.id.headphones_charging, if (isHeadsetBeingCharged) View.VISIBLE else View.GONE)
|
||||||
private fun createSingleBasicApplePods(device: BasicSingleApplePods): RemoteViews = RemoteViews(
|
}
|
||||||
context.packageName,
|
|
||||||
R.layout.monitor_notification_single_pods_basic_small
|
|
||||||
).apply {
|
|
||||||
device.apply {
|
|
||||||
setTextViewText(R.id.headphones_label, getLabel(context))
|
|
||||||
setImageViewResource(R.id.headphones_battery_icon, getBatteryDrawable(batteryHeadsetPercent))
|
|
||||||
setTextViewText(R.id.headphones_battery_label, getBatteryLevelHeadset(context))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package eu.darken.capod.pods.core
|
package eu.darken.capod.pods.core
|
||||||
|
|
||||||
interface HasDualPods {
|
interface DualPodDevice : PodDevice {
|
||||||
|
|
||||||
enum class Pod {
|
enum class Pod {
|
||||||
LEFT,
|
LEFT,
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package eu.darken.capod.pods.core
|
||||||
|
|
||||||
|
interface HasChargeDetection {
|
||||||
|
|
||||||
|
val isHeadsetBeingCharged: Boolean
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package eu.darken.capod.pods.core
|
||||||
|
|
||||||
|
interface HasChargeDetectionDual : HasChargeDetection {
|
||||||
|
|
||||||
|
val isLeftPodCharging: Boolean
|
||||||
|
|
||||||
|
val isRightPodCharging: Boolean
|
||||||
|
|
||||||
|
val isEitherPodCharging: Boolean
|
||||||
|
get() = isLeftPodCharging || isRightPodCharging
|
||||||
|
|
||||||
|
override val isHeadsetBeingCharged: Boolean
|
||||||
|
get() = isEitherPodCharging
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package eu.darken.capod.pods.core
|
||||||
|
|
||||||
|
interface HasDualMicrophone {
|
||||||
|
|
||||||
|
val isLeftPodMicrophone: Boolean
|
||||||
|
|
||||||
|
val isRightPodMicrophone: Boolean
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package eu.darken.capod.pods.core
|
package eu.darken.capod.pods.core
|
||||||
|
|
||||||
interface HasEarDetection : PodDevice {
|
interface HasEarDetection {
|
||||||
|
|
||||||
val isBeingWorn: Boolean
|
val isBeingWorn: Boolean
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package eu.darken.capod.pods.core
|
package eu.darken.capod.pods.core
|
||||||
|
|
||||||
interface HasDualEarDetection : HasEarDetection {
|
interface HasEarDetectionDual : HasEarDetection {
|
||||||
|
|
||||||
val isLeftPodInEar: Boolean
|
val isLeftPodInEar: Boolean
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package eu.darken.capod.pods.core
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.annotation.ColorRes
|
||||||
|
|
||||||
|
interface HasPodStyle {
|
||||||
|
|
||||||
|
val podStyle: PodStyle
|
||||||
|
|
||||||
|
interface PodStyle {
|
||||||
|
fun getLabel(context: Context): String
|
||||||
|
|
||||||
|
@ColorRes
|
||||||
|
fun getColor(context: Context): Int
|
||||||
|
|
||||||
|
val identifier: String
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package eu.darken.capod.pods.core
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
interface HasStateDetection {
|
||||||
|
|
||||||
|
val state: State
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
fun getLabel(context: Context): String
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -100,6 +100,12 @@ interface PodDevice {
|
|||||||
@Json(name = "beats.powerbeats.pro") POWERBEATS_PRO(
|
@Json(name = "beats.powerbeats.pro") POWERBEATS_PRO(
|
||||||
"Power Beats Pro"
|
"Power Beats Pro"
|
||||||
),
|
),
|
||||||
|
@Json(name = "fakes.tws.i99999") TWS_I99999(
|
||||||
|
"TWS i99999"
|
||||||
|
),
|
||||||
|
@Json(name = "fakes.varunr.airpodspro") VARUNR_AIRPODS_PRO(
|
||||||
|
"Fake AirPods Pro"
|
||||||
|
),
|
||||||
@Json(name = "unknown") UNKNOWN(
|
@Json(name = "unknown") UNKNOWN(
|
||||||
"Unknown"
|
"Unknown"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import java.time.Duration
|
|||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
fun HasDualPods.getBatteryLevelLeftPod(context: Context): String =
|
fun DualPodDevice.getBatteryLevelLeftPod(context: Context): String =
|
||||||
batteryLeftPodPercent?.let { "${(it * 100).roundToInt()}%" }
|
batteryLeftPodPercent?.let { "${(it * 100).roundToInt()}%" }
|
||||||
?: context.getString(R.string.general_value_not_available_label)
|
?: context.getString(R.string.general_value_not_available_label)
|
||||||
|
|
||||||
fun HasDualPods.getBatteryLevelRightPod(context: Context): String =
|
fun DualPodDevice.getBatteryLevelRightPod(context: Context): String =
|
||||||
batteryRightPodPercent?.let { "${(it * 100).roundToInt()}%" }
|
batteryRightPodPercent?.let { "${(it * 100).roundToInt()}%" }
|
||||||
?: context.getString(R.string.general_value_not_available_label)
|
?: context.getString(R.string.general_value_not_available_label)
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ fun HasCase.getBatteryLevelCase(context: Context): String =
|
|||||||
batteryCasePercent?.let { "${(it * 100).roundToInt()}%" }
|
batteryCasePercent?.let { "${(it * 100).roundToInt()}%" }
|
||||||
?: context.getString(R.string.general_value_not_available_label)
|
?: context.getString(R.string.general_value_not_available_label)
|
||||||
|
|
||||||
fun HasSinglePod.getBatteryLevelHeadset(context: Context): String =
|
fun SinglePodDevice.getBatteryLevelHeadset(context: Context): String =
|
||||||
batteryHeadsetPercent?.let { "${(it * 100).roundToInt()}%" }
|
batteryHeadsetPercent?.let { "${(it * 100).roundToInt()}%" }
|
||||||
?: context.getString(R.string.general_value_not_available_label)
|
?: context.getString(R.string.general_value_not_available_label)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package eu.darken.capod.pods.core
|
package eu.darken.capod.pods.core
|
||||||
|
|
||||||
interface HasSinglePod {
|
interface SinglePodDevice : PodDevice {
|
||||||
|
|
||||||
val batteryHeadsetPercent: Float?
|
val batteryHeadsetPercent: Float?
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package eu.darken.capod.pods.core.apple
|
package eu.darken.capod.pods.core.apple
|
||||||
|
|
||||||
import eu.darken.capod.common.bluetooth.BleScanResult
|
import eu.darken.capod.common.bluetooth.BleScanResult
|
||||||
import eu.darken.capod.common.debug.Bugs
|
|
||||||
import eu.darken.capod.common.debug.logging.Logging.Priority.WARN
|
import eu.darken.capod.common.debug.logging.Logging.Priority.WARN
|
||||||
import eu.darken.capod.common.debug.logging.asLog
|
import eu.darken.capod.common.debug.logging.asLog
|
||||||
import eu.darken.capod.common.debug.logging.log
|
import eu.darken.capod.common.debug.logging.log
|
||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
|
import eu.darken.capod.pods.core.apple.misc.UnknownAppleDevice
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ContinuityProtocol
|
import eu.darken.capod.pods.core.apple.protocol.ContinuityProtocol
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
@@ -54,25 +54,13 @@ class AppleFactory @Inject constructor(
|
|||||||
|
|
||||||
val factory = podFactories.firstOrNull { it.isResponsible(pm) }
|
val factory = podFactories.firstOrNull { it.isResponsible(pm) }
|
||||||
|
|
||||||
val device = (factory ?: unknownAppleFactory).create(
|
return@withLock (factory ?: unknownAppleFactory).create(
|
||||||
scanResult = scanResult,
|
scanResult = scanResult,
|
||||||
proximityMessage = pm,
|
message = pm,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (factory == null && !SILENCED_PMS.contains(device.rawDeviceModel) && scanResult.address != "6E:9E:D1:49:D2:6D") {
|
|
||||||
SILENCED_PMS.add(device.rawDeviceModel)
|
|
||||||
Bugs.report(
|
|
||||||
tag = TAG,
|
|
||||||
message = "Unknown proximity message type",
|
|
||||||
exception = IllegalArgumentException("Unknown ProximityMessage: $pm")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return@withLock device
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val SILENCED_PMS = mutableSetOf<UShort>()
|
|
||||||
private val TAG = logTag("Pod", "Apple", "Factory")
|
private val TAG = logTag("Pod", "Apple", "Factory")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,8 @@ import dagger.hilt.components.SingletonComponent
|
|||||||
import dagger.multibindings.IntoSet
|
import dagger.multibindings.IntoSet
|
||||||
import eu.darken.capod.pods.core.apple.airpods.*
|
import eu.darken.capod.pods.core.apple.airpods.*
|
||||||
import eu.darken.capod.pods.core.apple.beats.*
|
import eu.darken.capod.pods.core.apple.beats.*
|
||||||
|
import eu.darken.capod.pods.core.apple.misc.Twsi99999
|
||||||
|
import eu.darken.capod.pods.core.apple.misc.VarunrAirPodsPro
|
||||||
|
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
@Module
|
@Module
|
||||||
@@ -25,4 +27,8 @@ abstract class AppleFactoryModule {
|
|||||||
@Binds @IntoSet abstract fun beatsX(factory: BeatsX.Factory): ApplePodsFactory<out ApplePods>
|
@Binds @IntoSet abstract fun beatsX(factory: BeatsX.Factory): ApplePodsFactory<out ApplePods>
|
||||||
@Binds @IntoSet abstract fun powerBeats3(factory: PowerBeats3.Factory): ApplePodsFactory<out ApplePods>
|
@Binds @IntoSet abstract fun powerBeats3(factory: PowerBeats3.Factory): ApplePodsFactory<out ApplePods>
|
||||||
@Binds @IntoSet abstract fun powerBeatsPro(factory: PowerBeatsPro.Factory): ApplePodsFactory<out ApplePods>
|
@Binds @IntoSet abstract fun powerBeatsPro(factory: PowerBeatsPro.Factory): ApplePodsFactory<out ApplePods>
|
||||||
|
|
||||||
|
@Binds @IntoSet abstract fun fakesTwsi999999(factory: Twsi99999.Factory): ApplePodsFactory<out ApplePods>
|
||||||
|
@Binds @IntoSet
|
||||||
|
abstract fun fakesVarunrAirPodsPro(factory: VarunrAirPodsPro.Factory): ApplePodsFactory<out ApplePods>
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,9 @@ import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE
|
|||||||
import eu.darken.capod.common.debug.logging.log
|
import eu.darken.capod.common.debug.logging.log
|
||||||
import eu.darken.capod.common.lowerNibble
|
import eu.darken.capod.common.lowerNibble
|
||||||
import eu.darken.capod.common.upperNibble
|
import eu.darken.capod.common.upperNibble
|
||||||
|
import eu.darken.capod.pods.core.HasCase
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
|
import eu.darken.capod.pods.core.apple.airpods.AirPodsPro
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@@ -21,9 +23,9 @@ abstract class ApplePodsFactory<PodType : ApplePods>(private val tag: String) {
|
|||||||
val deviceColor: UByte,
|
val deviceColor: UByte,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun ProximityPairing.Message.getApplePodsMarkings(): Markings = Markings(
|
private fun ProximityPairing.Message.getApplePodsMarkings(): Markings = Markings(
|
||||||
vendor = ProximityPairing.CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING,
|
vendor = ProximityPairing.CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING,
|
||||||
length = ProximityPairing.PROXIMITY_PAIRING_MESSAGE_LENGTH.toUByte(),
|
length = ProximityPairing.PAIRING_MESSAGE_LENGTH.toUByte(),
|
||||||
device = (((data[1].toInt() and 255) shl 8) or (data[2].toInt() and 255)).toUShort(),
|
device = (((data[1].toInt() and 255) shl 8) or (data[2].toInt() and 255)).toUShort(),
|
||||||
// Make comparison order independent
|
// Make comparison order independent
|
||||||
podBatteryData = setOf(data[4].upperNibble, data[4].lowerNibble),
|
podBatteryData = setOf(data[4].upperNibble, data[4].lowerNibble),
|
||||||
@@ -70,6 +72,22 @@ abstract class ApplePodsFactory<PodType : ApplePods>(private val tag: String) {
|
|||||||
|
|
||||||
internal val knownDevices = mutableMapOf<PodDevice.Id, KnownDevice>()
|
internal val knownDevices = mutableMapOf<PodDevice.Id, KnownDevice>()
|
||||||
|
|
||||||
|
|
||||||
|
fun KnownDevice.getLatestCaseBattery(): Float? = history
|
||||||
|
.filterIsInstance<HasCase>()
|
||||||
|
.mapNotNull { it.batteryCasePercent }
|
||||||
|
.lastOrNull()
|
||||||
|
|
||||||
|
fun KnownDevice.getLatestCaseLidState(basic: DualAirPods): DualAirPods.LidState? {
|
||||||
|
val definitive = setOf(DualAirPods.LidState.OPEN, DualAirPods.LidState.CLOSED)
|
||||||
|
if (definitive.contains(basic.caseLidState)) return null
|
||||||
|
|
||||||
|
return history
|
||||||
|
.filterIsInstance<AirPodsPro>()
|
||||||
|
.lastOrNull { it.caseLidState != DualAirPods.LidState.NOT_IN_CASE }
|
||||||
|
?.caseLidState
|
||||||
|
}
|
||||||
|
|
||||||
internal open fun searchHistory(current: PodType): KnownDevice? {
|
internal open fun searchHistory(current: PodType): KnownDevice? {
|
||||||
val scanResult = current.scanResult
|
val scanResult = current.scanResult
|
||||||
val message = current.proximityMessage
|
val message = current.proximityMessage
|
||||||
@@ -138,10 +156,10 @@ abstract class ApplePodsFactory<PodType : ApplePods>(private val tag: String) {
|
|||||||
dirty = data[1]
|
dirty = data[1]
|
||||||
)
|
)
|
||||||
|
|
||||||
abstract fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean
|
abstract fun isResponsible(message: ProximityPairing.Message): Boolean
|
||||||
|
|
||||||
abstract fun create(
|
abstract fun create(
|
||||||
scanResult: BleScanResult,
|
scanResult: BleScanResult,
|
||||||
proximityMessage: ProximityPairing.Message,
|
message: ProximityPairing.Message,
|
||||||
): ApplePods
|
): ApplePods
|
||||||
}
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package eu.darken.capod.pods.core.apple
|
|
||||||
|
|
||||||
import eu.darken.capod.common.debug.logging.log
|
|
||||||
import eu.darken.capod.common.lowerNibble
|
|
||||||
import eu.darken.capod.pods.core.HasSinglePod
|
|
||||||
|
|
||||||
interface BasicSingleApplePods : ApplePods, HasSinglePod {
|
|
||||||
|
|
||||||
override val batteryHeadsetPercent: Float?
|
|
||||||
get() = when (val value = rawPodsBattery.lowerNibble.toInt()) {
|
|
||||||
15 -> null
|
|
||||||
else -> if (value > 10) {
|
|
||||||
log { "Left pod: Above 100% battery: $value" }
|
|
||||||
1.0f
|
|
||||||
} else {
|
|
||||||
(value / 10f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package eu.darken.capod.pods.core.apple
|
|
||||||
|
|
||||||
abstract class BasicSingleApplePodsFactory(private val tag: String) : ApplePodsFactory<BasicSingleApplePods>(tag)
|
|
||||||
+12
-36
@@ -7,12 +7,11 @@ import eu.darken.capod.common.debug.logging.log
|
|||||||
import eu.darken.capod.common.isBitSet
|
import eu.darken.capod.common.isBitSet
|
||||||
import eu.darken.capod.common.lowerNibble
|
import eu.darken.capod.common.lowerNibble
|
||||||
import eu.darken.capod.common.upperNibble
|
import eu.darken.capod.common.upperNibble
|
||||||
import eu.darken.capod.pods.core.HasCase
|
import eu.darken.capod.pods.core.*
|
||||||
import eu.darken.capod.pods.core.HasDualEarDetection
|
import eu.darken.capod.pods.core.DualPodDevice.Pod
|
||||||
import eu.darken.capod.pods.core.HasDualPods
|
|
||||||
import eu.darken.capod.pods.core.HasDualPods.Pod
|
|
||||||
|
|
||||||
interface DualApplePods : ApplePods, HasDualPods, HasDualEarDetection, HasCase {
|
interface DualAirPods : ApplePods, HasChargeDetectionDual, DualPodDevice, HasEarDetectionDual, HasCase,
|
||||||
|
HasStateDetection, HasDualMicrophone, HasAppleColor {
|
||||||
|
|
||||||
val primaryPod: Pod
|
val primaryPod: Pod
|
||||||
get() = when (rawStatus.isBitSet(5)) {
|
get() = when (rawStatus.isBitSet(5)) {
|
||||||
@@ -86,23 +85,23 @@ interface DualApplePods : ApplePods, HasDualPods, HasDualEarDetection, HasCase {
|
|||||||
* The data flip bit is set if the left pod is primary.
|
* The data flip bit is set if the left pod is primary.
|
||||||
* For the pod that is in the case, this is flipped again though.
|
* For the pod that is in the case, this is flipped again though.
|
||||||
*/
|
*/
|
||||||
val isLeftPodMicrophone: Boolean
|
override val isLeftPodMicrophone: Boolean
|
||||||
get() = rawStatus.isBitSet(5) xor isThisPodInThecase
|
get() = rawStatus.isBitSet(5) xor isThisPodInThecase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data flip bit is UNset if the right pod is primary.
|
* The data flip bit is UNset if the right pod is primary.
|
||||||
* For the pod that is in the case, this is flipped again though.
|
* For the pod that is in the case, this is flipped again though.
|
||||||
*/
|
*/
|
||||||
val isRightPodMicrophone: Boolean
|
override val isRightPodMicrophone: Boolean
|
||||||
get() = !rawStatus.isBitSet(5) xor isThisPodInThecase
|
get() = !rawStatus.isBitSet(5) xor isThisPodInThecase
|
||||||
|
|
||||||
val isLeftPodCharging: Boolean
|
override val isLeftPodCharging: Boolean
|
||||||
get() = when (areValuesFlipped) {
|
get() = when (areValuesFlipped) {
|
||||||
false -> rawFlags.isBitSet(0)
|
false -> rawFlags.isBitSet(0)
|
||||||
true -> rawFlags.isBitSet(1)
|
true -> rawFlags.isBitSet(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
val isRightPodCharging: Boolean
|
override val isRightPodCharging: Boolean
|
||||||
get() = when (areValuesFlipped) {
|
get() = when (areValuesFlipped) {
|
||||||
false -> rawFlags.isBitSet(1)
|
false -> rawFlags.isBitSet(1)
|
||||||
true -> rawFlags.isBitSet(0)
|
true -> rawFlags.isBitSet(0)
|
||||||
@@ -143,35 +142,10 @@ interface DualApplePods : ApplePods, HasDualPods, HasDualEarDetection, HasCase {
|
|||||||
UNKNOWN(0xFF..0xFF);
|
UNKNOWN(0xFF..0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
val deviceColor: DeviceColor
|
override val state: ConnectionState
|
||||||
get() = DeviceColor.values().firstOrNull { it.raw == rawDeviceColor } ?: DeviceColor.UNKNOWN
|
|
||||||
|
|
||||||
enum class DeviceColor(val raw: UByte?) {
|
|
||||||
|
|
||||||
WHITE(0x00),
|
|
||||||
BLACK(0x01),
|
|
||||||
RED(0x02),
|
|
||||||
BLUE(0x03),
|
|
||||||
PINK(0x04),
|
|
||||||
GRAY(0x05),
|
|
||||||
SILVER(0x06),
|
|
||||||
GOLD(0x07),
|
|
||||||
ROSE_GOLD(0x08),
|
|
||||||
SPACE_GRAY(0x09),
|
|
||||||
DARK_BLUE(0x0a),
|
|
||||||
LIGHT_BLUE(0x0b),
|
|
||||||
YELLOW(0x0c),
|
|
||||||
UNKNOWN(null);
|
|
||||||
|
|
||||||
constructor(raw: Int) : this(raw.toUByte())
|
|
||||||
}
|
|
||||||
|
|
||||||
val connectionState: ConnectionState
|
|
||||||
get() = ConnectionState.values().firstOrNull { rawSuffix == it.raw } ?: ConnectionState.UNKNOWN
|
get() = ConnectionState.values().firstOrNull { rawSuffix == it.raw } ?: ConnectionState.UNKNOWN
|
||||||
|
|
||||||
fun getConnectionStateLabel(context: Context): String = context.getString(connectionState.labelRes)
|
enum class ConnectionState(val raw: UByte?, @StringRes val labelRes: Int) : HasStateDetection.State {
|
||||||
|
|
||||||
enum class ConnectionState(val raw: UByte?, @StringRes val labelRes: Int) {
|
|
||||||
DISCONNECTED(0x00, R.string.pods_connection_state_disconnected_label),
|
DISCONNECTED(0x00, R.string.pods_connection_state_disconnected_label),
|
||||||
IDLE(0x04, R.string.pods_connection_state_idle_label),
|
IDLE(0x04, R.string.pods_connection_state_idle_label),
|
||||||
MUSIC(0x05, R.string.pods_connection_state_music_label),
|
MUSIC(0x05, R.string.pods_connection_state_music_label),
|
||||||
@@ -180,6 +154,8 @@ interface DualApplePods : ApplePods, HasDualPods, HasDualEarDetection, HasCase {
|
|||||||
HANGING_UP(0x09, R.string.pods_connection_state_hanging_up_label),
|
HANGING_UP(0x09, R.string.pods_connection_state_hanging_up_label),
|
||||||
UNKNOWN(null, R.string.pods_connection_state_unknown_label);
|
UNKNOWN(null, R.string.pods_connection_state_unknown_label);
|
||||||
|
|
||||||
|
override fun getLabel(context: Context): String = context.getString(labelRes)
|
||||||
|
|
||||||
constructor(raw: Int, @StringRes labelRes: Int) : this(raw.toUByte(), labelRes)
|
constructor(raw: Int, @StringRes labelRes: Int) : this(raw.toUByte(), labelRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3,18 +3,17 @@ package eu.darken.capod.pods.core.apple
|
|||||||
import eu.darken.capod.common.debug.logging.Logging.Priority.DEBUG
|
import eu.darken.capod.common.debug.logging.Logging.Priority.DEBUG
|
||||||
import eu.darken.capod.common.debug.logging.log
|
import eu.darken.capod.common.debug.logging.log
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.airpods.AirPodsPro
|
|
||||||
|
|
||||||
abstract class DualApplePodsFactory(private val tag: String) : ApplePodsFactory<DualApplePods>(tag) {
|
abstract class DualApplePodsFactory(private val tag: String) : ApplePodsFactory<DualAirPods>(tag) {
|
||||||
|
|
||||||
fun DualApplePods.getCaseMatchMarkings() = SplitPodsMarkings(
|
fun DualAirPods.getCaseMatchMarkings() = SplitPodsMarkings(
|
||||||
leftPodBattery = batteryLeftPodPercent,
|
leftPodBattery = batteryLeftPodPercent,
|
||||||
rightPodBattery = batteryRightPodPercent,
|
rightPodBattery = batteryRightPodPercent,
|
||||||
microPhoneLeft = isLeftPodMicrophone,
|
microPhoneLeft = isLeftPodMicrophone,
|
||||||
microPhoneRight = isRightPodMicrophone,
|
microPhoneRight = isRightPodMicrophone,
|
||||||
chargingLeft = isLeftPodCharging,
|
chargingLeft = isLeftPodCharging,
|
||||||
chargingRight = isRightPodCharging,
|
chargingRight = isRightPodCharging,
|
||||||
color = deviceColor,
|
color = rawDeviceColor,
|
||||||
model = model
|
model = model
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,36 +27,21 @@ abstract class DualApplePodsFactory(private val tag: String) : ApplePodsFactory<
|
|||||||
val microPhoneRight: Boolean,
|
val microPhoneRight: Boolean,
|
||||||
val chargingLeft: Boolean,
|
val chargingLeft: Boolean,
|
||||||
val chargingRight: Boolean,
|
val chargingRight: Boolean,
|
||||||
val color: DualApplePods.DeviceColor,
|
val color: UByte,
|
||||||
val model: PodDevice.Model,
|
val model: PodDevice.Model,
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun Collection<KnownDevice>.findSplitPodsMatch(device: DualApplePods): Collection<KnownDevice> {
|
private fun Collection<KnownDevice>.findSplitPodsMatch(device: DualAirPods): Collection<KnownDevice> {
|
||||||
val target = device.getCaseMatchMarkings()
|
val target = device.getCaseMatchMarkings()
|
||||||
|
|
||||||
return filter { known ->
|
return filter { known ->
|
||||||
known.history
|
known.history
|
||||||
.filterIsInstance<DualApplePods>()
|
.filterIsInstance<DualAirPods>()
|
||||||
.any { it.getCaseMatchMarkings() == target }
|
.any { it.getCaseMatchMarkings() == target }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KnownDevice.getLatestCaseBattery(): Float? = history
|
override fun searchHistory(current: DualAirPods): KnownDevice? {
|
||||||
.filterIsInstance<DualApplePods>()
|
|
||||||
.mapNotNull { it.batteryCasePercent }
|
|
||||||
.lastOrNull()
|
|
||||||
|
|
||||||
fun KnownDevice.getLatestCaseLidState(basic: DualApplePods): DualApplePods.LidState? {
|
|
||||||
val definitive = setOf(DualApplePods.LidState.OPEN, DualApplePods.LidState.CLOSED)
|
|
||||||
if (definitive.contains(basic.caseLidState)) return null
|
|
||||||
|
|
||||||
return history
|
|
||||||
.filterIsInstance<AirPodsPro>()
|
|
||||||
.lastOrNull { it.caseLidState != DualApplePods.LidState.NOT_IN_CASE }
|
|
||||||
?.caseLidState
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun searchHistory(current: DualApplePods): KnownDevice? {
|
|
||||||
val basicResult = super.searchHistory(current)
|
val basicResult = super.searchHistory(current)
|
||||||
|
|
||||||
val caseIgnored = knownDevices.values.findSplitPodsMatch(current)
|
val caseIgnored = knownDevices.values.findSplitPodsMatch(current)
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package eu.darken.capod.pods.core.apple
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import eu.darken.capod.pods.core.HasPodStyle
|
||||||
|
|
||||||
|
interface HasAppleColor : ApplePods, HasPodStyle {
|
||||||
|
|
||||||
|
override val podStyle: HasPodStyle.PodStyle
|
||||||
|
get() = DeviceColor.values()
|
||||||
|
.firstOrNull { it.raw == rawDeviceColor }
|
||||||
|
?: DeviceColor.UNKNOWN
|
||||||
|
|
||||||
|
enum class DeviceColor(val raw: UByte?) : HasPodStyle.PodStyle {
|
||||||
|
WHITE(0x00),
|
||||||
|
BLACK(0x01),
|
||||||
|
RED(0x02),
|
||||||
|
BLUE(0x03),
|
||||||
|
PINK(0x04),
|
||||||
|
GRAY(0x05),
|
||||||
|
SILVER(0x06),
|
||||||
|
GOLD(0x07),
|
||||||
|
ROSE_GOLD(0x08),
|
||||||
|
SPACE_GRAY(0x09),
|
||||||
|
DARK_BLUE(0x0a),
|
||||||
|
LIGHT_BLUE(0x0b),
|
||||||
|
YELLOW(0x0c),
|
||||||
|
UNKNOWN(null);
|
||||||
|
|
||||||
|
override fun getLabel(context: Context): String = this.name
|
||||||
|
|
||||||
|
override fun getColor(context: Context): Int = android.R.color.white
|
||||||
|
|
||||||
|
override val identifier: String
|
||||||
|
get() = name
|
||||||
|
|
||||||
|
constructor(raw: Int) : this(raw.toUByte())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,22 @@
|
|||||||
package eu.darken.capod.pods.core.apple
|
package eu.darken.capod.pods.core.apple
|
||||||
|
|
||||||
import eu.darken.capod.common.isBitSet
|
import eu.darken.capod.common.debug.logging.log
|
||||||
import eu.darken.capod.pods.core.HasEarDetection
|
import eu.darken.capod.common.lowerNibble
|
||||||
import eu.darken.capod.pods.core.HasSinglePod
|
import eu.darken.capod.pods.core.SinglePodDevice
|
||||||
|
|
||||||
interface SingleApplePods : BasicSingleApplePods, HasEarDetection, HasSinglePod {
|
/**
|
||||||
|
* Devices that only present a single charge level, e.g. most Beats devices
|
||||||
|
*/
|
||||||
|
interface SingleApplePods : ApplePods, SinglePodDevice, HasAppleColor {
|
||||||
|
|
||||||
val isHeadphonesBeingWorn: Boolean
|
override val batteryHeadsetPercent: Float?
|
||||||
get() = rawStatus.isBitSet(1)
|
get() = when (val value = rawPodsBattery.lowerNibble.toInt()) {
|
||||||
|
15 -> null
|
||||||
val isHeadsetBeingCharged: Boolean
|
else -> if (value > 10) {
|
||||||
get() = rawFlags.isBitSet(0)
|
log { "Headset above 100% battery: $value" }
|
||||||
|
1.0f
|
||||||
override val isBeingWorn: Boolean
|
} else {
|
||||||
get() = isHeadphonesBeingWorn
|
(value / 10f)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ import eu.darken.capod.common.bluetooth.BleScanResult
|
|||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
import eu.darken.capod.pods.core.apple.DualAirPods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePodsFactory
|
import eu.darken.capod.pods.core.apple.DualApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@@ -20,15 +20,15 @@ data class AirPodsGen1 constructor(
|
|||||||
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
private val cachedBatteryPercentage: Float? = null,
|
private val cachedBatteryPercentage: Float? = null,
|
||||||
private val cachedCaseState: DualApplePods.LidState? = null
|
private val cachedCaseState: DualAirPods.LidState? = null
|
||||||
) : DualApplePods {
|
) : DualAirPods {
|
||||||
|
|
||||||
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN1
|
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN1
|
||||||
|
|
||||||
override val batteryCasePercent: Float?
|
override val batteryCasePercent: Float?
|
||||||
get() = super.batteryCasePercent ?: cachedBatteryPercentage
|
get() = super.batteryCasePercent ?: cachedBatteryPercentage
|
||||||
|
|
||||||
override val caseLidState: DualApplePods.LidState
|
override val caseLidState: DualAirPods.LidState
|
||||||
get() = cachedCaseState ?: super.caseLidState
|
get() = cachedCaseState ?: super.caseLidState
|
||||||
|
|
||||||
override val rssi: Int
|
override val rssi: Int
|
||||||
@@ -36,11 +36,13 @@ data class AirPodsGen1 constructor(
|
|||||||
|
|
||||||
class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().full == DEVICE_CODE
|
getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
|
||||||
var basic = AirPodsGen1(scanResult = scanResult, proximityMessage = proximityMessage)
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
|
var basic = AirPodsGen1(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import eu.darken.capod.common.bluetooth.BleScanResult
|
|||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
import eu.darken.capod.pods.core.apple.DualAirPods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePodsFactory
|
import eu.darken.capod.pods.core.apple.DualApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@@ -20,15 +20,15 @@ data class AirPodsGen2 constructor(
|
|||||||
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
private val cachedBatteryPercentage: Float? = null,
|
private val cachedBatteryPercentage: Float? = null,
|
||||||
private val cachedCaseState: DualApplePods.LidState? = null
|
private val cachedCaseState: DualAirPods.LidState? = null
|
||||||
) : DualApplePods {
|
) : DualAirPods {
|
||||||
|
|
||||||
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN2
|
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN2
|
||||||
|
|
||||||
override val batteryCasePercent: Float?
|
override val batteryCasePercent: Float?
|
||||||
get() = super.batteryCasePercent ?: cachedBatteryPercentage
|
get() = super.batteryCasePercent ?: cachedBatteryPercentage
|
||||||
|
|
||||||
override val caseLidState: DualApplePods.LidState
|
override val caseLidState: DualAirPods.LidState
|
||||||
get() = cachedCaseState ?: super.caseLidState
|
get() = cachedCaseState ?: super.caseLidState
|
||||||
|
|
||||||
override val rssi: Int
|
override val rssi: Int
|
||||||
@@ -36,11 +36,12 @@ data class AirPodsGen2 constructor(
|
|||||||
|
|
||||||
class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().full == DEVICE_CODE
|
getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
var basic = AirPodsGen2(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = AirPodsGen2(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import eu.darken.capod.common.bluetooth.BleScanResult
|
|||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
import eu.darken.capod.pods.core.apple.DualAirPods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePodsFactory
|
import eu.darken.capod.pods.core.apple.DualApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@@ -20,14 +20,14 @@ data class AirPodsGen3 constructor(
|
|||||||
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
private val cachedBatteryPercentage: Float? = null,
|
private val cachedBatteryPercentage: Float? = null,
|
||||||
private val cachedCaseState: DualApplePods.LidState? = null
|
private val cachedCaseState: DualAirPods.LidState? = null
|
||||||
) : DualApplePods {
|
) : DualAirPods {
|
||||||
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN3
|
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN3
|
||||||
|
|
||||||
override val batteryCasePercent: Float?
|
override val batteryCasePercent: Float?
|
||||||
get() = super.batteryCasePercent ?: cachedBatteryPercentage
|
get() = super.batteryCasePercent ?: cachedBatteryPercentage
|
||||||
|
|
||||||
override val caseLidState: DualApplePods.LidState
|
override val caseLidState: DualAirPods.LidState
|
||||||
get() = cachedCaseState ?: super.caseLidState
|
get() = cachedCaseState ?: super.caseLidState
|
||||||
|
|
||||||
override val rssi: Int
|
override val rssi: Int
|
||||||
@@ -35,11 +35,12 @@ data class AirPodsGen3 constructor(
|
|||||||
|
|
||||||
class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().full == DEVICE_CODE
|
getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
var basic = AirPodsGen3(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = AirPodsGen3(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package eu.darken.capod.pods.core.apple.airpods
|
|||||||
|
|
||||||
import eu.darken.capod.common.bluetooth.BleScanResult
|
import eu.darken.capod.common.bluetooth.BleScanResult
|
||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
|
import eu.darken.capod.common.isBitSet
|
||||||
|
import eu.darken.capod.pods.core.HasEarDetection
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.SingleApplePods
|
import eu.darken.capod.pods.core.apple.SingleApplePods
|
||||||
@@ -19,20 +21,30 @@ data class AirPodsMax(
|
|||||||
override val proximityMessage: ProximityPairing.Message,
|
override val proximityMessage: ProximityPairing.Message,
|
||||||
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
) : SingleApplePods {
|
) : SingleApplePods, HasEarDetection {
|
||||||
|
|
||||||
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_MAX
|
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_MAX
|
||||||
|
|
||||||
override val rssi: Int
|
override val rssi: Int
|
||||||
get() = rssiAverage ?: super.rssi
|
get() = rssiAverage ?: super.rssi
|
||||||
|
|
||||||
|
val isHeadphonesBeingWorn: Boolean
|
||||||
|
get() = rawStatus.isBitSet(1)
|
||||||
|
|
||||||
|
val isHeadsetBeingCharged: Boolean
|
||||||
|
get() = rawFlags.isBitSet(0)
|
||||||
|
|
||||||
|
override val isBeingWorn: Boolean
|
||||||
|
get() = isHeadphonesBeingWorn
|
||||||
|
|
||||||
class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().dirty == DEVICE_CODE_DIRTY
|
getModelInfo().dirty == DEVICE_CODE_DIRTY && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
var basic = AirPodsMax(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = AirPodsMax(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
@@ -48,7 +60,6 @@ data class AirPodsMax(
|
|||||||
rssiAverage = result.averageRssi(basic.rssi),
|
rssiAverage = result.averageRssi(basic.rssi),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
|
|||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
import eu.darken.capod.pods.core.apple.DualAirPods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods.LidState
|
import eu.darken.capod.pods.core.apple.DualAirPods.LidState
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePodsFactory
|
import eu.darken.capod.pods.core.apple.DualApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@@ -22,7 +22,7 @@ data class AirPodsPro(
|
|||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
private val cachedBatteryPercentage: Float? = null,
|
private val cachedBatteryPercentage: Float? = null,
|
||||||
private val cachedCaseState: LidState? = null
|
private val cachedCaseState: LidState? = null
|
||||||
) : DualApplePods {
|
) : DualAirPods {
|
||||||
|
|
||||||
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_PRO
|
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_PRO
|
||||||
|
|
||||||
@@ -37,11 +37,12 @@ data class AirPodsPro(
|
|||||||
|
|
||||||
class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().full == DEVICE_CODE
|
getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
var basic = AirPodsPro(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = AirPodsPro(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
|
|||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
import eu.darken.capod.pods.core.apple.SingleApplePods
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePodsFactory
|
import eu.darken.capod.pods.core.apple.SingleApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -19,20 +19,21 @@ data class BeatsFlex(
|
|||||||
override val proximityMessage: ProximityPairing.Message,
|
override val proximityMessage: ProximityPairing.Message,
|
||||||
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
) : BasicSingleApplePods {
|
) : SingleApplePods {
|
||||||
|
|
||||||
override val model: PodDevice.Model = PodDevice.Model.BEATS_FLEX
|
override val model: PodDevice.Model = PodDevice.Model.BEATS_FLEX
|
||||||
|
|
||||||
override val rssi: Int
|
override val rssi: Int
|
||||||
get() = rssiAverage ?: super.rssi
|
get() = rssiAverage ?: super.rssi
|
||||||
|
|
||||||
class Factory @Inject constructor() : BasicSingleApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().full == DEVICE_CODE
|
getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
var basic = BeatsFlex(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = BeatsFlex(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
|
|||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
import eu.darken.capod.pods.core.apple.SingleApplePods
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePodsFactory
|
import eu.darken.capod.pods.core.apple.SingleApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -19,19 +19,20 @@ data class BeatsSolo3(
|
|||||||
override val proximityMessage: ProximityPairing.Message,
|
override val proximityMessage: ProximityPairing.Message,
|
||||||
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
) : BasicSingleApplePods {
|
) : SingleApplePods {
|
||||||
|
|
||||||
override val model: PodDevice.Model = PodDevice.Model.BEATS_SOLO_3
|
override val model: PodDevice.Model = PodDevice.Model.BEATS_SOLO_3
|
||||||
override val rssi: Int
|
override val rssi: Int
|
||||||
get() = rssiAverage ?: super.rssi
|
get() = rssiAverage ?: super.rssi
|
||||||
|
|
||||||
class Factory @Inject constructor() : BasicSingleApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().full == DEVICE_CODE
|
getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
var basic = BeatsSolo3(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = BeatsSolo3(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
|
|||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
import eu.darken.capod.pods.core.apple.SingleApplePods
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePodsFactory
|
import eu.darken.capod.pods.core.apple.SingleApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -19,17 +19,18 @@ data class BeatsStudio3(
|
|||||||
override val proximityMessage: ProximityPairing.Message,
|
override val proximityMessage: ProximityPairing.Message,
|
||||||
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
) : BasicSingleApplePods {
|
) : SingleApplePods {
|
||||||
|
|
||||||
override val model: PodDevice.Model = PodDevice.Model.BEATS_STUDIO_3
|
override val model: PodDevice.Model = PodDevice.Model.BEATS_STUDIO_3
|
||||||
|
|
||||||
class Factory @Inject constructor() : BasicSingleApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().dirty == DEVICE_CODE_DIRTY
|
getModelInfo().dirty == DEVICE_CODE_DIRTY && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
var basic = BeatsStudio3(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = BeatsStudio3(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
@@ -45,7 +46,6 @@ data class BeatsStudio3(
|
|||||||
rssiAverage = result.averageRssi(basic.rssi),
|
rssiAverage = result.averageRssi(basic.rssi),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
|
|||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
import eu.darken.capod.pods.core.apple.SingleApplePods
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePodsFactory
|
import eu.darken.capod.pods.core.apple.SingleApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -19,20 +19,21 @@ data class BeatsX(
|
|||||||
override val proximityMessage: ProximityPairing.Message,
|
override val proximityMessage: ProximityPairing.Message,
|
||||||
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
) : BasicSingleApplePods {
|
) : SingleApplePods {
|
||||||
|
|
||||||
override val model: PodDevice.Model = PodDevice.Model.BEATS_X
|
override val model: PodDevice.Model = PodDevice.Model.BEATS_X
|
||||||
|
|
||||||
override val rssi: Int
|
override val rssi: Int
|
||||||
get() = rssiAverage ?: super.rssi
|
get() = rssiAverage ?: super.rssi
|
||||||
|
|
||||||
class Factory @Inject constructor() : BasicSingleApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().full == DEVICE_CODE
|
getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
var basic = BeatsX(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = BeatsX(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
|
|||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
import eu.darken.capod.pods.core.apple.SingleApplePods
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePodsFactory
|
import eu.darken.capod.pods.core.apple.SingleApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -19,19 +19,21 @@ data class PowerBeats3(
|
|||||||
override val proximityMessage: ProximityPairing.Message,
|
override val proximityMessage: ProximityPairing.Message,
|
||||||
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
) : BasicSingleApplePods {
|
) : SingleApplePods {
|
||||||
|
|
||||||
override val model: PodDevice.Model = PodDevice.Model.POWERBEATS_3
|
override val model: PodDevice.Model = PodDevice.Model.POWERBEATS_3
|
||||||
|
|
||||||
override val rssi: Int
|
override val rssi: Int
|
||||||
get() = rssiAverage ?: super.rssi
|
get() = rssiAverage ?: super.rssi
|
||||||
|
|
||||||
class Factory @Inject constructor() : BasicSingleApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().full == DEVICE_CODE
|
getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
var basic = PowerBeats3(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = PowerBeats3(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import eu.darken.capod.common.bluetooth.BleScanResult
|
|||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.ApplePods
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
import eu.darken.capod.pods.core.apple.DualAirPods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePodsFactory
|
import eu.darken.capod.pods.core.apple.DualApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@@ -20,15 +20,15 @@ data class PowerBeatsPro(
|
|||||||
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
private val rssiAverage: Int? = null,
|
private val rssiAverage: Int? = null,
|
||||||
private val cachedBatteryPercentage: Float? = null,
|
private val cachedBatteryPercentage: Float? = null,
|
||||||
private val cachedCaseState: DualApplePods.LidState? = null
|
private val cachedCaseState: DualAirPods.LidState? = null
|
||||||
) : DualApplePods {
|
) : DualAirPods {
|
||||||
|
|
||||||
override val model: PodDevice.Model = PodDevice.Model.POWERBEATS_PRO
|
override val model: PodDevice.Model = PodDevice.Model.POWERBEATS_PRO
|
||||||
|
|
||||||
override val batteryCasePercent: Float?
|
override val batteryCasePercent: Float?
|
||||||
get() = super.batteryCasePercent ?: cachedBatteryPercentage
|
get() = super.batteryCasePercent ?: cachedBatteryPercentage
|
||||||
|
|
||||||
override val caseLidState: DualApplePods.LidState
|
override val caseLidState: DualAirPods.LidState
|
||||||
get() = cachedCaseState ?: super.caseLidState
|
get() = cachedCaseState ?: super.caseLidState
|
||||||
|
|
||||||
override val rssi: Int
|
override val rssi: Int
|
||||||
@@ -36,11 +36,12 @@ data class PowerBeatsPro(
|
|||||||
|
|
||||||
class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
|
class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
|
||||||
|
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean =
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
proximityMessage.getModelInfo().dirty == DEVICE_CODE_DIRTY
|
getModelInfo().dirty == DEVICE_CODE_DIRTY && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
var basic = PowerBeatsPro(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = PowerBeatsPro(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
package eu.darken.capod.pods.core.apple.misc
|
||||||
|
|
||||||
|
import eu.darken.capod.common.bluetooth.BleScanResult
|
||||||
|
import eu.darken.capod.common.debug.logging.log
|
||||||
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
|
import eu.darken.capod.common.isBitSet
|
||||||
|
import eu.darken.capod.common.lowerNibble
|
||||||
|
import eu.darken.capod.common.upperNibble
|
||||||
|
import eu.darken.capod.pods.core.DualPodDevice
|
||||||
|
import eu.darken.capod.pods.core.HasCase
|
||||||
|
import eu.darken.capod.pods.core.HasDualMicrophone
|
||||||
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
|
import eu.darken.capod.pods.core.apple.ApplePodsFactory
|
||||||
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
|
import java.time.Instant
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basically an AirPods GEN1 clone
|
||||||
|
* Similar data structure but a lot of placeholder values or hardcoded values
|
||||||
|
*/
|
||||||
|
data class Twsi99999 constructor(
|
||||||
|
override val identifier: PodDevice.Id = PodDevice.Id(),
|
||||||
|
override val seenLastAt: Instant = Instant.now(),
|
||||||
|
override val seenFirstAt: Instant = Instant.now(),
|
||||||
|
override val seenCounter: Int = 1,
|
||||||
|
override val scanResult: BleScanResult,
|
||||||
|
override val proximityMessage: ProximityPairing.Message,
|
||||||
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
|
private val rssiAverage: Int? = null,
|
||||||
|
private val cachedBatteryPercentage: Float? = null,
|
||||||
|
) : ApplePods, DualPodDevice, HasDualMicrophone, HasCase {
|
||||||
|
|
||||||
|
override val model: PodDevice.Model = PodDevice.Model.TWS_I99999
|
||||||
|
|
||||||
|
override val rssi: Int
|
||||||
|
get() = rssiAverage ?: super<ApplePods>.rssi
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normally values for the left pod are in the lower nibbles, if the left pod is primary (microphone)
|
||||||
|
* If the right pod is the primary, the values are flipped.
|
||||||
|
*/
|
||||||
|
val areValuesFlipped: Boolean
|
||||||
|
get() = !rawStatus.isBitSet(5)
|
||||||
|
|
||||||
|
override val batteryLeftPodPercent: Float?
|
||||||
|
get() {
|
||||||
|
val value = when (areValuesFlipped) {
|
||||||
|
true -> rawPodsBattery.upperNibble.toInt()
|
||||||
|
false -> rawPodsBattery.lowerNibble.toInt()
|
||||||
|
}
|
||||||
|
return when (value) {
|
||||||
|
15 -> null
|
||||||
|
else -> if (value > 10) {
|
||||||
|
log { "Left pod: Above 100% battery: $value" }
|
||||||
|
1.0f
|
||||||
|
} else {
|
||||||
|
(value / 10f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val batteryRightPodPercent: Float?
|
||||||
|
get() {
|
||||||
|
val value = when (areValuesFlipped) {
|
||||||
|
true -> rawPodsBattery.lowerNibble.toInt()
|
||||||
|
false -> rawPodsBattery.upperNibble.toInt()
|
||||||
|
}
|
||||||
|
return when (value) {
|
||||||
|
15 -> null
|
||||||
|
else -> if (value > 10) {
|
||||||
|
log { "Right pod: Above 100% battery: $value" }
|
||||||
|
1.0f
|
||||||
|
} else {
|
||||||
|
value / 10f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val isThisPodInThecase: Boolean
|
||||||
|
get() = rawStatus.isBitSet(6)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data flip bit is set if the left pod is primary.
|
||||||
|
* For the pod that is in the case, this is flipped again though.
|
||||||
|
*/
|
||||||
|
override val isLeftPodMicrophone: Boolean
|
||||||
|
get() = rawStatus.isBitSet(5) xor isThisPodInThecase
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data flip bit is UNset if the right pod is primary.
|
||||||
|
* For the pod that is in the case, this is flipped again though.
|
||||||
|
*/
|
||||||
|
override val isRightPodMicrophone: Boolean
|
||||||
|
get() = !rawStatus.isBitSet(5) xor isThisPodInThecase
|
||||||
|
|
||||||
|
override val batteryCasePercent: Float?
|
||||||
|
get() = when (val value = rawCaseBattery.toInt()) {
|
||||||
|
15 -> cachedBatteryPercentage
|
||||||
|
else -> if (value > 10) {
|
||||||
|
log { "Case: Above 100% battery: $value" }
|
||||||
|
1.0f
|
||||||
|
} else {
|
||||||
|
value / 10f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val isCaseCharging: Boolean
|
||||||
|
get() = rawFlags.isBitSet(2)
|
||||||
|
|
||||||
|
class Factory @Inject constructor() : ApplePodsFactory<Twsi99999>(TAG) {
|
||||||
|
|
||||||
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
|
// Official message length is 19HEX, i.e. binary 25, did they copy this wrong?
|
||||||
|
getModelInfo().full == DEVICE_CODE && length == 19
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
|
var basic = Twsi99999(scanResult = scanResult, proximityMessage = message)
|
||||||
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
updateHistory(basic)
|
||||||
|
|
||||||
|
if (result == null) return basic
|
||||||
|
|
||||||
|
return basic.copy(
|
||||||
|
identifier = result.id,
|
||||||
|
seenFirstAt = result.seenFirstAt,
|
||||||
|
seenCounter = result.seenCounter,
|
||||||
|
confidence = result.confidence,
|
||||||
|
cachedBatteryPercentage = result.getLatestCaseBattery(),
|
||||||
|
rssiAverage = result.averageRssi(basic.rssi),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DEVICE_CODE = 0x0220.toUShort()
|
||||||
|
private val TAG = logTag("PodDevice", "Apple", "TWS", "i99999")
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-4
@@ -1,10 +1,12 @@
|
|||||||
package eu.darken.capod.pods.core.apple
|
package eu.darken.capod.pods.core.apple.misc
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import eu.darken.capod.R
|
import eu.darken.capod.R
|
||||||
import eu.darken.capod.common.bluetooth.BleScanResult
|
import eu.darken.capod.common.bluetooth.BleScanResult
|
||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
|
import eu.darken.capod.pods.core.apple.ApplePodsFactory
|
||||||
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -28,13 +30,13 @@ data class UnknownAppleDevice(
|
|||||||
get() = rssiAverage ?: super.rssi
|
get() = rssiAverage ?: super.rssi
|
||||||
|
|
||||||
class Factory @Inject constructor() : ApplePodsFactory<ApplePods>(TAG) {
|
class Factory @Inject constructor() : ApplePodsFactory<ApplePods>(TAG) {
|
||||||
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = true
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = true
|
||||||
|
|
||||||
override fun create(
|
override fun create(
|
||||||
scanResult: BleScanResult,
|
scanResult: BleScanResult,
|
||||||
proximityMessage: ProximityPairing.Message,
|
message: ProximityPairing.Message,
|
||||||
): ApplePods {
|
): ApplePods {
|
||||||
var basic = UnknownAppleDevice(scanResult = scanResult, proximityMessage = proximityMessage)
|
var basic = UnknownAppleDevice(scanResult = scanResult, proximityMessage = message)
|
||||||
val result = searchHistory(basic)
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
if (result != null) basic = basic.copy(identifier = result.id)
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
package eu.darken.capod.pods.core.apple.misc
|
||||||
|
|
||||||
|
import eu.darken.capod.common.bluetooth.BleScanResult
|
||||||
|
import eu.darken.capod.common.debug.logging.log
|
||||||
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
|
import eu.darken.capod.common.isBitSet
|
||||||
|
import eu.darken.capod.common.lowerNibble
|
||||||
|
import eu.darken.capod.common.upperNibble
|
||||||
|
import eu.darken.capod.pods.core.DualPodDevice
|
||||||
|
import eu.darken.capod.pods.core.HasCase
|
||||||
|
import eu.darken.capod.pods.core.HasDualMicrophone
|
||||||
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
|
import eu.darken.capod.pods.core.apple.ApplePods
|
||||||
|
import eu.darken.capod.pods.core.apple.ApplePodsFactory
|
||||||
|
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
|
||||||
|
import java.time.Instant
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AirPods Pro clone similar to Twsi999999.
|
||||||
|
* Shorter data structure.
|
||||||
|
*/
|
||||||
|
data class VarunrAirPodsPro constructor(
|
||||||
|
override val identifier: PodDevice.Id = PodDevice.Id(),
|
||||||
|
override val seenLastAt: Instant = Instant.now(),
|
||||||
|
override val seenFirstAt: Instant = Instant.now(),
|
||||||
|
override val seenCounter: Int = 1,
|
||||||
|
override val scanResult: BleScanResult,
|
||||||
|
override val proximityMessage: ProximityPairing.Message,
|
||||||
|
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
|
||||||
|
private val rssiAverage: Int? = null,
|
||||||
|
private val cachedBatteryPercentage: Float? = null,
|
||||||
|
) : ApplePods, DualPodDevice, HasDualMicrophone, HasCase {
|
||||||
|
|
||||||
|
override val model: PodDevice.Model = PodDevice.Model.VARUNR_AIRPODS_PRO
|
||||||
|
|
||||||
|
override val rssi: Int
|
||||||
|
get() = rssiAverage ?: super<ApplePods>.rssi
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normally values for the left pod are in the lower nibbles, if the left pod is primary (microphone)
|
||||||
|
* If the right pod is the primary, the values are flipped.
|
||||||
|
*/
|
||||||
|
val areValuesFlipped: Boolean
|
||||||
|
get() = !rawStatus.isBitSet(5)
|
||||||
|
|
||||||
|
override val batteryLeftPodPercent: Float?
|
||||||
|
get() {
|
||||||
|
val value = when (areValuesFlipped) {
|
||||||
|
true -> rawPodsBattery.upperNibble.toInt()
|
||||||
|
false -> rawPodsBattery.lowerNibble.toInt()
|
||||||
|
}
|
||||||
|
return when (value) {
|
||||||
|
15 -> null
|
||||||
|
else -> if (value > 10) {
|
||||||
|
log { "Left pod: Above 100% battery: $value" }
|
||||||
|
1.0f
|
||||||
|
} else {
|
||||||
|
(value / 10f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val batteryRightPodPercent: Float?
|
||||||
|
get() {
|
||||||
|
val value = when (areValuesFlipped) {
|
||||||
|
true -> rawPodsBattery.lowerNibble.toInt()
|
||||||
|
false -> rawPodsBattery.upperNibble.toInt()
|
||||||
|
}
|
||||||
|
return when (value) {
|
||||||
|
15 -> null
|
||||||
|
else -> if (value > 10) {
|
||||||
|
log { "Right pod: Above 100% battery: $value" }
|
||||||
|
1.0f
|
||||||
|
} else {
|
||||||
|
value / 10f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val isThisPodInThecase: Boolean
|
||||||
|
get() = rawStatus.isBitSet(6)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data flip bit is set if the left pod is primary.
|
||||||
|
* For the pod that is in the case, this is flipped again though.
|
||||||
|
*/
|
||||||
|
override val isLeftPodMicrophone: Boolean
|
||||||
|
get() = rawStatus.isBitSet(5) xor isThisPodInThecase
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data flip bit is UNset if the right pod is primary.
|
||||||
|
* For the pod that is in the case, this is flipped again though.
|
||||||
|
*/
|
||||||
|
override val isRightPodMicrophone: Boolean
|
||||||
|
get() = !rawStatus.isBitSet(5) xor isThisPodInThecase
|
||||||
|
|
||||||
|
override val batteryCasePercent: Float?
|
||||||
|
get() = when (val value = rawCaseBattery.toInt()) {
|
||||||
|
15 -> cachedBatteryPercentage
|
||||||
|
else -> if (value > 10) {
|
||||||
|
log { "Case: Above 100% battery: $value" }
|
||||||
|
1.0f
|
||||||
|
} else {
|
||||||
|
value / 10f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val isCaseCharging: Boolean
|
||||||
|
get() = rawFlags.isBitSet(2)
|
||||||
|
|
||||||
|
class Factory @Inject constructor() : ApplePodsFactory<VarunrAirPodsPro>(TAG) {
|
||||||
|
|
||||||
|
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
|
||||||
|
// Official message length is 19HEX, i.e. binary 25, did they copy this wrong?
|
||||||
|
getModelInfo().full == DEVICE_CODE && length == 19
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
|
||||||
|
var basic = VarunrAirPodsPro(scanResult = scanResult, proximityMessage = message)
|
||||||
|
val result = searchHistory(basic)
|
||||||
|
|
||||||
|
if (result != null) basic = basic.copy(identifier = result.id)
|
||||||
|
updateHistory(basic)
|
||||||
|
|
||||||
|
if (result == null) return basic
|
||||||
|
|
||||||
|
return basic.copy(
|
||||||
|
identifier = result.id,
|
||||||
|
seenFirstAt = result.seenFirstAt,
|
||||||
|
seenCounter = result.seenCounter,
|
||||||
|
confidence = result.confidence,
|
||||||
|
cachedBatteryPercentage = result.getLatestCaseBattery(),
|
||||||
|
rssiAverage = result.averageRssi(basic.rssi),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DEVICE_CODE = 0x0E20.toUShort()
|
||||||
|
private val TAG = logTag("PodDevice", "Apple", "Varunr", "AirPodsPro")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,10 +27,6 @@ object ProximityPairing {
|
|||||||
log { "Not a proximity pairing message: $this" }
|
log { "Not a proximity pairing message: $this" }
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (message.length != PROXIMITY_PAIRING_MESSAGE_LENGTH) {
|
|
||||||
log { "Proximity pairing message has invalid length." }
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return Message(
|
return Message(
|
||||||
type = message.type,
|
type = message.type,
|
||||||
@@ -43,7 +39,7 @@ object ProximityPairing {
|
|||||||
fun getBleScanFilter(): Set<ScanFilter> {
|
fun getBleScanFilter(): Set<ScanFilter> {
|
||||||
val manufacturerData = ByteArray(CONTINUITY_PROTOCOL_MESSAGE_LENGTH).apply {
|
val manufacturerData = ByteArray(CONTINUITY_PROTOCOL_MESSAGE_LENGTH).apply {
|
||||||
this[0] = CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING.toByte()
|
this[0] = CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING.toByte()
|
||||||
this[1] = PROXIMITY_PAIRING_MESSAGE_LENGTH.toByte()
|
this[1] = PAIRING_MESSAGE_LENGTH.toByte()
|
||||||
}
|
}
|
||||||
|
|
||||||
val manufacturerDataMask = ByteArray(CONTINUITY_PROTOCOL_MESSAGE_LENGTH).apply {
|
val manufacturerDataMask = ByteArray(CONTINUITY_PROTOCOL_MESSAGE_LENGTH).apply {
|
||||||
@@ -62,5 +58,7 @@ object ProximityPairing {
|
|||||||
|
|
||||||
private const val CONTINUITY_PROTOCOL_MESSAGE_LENGTH = 27
|
private const val CONTINUITY_PROTOCOL_MESSAGE_LENGTH = 27
|
||||||
internal val CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING = 0x07.toUByte()
|
internal val CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING = 0x07.toUByte()
|
||||||
internal const val PROXIMITY_PAIRING_MESSAGE_LENGTH = 25
|
|
||||||
|
// This is the default message length among official Apple devices, clones may have different length
|
||||||
|
internal const val PAIRING_MESSAGE_LENGTH = 25
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import eu.darken.capod.common.debug.logging.logTag
|
|||||||
import eu.darken.capod.common.flow.setupCommonEventHandlers
|
import eu.darken.capod.common.flow.setupCommonEventHandlers
|
||||||
import eu.darken.capod.main.core.GeneralSettings
|
import eu.darken.capod.main.core.GeneralSettings
|
||||||
import eu.darken.capod.monitor.core.PodMonitor
|
import eu.darken.capod.monitor.core.PodMonitor
|
||||||
import eu.darken.capod.pods.core.HasDualEarDetection
|
|
||||||
import eu.darken.capod.pods.core.HasEarDetection
|
import eu.darken.capod.pods.core.HasEarDetection
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
import eu.darken.capod.pods.core.HasEarDetectionDual
|
||||||
|
import eu.darken.capod.pods.core.apple.DualAirPods
|
||||||
import eu.darken.capod.reaction.settings.ReactionSettings
|
import eu.darken.capod.reaction.settings.ReactionSettings
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -68,12 +68,12 @@ class AutoConnect @Inject constructor(
|
|||||||
val conditionFulfilled = when (condition) {
|
val conditionFulfilled = when (condition) {
|
||||||
AutoConnectCondition.WHEN_SEEN -> true
|
AutoConnectCondition.WHEN_SEEN -> true
|
||||||
AutoConnectCondition.CASE_OPEN -> when (mainDevice) {
|
AutoConnectCondition.CASE_OPEN -> when (mainDevice) {
|
||||||
is DualApplePods -> mainDevice.caseLidState == DualApplePods.LidState.OPEN
|
is DualAirPods -> mainDevice.caseLidState == DualAirPods.LidState.OPEN
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
AutoConnectCondition.IN_EAR -> when (mainDevice) {
|
AutoConnectCondition.IN_EAR -> when (mainDevice) {
|
||||||
is HasEarDetection -> {
|
is HasEarDetection -> {
|
||||||
if (mainDevice is HasDualEarDetection && reactionSettings.onePodMode.value) {
|
if (mainDevice is HasEarDetectionDual && reactionSettings.onePodMode.value) {
|
||||||
mainDevice.isEitherPodInEar
|
mainDevice.isEitherPodInEar
|
||||||
} else {
|
} else {
|
||||||
mainDevice.isBeingWorn
|
mainDevice.isBeingWorn
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import eu.darken.capod.common.debug.logging.logTag
|
|||||||
import eu.darken.capod.common.flow.setupCommonEventHandlers
|
import eu.darken.capod.common.flow.setupCommonEventHandlers
|
||||||
import eu.darken.capod.common.flow.withPrevious
|
import eu.darken.capod.common.flow.withPrevious
|
||||||
import eu.darken.capod.monitor.core.PodMonitor
|
import eu.darken.capod.monitor.core.PodMonitor
|
||||||
import eu.darken.capod.pods.core.HasDualEarDetection
|
|
||||||
import eu.darken.capod.pods.core.HasEarDetection
|
import eu.darken.capod.pods.core.HasEarDetection
|
||||||
|
import eu.darken.capod.pods.core.HasEarDetectionDual
|
||||||
import eu.darken.capod.reaction.settings.ReactionSettings
|
import eu.darken.capod.reaction.settings.ReactionSettings
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -48,7 +48,7 @@ class PlayPause @Inject constructor(
|
|||||||
return@onEach
|
return@onEach
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previous is HasDualEarDetection && current is HasDualEarDetection && reactionSettings.onePodMode.value) {
|
if (previous is HasEarDetectionDual && current is HasEarDetectionDual && reactionSettings.onePodMode.value) {
|
||||||
log(TAG) { "Ear status changed for dual pod device in single pod mode." }
|
log(TAG) { "Ear status changed for dual pod device in single pod mode." }
|
||||||
val previousWorn = previous.isEitherPodInEar
|
val previousWorn = previous.isEitherPodInEar
|
||||||
val currentWorn = current.isEitherPodInEar
|
val currentWorn = current.isEitherPodInEar
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import eu.darken.capod.common.flow.setupCommonEventHandlers
|
|||||||
import eu.darken.capod.common.flow.withPrevious
|
import eu.darken.capod.common.flow.withPrevious
|
||||||
import eu.darken.capod.monitor.core.PodMonitor
|
import eu.darken.capod.monitor.core.PodMonitor
|
||||||
import eu.darken.capod.pods.core.PodDevice
|
import eu.darken.capod.pods.core.PodDevice
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
import eu.darken.capod.pods.core.apple.DualAirPods
|
||||||
import eu.darken.capod.reaction.popup.ui.PopUpWindow
|
import eu.darken.capod.reaction.popup.ui.PopUpWindow
|
||||||
import eu.darken.capod.reaction.settings.ReactionSettings
|
import eu.darken.capod.reaction.settings.ReactionSettings
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
@@ -39,7 +39,7 @@ class PopUpReaction @Inject constructor(
|
|||||||
.withPrevious()
|
.withPrevious()
|
||||||
.setupCommonEventHandlers(TAG) { "monitor" }
|
.setupCommonEventHandlers(TAG) { "monitor" }
|
||||||
.map { (previous, current) ->
|
.map { (previous, current) ->
|
||||||
if (previous is DualApplePods? && current is DualApplePods) {
|
if (previous is DualAirPods? && current is DualAirPods) {
|
||||||
log(TAG, VERBOSE) {
|
log(TAG, VERBOSE) {
|
||||||
val prev = previous?.rawCaseLidState?.let { String.format("%02X", it.toByte()) }
|
val prev = previous?.rawCaseLidState?.let { String.format("%02X", it.toByte()) }
|
||||||
val cur = current.rawCaseLidState.let { String.format("%02X", it.toByte()) }
|
val cur = current.rawCaseLidState.let { String.format("%02X", it.toByte()) }
|
||||||
@@ -60,8 +60,8 @@ class PopUpReaction @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun tryPopWindow(current: DualApplePods) {
|
private suspend fun tryPopWindow(current: DualAirPods) {
|
||||||
if (current.caseLidState == DualApplePods.LidState.OPEN) {
|
if (current.caseLidState == DualAirPods.LidState.OPEN) {
|
||||||
log(TAG, INFO) { "Show popup" }
|
log(TAG, INFO) { "Show popup" }
|
||||||
|
|
||||||
val now = Instant.now()
|
val now = Instant.now()
|
||||||
@@ -78,9 +78,9 @@ class PopUpReaction @Inject constructor(
|
|||||||
withContext(dispatcherProvider.Main) {
|
withContext(dispatcherProvider.Main) {
|
||||||
popupWindow.show(current)
|
popupWindow.show(current)
|
||||||
}
|
}
|
||||||
} else if (current.caseLidState != DualApplePods.LidState.OPEN) {
|
} else if (current.caseLidState != DualAirPods.LidState.OPEN) {
|
||||||
when (current.caseLidState) {
|
when (current.caseLidState) {
|
||||||
DualApplePods.LidState.CLOSED -> {
|
DualAirPods.LidState.CLOSED -> {
|
||||||
log(TAG, INFO) { "Lid was actively closed, resetting cooldown." }
|
log(TAG, INFO) { "Lid was actively closed, resetting cooldown." }
|
||||||
coolDowns.remove(current.identifier)
|
coolDowns.remove(current.identifier)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
|||||||
import eu.darken.capod.R
|
import eu.darken.capod.R
|
||||||
import eu.darken.capod.common.debug.autoreport.DebugSettings
|
import eu.darken.capod.common.debug.autoreport.DebugSettings
|
||||||
import eu.darken.capod.databinding.PopupNotificationDualPodsBinding
|
import eu.darken.capod.databinding.PopupNotificationDualPodsBinding
|
||||||
import eu.darken.capod.databinding.PopupNotificationSinglePodsBasicBinding
|
|
||||||
import eu.darken.capod.databinding.PopupNotificationSinglePodsBinding
|
import eu.darken.capod.databinding.PopupNotificationSinglePodsBinding
|
||||||
import eu.darken.capod.pods.core.*
|
import eu.darken.capod.pods.core.*
|
||||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
import eu.darken.capod.pods.core.apple.DualAirPods
|
||||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
|
||||||
import eu.darken.capod.pods.core.apple.SingleApplePods
|
import eu.darken.capod.pods.core.apple.SingleApplePods
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -28,16 +26,13 @@ class PopUpPodViewFactory @Inject constructor(
|
|||||||
private val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
private val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||||
|
|
||||||
fun createContentView(parent: ViewGroup, device: PodDevice): View = when (device) {
|
fun createContentView(parent: ViewGroup, device: PodDevice): View = when (device) {
|
||||||
is DualApplePods -> createDualApplePods(parent, device)
|
is DualAirPods -> createDualApplePods(parent, device)
|
||||||
is SingleApplePods -> createSingleApplePods(parent, device) // Unused, has no case to trigger reaction?
|
// Unused, has no case to trigger reaction?
|
||||||
is BasicSingleApplePods -> createSingleBasicApplePods(
|
is SingleApplePods -> createSingleApplePods(parent, device)
|
||||||
parent,
|
|
||||||
device
|
|
||||||
) // Unused, has no case to trigger reaction?
|
|
||||||
else -> throw IllegalArgumentException("Unexpected device: $device")
|
else -> throw IllegalArgumentException("Unexpected device: $device")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createDualApplePods(parent: ViewGroup, device: DualApplePods): View =
|
private fun createDualApplePods(parent: ViewGroup, device: DualAirPods): View =
|
||||||
PopupNotificationDualPodsBinding.inflate(layoutInflater, parent, false).apply {
|
PopupNotificationDualPodsBinding.inflate(layoutInflater, parent, false).apply {
|
||||||
device.apply {
|
device.apply {
|
||||||
podIcon.setImageResource(iconRes)
|
podIcon.setImageResource(iconRes)
|
||||||
@@ -72,17 +67,4 @@ class PopUpPodViewFactory @Inject constructor(
|
|||||||
}
|
}
|
||||||
}.root
|
}.root
|
||||||
|
|
||||||
private fun createSingleBasicApplePods(parent: ViewGroup, device: BasicSingleApplePods): View =
|
|
||||||
PopupNotificationSinglePodsBasicBinding.inflate(layoutInflater, parent, false).apply {
|
|
||||||
device.apply {
|
|
||||||
headphonesIcon.setImageResource(iconRes)
|
|
||||||
headphonesLabel.text = getLabel(context)
|
|
||||||
signal.text = getSignalQuality(context)
|
|
||||||
signal.isInvisible = debugSettings.isDebugModeEnabled.value
|
|
||||||
|
|
||||||
headphonesBatteryIcon.setImageResource(getBatteryDrawable(batteryHeadsetPercent))
|
|
||||||
headphonesBatteryLabel.text = getBatteryLevelHeadset(context)
|
|
||||||
}
|
|
||||||
}.root
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -12,13 +12,11 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
import eu.darken.capod.R
|
import eu.darken.capod.R
|
||||||
import eu.darken.capod.common.uix.PreferenceFragment2
|
import eu.darken.capod.common.uix.PreferenceFragment2
|
||||||
import eu.darken.capod.common.upgrade.UpgradeRepo
|
import eu.darken.capod.common.upgrade.UpgradeRepo
|
||||||
import eu.darken.capod.common.upgrade.isPro
|
|
||||||
import eu.darken.capod.main.core.GeneralSettings
|
import eu.darken.capod.main.core.GeneralSettings
|
||||||
import eu.darken.capod.main.core.MonitorMode
|
import eu.darken.capod.main.core.MonitorMode
|
||||||
import eu.darken.capod.main.ui.settings.general.DeviceSelectionDialogFactory
|
import eu.darken.capod.main.ui.settings.general.DeviceSelectionDialogFactory
|
||||||
import eu.darken.capod.reaction.autoconnect.AutoConnectCondition
|
import eu.darken.capod.reaction.autoconnect.AutoConnectCondition
|
||||||
import eu.darken.capod.reaction.settings.ReactionSettings
|
import eu.darken.capod.reaction.settings.ReactionSettings
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
@@ -36,6 +34,7 @@ class ReactionSettingsFragment : PreferenceFragment2() {
|
|||||||
|
|
||||||
override val preferenceFile: Int = R.xml.preferences_reactions
|
override val preferenceFile: Int = R.xml.preferences_reactions
|
||||||
|
|
||||||
|
private var isPro: Boolean = false
|
||||||
private val autoConnectConditionPref by lazy { findPreference<ListPreference>(settings.autoConnectCondition.key)!! }
|
private val autoConnectConditionPref by lazy { findPreference<ListPreference>(settings.autoConnectCondition.key)!! }
|
||||||
|
|
||||||
override fun onPreferencesCreated() {
|
override fun onPreferencesCreated() {
|
||||||
@@ -44,12 +43,11 @@ class ReactionSettingsFragment : PreferenceFragment2() {
|
|||||||
entryValues = AutoConnectCondition.values().map { settings.autoConnectCondition.rawWriter(it) as String }
|
entryValues = AutoConnectCondition.values().map { settings.autoConnectCondition.rawWriter(it) as String }
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onPreferencesCreated()
|
super.onPreferencesCreated()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
||||||
val isPro = runBlocking { upgradeRepo.isPro() }
|
|
||||||
|
|
||||||
if (preference.key == reactionSettings.autoPlay.key && !isPro) {
|
if (preference.key == reactionSettings.autoPlay.key && !isPro) {
|
||||||
preference as CheckBoxPreference
|
preference as CheckBoxPreference
|
||||||
upgradeRepo.launchBillingFlow(requireActivity())
|
upgradeRepo.launchBillingFlow(requireActivity())
|
||||||
@@ -95,6 +93,8 @@ class ReactionSettingsFragment : PreferenceFragment2() {
|
|||||||
autoConnectConditionPref.isEnabled = it
|
autoConnectConditionPref.isEnabled = it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vm.isPro.observe2 { isPro = true }
|
||||||
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import eu.darken.capod.common.bluetooth.BluetoothManager2
|
|||||||
import eu.darken.capod.common.coroutine.DispatcherProvider
|
import eu.darken.capod.common.coroutine.DispatcherProvider
|
||||||
import eu.darken.capod.common.debug.logging.logTag
|
import eu.darken.capod.common.debug.logging.logTag
|
||||||
import eu.darken.capod.common.uix.ViewModel3
|
import eu.darken.capod.common.uix.ViewModel3
|
||||||
|
import eu.darken.capod.common.upgrade.UpgradeRepo
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
@@ -13,10 +15,13 @@ class ReactionSettingsFragmentVM @Inject constructor(
|
|||||||
private val handle: SavedStateHandle,
|
private val handle: SavedStateHandle,
|
||||||
private val dispatcherProvider: DispatcherProvider,
|
private val dispatcherProvider: DispatcherProvider,
|
||||||
private val bluetoothManager: BluetoothManager2,
|
private val bluetoothManager: BluetoothManager2,
|
||||||
|
private val upgradeRepo: UpgradeRepo,
|
||||||
) : ViewModel3(dispatcherProvider) {
|
) : ViewModel3(dispatcherProvider) {
|
||||||
|
|
||||||
val bondedDevices = bluetoothManager.bondedDevices().toList()
|
val bondedDevices = bluetoothManager.bondedDevices().toList()
|
||||||
|
|
||||||
|
val isPro = upgradeRepo.upgradeInfo.map { it.isPro }.asLiveData2()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = logTag("Settings", "Reaction", "VM")
|
private val TAG = logTag("Settings", "Reaction", "VM")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
tools:listitem="@layout/overview_pods_apple_dual_item"
|
tools:listitem="@layout/overview_pods_dual_item"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/toolbar" />
|
app:layout_constraintTop_toBottomOf="@id/toolbar" />
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,12 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/pod_left_icon"
|
android:id="@+id/pod_left_icon"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_airpod_left_24" />
|
android:src="@drawable/ic_airpod_left_24" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/pod_left_label"
|
android:id="@+id/pod_left_label"
|
||||||
style="@style/TextAppearance.Compat.Notification.Title"
|
style="@style/PodInfoItemText.Notification"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
@@ -31,12 +31,12 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/pod_left_charging"
|
android:id="@+id/pod_left_charging"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_baseline_power_24" />
|
android:src="@drawable/ic_baseline_power_24" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/pod_left_ear"
|
android:id="@+id/pod_left_ear"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_baseline_hearing_24" />
|
android:src="@drawable/ic_baseline_hearing_24" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -52,12 +52,12 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/pod_case_icon"
|
android:id="@+id/pod_case_icon"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_airpod_case_24" />
|
android:src="@drawable/ic_airpod_case_24" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/pod_case_label"
|
android:id="@+id/pod_case_label"
|
||||||
style="@style/TextAppearance.Compat.Notification.Title"
|
style="@style/PodInfoItemText.Notification"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/pod_case_charging"
|
android:id="@+id/pod_case_charging"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_baseline_power_24" />
|
android:src="@drawable/ic_baseline_power_24" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -81,12 +81,12 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/pod_right_icon"
|
android:id="@+id/pod_right_icon"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_airpod_right_24" />
|
android:src="@drawable/ic_airpod_right_24" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/pod_right_label"
|
android:id="@+id/pod_right_label"
|
||||||
style="@style/TextAppearance.Compat.Notification.Title"
|
style="@style/PodInfoItemText.Notification"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
@@ -94,12 +94,12 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/pod_right_charging"
|
android:id="@+id/pod_right_charging"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_baseline_power_24" />
|
android:src="@drawable/ic_baseline_power_24" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/pod_right_ear"
|
android:id="@+id/pod_right_ear"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_baseline_hearing_24" />
|
android:src="@drawable/ic_baseline_hearing_24" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_horizontal">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/headphones_label"
|
|
||||||
style="@style/TextAppearance.Compat.Notification.Title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
tools:text="Beats Solo 3" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="8dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/headphones_battery_icon"
|
|
||||||
style="@style/PodInfoItemIcon"
|
|
||||||
android:src="@drawable/ic_baseline_battery_unknown_24" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/headphones_battery_label"
|
|
||||||
style="@style/TextAppearance.Compat.Notification.Title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginHorizontal="8dp"
|
|
||||||
tools:text="100%" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/headphones_label"
|
android:id="@+id/headphones_label"
|
||||||
style="@style/TextAppearance.Compat.Notification.Title"
|
style="@style/PodInfoItemText.Notification"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/headphones_battery_icon"
|
android:id="@+id/headphones_battery_icon"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_baseline_battery_unknown_24" />
|
android:src="@drawable/ic_baseline_battery_unknown_24" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/headphones_battery_label"
|
android:id="@+id/headphones_battery_label"
|
||||||
style="@style/TextAppearance.Compat.Notification.Title"
|
style="@style/PodInfoItemText.Notification"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
@@ -35,12 +35,12 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/headphones_charging"
|
android:id="@+id/headphones_charging"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_baseline_power_24" />
|
android:src="@drawable/ic_baseline_power_24" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/headphones_worn"
|
android:id="@+id/headphones_worn"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon.Notification"
|
||||||
android:src="@drawable/ic_baseline_hearing_24" />
|
android:src="@drawable/ic_baseline_hearing_24" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/device"
|
android:id="@+id/device"
|
||||||
style="@style/TextAppearance.Compat.Notification.Title"
|
style="@style/PodInfoItemText.Notification"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="8dp"
|
android:layout_marginHorizontal="8dp"
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/card"
|
|
||||||
style="@style/MyCardView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginVertical="8dp"
|
|
||||||
tools:context=".main.ui.MainActivity">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/card_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/device_icon"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/name"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/name"
|
|
||||||
app:srcCompat="@drawable/ic_device_generic_headphones" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/name"
|
|
||||||
style="@style/TextAppearance.MaterialComponents.Body2"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="16dp"
|
|
||||||
android:layout_marginStart="4dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/last_seen"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/reception"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/device_icon"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="Power Beats 3" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/last_seen"
|
|
||||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/barrier_top"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/name"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/name"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/name"
|
|
||||||
tools:text="3s ago" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/reception"
|
|
||||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="16dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:gravity="center"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/name"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/reception_icon"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/name"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/name"
|
|
||||||
tools:text="Yours (RSSI -61)" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/reception_icon"
|
|
||||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
|
||||||
android:layout_width="16dp"
|
|
||||||
android:layout_height="16dp"
|
|
||||||
android:layout_marginHorizontal="16dp"
|
|
||||||
android:layout_marginStart="4dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:gravity="center"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/reception"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/reception"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/reception"
|
|
||||||
app:srcCompat="@drawable/ic_baseline_settings_input_antenna_24"
|
|
||||||
tools:text="Yours (RSSI -61)" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
|
||||||
android:id="@+id/barrier_top"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:barrierDirection="top"
|
|
||||||
app:constraint_referenced_ids="headphones"
|
|
||||||
tools:layout_editor_absoluteY="60dp" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/headphones"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/barrier_bottom"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/barrier_top"
|
|
||||||
app:layout_constraintVertical_bias="0.0"
|
|
||||||
app:layout_goneMarginBottom="16dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/battery_icon"
|
|
||||||
style="@style/PodInfoItemIcon"
|
|
||||||
android:src="@drawable/ic_baseline_battery_unknown_24"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/battery_label"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/battery_label" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/battery_label"
|
|
||||||
style="@style/PodInfoItemText"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:text="@string/general_value_not_available_label"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/battery_icon"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
|
||||||
android:id="@+id/barrier_bottom"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:barrierDirection="bottom"
|
|
||||||
app:constraint_referenced_ids="headphones" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/status"
|
|
||||||
style="@style/TextAppearance.MaterialComponents.Body2"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="16dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/barrier_bottom"
|
|
||||||
tools:text="Music Active, Case Closed" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
+4
-4
@@ -12,7 +12,8 @@
|
|||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/card_content"
|
android:id="@+id/card_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/device_icon"
|
android:id="@+id/device_icon"
|
||||||
@@ -107,7 +108,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginEnd="4dp"
|
android:layout_marginEnd="4dp"
|
||||||
android:minHeight="108dp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/barrier_bottom"
|
app:layout_constraintBottom_toTopOf="@id/barrier_bottom"
|
||||||
app:layout_constraintEnd_toStartOf="@id/pod_case_container"
|
app:layout_constraintEnd_toStartOf="@id/pod_case_container"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
@@ -117,6 +117,7 @@
|
|||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/pod_left_icon"
|
android:id="@+id/pod_left_icon"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon"
|
||||||
|
android:contentDescription="@string/pods_dual_left_label"
|
||||||
android:src="@drawable/ic_airpod_left_24"
|
android:src="@drawable/ic_airpod_left_24"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/pod_left_label"
|
app:layout_constraintBottom_toBottomOf="@id/pod_left_label"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
@@ -322,6 +323,7 @@
|
|||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/pod_right_icon"
|
android:id="@+id/pod_right_icon"
|
||||||
style="@style/PodInfoItemIcon"
|
style="@style/PodInfoItemIcon"
|
||||||
|
android:contentDescription="@string/pods_dual_right_label"
|
||||||
android:src="@drawable/ic_airpod_right_24"
|
android:src="@drawable/ic_airpod_right_24"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/pod_right_label"
|
app:layout_constraintBottom_toBottomOf="@id/pod_right_label"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
@@ -420,7 +422,6 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/pod_right_microphone_label" />
|
app:layout_constraintTop_toBottomOf="@id/pod_right_microphone_label" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
<androidx.constraintlayout.widget.Barrier
|
||||||
android:id="@+id/barrier_bottom"
|
android:id="@+id/barrier_bottom"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -435,7 +436,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
+3
-5
@@ -12,7 +12,8 @@
|
|||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/card_content"
|
android:id="@+id/card_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/device_icon"
|
android:id="@+id/device_icon"
|
||||||
@@ -96,13 +97,11 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:minHeight="64dp"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/barrier_bottom"
|
app:layout_constraintBottom_toTopOf="@id/barrier_bottom"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/barrier_top"
|
app:layout_constraintTop_toBottomOf="@id/barrier_top"
|
||||||
app:layout_constraintVertical_bias="0.0"
|
app:layout_constraintVertical_bias="0.0">
|
||||||
app:layout_goneMarginBottom="16dp">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/battery_icon"
|
android:id="@+id/battery_icon"
|
||||||
@@ -180,7 +179,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/headphones_icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/ic_device_generic_earbuds"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/headphones_label"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/headphones_label"
|
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/headphones_label" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/headphones_label"
|
|
||||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginHorizontal="8dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/signal"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/headphones_icon"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="Beats Solo 3" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/signal"
|
|
||||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:drawableEnd="@drawable/ic_baseline_signal_cellular_alt_24"
|
|
||||||
android:gravity="center"
|
|
||||||
android:minWidth="44dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/headphones_label"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/headphones_label"
|
|
||||||
tools:text="-90%" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/headphones_container"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintHorizontal_chainStyle="spread"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/headphones_label">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@id/headphones_battery_icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/ic_baseline_battery_unknown_24"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/headphones_battery_label"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/headphones_battery_label"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/headphones_battery_label" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/headphones_battery_label"
|
|
||||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="4dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/headphones_battery_icon"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="100%" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Bütün tətbiqə təsir edən ümumi incə tənzimləmələr.</string>
|
<string name="settings_general_description">Bütün tətbiqə təsir edən ümumi incə tənzimləmələr.</string>
|
||||||
<string name="settings_acknowledgements_label">Təşəkkürlər</string>
|
<string name="settings_acknowledgements_label">Təşəkkürlər</string>
|
||||||
<string name="changelog_label">Dəyişiklik jurnalı</string>
|
<string name="changelog_label">Dəyişiklik jurnalı</string>
|
||||||
<string name="settings_support_email_developer_label">Tərtibatçıya e-poçt göndər</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">Tərtibatçıya e-poçt göndər</string>
|
||||||
<string name="settings_support_installid_label">Quraşdırma kimliyi</string>
|
<string name="settings_support_installid_label">Quraşdırma kimliyi</string>
|
||||||
<string name="settings_support_installid_desc">Avtomatik xəta hesabatları anonimdir. Tərtibatçının xəta hesabatlarınızı tapmasına ehtiyacı varsa quraşdırma kimliyinizi paylaşın.</string>
|
<string name="settings_support_installid_desc">Avtomatik xəta hesabatları anonimdir. Tərtibatçının xəta hesabatlarınızı tapmasına ehtiyacı varsa quraşdırma kimliyinizi paylaşın.</string>
|
||||||
<string name="settings_support_label">Dəstək</string>
|
<string name="settings_support_label">Dəstək</string>
|
||||||
@@ -81,7 +81,6 @@
|
|||||||
<string name="settings_monitor_mode_label">Müşahidə rejimi</string>
|
<string name="settings_monitor_mode_label">Müşahidə rejimi</string>
|
||||||
<string name="settings_monitor_mode_description">Bu tətbiq hansı şərtlər altında Bluetooth verilənlərini müşahidə edir.</string>
|
<string name="settings_monitor_mode_description">Bu tətbiq hansı şərtlər altında Bluetooth verilənlərini müşahidə edir.</string>
|
||||||
<string name="settings_scanner_mode_label">Skaner rejimi</string>
|
<string name="settings_scanner_mode_label">Skaner rejimi</string>
|
||||||
<string name="settings_scanner_mode_description">Bluetooth Zəif Enerji skaneri performansa üstünlük verməlidir, yoxsa enerjiyə qənaət etməlidir?</string>
|
|
||||||
<string name="settings_monitor_mode_manual_label">Tətbiq açılanda</string>
|
<string name="settings_monitor_mode_manual_label">Tətbiq açılanda</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">Cihazla bağlantı qurulanda</string>
|
<string name="settings_monitor_mode_automatic_label">Cihazla bağlantı qurulanda</string>
|
||||||
<string name="settings_monitor_mode_always_label">Həmişə</string>
|
<string name="settings_monitor_mode_always_label">Həmişə</string>
|
||||||
@@ -89,13 +88,10 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">Tarazlı</string>
|
<string name="settings_scanner_mode_balanced_label">Tarazlı</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">Aşağı gecikmə</string>
|
<string name="settings_scanner_mode_lowlatency_label">Aşağı gecikmə</string>
|
||||||
<string name="settings_autopause_label">Avto-fasilə</string>
|
<string name="settings_autopause_label">Avto-fasilə</string>
|
||||||
<string name="settings_autopause_description">Cihazı qulağınızdan çıxaranda musiqiyə fasilə verilsin.</string>
|
|
||||||
<string name="settings_showall_label">Bütün cihazları göstər</string>
|
<string name="settings_showall_label">Bütün cihazları göstər</string>
|
||||||
<string name="settings_showall_description">Sizə yaxın olan digər insanların cihazlarını göstər.</string>
|
<string name="settings_showall_description">Sizə yaxın olan digər insanların cihazlarını göstər.</string>
|
||||||
<string name="settings_autopplay_label">Avto-oynatma</string>
|
<string name="settings_autopplay_label">Avto-oynatma</string>
|
||||||
<string name="settings_autoplay_description">Cihazı qulağa taxanda musiqini oynat.</string>
|
|
||||||
<string name="settings_fake_data_label">Saxta verilənlər</string>
|
<string name="settings_fake_data_label">Saxta verilənlər</string>
|
||||||
<string name="settings_fake_data_description">Saxta verilənləri göstər, yəni, mövcud olmayan cihazı simulyasiya edin.</string>
|
|
||||||
<string name="settings_debug_label">Sazlama tənzimləmələri</string>
|
<string name="settings_debug_label">Sazlama tənzimləmələri</string>
|
||||||
<string name="settings_debug_description">Tətbiqlə əlaqəli problemləri aradan qaldırmağa kömək edəcək əlavə tənzimləmələr.</string>
|
<string name="settings_debug_description">Tətbiqlə əlaqəli problemləri aradan qaldırmağa kömək edəcək əlavə tənzimləmələr.</string>
|
||||||
<string name="settings_signal_minimum_label">Minimum siqnal keyfiyyəti</string>
|
<string name="settings_signal_minimum_label">Minimum siqnal keyfiyyəti</string>
|
||||||
@@ -119,11 +115,9 @@
|
|||||||
<string name="upgrade_capod_description">Əlavə özəllikləri əldə edin və tərtibatçını dəstəkləyin.</string>
|
<string name="upgrade_capod_description">Əlavə özəllikləri əldə edin və tərtibatçını dəstəkləyin.</string>
|
||||||
<string name="settings_popup_caseopen_label">Açılan pəncərəni göstər</string>
|
<string name="settings_popup_caseopen_label">Açılan pəncərəni göstər</string>
|
||||||
<string name="settings_popup_caseopen_description">Cihazın qutusu açılanda bir açılan pəncərə göstər (təcrübi).</string>
|
<string name="settings_popup_caseopen_description">Cihazın qutusu açılanda bir açılan pəncərə göstər (təcrübi).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Açılan cihaz reaksiyaları</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Bluetooth sıradan çıxarıldı</string>
|
<string name="overview_bluetooth_disabled_label">Bluetooth sıradan çıxarıldı</string>
|
||||||
<string name="overview_bluetooth_disabled_description">Bluetooth sıradan çıxarıldı, fəallaşdırın ;)</string>
|
<string name="overview_bluetooth_disabled_description">Bluetooth sıradan çıxarıldı, fəallaşdırın ;)</string>
|
||||||
<string name="help_translate_label">Tərcümə</string>
|
<string name="help_translate_label">Tərcümə</string>
|
||||||
<string name="help_translate_description">Bunu sevimli dilinizə tərcümə etməyə kömək edin.</string>
|
|
||||||
<string name="settings_onepod_mode_label">Tək tərəf rejimi</string>
|
<string name="settings_onepod_mode_label">Tək tərəf rejimi</string>
|
||||||
<string name="settings_onepod_mode_description">Hər iki tərəfi də taxmağa ehtiyac yoxdur, reaksiyaları tətikləmək üçün tək tərəfi taxmaq yetərlidir.</string>
|
<string name="settings_onepod_mode_description">Hər iki tərəfi də taxmağa ehtiyac yoxdur, reaksiyaları tətikləmək üçün tək tərəfi taxmaq yetərlidir.</string>
|
||||||
<string name="permission_system_alert_window_label">Sistem xəbərdarlıq pəncərəsi</string>
|
<string name="permission_system_alert_window_label">Sistem xəbərdarlıq pəncərəsi</string>
|
||||||
|
|||||||
@@ -1,2 +1,29 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="app_name">CAPod</string>
|
||||||
|
<string name="app_name_pro">CAPod Pro</string>
|
||||||
|
<string name="app_name_foss">CAPod FOSS</string>
|
||||||
|
<string name="notification_channel_device_status_label">Статус прылады</string>
|
||||||
|
<string name="general_error_label">Памылка</string>
|
||||||
|
<string name="general_share_action">Падзяліцца</string>
|
||||||
|
<string name="general_done_action">Гатова</string>
|
||||||
|
<string name="general_copy_action">Скапіраваць</string>
|
||||||
|
<string name="general_thank_you_label">Дзякуй</string>
|
||||||
|
<string name="general_value_not_available_label">Н/д</string>
|
||||||
|
<string name="general_grant_permission_action">Даць дазвол</string>
|
||||||
|
<string name="general_upgrade_action">Палепшыць</string>
|
||||||
|
<string name="general_check_action">Праверыць</string>
|
||||||
|
<string name="general_close_action">Закрыць</string>
|
||||||
|
<string name="debug_debuglog_size_label">Памер</string>
|
||||||
|
<string name="debug_debuglog_size_compressed_label">Сціснуты памер</string>
|
||||||
|
<string name="debug_notification_channel_label">Апавяшчэнні адладкі</string>
|
||||||
|
<string name="debug_debuglog_file_label">Файл журнала</string>
|
||||||
|
<string name="debug_debuglog_record_action">Запісаць лог аладкі ў журнал</string>
|
||||||
|
<string name="permission_bluetooth_connect_label">Злучэнне па Bluetooth</string>
|
||||||
|
<string name="permission_bluetooth_connect_description">Гэтай праграме патрабуецца дазвол на выкарыстанне Bluetooth для ўзаемадзеяння са спалучанымі прыладамі і стварэння новых злучэнняў.</string>
|
||||||
|
<string name="permission_bluetooth_scan_label">Сканіраванне Bluetooth</string>
|
||||||
|
<string name="permission_bluetooth_scan_description">Дазвол на сканіраванне Bluetooth дасць магчымасць гэтай праграме выяўляць і атрымліваць даныя па Bluetooth з навакольных прылад, такіх як вашы AirPods.</string>
|
||||||
|
<string name="permission_bluetooth_label">Bluetooth</string>
|
||||||
|
<string name="permission_bluetooth_description">Гэтай праграме патрабуецца дазвол на выкарыстанне Bluetooth для злучэння са спалучанымі прыладамі.</string>
|
||||||
|
<string name="permission_access_fine_location_label">Доступ да дакладнага месцазнаходжання</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="general_done_action">সম্পন্ন</string>
|
||||||
|
<string name="general_thank_you_label">ধন্যবাদ</string>
|
||||||
|
<string name="general_grant_permission_action">অনুমতি প্রদান করুন</string>
|
||||||
|
<string name="general_upgrade_action">আপগ্রেড</string>
|
||||||
|
<string name="debug_debuglog_size_label">আকার</string>
|
||||||
|
<string name="settings_general_label">সেটিংস</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Configuracions generals que afecten a tota l\'aplicació.</string>
|
<string name="settings_general_description">Configuracions generals que afecten a tota l\'aplicació.</string>
|
||||||
<string name="settings_acknowledgements_label">Agraïments</string>
|
<string name="settings_acknowledgements_label">Agraïments</string>
|
||||||
<string name="changelog_label">Registre de canvis</string>
|
<string name="changelog_label">Registre de canvis</string>
|
||||||
<string name="settings_support_email_developer_label">Correu del desenvolupador</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">Correu del desenvolupador</string>
|
||||||
<string name="settings_support_installid_label">ID d\'instal·lació</string>
|
<string name="settings_support_installid_label">ID d\'instal·lació</string>
|
||||||
<string name="settings_support_installid_desc">Els informes d\'error automàtics són anònims. Compartiu el vostre ID d\'instal·lació si el desenvolupador necessita trobar els vostres informes d\'error.</string>
|
<string name="settings_support_installid_desc">Els informes d\'error automàtics són anònims. Compartiu el vostre ID d\'instal·lació si el desenvolupador necessita trobar els vostres informes d\'error.</string>
|
||||||
<string name="settings_support_label">Suport</string>
|
<string name="settings_support_label">Suport</string>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<string name="settings_monitor_mode_label">Mode monitor</string>
|
<string name="settings_monitor_mode_label">Mode monitor</string>
|
||||||
<string name="settings_monitor_mode_description">En quines circumstàncies aquesta aplicació supervisa les dades Bluetooth.</string>
|
<string name="settings_monitor_mode_description">En quines circumstàncies aquesta aplicació supervisa les dades Bluetooth.</string>
|
||||||
<string name="settings_scanner_mode_label">Mode escàner</string>
|
<string name="settings_scanner_mode_label">Mode escàner</string>
|
||||||
<string name="settings_scanner_mode_description">L\'escàner Bluetooth Low Energy hauria de prioritzar el rendiment o estalviar energia?</string>
|
<string name="settings_scanner_mode_description">L\'escàner de dades Bluetooth Low Energy hauria de prioritzar el rendiment o estalviar energia?</string>
|
||||||
<string name="settings_monitor_mode_manual_label">Quan l\'aplicació està oberta</string>
|
<string name="settings_monitor_mode_manual_label">Quan l\'aplicació està oberta</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">Quan el dispositiu està connectat</string>
|
<string name="settings_monitor_mode_automatic_label">Quan el dispositiu està connectat</string>
|
||||||
<string name="settings_monitor_mode_always_label">Sempre</string>
|
<string name="settings_monitor_mode_always_label">Sempre</string>
|
||||||
@@ -89,13 +89,13 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">Equilibrat</string>
|
<string name="settings_scanner_mode_balanced_label">Equilibrat</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">Baixa latència</string>
|
<string name="settings_scanner_mode_lowlatency_label">Baixa latència</string>
|
||||||
<string name="settings_autopause_label">Pausa automàtica</string>
|
<string name="settings_autopause_label">Pausa automàtica</string>
|
||||||
<string name="settings_autopause_description">Pausa la música quan ús tragueu el dispositiu de l\'orella.</string>
|
<string name="settings_autopause_description">Pausa l\'àudio quan ús tragueu el dispositiu de l\'orella.</string>
|
||||||
<string name="settings_showall_label">Mostra tots els dispositius</string>
|
<string name="settings_showall_label">Mostra tots els dispositius</string>
|
||||||
<string name="settings_showall_description">Mostra els dispositius d\'altres persones que estan a prop vostre.</string>
|
<string name="settings_showall_description">Mostra els dispositius d\'altres persones que estan a prop vostre.</string>
|
||||||
<string name="settings_autopplay_label">Reproducció automàtica</string>
|
<string name="settings_autopplay_label">Reproducció automàtica</string>
|
||||||
<string name="settings_autoplay_description">Inicia la reproducció de música quan ús poseu el dispositiu.</string>
|
<string name="settings_autoplay_description">Inicia la reproducció d\'àudio en utilitzar el dispositiu.</string>
|
||||||
<string name="settings_fake_data_label">Dades falses</string>
|
<string name="settings_fake_data_label">Dades falses</string>
|
||||||
<string name="settings_fake_data_description">Mostra dades falses. Per exemple: simula un dispositiu que no existeix.</string>
|
<string name="settings_fake_data_description">Mostra dades falses. Per exemple: simula dispositius que no existeixen.</string>
|
||||||
<string name="settings_debug_label">Configuració de depuració</string>
|
<string name="settings_debug_label">Configuració de depuració</string>
|
||||||
<string name="settings_debug_description">Configuració addicional per ajudar a resoldre problemes amb l\'aplicació.</string>
|
<string name="settings_debug_description">Configuració addicional per ajudar a resoldre problemes amb l\'aplicació.</string>
|
||||||
<string name="settings_signal_minimum_label">Qualitat de senyal mínima</string>
|
<string name="settings_signal_minimum_label">Qualitat de senyal mínima</string>
|
||||||
@@ -119,7 +119,6 @@
|
|||||||
<string name="upgrade_capod_description">Obteniu característiques addicionals i doneu suport al desenvolupador.</string>
|
<string name="upgrade_capod_description">Obteniu característiques addicionals i doneu suport al desenvolupador.</string>
|
||||||
<string name="settings_popup_caseopen_label">Mostra la finestra emergent</string>
|
<string name="settings_popup_caseopen_label">Mostra la finestra emergent</string>
|
||||||
<string name="settings_popup_caseopen_description">Mostra una finestra emergent quan s\'obre la funda del dispositiu (experimental).</string>
|
<string name="settings_popup_caseopen_description">Mostra una finestra emergent quan s\'obre la funda del dispositiu (experimental).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Reaccions emergents del dispositiu</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">El Bluetooth està desactivat</string>
|
<string name="overview_bluetooth_disabled_label">El Bluetooth està desactivat</string>
|
||||||
<string name="overview_bluetooth_disabled_description">El Bluetooth està desactivat, activeu-lo ;)</string>
|
<string name="overview_bluetooth_disabled_description">El Bluetooth està desactivat, activeu-lo ;)</string>
|
||||||
<string name="help_translate_label">Traducció</string>
|
<string name="help_translate_label">Traducció</string>
|
||||||
@@ -133,4 +132,8 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">Dades BLE sense filtrar</string>
|
<string name="settings_blescanner_unfiltered_label">Dades BLE sense filtrar</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">Elimina els filtres de l\'escàner BLE per mostrar totes les dades BLE emeses. Útil per afegir suport a nous tipus d\'auriculars.</string>
|
<string name="settings_blescanner_unfiltered_description">Elimina els filtres de l\'escàner BLE per mostrar totes les dades BLE emeses. Útil per afegir suport a nous tipus d\'auriculars.</string>
|
||||||
<string name="permission_required_title">Cal el permís següent:</string>
|
<string name="permission_required_title">Cal el permís següent:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Mode de compatibilitat</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Desactiva les optimitzacions per millorar la compatibilitat. Proveu això si no veieu cap dada.</string>
|
||||||
|
<string name="translators_thanks_title">Traductors</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">Jaime Muñoz(jmmartin_5@outlook.com)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Obecná vylepšení, která ovlivňují celou aplikaci.</string>
|
<string name="settings_general_description">Obecná vylepšení, která ovlivňují celou aplikaci.</string>
|
||||||
<string name="settings_acknowledgements_label">Poděkování</string>
|
<string name="settings_acknowledgements_label">Poděkování</string>
|
||||||
<string name="changelog_label">Seznam změn</string>
|
<string name="changelog_label">Seznam změn</string>
|
||||||
<string name="settings_support_email_developer_label">E-mail vývojáři</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">E-mail vývojáři</string>
|
||||||
<string name="settings_support_installid_label">ID instalace</string>
|
<string name="settings_support_installid_label">ID instalace</string>
|
||||||
<string name="settings_support_installid_desc">Automatická hlášení chyb jsou anonymní. Sdílíte pouze své ID instalace, pokud vývojář potřebuje najít vaše chybová hlášení.</string>
|
<string name="settings_support_installid_desc">Automatická hlášení chyb jsou anonymní. Sdílíte pouze své ID instalace, pokud vývojář potřebuje najít vaše chybová hlášení.</string>
|
||||||
<string name="settings_support_label">Podpora</string>
|
<string name="settings_support_label">Podpora</string>
|
||||||
@@ -89,11 +89,11 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">Vyvážený</string>
|
<string name="settings_scanner_mode_balanced_label">Vyvážený</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">Nízká latence</string>
|
<string name="settings_scanner_mode_lowlatency_label">Nízká latence</string>
|
||||||
<string name="settings_autopause_label">Autom. pozastavení</string>
|
<string name="settings_autopause_label">Autom. pozastavení</string>
|
||||||
<string name="settings_autopause_description">Při vyjmutí zařízení z ucha pozastavit přehrávání hudby.</string>
|
<string name="settings_autopause_description">Pozastavení zvuku při vyjmutí zařízení z ucha.</string>
|
||||||
<string name="settings_showall_label">Zobrazit všechna zařízení</string>
|
<string name="settings_showall_label">Zobrazit všechna zařízení</string>
|
||||||
<string name="settings_showall_description">Zobrazit zařízení ostatních osob, které se nacházejí ve vaší blízkosti.</string>
|
<string name="settings_showall_description">Zobrazit zařízení ostatních osob, které se nacházejí ve vaší blízkosti.</string>
|
||||||
<string name="settings_autopplay_label">Autom. přehrávání</string>
|
<string name="settings_autopplay_label">Autom. přehrávání</string>
|
||||||
<string name="settings_autoplay_description">Spustit přehrávání hudby při použití zařízení.</string>
|
<string name="settings_autoplay_description">Spuštění přehrávání zvuku při nošení zařízení.</string>
|
||||||
<string name="settings_fake_data_label">Falešná data</string>
|
<string name="settings_fake_data_label">Falešná data</string>
|
||||||
<string name="settings_fake_data_description">Zobrazit falešná data např. simulovat zařízení, které neexistuje.</string>
|
<string name="settings_fake_data_description">Zobrazit falešná data např. simulovat zařízení, které neexistuje.</string>
|
||||||
<string name="settings_debug_label">Nastavení ladění</string>
|
<string name="settings_debug_label">Nastavení ladění</string>
|
||||||
@@ -119,7 +119,6 @@
|
|||||||
<string name="upgrade_capod_description">Získat další funkce a podpořit vývojáře.</string>
|
<string name="upgrade_capod_description">Získat další funkce a podpořit vývojáře.</string>
|
||||||
<string name="settings_popup_caseopen_label">Zobrazit vyskakovací okno</string>
|
<string name="settings_popup_caseopen_label">Zobrazit vyskakovací okno</string>
|
||||||
<string name="settings_popup_caseopen_description">Zobrazit vyskakovací okno, pokud je pouzdro zařízení otevřeno (experimentální).</string>
|
<string name="settings_popup_caseopen_description">Zobrazit vyskakovací okno, pokud je pouzdro zařízení otevřeno (experimentální).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Vyskakovací okno reakcí zařízení</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Bluetooth je vypnuto</string>
|
<string name="overview_bluetooth_disabled_label">Bluetooth je vypnuto</string>
|
||||||
<string name="overview_bluetooth_disabled_description">Bluetooth je vypnuto, zapněte jej ;)</string>
|
<string name="overview_bluetooth_disabled_description">Bluetooth je vypnuto, zapněte jej ;)</string>
|
||||||
<string name="help_translate_label">Překlad</string>
|
<string name="help_translate_label">Překlad</string>
|
||||||
@@ -133,4 +132,8 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">Nefiltrovaná data BLE</string>
|
<string name="settings_blescanner_unfiltered_label">Nefiltrovaná data BLE</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">Aby se zobrazovala všechna vysílaná data BLE, odstraňte ze skenování BLE všechny filtry. Užitečné pro přidání podpory nových typů sluchátek.</string>
|
<string name="settings_blescanner_unfiltered_description">Aby se zobrazovala všechna vysílaná data BLE, odstraňte ze skenování BLE všechny filtry. Užitečné pro přidání podpory nových typů sluchátek.</string>
|
||||||
<string name="permission_required_title">Je vyžadováno následující oprávnění:</string>
|
<string name="permission_required_title">Je vyžadováno následující oprávnění:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Režim kompatibility</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Vypnutí optimalizace pro zlepšení kompatibility. Zkuste to, pokud se vám nezobrazují žádná data.</string>
|
||||||
|
<string name="translators_thanks_title">Překladatelé</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">novas78@xda; woytazzer</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Allgemeine Optimierungen, die die gesamte App betreffen.</string>
|
<string name="settings_general_description">Allgemeine Optimierungen, die die gesamte App betreffen.</string>
|
||||||
<string name="settings_acknowledgements_label">Danksagungen</string>
|
<string name="settings_acknowledgements_label">Danksagungen</string>
|
||||||
<string name="changelog_label">Änderungsprotokoll</string>
|
<string name="changelog_label">Änderungsprotokoll</string>
|
||||||
<string name="settings_support_email_developer_label">E-Mail-Entwickler</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">E-Mail-Entwickler</string>
|
||||||
<string name="settings_support_installid_label">ID installieren</string>
|
<string name="settings_support_installid_label">ID installieren</string>
|
||||||
<string name="settings_support_installid_desc">Automatische Fehlermeldungen sind anonym. Teilen Sie Ihre Installations- ID mit, wenn der Entwickler Ihre Fehlerberichte finden muss.</string>
|
<string name="settings_support_installid_desc">Automatische Fehlermeldungen sind anonym. Teilen Sie Ihre Installations- ID mit, wenn der Entwickler Ihre Fehlerberichte finden muss.</string>
|
||||||
<string name="settings_support_label">Unterstützung</string>
|
<string name="settings_support_label">Unterstützung</string>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<string name="settings_monitor_mode_label">Überwachungsmodus</string>
|
<string name="settings_monitor_mode_label">Überwachungsmodus</string>
|
||||||
<string name="settings_monitor_mode_description">Unter welchen Umständen überwacht diese App Bluetooth-Daten.</string>
|
<string name="settings_monitor_mode_description">Unter welchen Umständen überwacht diese App Bluetooth-Daten.</string>
|
||||||
<string name="settings_scanner_mode_label">Scannermodus</string>
|
<string name="settings_scanner_mode_label">Scannermodus</string>
|
||||||
<string name="settings_scanner_mode_description">Soll der Bluetooth Low Energie-Scanner Leistung priorisieren oder Energie sparen?</string>
|
<string name="settings_scanner_mode_description">Soll der Bluetooth Low Energy Datenscanner Leistung priorisieren oder Energie sparen?</string>
|
||||||
<string name="settings_monitor_mode_manual_label">Wenn die App geöffnet ist</string>
|
<string name="settings_monitor_mode_manual_label">Wenn die App geöffnet ist</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">Wenn das Gerät verbunden ist</string>
|
<string name="settings_monitor_mode_automatic_label">Wenn das Gerät verbunden ist</string>
|
||||||
<string name="settings_monitor_mode_always_label">Stets</string>
|
<string name="settings_monitor_mode_always_label">Stets</string>
|
||||||
@@ -89,13 +89,13 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">Ausgewogen</string>
|
<string name="settings_scanner_mode_balanced_label">Ausgewogen</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">Geringe Latenz</string>
|
<string name="settings_scanner_mode_lowlatency_label">Geringe Latenz</string>
|
||||||
<string name="settings_autopause_label">Automatische Pause</string>
|
<string name="settings_autopause_label">Automatische Pause</string>
|
||||||
<string name="settings_autopause_description">Halten Sie die Musik an, wenn Sie das Gerät von Ihrem Ohr entfernen.</string>
|
<string name="settings_autopause_description">Halten Sie den Ton an, wenn Sie das Gerät von Ihrem Ohr entfernen.</string>
|
||||||
<string name="settings_showall_label">Alle Geräte anzeigen</string>
|
<string name="settings_showall_label">Alle Geräte anzeigen</string>
|
||||||
<string name="settings_showall_description">Zeigen Sie die Geräte anderer Personen in Ihrer Nähe an.</string>
|
<string name="settings_showall_description">Zeigen Sie die Geräte anderer Personen in Ihrer Nähe an.</string>
|
||||||
<string name="settings_autopplay_label">Automatisches Abspielen</string>
|
<string name="settings_autopplay_label">Automatisches Abspielen</string>
|
||||||
<string name="settings_autoplay_description">Starten Sie die Musikwiedergabe, wenn Sie das Gerät tragen.</string>
|
<string name="settings_autoplay_description">Starten Sie die Audiowiedergabe, wenn das Gerät getragen wird.</string>
|
||||||
<string name="settings_fake_data_label">Gefälschte Daten</string>
|
<string name="settings_fake_data_label">Gefälschte Daten</string>
|
||||||
<string name="settings_fake_data_description">Gefälschte Daten anzeigen, Geräte simulieren, die nicht existieren.</string>
|
<string name="settings_fake_data_description">Falsche Daten anzeigen, also nicht existierende Geräte simulieren.</string>
|
||||||
<string name="settings_debug_label">Debug-Einstellungen</string>
|
<string name="settings_debug_label">Debug-Einstellungen</string>
|
||||||
<string name="settings_debug_description">Zusätzliche Einstellungen zur Behebung von Problemen mit der App.</string>
|
<string name="settings_debug_description">Zusätzliche Einstellungen zur Behebung von Problemen mit der App.</string>
|
||||||
<string name="settings_signal_minimum_label">Minimale Signalqualität</string>
|
<string name="settings_signal_minimum_label">Minimale Signalqualität</string>
|
||||||
@@ -119,11 +119,10 @@
|
|||||||
<string name="upgrade_capod_description">Erhalten Sie zusätzliche Funktionen und unterstützen Sie den Entwickler.</string>
|
<string name="upgrade_capod_description">Erhalten Sie zusätzliche Funktionen und unterstützen Sie den Entwickler.</string>
|
||||||
<string name="settings_popup_caseopen_label">Popup zeigen</string>
|
<string name="settings_popup_caseopen_label">Popup zeigen</string>
|
||||||
<string name="settings_popup_caseopen_description">Ein Popup anzeigen, wenn das Gerätegehäuse geöffnet wird (experimentell).</string>
|
<string name="settings_popup_caseopen_description">Ein Popup anzeigen, wenn das Gerätegehäuse geöffnet wird (experimentell).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Popup-Gerätereaktionen</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Bluetooth ist deaktiviert</string>
|
<string name="overview_bluetooth_disabled_label">Bluetooth ist deaktiviert</string>
|
||||||
<string name="overview_bluetooth_disabled_description">Bluetooth ist deaktiviert, aktiviere es ;)</string>
|
<string name="overview_bluetooth_disabled_description">Bluetooth ist deaktiviert, aktiviere es ;)</string>
|
||||||
<string name="help_translate_label">Übersetzung</string>
|
<string name="help_translate_label">Übersetzung</string>
|
||||||
<string name="help_translate_description">Helfen Sie mit, dies in Ihre Lieblingssprache zu übersetzen.</string>
|
<string name="help_translate_description">Helfen Sie mit, diese App in Ihre Lieblingssprache zu übersetzen.</string>
|
||||||
<string name="settings_onepod_mode_label">Ein-Pod-Modus</string>
|
<string name="settings_onepod_mode_label">Ein-Pod-Modus</string>
|
||||||
<string name="settings_onepod_mode_description">Das Tragen beider Pods ist nicht erforderlich, das Tragen eines einzigen Pods reicht aus, um Reaktionen auszulösen.</string>
|
<string name="settings_onepod_mode_description">Das Tragen beider Pods ist nicht erforderlich, das Tragen eines einzigen Pods reicht aus, um Reaktionen auszulösen.</string>
|
||||||
<string name="permission_system_alert_window_label">Systemwarnungsfenster</string>
|
<string name="permission_system_alert_window_label">Systemwarnungsfenster</string>
|
||||||
@@ -133,4 +132,8 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">Ungefilterte BLE-Daten</string>
|
<string name="settings_blescanner_unfiltered_label">Ungefilterte BLE-Daten</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">Entfernen Sie alle Filter aus dem BLE-Scanner, um alle übertragenen BLE-Daten anzuzeigen. Nützlich, um Unterstützung für neue Kopfhörertypen hinzuzufügen.</string>
|
<string name="settings_blescanner_unfiltered_description">Entfernen Sie alle Filter aus dem BLE-Scanner, um alle übertragenen BLE-Daten anzuzeigen. Nützlich, um Unterstützung für neue Kopfhörertypen hinzuzufügen.</string>
|
||||||
<string name="permission_required_title">Die folgende Genehmigung ist erforderlich:</string>
|
<string name="permission_required_title">Die folgende Genehmigung ist erforderlich:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Kompatibilitätsmodus</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Deaktivieren Sie Optimierungen, um die Kompatibilität zu verbessern. Versuchen Sie dies, wenn Sie keine Daten sehen.</string>
|
||||||
|
<string name="translators_thanks_title">Übersetzer</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">Gamechanger181</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
<string name="pods_case_status_open_label">Ανοιχτή</string>
|
<string name="pods_case_status_open_label">Ανοιχτή</string>
|
||||||
<string name="pods_case_status_closed_label">Κλειστή</string>
|
<string name="pods_case_status_closed_label">Κλειστή</string>
|
||||||
<string name="pods_connection_state_disconnected_label">Δεν είναι συνδεδεμένο σε συσκευή</string>
|
<string name="pods_connection_state_disconnected_label">Δεν είναι συνδεδεμένο σε συσκευή</string>
|
||||||
<string name="pods_connection_state_idle_label">Συνδεδεμένο σε κάποια συσκευή, αλλά αδρανές</string>
|
<string name="pods_connection_state_idle_label">Συνδεδεμένο σε συσκευή, αλλά αδρανές</string>
|
||||||
<string name="pods_connection_state_music_label">Σε λειτουργία μουσικής</string>
|
<string name="pods_connection_state_music_label">Σε λειτουργία μουσικής</string>
|
||||||
<string name="pods_connection_state_call_label">Σε λειτουργία κλήσης</string>
|
<string name="pods_connection_state_call_label">Σε λειτουργία κλήσης</string>
|
||||||
<string name="pods_connection_state_ringing_label">Κουδούνισμα</string>
|
<string name="pods_connection_state_ringing_label">Κουδούνισμα</string>
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Γενικές ρυθμίσεις που επηρεάζουν όλη την εφαρμογή.</string>
|
<string name="settings_general_description">Γενικές ρυθμίσεις που επηρεάζουν όλη την εφαρμογή.</string>
|
||||||
<string name="settings_acknowledgements_label">Ευχαριστίες</string>
|
<string name="settings_acknowledgements_label">Ευχαριστίες</string>
|
||||||
<string name="changelog_label">Αρχείο αλλαγών</string>
|
<string name="changelog_label">Αρχείο αλλαγών</string>
|
||||||
<string name="settings_support_email_developer_label">Email στον προγραμματιστή</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">Email στον προγραμματιστή</string>
|
||||||
<string name="settings_support_installid_label">Αναγνωριστικό εγκατάστασης</string>
|
<string name="settings_support_installid_label">Αναγνωριστικό εγκατάστασης</string>
|
||||||
<string name="settings_support_installid_desc">Οι αυτόματες αναφορές σφαλμάτων είναι ανώνυμες. Κοινοποιήστε το αναγνωριστικό εγκατάστασης εάν ο προγραμματιστής πρέπει να βρει τις αναφορές σας σφαλμάτων.</string>
|
<string name="settings_support_installid_desc">Οι αυτόματες αναφορές σφαλμάτων είναι ανώνυμες. Κοινοποιήστε το αναγνωριστικό εγκατάστασης εάν ο προγραμματιστής πρέπει να βρει τις αναφορές σας σφαλμάτων.</string>
|
||||||
<string name="settings_support_label">Υποστήριξη</string>
|
<string name="settings_support_label">Υποστήριξη</string>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<string name="settings_monitor_mode_label">Λειτουργία παρακολούθησης</string>
|
<string name="settings_monitor_mode_label">Λειτουργία παρακολούθησης</string>
|
||||||
<string name="settings_monitor_mode_description">Κάτω από ποιες συνθήκες αυτή η εφαρμογή παρακολουθεί τα δεδομένα Bluetooth.</string>
|
<string name="settings_monitor_mode_description">Κάτω από ποιες συνθήκες αυτή η εφαρμογή παρακολουθεί τα δεδομένα Bluetooth.</string>
|
||||||
<string name="settings_scanner_mode_label">Λειτουργία σάρωσης</string>
|
<string name="settings_scanner_mode_label">Λειτουργία σάρωσης</string>
|
||||||
<string name="settings_scanner_mode_description">Ο σαρωτής Bluetooth Low Energy να δώσει προτεραιότητα στην απόδοση ή στη διατήρηση ενέργειας;</string>
|
<string name="settings_scanner_mode_description">Θα πρέπει η σάρωση δεδομένων χαμηλής ενέργειας Bluetooth να δίνει προτεραιότητα στην απόδοση ή να εξοικονομεί ενέργεια;</string>
|
||||||
<string name="settings_monitor_mode_manual_label">Όταν η εφαρμογή είναι ανοιχτή</string>
|
<string name="settings_monitor_mode_manual_label">Όταν η εφαρμογή είναι ανοιχτή</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">Όταν η συσκευή είναι συνδεδεμένη</string>
|
<string name="settings_monitor_mode_automatic_label">Όταν η συσκευή είναι συνδεδεμένη</string>
|
||||||
<string name="settings_monitor_mode_always_label">Πάντα</string>
|
<string name="settings_monitor_mode_always_label">Πάντα</string>
|
||||||
@@ -89,13 +89,13 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">Εξισορρόπηση</string>
|
<string name="settings_scanner_mode_balanced_label">Εξισορρόπηση</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">Χαμηλή καθυστέρηση</string>
|
<string name="settings_scanner_mode_lowlatency_label">Χαμηλή καθυστέρηση</string>
|
||||||
<string name="settings_autopause_label">Αυτόματη παύση</string>
|
<string name="settings_autopause_label">Αυτόματη παύση</string>
|
||||||
<string name="settings_autopause_description">Παύση μουσικής όταν αφαιρείται τη συσκευή από το αυτί σας.</string>
|
<string name="settings_autopause_description">Παύση ήχου όταν αφαιρείται τη συσκευή από το αυτί σας.</string>
|
||||||
<string name="settings_showall_label">Εμφάνιση όλων των συσκευών</string>
|
<string name="settings_showall_label">Εμφάνιση όλων των συσκευών</string>
|
||||||
<string name="settings_showall_description">Εμφάνιση συσκευών άλλων ανθρώπων που είναι κοντά σας.</string>
|
<string name="settings_showall_description">Εμφάνιση συσκευών άλλων ανθρώπων που είναι κοντά σας.</string>
|
||||||
<string name="settings_autopplay_label">Αυτόματη αναπαραγωγή</string>
|
<string name="settings_autopplay_label">Αυτόματη αναπαραγωγή</string>
|
||||||
<string name="settings_autoplay_description">Αναπαραγωγή μουσικής όταν φοριέται η συσκευή.</string>
|
<string name="settings_autoplay_description">Έναρξη αναπαραγωγής ήχου όταν φορεθεί η συσκευή.</string>
|
||||||
<string name="settings_fake_data_label">Ψευδή δεδομένα</string>
|
<string name="settings_fake_data_label">Ψευδή δεδομένα</string>
|
||||||
<string name="settings_fake_data_description">Εμφάνιση ψευδών δεδομένων, π.χ. προσομοίωση συσκευής που δεν υπάρχει.</string>
|
<string name="settings_fake_data_description">Εμφάνιση ψευδών δεδομένων, π.χ., προσομοίωση συσκευών που δεν υπάρχουν.</string>
|
||||||
<string name="settings_debug_label">Ρυθμίσεις αντιμετώπισης σφαλμάτων</string>
|
<string name="settings_debug_label">Ρυθμίσεις αντιμετώπισης σφαλμάτων</string>
|
||||||
<string name="settings_debug_description">Πρόσθετες ρυθμίσεις που βοηθούν στην αντιμετώπιση προβλημάτων με την εφαρμογή.</string>
|
<string name="settings_debug_description">Πρόσθετες ρυθμίσεις που βοηθούν στην αντιμετώπιση προβλημάτων με την εφαρμογή.</string>
|
||||||
<string name="settings_signal_minimum_label">Ελάχιστη ποιότητα σήματος</string>
|
<string name="settings_signal_minimum_label">Ελάχιστη ποιότητα σήματος</string>
|
||||||
@@ -119,11 +119,10 @@
|
|||||||
<string name="upgrade_capod_description">Λάβετε επιπλέον λειτουργίες και υποστηρίξτε τον προγραμματιστή.</string>
|
<string name="upgrade_capod_description">Λάβετε επιπλέον λειτουργίες και υποστηρίξτε τον προγραμματιστή.</string>
|
||||||
<string name="settings_popup_caseopen_label">Εμφάνιση αναδυόμενου</string>
|
<string name="settings_popup_caseopen_label">Εμφάνιση αναδυόμενου</string>
|
||||||
<string name="settings_popup_caseopen_description">Εμφάνιση αναδυόμενου όταν η θήκη της συσκευής είναι ανοιχτή (πειραματικό).</string>
|
<string name="settings_popup_caseopen_description">Εμφάνιση αναδυόμενου όταν η θήκη της συσκευής είναι ανοιχτή (πειραματικό).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Αναδυόμενες αντιδράσεις συσκευών</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Το Bluetooth είναι απενεργοποιημένο</string>
|
<string name="overview_bluetooth_disabled_label">Το Bluetooth είναι απενεργοποιημένο</string>
|
||||||
<string name="overview_bluetooth_disabled_description">Το Bluetooth είναι απενεργοποιημένο, ενεργοποιήστε το ;)</string>
|
<string name="overview_bluetooth_disabled_description">Το Bluetooth είναι απενεργοποιημένο, ενεργοποιήστε το ;)</string>
|
||||||
<string name="help_translate_label">Μετάφραση</string>
|
<string name="help_translate_label">Μετάφραση</string>
|
||||||
<string name="help_translate_description">Βοηθήστε να μεταφραστεί στην αγαπημένη σας γλώσσα.</string>
|
<string name="help_translate_description">Βοηθήστε να μεταφραστεί αυτή η εφαρμογή στην αγαπημένη σας γλώσσα.</string>
|
||||||
<string name="settings_onepod_mode_label">Λειτουργία ενός pod</string>
|
<string name="settings_onepod_mode_label">Λειτουργία ενός pod</string>
|
||||||
<string name="settings_onepod_mode_description">Δεν απαιτείται να φοράτε και τα δύο pods, αρκεί να φοράτε ένα μόνο pod για να ενεργοποιούνται αντιδράσεις.</string>
|
<string name="settings_onepod_mode_description">Δεν απαιτείται να φοράτε και τα δύο pods, αρκεί να φοράτε ένα μόνο pod για να ενεργοποιούνται αντιδράσεις.</string>
|
||||||
<string name="permission_system_alert_window_label">Παράθυρο ειδοποίησης συστήματος</string>
|
<string name="permission_system_alert_window_label">Παράθυρο ειδοποίησης συστήματος</string>
|
||||||
@@ -133,4 +132,8 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">Μη φιλτραρισμένα δεδομένα BLE</string>
|
<string name="settings_blescanner_unfiltered_label">Μη φιλτραρισμένα δεδομένα BLE</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">Αφαιρέστε τυχόν φίλτρα από τη σάρωση BLE για να εμφανίσετε όλα τα δεδομένα BLE που μεταδίδονται. Χρήσιμο για την προσθήκη υποστήριξης για νέους τύπους ακουστικών.</string>
|
<string name="settings_blescanner_unfiltered_description">Αφαιρέστε τυχόν φίλτρα από τη σάρωση BLE για να εμφανίσετε όλα τα δεδομένα BLE που μεταδίδονται. Χρήσιμο για την προσθήκη υποστήριξης για νέους τύπους ακουστικών.</string>
|
||||||
<string name="permission_required_title">Η ακόλουθη άδεια είναι απαραίτητη:</string>
|
<string name="permission_required_title">Η ακόλουθη άδεια είναι απαραίτητη:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Λειτουργία συμβατότητας</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Απενεργοποίηση βελτιστοποιήσεων για βελτίωση συμβατότητας. Δοκιμάστε αυτό εάν δε βλέπετε δεδομένα.</string>
|
||||||
|
<string name="translators_thanks_title">Μεταφραστές</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">Vagelis1608</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -25,4 +25,31 @@
|
|||||||
<string name="permission_bluetooth_scan_description">El permiso \"Escaneo Bluetooth\" permite que esta aplicación descubra y reciba datos de Bluetooth de dispositivos cercanos como tus AirPods.</string>
|
<string name="permission_bluetooth_scan_description">El permiso \"Escaneo Bluetooth\" permite que esta aplicación descubra y reciba datos de Bluetooth de dispositivos cercanos como tus AirPods.</string>
|
||||||
<string name="permission_bluetooth_label">Bluetooth</string>
|
<string name="permission_bluetooth_label">Bluetooth</string>
|
||||||
<string name="permission_bluetooth_description">Esta aplicacion requiere el permiso \"Bluetooth\" para conectarse a los dispositivos vinculados.</string>
|
<string name="permission_bluetooth_description">Esta aplicacion requiere el permiso \"Bluetooth\" para conectarse a los dispositivos vinculados.</string>
|
||||||
|
<string name="permission_access_fine_location_label">Acceso a la ubicación precisa</string>
|
||||||
|
<string name="permission_access_fine_location_description">CAPod utiliza el permiso de \"ubicación precisa\" para recibir Datos de Bluetooth de bajo consumo. Sus auriculares utilizan la tecnología Datos de Bluetooth de bajo consumo para transmitir su estado. Esta aplicación NO utilizará datos de Bluetooth para determinar su ubicación.</string>
|
||||||
|
<string name="permission_background_location_label">Acceso a la ubicación en segundo plano</string>
|
||||||
|
<string name="permission_background_location_description">CAPod usa el \"acceso a la ubicación en segundo plano\" para habilitar funciones como \"Mostrar ventana emergente\" y \"Conexión automática\" mientras la aplicación está cerrada. El acceso a la ubicación en segundo plano permite que la aplicación reciba datos de Bluetooth de bajo consumo mientras está en segundo plano. Esta aplicación NO utilizará datos de Bluetooth para determinar su ubicación.</string>
|
||||||
|
<string name="permission_ignore_battery_optimizations_label">Deshabilitar optimizaciones de batería</string>
|
||||||
|
<string name="permission_ignore_battery_optimizations_description">Las optimizaciones de la batería evitan que esta aplicación reciba datos de Bluetooth de manera confiable mientras la aplicación está en segundo plano.</string>
|
||||||
|
<string name="pods_dual_left_label">Audífono izquierdo</string>
|
||||||
|
<string name="pods_dual_right_label">Audífono derecho</string>
|
||||||
|
<string name="pods_case_label">Estuche</string>
|
||||||
|
<string name="pods_case_status_open_label">Estuche abierto</string>
|
||||||
|
<string name="pods_case_status_closed_label">Estuche cerrado</string>
|
||||||
|
<string name="pods_connection_state_disconnected_label">No está conectado a un dispositivo</string>
|
||||||
|
<string name="pods_connection_state_idle_label">Conectado a un dispositivo, pero inactivo</string>
|
||||||
|
<string name="pods_connection_state_music_label">En modo música</string>
|
||||||
|
<string name="pods_connection_state_call_label">En modo llamada</string>
|
||||||
|
<string name="pods_connection_state_ringing_label">Sonando</string>
|
||||||
|
<string name="pods_connection_state_hanging_up_label">Colgar</string>
|
||||||
|
<string name="pods_connection_state_unknown_label">Estado de conexión desconocido</string>
|
||||||
|
<string name="pods_unknown_raw_data_label">Datos sin procesar</string>
|
||||||
|
<string name="pods_unknown_label">Dispositivo desconocido</string>
|
||||||
|
<string name="pods_unknown_contact_dev">Este es un dispositivo desconocido, pero está usando un formato de mensaje similar. Agreguemos soporte para ello, contáctame :)</string>
|
||||||
|
<string name="pods_none_label_short">Sin dispositivo</string>
|
||||||
|
<string name="pods_charging_label">Cargando</string>
|
||||||
|
<string name="pods_inear_label">En el oído</string>
|
||||||
|
<string name="pods_microphone_label">Micrófono</string>
|
||||||
|
<string name="pods_yours">Tuyos</string>
|
||||||
|
<string name="headset_being_worn_label">En uso</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Ajustes generales que afectan a toda la aplicación.</string>
|
<string name="settings_general_description">Ajustes generales que afectan a toda la aplicación.</string>
|
||||||
<string name="settings_acknowledgements_label">Agradecimientos</string>
|
<string name="settings_acknowledgements_label">Agradecimientos</string>
|
||||||
<string name="changelog_label">Registro de cambios</string>
|
<string name="changelog_label">Registro de cambios</string>
|
||||||
<string name="settings_support_email_developer_label">Correo del desarrollador</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">Correo del desarrollador</string>
|
||||||
<string name="settings_support_installid_label">ID de instalación</string>
|
<string name="settings_support_installid_label">ID de instalación</string>
|
||||||
<string name="settings_support_installid_desc">Los informes automáticos de errores son anónimos. Comparta su ID de instalación si el desarrollador necesita encontrar sus informes de error.</string>
|
<string name="settings_support_installid_desc">Los informes automáticos de errores son anónimos. Comparta su ID de instalación si el desarrollador necesita encontrar sus informes de error.</string>
|
||||||
<string name="settings_support_label">Ayuda</string>
|
<string name="settings_support_label">Ayuda</string>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<string name="settings_monitor_mode_label">Modo monitor</string>
|
<string name="settings_monitor_mode_label">Modo monitor</string>
|
||||||
<string name="settings_monitor_mode_description">Bajo qué circunstancias esta aplicación monitorea los datos Bluetooth.</string>
|
<string name="settings_monitor_mode_description">Bajo qué circunstancias esta aplicación monitorea los datos Bluetooth.</string>
|
||||||
<string name="settings_scanner_mode_label">Modo escáner</string>
|
<string name="settings_scanner_mode_label">Modo escáner</string>
|
||||||
<string name="settings_scanner_mode_description">¿El escáner Bluetooth Low Energy debe priorizar el rendimiento o ahorrar energía?</string>
|
<string name="settings_scanner_mode_description">¿El escáner de datos Bluetooth Low Energy debe priorizar el rendimiento o ahorrar energía?</string>
|
||||||
<string name="settings_monitor_mode_manual_label">Cuando la aplicación está abierta</string>
|
<string name="settings_monitor_mode_manual_label">Cuando la aplicación está abierta</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">Cuando el dispositivo está conectado</string>
|
<string name="settings_monitor_mode_automatic_label">Cuando el dispositivo está conectado</string>
|
||||||
<string name="settings_monitor_mode_always_label">Siempre</string>
|
<string name="settings_monitor_mode_always_label">Siempre</string>
|
||||||
@@ -89,11 +89,11 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">Balanceado</string>
|
<string name="settings_scanner_mode_balanced_label">Balanceado</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">Baja latencia</string>
|
<string name="settings_scanner_mode_lowlatency_label">Baja latencia</string>
|
||||||
<string name="settings_autopause_label">Pausar automáticamente</string>
|
<string name="settings_autopause_label">Pausar automáticamente</string>
|
||||||
<string name="settings_autopause_description">Pausa la música cuando se quites el dispositivo de la oreja.</string>
|
<string name="settings_autopause_description">Pausa el audio cuando te quites el dispositivo de la oreja.</string>
|
||||||
<string name="settings_showall_label">Mostrar todos los dispositivos</string>
|
<string name="settings_showall_label">Mostrar todos los dispositivos</string>
|
||||||
<string name="settings_showall_description">Muestra los dispositivos de otras personas que están cerca de ti.</string>
|
<string name="settings_showall_description">Muestra los dispositivos de otras personas que están cerca de ti.</string>
|
||||||
<string name="settings_autopplay_label">Reproducción automática</string>
|
<string name="settings_autopplay_label">Reproducción automática</string>
|
||||||
<string name="settings_autoplay_description">Iniciar la reproducción de música cuando use el dispositivo.</string>
|
<string name="settings_autoplay_description">Inicia la reproducción de audio cuando se use el dispositivo.</string>
|
||||||
<string name="settings_fake_data_label">Información falsa</string>
|
<string name="settings_fake_data_label">Información falsa</string>
|
||||||
<string name="settings_fake_data_description">Mostrar datos falsos. Por ejemplo: simular un dispositivo que no existe.</string>
|
<string name="settings_fake_data_description">Mostrar datos falsos. Por ejemplo: simular un dispositivo que no existe.</string>
|
||||||
<string name="settings_debug_label">Configuración de depuración</string>
|
<string name="settings_debug_label">Configuración de depuración</string>
|
||||||
@@ -119,11 +119,10 @@
|
|||||||
<string name="upgrade_capod_description">Obtenga funciones adicionales y apoye al desarrollador.</string>
|
<string name="upgrade_capod_description">Obtenga funciones adicionales y apoye al desarrollador.</string>
|
||||||
<string name="settings_popup_caseopen_label">Mostrar ventanas emergentes</string>
|
<string name="settings_popup_caseopen_label">Mostrar ventanas emergentes</string>
|
||||||
<string name="settings_popup_caseopen_description">Muestra una ventana emergente cuando se abre el estuche del dispositivo (experimental).</string>
|
<string name="settings_popup_caseopen_description">Muestra una ventana emergente cuando se abre el estuche del dispositivo (experimental).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Reacciones emergentes de dispositivos</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Bluetooth deshabilitado</string>
|
<string name="overview_bluetooth_disabled_label">Bluetooth deshabilitado</string>
|
||||||
<string name="overview_bluetooth_disabled_description">El Bluetooth está deshabilitado, habilítelo ;)</string>
|
<string name="overview_bluetooth_disabled_description">El Bluetooth está deshabilitado, habilítelo ;)</string>
|
||||||
<string name="help_translate_label">Traducción</string>
|
<string name="help_translate_label">Traducción</string>
|
||||||
<string name="help_translate_description">Ayude a traducir esta aplicación a su idioma favorito.</string>
|
<string name="help_translate_description">Ayuda a traducir esta aplicación a tu idioma favorito.</string>
|
||||||
<string name="settings_onepod_mode_label">Modo un audífono</string>
|
<string name="settings_onepod_mode_label">Modo un audífono</string>
|
||||||
<string name="settings_onepod_mode_description">No es necesario usar ambos AirPods, usar un solo AirPod es suficiente para desencadenar reacciones.</string>
|
<string name="settings_onepod_mode_description">No es necesario usar ambos AirPods, usar un solo AirPod es suficiente para desencadenar reacciones.</string>
|
||||||
<string name="permission_system_alert_window_label">Ventana de alerta del sistema</string>
|
<string name="permission_system_alert_window_label">Ventana de alerta del sistema</string>
|
||||||
@@ -133,4 +132,8 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">Datos BLE sin filtrar</string>
|
<string name="settings_blescanner_unfiltered_label">Datos BLE sin filtrar</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">Elimina los filtros del escáner BLE para mostrar todos los datos BLE transmitidos. Útil para agregar soporte para nuevos tipos de auriculares.</string>
|
<string name="settings_blescanner_unfiltered_description">Elimina los filtros del escáner BLE para mostrar todos los datos BLE transmitidos. Útil para agregar soporte para nuevos tipos de auriculares.</string>
|
||||||
<string name="permission_required_title">Se requiere el siguiente permiso:</string>
|
<string name="permission_required_title">Se requiere el siguiente permiso:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Modo de compatibilidad</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Deshabilita las optimizaciones para mejorar la compatibilidad. Prueba esto si no ves ningún dato.</string>
|
||||||
|
<string name="translators_thanks_title">Traductores</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">Jaime Muñoz(jmmartin_5@outlook.com)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="pods_dual_left_label">Vasak klapp</string>
|
||||||
|
<string name="pods_dual_right_label">Parem klapp</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -13,5 +13,19 @@
|
|||||||
<string name="debug_debuglog_size_label">Sukat</string>
|
<string name="debug_debuglog_size_label">Sukat</string>
|
||||||
<string name="permission_bluetooth_connect_description">Ang app na ito ay kailangan ng \"Bluetooth connect\" permission para makipag interact sa mga na-paired na devices at maka gawa ng connection.</string>
|
<string name="permission_bluetooth_connect_description">Ang app na ito ay kailangan ng \"Bluetooth connect\" permission para makipag interact sa mga na-paired na devices at maka gawa ng connection.</string>
|
||||||
<string name="permission_bluetooth_scan_description">Ang \"Bluetooth scanning\" permission ay pag na ibigay, itong app na ito ay puwedeng mag diskubre o maka receive ng data galing sa isang malapit na Bluetooth devices tulad ng iyong AirPods.</string>
|
<string name="permission_bluetooth_scan_description">Ang \"Bluetooth scanning\" permission ay pag na ibigay, itong app na ito ay puwedeng mag diskubre o maka receive ng data galing sa isang malapit na Bluetooth devices tulad ng iyong AirPods.</string>
|
||||||
|
<string name="permission_bluetooth_label">Bluetooth</string>
|
||||||
|
<string name="permission_bluetooth_description">Ang app na ito ay kailangan ng \"Bluetooth\" permission upang maka connect sa naka-paired na bluetooth device.</string>
|
||||||
<string name="permission_access_fine_location_description">Ang CAPod app ay gumagamit ng \"Fine location\" permission para maka receiveng Bluetooth Low Energy Data. Iyong headphones ay gumagamit ng Bluetooth Low Energy technology pa ma-broadcaast ang kanilang Status. Itong app na ito ay HINDI gagamitin ang Bluetooth data para malaman ang iyong lokasyon.</string>
|
<string name="permission_access_fine_location_description">Ang CAPod app ay gumagamit ng \"Fine location\" permission para maka receiveng Bluetooth Low Energy Data. Iyong headphones ay gumagamit ng Bluetooth Low Energy technology pa ma-broadcaast ang kanilang Status. Itong app na ito ay HINDI gagamitin ang Bluetooth data para malaman ang iyong lokasyon.</string>
|
||||||
|
<string name="pods_dual_left_label">Kaliwang pod</string>
|
||||||
|
<string name="pods_dual_right_label">Kanan na pod</string>
|
||||||
|
<string name="pods_case_status_open_label">Buksan</string>
|
||||||
|
<string name="pods_case_status_closed_label">Sarado</string>
|
||||||
|
<string name="pods_connection_state_disconnected_label">Hindi Konektado sa device</string>
|
||||||
|
<string name="pods_unknown_contact_dev">Ito ay hindi kilalang Device, pero ginagamit ang kilalang message format. lagyan nating ng support para diyan, contact mo ko :)</string>
|
||||||
|
<string name="pods_yours">Sayo</string>
|
||||||
|
<string name="headset_being_worn_label">Ginagamit</string>
|
||||||
|
<string name="pods_case_unknown_state">Hindi alam ang stado</string>
|
||||||
|
<string name="overview_nomaindevice_description">Lahat ng mga device ay malabong saiyo. I-power on at i-connect ang device mo o i-adjust ang settings.</string>
|
||||||
|
<string name="settings_licenses_label">Lisensiya</string>
|
||||||
|
<string name="settings_category_other_label">Iba</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Réglage généraux qui affectent l\'appli entière.</string>
|
<string name="settings_general_description">Réglage généraux qui affectent l\'appli entière.</string>
|
||||||
<string name="settings_acknowledgements_label">Remerciements</string>
|
<string name="settings_acknowledgements_label">Remerciements</string>
|
||||||
<string name="changelog_label">Journal des changements</string>
|
<string name="changelog_label">Journal des changements</string>
|
||||||
<string name="settings_support_email_developer_label">Envoyer un courriel au développeur</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">Envoyer un courriel au développeur</string>
|
||||||
<string name="settings_support_installid_label">ID d’installation</string>
|
<string name="settings_support_installid_label">ID d’installation</string>
|
||||||
<string name="settings_support_installid_desc">Les relevés automatiques d’erreur sont anonymes. Partagez votre ID d’installation au cas où le développeur aurait besoin de trouver votre relevé d’erreur.</string>
|
<string name="settings_support_installid_desc">Les relevés automatiques d’erreur sont anonymes. Partagez votre ID d’installation au cas où le développeur aurait besoin de trouver votre relevé d’erreur.</string>
|
||||||
<string name="settings_support_label">Assistance</string>
|
<string name="settings_support_label">Assistance</string>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<string name="settings_monitor_mode_label">Mode surveillance</string>
|
<string name="settings_monitor_mode_label">Mode surveillance</string>
|
||||||
<string name="settings_monitor_mode_description">Les circonstances de surveillance des données Bluetooth par l’appli.</string>
|
<string name="settings_monitor_mode_description">Les circonstances de surveillance des données Bluetooth par l’appli.</string>
|
||||||
<string name="settings_scanner_mode_label">Mode analyse</string>
|
<string name="settings_scanner_mode_label">Mode analyse</string>
|
||||||
<string name="settings_scanner_mode_description">Le mode analyse des données « basse énergie » de Bluetooth devrait-il prioriser les performances ou préserver l’énergie ?</string>
|
<string name="settings_scanner_mode_description">L’analyseur des données « basse énergie » de Bluetooth devrait-il prioriser les performances ou préserver l’énergie ?</string>
|
||||||
<string name="settings_monitor_mode_manual_label">Si l’appli est en fonction</string>
|
<string name="settings_monitor_mode_manual_label">Si l’appli est en fonction</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">Si l’appareil est connecté</string>
|
<string name="settings_monitor_mode_automatic_label">Si l’appareil est connecté</string>
|
||||||
<string name="settings_monitor_mode_always_label">Toujours</string>
|
<string name="settings_monitor_mode_always_label">Toujours</string>
|
||||||
@@ -93,9 +93,9 @@
|
|||||||
<string name="settings_showall_label">Afficher tous les appareils</string>
|
<string name="settings_showall_label">Afficher tous les appareils</string>
|
||||||
<string name="settings_showall_description">Afficher les appareils d’autres personnes à proximité.</string>
|
<string name="settings_showall_description">Afficher les appareils d’autres personnes à proximité.</string>
|
||||||
<string name="settings_autopplay_label">Lecture automatique</string>
|
<string name="settings_autopplay_label">Lecture automatique</string>
|
||||||
<string name="settings_autoplay_description">Lire le contenu audio si l’appareil est porté.</string>
|
<string name="settings_autoplay_description">Démarrer la lecture du son quand l’appareil est porté.</string>
|
||||||
<string name="settings_fake_data_label">Fausses données</string>
|
<string name="settings_fake_data_label">Fausses données</string>
|
||||||
<string name="settings_fake_data_description">Afficher les fausses données, c.-à-d. simuler un appareil qui n’existe pas.</string>
|
<string name="settings_fake_data_description">Afficher les fausses données, c.-à-d. simuler les appareils qui n’existent pas.</string>
|
||||||
<string name="settings_debug_label">Paramètres de débogage</string>
|
<string name="settings_debug_label">Paramètres de débogage</string>
|
||||||
<string name="settings_debug_description">Autres paramètres pour aider à diagnostiquer les problèmes de l’appli.</string>
|
<string name="settings_debug_description">Autres paramètres pour aider à diagnostiquer les problèmes de l’appli.</string>
|
||||||
<string name="settings_signal_minimum_label">Qualité minimale du signal</string>
|
<string name="settings_signal_minimum_label">Qualité minimale du signal</string>
|
||||||
@@ -119,11 +119,10 @@
|
|||||||
<string name="upgrade_capod_description">Obtenez des fonctions supplémentaires et soutenez le développeur.</string>
|
<string name="upgrade_capod_description">Obtenez des fonctions supplémentaires et soutenez le développeur.</string>
|
||||||
<string name="settings_popup_caseopen_label">Afficher une notification</string>
|
<string name="settings_popup_caseopen_label">Afficher une notification</string>
|
||||||
<string name="settings_popup_caseopen_description">Afficher une notification à l’ouverture de l’étui de l\'appareil (expérimental).</string>
|
<string name="settings_popup_caseopen_description">Afficher une notification à l’ouverture de l’étui de l\'appareil (expérimental).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Afficher les réactions de l’appareil</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Le Bluetooth est désactivé</string>
|
<string name="overview_bluetooth_disabled_label">Le Bluetooth est désactivé</string>
|
||||||
<string name="overview_bluetooth_disabled_description">Le Bluetooth est désactivé, activez-le ;)</string>
|
<string name="overview_bluetooth_disabled_description">Le Bluetooth est désactivé, activez-le ;)</string>
|
||||||
<string name="help_translate_label">Traduction</string>
|
<string name="help_translate_label">Traduction</string>
|
||||||
<string name="help_translate_description">Aidez à traduire l’appli dans votre langue préférée.</string>
|
<string name="help_translate_description">Aider à traduire cette appli dans votre langue préférée.</string>
|
||||||
<string name="settings_onepod_mode_label">Mode à un seul AirPod</string>
|
<string name="settings_onepod_mode_label">Mode à un seul AirPod</string>
|
||||||
<string name="settings_onepod_mode_description">Il n’est pas nécessaire de porter deux AirPods, en porter un seul suffit à déclencher les réactions.</string>
|
<string name="settings_onepod_mode_description">Il n’est pas nécessaire de porter deux AirPods, en porter un seul suffit à déclencher les réactions.</string>
|
||||||
<string name="permission_system_alert_window_label">Fenêtre d’alerte système</string>
|
<string name="permission_system_alert_window_label">Fenêtre d’alerte système</string>
|
||||||
@@ -133,4 +132,8 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">Données BÉB non filtrées</string>
|
<string name="settings_blescanner_unfiltered_label">Données BÉB non filtrées</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">Supprimer tous les filtres de l’analyseur BÉB pour afficher toutes les données BÉB diffusées. Utile pour prendre en charge les nouveaux types de casques-micros.</string>
|
<string name="settings_blescanner_unfiltered_description">Supprimer tous les filtres de l’analyseur BÉB pour afficher toutes les données BÉB diffusées. Utile pour prendre en charge les nouveaux types de casques-micros.</string>
|
||||||
<string name="permission_required_title">L’autorisation suivante est nécessaire :</string>
|
<string name="permission_required_title">L’autorisation suivante est nécessaire :</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Mode de compatibilité</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Désactiver les optimisations pour améliorer la compatibilité. À essayer si vous ne voyez aucune donnée.</string>
|
||||||
|
<string name="translators_thanks_title">Traducteurs</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">AO</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="app_name">CAPod</string>
|
||||||
|
<string name="app_name_pro">CAPod Pro</string>
|
||||||
|
<string name="app_name_foss">CAPod FOSS</string>
|
||||||
|
<string name="notification_channel_device_status_label">उपकरण की स्थिति</string>
|
||||||
|
<string name="general_error_label">त्रुटि</string>
|
||||||
|
<string name="general_share_action">साझा करना</string>
|
||||||
|
<string name="general_done_action">पूर्ण</string>
|
||||||
|
<string name="general_copy_action">प्रतिलिपि</string>
|
||||||
|
<string name="general_thank_you_label">शुक्रिया</string>
|
||||||
|
<string name="general_value_not_available_label">N/A</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Általános módosítások, amelyek az egész alkalmazást érintik.</string>
|
<string name="settings_general_description">Általános módosítások, amelyek az egész alkalmazást érintik.</string>
|
||||||
<string name="settings_acknowledgements_label">Köszönetnyilvánítások</string>
|
<string name="settings_acknowledgements_label">Köszönetnyilvánítások</string>
|
||||||
<string name="changelog_label">Napló</string>
|
<string name="changelog_label">Napló</string>
|
||||||
<string name="settings_support_email_developer_label">Fejlesztő Email címe</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">Fejlesztő Email címe</string>
|
||||||
<string name="settings_support_installid_label">Azonosító</string>
|
<string name="settings_support_installid_label">Azonosító</string>
|
||||||
<string name="settings_support_installid_desc">Az automatikus hibajelentések névtelenek. Ossza meg azonosítóját, hogy a fejlesztő megtalálja a hibajelentéseket.</string>
|
<string name="settings_support_installid_desc">Az automatikus hibajelentések névtelenek. Ossza meg azonosítóját, hogy a fejlesztő megtalálja a hibajelentéseket.</string>
|
||||||
<string name="settings_support_label">Támogatás</string>
|
<string name="settings_support_label">Támogatás</string>
|
||||||
@@ -81,7 +81,6 @@
|
|||||||
<string name="settings_monitor_mode_label">Monitor mód</string>
|
<string name="settings_monitor_mode_label">Monitor mód</string>
|
||||||
<string name="settings_monitor_mode_description">Milyen körülmények között figyeli ez az alkalmazás a Bluetooth-adatokat.</string>
|
<string name="settings_monitor_mode_description">Milyen körülmények között figyeli ez az alkalmazás a Bluetooth-adatokat.</string>
|
||||||
<string name="settings_scanner_mode_label">Szkenner mód</string>
|
<string name="settings_scanner_mode_label">Szkenner mód</string>
|
||||||
<string name="settings_scanner_mode_description">A \"Bluetooth alacsony töltöttség\" a szkennernek a teljesítményt kell előnyben részesítenie, vagy energiát takaríthat meg?</string>
|
|
||||||
<string name="settings_monitor_mode_manual_label">Amikor az alkalmazás nyitva van</string>
|
<string name="settings_monitor_mode_manual_label">Amikor az alkalmazás nyitva van</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">Amikor az eszköz csatlakoztatva van</string>
|
<string name="settings_monitor_mode_automatic_label">Amikor az eszköz csatlakoztatva van</string>
|
||||||
<string name="settings_monitor_mode_always_label">Mindig</string>
|
<string name="settings_monitor_mode_always_label">Mindig</string>
|
||||||
@@ -89,13 +88,10 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">Kiegyensúlyozott</string>
|
<string name="settings_scanner_mode_balanced_label">Kiegyensúlyozott</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">Alacsony késleltetés</string>
|
<string name="settings_scanner_mode_lowlatency_label">Alacsony késleltetés</string>
|
||||||
<string name="settings_autopause_label">Automatikus megszakítás</string>
|
<string name="settings_autopause_label">Automatikus megszakítás</string>
|
||||||
<string name="settings_autopause_description">A zene szüneteltetése, amikor eltávolítja a készüléket a füléről.</string>
|
|
||||||
<string name="settings_showall_label">Az összes eszköz megjelenítése</string>
|
<string name="settings_showall_label">Az összes eszköz megjelenítése</string>
|
||||||
<string name="settings_showall_description">Mutassa meg másoknak az Ön közelében lévő eszközeit.</string>
|
<string name="settings_showall_description">Mutassa meg másoknak az Ön közelében lévő eszközeit.</string>
|
||||||
<string name="settings_autopplay_label">Automatikus lejátszás</string>
|
<string name="settings_autopplay_label">Automatikus lejátszás</string>
|
||||||
<string name="settings_autoplay_description">Indítsa el a zenelejátszást a készülék használatakor.</string>
|
|
||||||
<string name="settings_fake_data_label">Hamis adat</string>
|
<string name="settings_fake_data_label">Hamis adat</string>
|
||||||
<string name="settings_fake_data_description">Hamis adatok megjelenítése, azaz olyan eszköz szimulálása, amely nem létezik.</string>
|
|
||||||
<string name="settings_debug_label">Hibakeresési beállítások</string>
|
<string name="settings_debug_label">Hibakeresési beállítások</string>
|
||||||
<string name="settings_debug_description">További beállítások az alkalmazással kapcsolatos problémák megoldásához.</string>
|
<string name="settings_debug_description">További beállítások az alkalmazással kapcsolatos problémák megoldásához.</string>
|
||||||
<string name="settings_signal_minimum_label">Minimális jelerősség</string>
|
<string name="settings_signal_minimum_label">Minimális jelerősség</string>
|
||||||
@@ -119,11 +115,9 @@
|
|||||||
<string name="upgrade_capod_description">Szerezzen be további funkciókat és támogassa a fejlesztőt.</string>
|
<string name="upgrade_capod_description">Szerezzen be további funkciókat és támogassa a fejlesztőt.</string>
|
||||||
<string name="settings_popup_caseopen_label">Előugró ablak megjelenítése</string>
|
<string name="settings_popup_caseopen_label">Előugró ablak megjelenítése</string>
|
||||||
<string name="settings_popup_caseopen_description">Egy előugró ablak megjelenítése az eszköz házának kinyitásakor (kísérleti).</string>
|
<string name="settings_popup_caseopen_description">Egy előugró ablak megjelenítése az eszköz házának kinyitásakor (kísérleti).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Előugró eszköz reakciói</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">A Bluetooth kikapcsolva</string>
|
<string name="overview_bluetooth_disabled_label">A Bluetooth kikapcsolva</string>
|
||||||
<string name="overview_bluetooth_disabled_description">Bluetooth kikapcsolva, engedélyezd ;)</string>
|
<string name="overview_bluetooth_disabled_description">Bluetooth kikapcsolva, engedélyezd ;)</string>
|
||||||
<string name="help_translate_label">Fordítás</string>
|
<string name="help_translate_label">Fordítás</string>
|
||||||
<string name="help_translate_description">Segíts lefordítani a nyelvedre.</string>
|
|
||||||
<string name="settings_onepod_mode_label">Egy fülhallgató mód</string>
|
<string name="settings_onepod_mode_label">Egy fülhallgató mód</string>
|
||||||
<string name="settings_onepod_mode_description">Nem szükséges mindkét fülhallgató viselése, elég egy, a működéshez.</string>
|
<string name="settings_onepod_mode_description">Nem szükséges mindkét fülhallgató viselése, elég egy, a működéshez.</string>
|
||||||
<string name="permission_system_alert_window_label">Rendszer figyelmeztető ablak</string>
|
<string name="permission_system_alert_window_label">Rendszer figyelmeztető ablak</string>
|
||||||
@@ -133,4 +127,5 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">Szűretlen BLE adatok</string>
|
<string name="settings_blescanner_unfiltered_label">Szűretlen BLE adatok</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">Távolítson el minden szűrőt a BLE szkennerből, hogy megjelenjen az összes adat. Hasznos új fejhallgató típusok támogatásához.</string>
|
<string name="settings_blescanner_unfiltered_description">Távolítson el minden szűrőt a BLE szkennerből, hogy megjelenjen az összes adat. Hasznos új fejhallgató típusok támogatásához.</string>
|
||||||
<string name="permission_required_title">A következő engedély szükséges:</string>
|
<string name="permission_required_title">A következő engedély szükséges:</string>
|
||||||
|
<string name="translators_thanks_title">Fordító</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Penyesuaian umum yang memengaruhi seluruh aplikasi.</string>
|
<string name="settings_general_description">Penyesuaian umum yang memengaruhi seluruh aplikasi.</string>
|
||||||
<string name="settings_acknowledgements_label">Ucapan terima kasih</string>
|
<string name="settings_acknowledgements_label">Ucapan terima kasih</string>
|
||||||
<string name="changelog_label">Catatan perubahan</string>
|
<string name="changelog_label">Catatan perubahan</string>
|
||||||
<string name="settings_support_email_developer_label">Email pengembang</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">Email pengembang</string>
|
||||||
<string name="settings_support_installid_label">ID pemasangan</string>
|
<string name="settings_support_installid_label">ID pemasangan</string>
|
||||||
<string name="settings_support_installid_desc">Laporan kesalahan otomatis bersifat anonim. Bagikan ID pemasangan anda jika pengembang perlu menemukan laporan kesalahan anda.</string>
|
<string name="settings_support_installid_desc">Laporan kesalahan otomatis bersifat anonim. Bagikan ID pemasangan anda jika pengembang perlu menemukan laporan kesalahan anda.</string>
|
||||||
<string name="settings_support_label">Dukungan</string>
|
<string name="settings_support_label">Dukungan</string>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<string name="settings_monitor_mode_label">Mode monitor</string>
|
<string name="settings_monitor_mode_label">Mode monitor</string>
|
||||||
<string name="settings_monitor_mode_description">Dalam keadaan apa aplikasi ini memonitor data Bluetooth.</string>
|
<string name="settings_monitor_mode_description">Dalam keadaan apa aplikasi ini memonitor data Bluetooth.</string>
|
||||||
<string name="settings_scanner_mode_label">Modus memindai</string>
|
<string name="settings_scanner_mode_label">Modus memindai</string>
|
||||||
<string name="settings_scanner_mode_description">Haruskah pemindai Bluetooth Hemat Energi memprioritaskan kinerja atau menghemat energi?</string>
|
<string name="settings_scanner_mode_description">Haruskah pemindai data Bluetooth Hemat Energi memprioritaskan kinerja atau menghemat energi?</string>
|
||||||
<string name="settings_monitor_mode_manual_label">Saat aplikasi terbuka</string>
|
<string name="settings_monitor_mode_manual_label">Saat aplikasi terbuka</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">Saat perangkat terhubung</string>
|
<string name="settings_monitor_mode_automatic_label">Saat perangkat terhubung</string>
|
||||||
<string name="settings_monitor_mode_always_label">Selalu</string>
|
<string name="settings_monitor_mode_always_label">Selalu</string>
|
||||||
@@ -89,13 +89,13 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">Seimbang</string>
|
<string name="settings_scanner_mode_balanced_label">Seimbang</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">Latemsi rendah</string>
|
<string name="settings_scanner_mode_lowlatency_label">Latemsi rendah</string>
|
||||||
<string name="settings_autopause_label">Jeda otomatis</string>
|
<string name="settings_autopause_label">Jeda otomatis</string>
|
||||||
<string name="settings_autopause_description">Jeda musik saat melepaskan perangkat dari telinga anda.</string>
|
<string name="settings_autopause_description">Jeda audio saat melepaskan perangkat dari telinga anda.</string>
|
||||||
<string name="settings_showall_label">Tampilkan semua perangkat</string>
|
<string name="settings_showall_label">Tampilkan semua perangkat</string>
|
||||||
<string name="settings_showall_description">Tampilkan perangkat orang lain yang ada di dekat anda.</string>
|
<string name="settings_showall_description">Tampilkan perangkat orang lain yang ada di dekat anda.</string>
|
||||||
<string name="settings_autopplay_label">Putar otomatis</string>
|
<string name="settings_autopplay_label">Putar otomatis</string>
|
||||||
<string name="settings_autoplay_description">Mulai pemutaran musik musik saat memakai perangkat.</string>
|
<string name="settings_autoplay_description">Mulai pemutaran audio saat perangkat dipakai.</string>
|
||||||
<string name="settings_fake_data_label">Data palsu</string>
|
<string name="settings_fake_data_label">Data palsu</string>
|
||||||
<string name="settings_fake_data_description">Tampilkan data palsu, mis: mensimulasikan perangkat yang tidak ada.</string>
|
<string name="settings_fake_data_description">Tampilkan data palsu, yaitu, mensimulasikan perangkat yang tidak ada.</string>
|
||||||
<string name="settings_debug_label">Pengaturan debug</string>
|
<string name="settings_debug_label">Pengaturan debug</string>
|
||||||
<string name="settings_debug_description">Pengaturan tambahan untuk membantu memecahkan masalah dengan aplikasi.</string>
|
<string name="settings_debug_description">Pengaturan tambahan untuk membantu memecahkan masalah dengan aplikasi.</string>
|
||||||
<string name="settings_signal_minimum_label">Kualitas sinyal minimum</string>
|
<string name="settings_signal_minimum_label">Kualitas sinyal minimum</string>
|
||||||
@@ -119,11 +119,10 @@
|
|||||||
<string name="upgrade_capod_description">Dapatkan fitur tambahan & bantu dukung pengembang.</string>
|
<string name="upgrade_capod_description">Dapatkan fitur tambahan & bantu dukung pengembang.</string>
|
||||||
<string name="settings_popup_caseopen_label">Tampilkan popup</string>
|
<string name="settings_popup_caseopen_label">Tampilkan popup</string>
|
||||||
<string name="settings_popup_caseopen_description">Tampilkan popup saat kasing perangkat dibuka (eksperimental).</string>
|
<string name="settings_popup_caseopen_description">Tampilkan popup saat kasing perangkat dibuka (eksperimental).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Reaksi perangkat popup</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Bluetooth dinonaktifkan</string>
|
<string name="overview_bluetooth_disabled_label">Bluetooth dinonaktifkan</string>
|
||||||
<string name="overview_bluetooth_disabled_description">Bluetooth dinonaktifkan, aktifkan terlebih dahulu ;)</string>
|
<string name="overview_bluetooth_disabled_description">Bluetooth dinonaktifkan, aktifkan terlebih dahulu ;)</string>
|
||||||
<string name="help_translate_label">Terjemahan</string>
|
<string name="help_translate_label">Terjemahan</string>
|
||||||
<string name="help_translate_description">Bantu terjemahkan ini ke bahasa favorit anda.</string>
|
<string name="help_translate_description">Bantu terjemahkan applikasi ini ke bahasa favorit anda.</string>
|
||||||
<string name="settings_onepod_mode_label">Mode satu pod</string>
|
<string name="settings_onepod_mode_label">Mode satu pod</string>
|
||||||
<string name="settings_onepod_mode_description">Menggunakan kedua pod tidak diperlukan, memakai satu pod sudah cukup untuk memicu reaksi.</string>
|
<string name="settings_onepod_mode_description">Menggunakan kedua pod tidak diperlukan, memakai satu pod sudah cukup untuk memicu reaksi.</string>
|
||||||
<string name="permission_system_alert_window_label">Jendela Peringatan Sistem</string>
|
<string name="permission_system_alert_window_label">Jendela Peringatan Sistem</string>
|
||||||
@@ -133,4 +132,16 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">Data BLE yang tidak difilter</string>
|
<string name="settings_blescanner_unfiltered_label">Data BLE yang tidak difilter</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">Hapus semua filter dari pemindai BLE untuk menampilkan semua data BLE yang disiarkan. Berguna untuk menambahkan dukungan pada jenis headphone baru.</string>
|
<string name="settings_blescanner_unfiltered_description">Hapus semua filter dari pemindai BLE untuk menampilkan semua data BLE yang disiarkan. Berguna untuk menambahkan dukungan pada jenis headphone baru.</string>
|
||||||
<string name="permission_required_title">Izin berikut diperlukan:</string>
|
<string name="permission_required_title">Izin berikut diperlukan:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Mode kompatibilitas</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Nonaktifkan pengoptimalan untuk meningkatkan kompatibilitas. Coba ini jika anda tidak melihat data apa pun.</string>
|
||||||
|
<string name="translators_thanks_title">Penerjemah</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">nama anda dapat ditambahkan sebagai relawan di sini dan ditampilkan di aplikasi. Itu akan ditampilkan pada bagian Pengaturan>Penghargaan>Terima kasih
|
||||||
|
|
||||||
|
Pisahkan nama dengan titik koma dan email opsional dapat dimasukkan dalam tanda kurung, contoh:
|
||||||
|
|
||||||
|
𝓼𝓾𝓵𝓽𝓪𝓷 𝓱𝓪𝓶𝓴𝓪(sultanhamka@gmail.com); John Doe(john@example.com)
|
||||||
|
|
||||||
|
\"𝓼𝓾𝓵𝓽𝓪𝓷 𝓱𝓪𝓶𝓴𝓪\" hanyalah pengganti dan tidak harus disimpan jika/ketika anda menambahkan milik anda.
|
||||||
|
|
||||||
|
Bersikap baik satu sama lain!</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
<string name="permission_bluetooth_scan_label">Scansione bluetooth</string>
|
<string name="permission_bluetooth_scan_label">Scansione bluetooth</string>
|
||||||
<string name="permission_bluetooth_scan_description">Il permesso di \"Scansione bluetooth\" permette a questa app di trovare e ricevere dati Bluetooth da dispositivi vicini come le tue Airpods.</string>
|
<string name="permission_bluetooth_scan_description">Il permesso di \"Scansione bluetooth\" permette a questa app di trovare e ricevere dati Bluetooth da dispositivi vicini come le tue Airpods.</string>
|
||||||
<string name="permission_bluetooth_label">Bluetooth</string>
|
<string name="permission_bluetooth_label">Bluetooth</string>
|
||||||
|
<string name="permission_bluetooth_description">Questa app richiede il permesso \"Bluetooth\" per connettersi ai dispoitivi Bluetooth.</string>
|
||||||
<string name="permission_access_fine_location_label">Access fine location</string>
|
<string name="permission_access_fine_location_label">Access fine location</string>
|
||||||
<string name="permission_access_fine_location_description">CAPod usa i permessi di Geolocalizzazione per ricevere dati Bluetooth a basso consumo. Le tue cuffie suano la tecnologia Bluetooth a basso consumo per inviare al dispositivo al quale sono connesse il loro stato. Questa app non utilizza i dati Bluetooth per geolocalizzarti.</string>
|
<string name="permission_access_fine_location_description">CAPod usa i permessi di Geolocalizzazione per ricevere dati Bluetooth a basso consumo. Le tue cuffie suano la tecnologia Bluetooth a basso consumo per inviare al dispositivo al quale sono connesse il loro stato. Questa app non utilizza i dati Bluetooth per geolocalizzarti.</string>
|
||||||
<string name="permission_background_location_label">Accesso in background alla tua posizione</string>
|
<string name="permission_background_location_label">Accesso in background alla tua posizione</string>
|
||||||
@@ -44,12 +45,14 @@
|
|||||||
<string name="pods_connection_state_unknown_label">Stato di connessione sconosciuto</string>
|
<string name="pods_connection_state_unknown_label">Stato di connessione sconosciuto</string>
|
||||||
<string name="pods_unknown_raw_data_label">Dati non elaborati</string>
|
<string name="pods_unknown_raw_data_label">Dati non elaborati</string>
|
||||||
<string name="pods_unknown_label">Dispositivo sconosciuto</string>
|
<string name="pods_unknown_label">Dispositivo sconosciuto</string>
|
||||||
|
<string name="pods_unknown_contact_dev">Questo é un dispositivo sconosciutom ma sta utilizzando un formato di comunicazione noto. Aggiungiamo il supporto per questo device, Contattami! :)</string>
|
||||||
<string name="pods_none_label_short">Nessun dispositivo</string>
|
<string name="pods_none_label_short">Nessun dispositivo</string>
|
||||||
<string name="pods_charging_label">In ricarica</string>
|
<string name="pods_charging_label">In ricarica</string>
|
||||||
<string name="pods_inear_label">Nell\'orecchio</string>
|
<string name="pods_inear_label">Nell\'orecchio</string>
|
||||||
<string name="pods_microphone_label">Microfono</string>
|
<string name="pods_microphone_label">Microfono</string>
|
||||||
<string name="pods_yours">Tuoi</string>
|
<string name="pods_yours">Tuoi</string>
|
||||||
<string name="headset_being_worn_label">Indossato</string>
|
<string name="headset_being_worn_label">Indossato</string>
|
||||||
|
<string name="pods_case_unknown_state">Stato sconosciuto</string>
|
||||||
<string name="overview_nomaindevice_label">Nessun device primario</string>
|
<string name="overview_nomaindevice_label">Nessun device primario</string>
|
||||||
<string name="overview_nomaindevice_description">Tutti i dispositivi rilevati molto probabilmente non sono tuoi. Accendi e connetti i tuoi dispositivi oppure sistema le impostazioni.</string>
|
<string name="overview_nomaindevice_description">Tutti i dispositivi rilevati molto probabilmente non sono tuoi. Accendi e connetti i tuoi dispositivi oppure sistema le impostazioni.</string>
|
||||||
<string name="settings_label">Impostazioni</string>
|
<string name="settings_label">Impostazioni</string>
|
||||||
@@ -61,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Modifiche generali che riguardano l\'intera applicazione.</string>
|
<string name="settings_general_description">Modifiche generali che riguardano l\'intera applicazione.</string>
|
||||||
<string name="settings_acknowledgements_label">Riconoscimenti</string>
|
<string name="settings_acknowledgements_label">Riconoscimenti</string>
|
||||||
<string name="changelog_label">Changelog</string>
|
<string name="changelog_label">Changelog</string>
|
||||||
<string name="settings_support_email_developer_label">Email sviluppatore</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">Email sviluppatore</string>
|
||||||
<string name="settings_support_installid_label">ID installazione</string>
|
<string name="settings_support_installid_label">ID installazione</string>
|
||||||
<string name="settings_support_installid_desc">Le segnalazioni automatiche degli errori sono anonime. Condividi il tuo ID di installazione con lo sviluppatore se necessità di trovare la tua segnalazione all\'interno del registro segnalazioni.</string>
|
<string name="settings_support_installid_desc">Le segnalazioni automatiche degli errori sono anonime. Condividi il tuo ID di installazione con lo sviluppatore se necessità di trovare la tua segnalazione all\'interno del registro segnalazioni.</string>
|
||||||
<string name="settings_support_label">Supporto</string>
|
<string name="settings_support_label">Supporto</string>
|
||||||
@@ -86,13 +89,13 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">Bilanciato</string>
|
<string name="settings_scanner_mode_balanced_label">Bilanciato</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">Bassa latenza</string>
|
<string name="settings_scanner_mode_lowlatency_label">Bassa latenza</string>
|
||||||
<string name="settings_autopause_label">Pausa automatica</string>
|
<string name="settings_autopause_label">Pausa automatica</string>
|
||||||
<string name="settings_autopause_description">Metti in pausa la musica quando viene rimossa la cuffia da un orecchio.</string>
|
<string name="settings_autopause_description">Metti in pausa l\'audio quando viene rimossa la cuffia da un orecchio.</string>
|
||||||
<string name="settings_showall_label">Mostra tutti i dispositivi</string>
|
<string name="settings_showall_label">Mostra tutti i dispositivi</string>
|
||||||
<string name="settings_showall_description">Mostra i dispositivi delle altre persone vicine a te.</string>
|
<string name="settings_showall_description">Mostra i dispositivi delle altre persone vicine a te.</string>
|
||||||
<string name="settings_autopplay_label">Riproduzione automatica</string>
|
<string name="settings_autopplay_label">Riproduzione automatica</string>
|
||||||
<string name="settings_autoplay_description">Avvia la riproduzione della musica quando indossi il dispositivo.</string>
|
<string name="settings_autoplay_description">Avvia riproduzione audio quando il dispositivo è indossato.</string>
|
||||||
<string name="settings_fake_data_label">Dati immaginari</string>
|
<string name="settings_fake_data_label">Dati immaginari</string>
|
||||||
<string name="settings_fake_data_description">Mostra dati immaginari così da poter simulare dispositivi che in realtà non esistono.</string>
|
<string name="settings_fake_data_description">Mostra dati fittizi, ovvero simula dispositivi che in realtà non esistono.</string>
|
||||||
<string name="settings_debug_label">Impostazioni di debug</string>
|
<string name="settings_debug_label">Impostazioni di debug</string>
|
||||||
<string name="settings_debug_description">Impostazioni aggiuntive che possono aiutare a risolvere i problemi con l\'applicazione.</string>
|
<string name="settings_debug_description">Impostazioni aggiuntive che possono aiutare a risolvere i problemi con l\'applicazione.</string>
|
||||||
<string name="settings_signal_minimum_label">Qualità del segnale minima</string>
|
<string name="settings_signal_minimum_label">Qualità del segnale minima</string>
|
||||||
@@ -116,8 +119,8 @@
|
|||||||
<string name="upgrade_capod_description">Ottieni funzionalità aggiuntive e supporta lo sviluppatore.</string>
|
<string name="upgrade_capod_description">Ottieni funzionalità aggiuntive e supporta lo sviluppatore.</string>
|
||||||
<string name="settings_popup_caseopen_label">Mostra popup</string>
|
<string name="settings_popup_caseopen_label">Mostra popup</string>
|
||||||
<string name="settings_popup_caseopen_description">Mostra un popup quando la custodia del dispositivo è aperta (sperimentale).</string>
|
<string name="settings_popup_caseopen_description">Mostra un popup quando la custodia del dispositivo è aperta (sperimentale).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Popup reazioni dispositivo</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Il Bluetooth é disabilitato</string>
|
<string name="overview_bluetooth_disabled_label">Il Bluetooth é disabilitato</string>
|
||||||
|
<string name="overview_bluetooth_disabled_description">Il bluetooth é disabilitato, abilitalo ;)</string>
|
||||||
<string name="help_translate_label">Traduzione</string>
|
<string name="help_translate_label">Traduzione</string>
|
||||||
<string name="help_translate_description">Aiuta a tradurre l\'applicazione nella tua lingua preferita.</string>
|
<string name="help_translate_description">Aiuta a tradurre l\'applicazione nella tua lingua preferita.</string>
|
||||||
<string name="settings_onepod_mode_label">Modalità singolo pod</string>
|
<string name="settings_onepod_mode_label">Modalità singolo pod</string>
|
||||||
@@ -126,4 +129,10 @@
|
|||||||
<string name="permission_system_alert_window_description">Permetti a CAPod di far apprarire overlay sopra le altre applicazioni per far funzionare \"Mostra PopUp\".</string>
|
<string name="permission_system_alert_window_description">Permetti a CAPod di far apprarire overlay sopra le altre applicazioni per far funzionare \"Mostra PopUp\".</string>
|
||||||
<string name="last_seen_x">Ultimo accesso: %s</string>
|
<string name="last_seen_x">Ultimo accesso: %s</string>
|
||||||
<string name="first_seen_x">Primo accesso: %s</string>
|
<string name="first_seen_x">Primo accesso: %s</string>
|
||||||
|
<string name="settings_blescanner_unfiltered_label">Dati BLE non filtrati</string>
|
||||||
|
<string name="settings_blescanner_unfiltered_description">Rimuovi eventuali filtri dallo scanner BLE per mostrate tutti i dati BLE trasmetti. Utile per aggiungere supporto per nuovi tipi di cuffie.</string>
|
||||||
|
<string name="permission_required_title">È richiesta la seguente autorizzazione:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Modalità di compatibilità</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Disattiva le ottimizzazioni per migliorare la compatibilità. Prova questa opzione se non vedi alcun dato.</string>
|
||||||
|
<string name="translators_thanks_title">Traduttori</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<string name="general_done_action">בוצע</string>
|
<string name="general_done_action">בוצע</string>
|
||||||
<string name="general_copy_action">העתק</string>
|
<string name="general_copy_action">העתק</string>
|
||||||
<string name="general_thank_you_label">תודה רבה</string>
|
<string name="general_thank_you_label">תודה רבה</string>
|
||||||
<string name="general_value_not_available_label">לא ישים</string>
|
<string name="general_value_not_available_label">לא זמין</string>
|
||||||
<string name="general_grant_permission_action">מתן רשות</string>
|
<string name="general_grant_permission_action">מתן רשות</string>
|
||||||
<string name="general_upgrade_action">שידרוג</string>
|
<string name="general_upgrade_action">שידרוג</string>
|
||||||
<string name="general_check_action">בדיקה</string>
|
<string name="general_check_action">בדיקה</string>
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">שינויים כלליים שמשפיעים על האפליקציה כולה.</string>
|
<string name="settings_general_description">שינויים כלליים שמשפיעים על האפליקציה כולה.</string>
|
||||||
<string name="settings_acknowledgements_label">תודות</string>
|
<string name="settings_acknowledgements_label">תודות</string>
|
||||||
<string name="changelog_label">יומן שינויים</string>
|
<string name="changelog_label">יומן שינויים</string>
|
||||||
<string name="settings_support_email_developer_label">אימייל של המפתח</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">אימייל של המפתח</string>
|
||||||
<string name="settings_support_installid_label">מזהה התקנה</string>
|
<string name="settings_support_installid_label">מזהה התקנה</string>
|
||||||
<string name="settings_support_installid_desc">דוחות שגיאה אוטומטיים הם אנונימיים. שתף את מזהה ההתקנה שלך אם המפתח צריך למצוא את דוחות השגיאות שלך.</string>
|
<string name="settings_support_installid_desc">דוחות שגיאה אוטומטיים הם אנונימיים. שתף את מזהה ההתקנה שלך אם המפתח צריך למצוא את דוחות השגיאות שלך.</string>
|
||||||
<string name="settings_support_label">תמיכה</string>
|
<string name="settings_support_label">תמיכה</string>
|
||||||
@@ -89,13 +89,13 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">מאוזן</string>
|
<string name="settings_scanner_mode_balanced_label">מאוזן</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">זמן אחזור נמוך</string>
|
<string name="settings_scanner_mode_lowlatency_label">זמן אחזור נמוך</string>
|
||||||
<string name="settings_autopause_label">השהייה אוטומטית</string>
|
<string name="settings_autopause_label">השהייה אוטומטית</string>
|
||||||
<string name="settings_autopause_description">השהה מוזיקה בעת הסרת המכשיר מהאוזן.</string>
|
<string name="settings_autopause_description">עצירת אודיו בהסרת המכשיר מהאוזן.</string>
|
||||||
<string name="settings_showall_label">הצג את כל המכשירים</string>
|
<string name="settings_showall_label">הצג את כל המכשירים</string>
|
||||||
<string name="settings_showall_description">הצג מכשירים של אנשים אחרים שנמצאים בקרבתך.</string>
|
<string name="settings_showall_description">הצג מכשירים של אנשים אחרים שנמצאים בקרבתך.</string>
|
||||||
<string name="settings_autopplay_label">הפעלה אוטומטית</string>
|
<string name="settings_autopplay_label">הפעלה אוטומטית</string>
|
||||||
<string name="settings_autoplay_description">התחל מוזיקה בהשמעת מוזיקה כאשר אתה לובש את המכשיר.</string>
|
<string name="settings_autoplay_description">התחלת ניגון אודיו בלבישת המכשיר.</string>
|
||||||
<string name="settings_fake_data_label">נתונים מזויפים</string>
|
<string name="settings_fake_data_label">נתונים מזויפים</string>
|
||||||
<string name="settings_fake_data_description">הצג נתונים מזויפים, כלומר הדמיית מכשיר שלא קיים.</string>
|
<string name="settings_fake_data_description">הצגת נתונים מזויפים, לרבות, הדמיית מכשירים שאינם קיימים.</string>
|
||||||
<string name="settings_debug_label">הגדרות ניפוי באגים</string>
|
<string name="settings_debug_label">הגדרות ניפוי באגים</string>
|
||||||
<string name="settings_debug_description">הגדרות נוספות שיסייעו בפתרון בעיות באפליקציה.</string>
|
<string name="settings_debug_description">הגדרות נוספות שיסייעו בפתרון בעיות באפליקציה.</string>
|
||||||
<string name="settings_signal_minimum_label">איכות אות מינימלית</string>
|
<string name="settings_signal_minimum_label">איכות אות מינימלית</string>
|
||||||
@@ -119,11 +119,10 @@
|
|||||||
<string name="upgrade_capod_description">קבל תכונות נוספות ותמיכה במפתח.</string>
|
<string name="upgrade_capod_description">קבל תכונות נוספות ותמיכה במפתח.</string>
|
||||||
<string name="settings_popup_caseopen_label">הצג הודעה</string>
|
<string name="settings_popup_caseopen_label">הצג הודעה</string>
|
||||||
<string name="settings_popup_caseopen_description">הצג חלון הודעה כאשר מארז המכשיר נפתח (ניסיוני).</string>
|
<string name="settings_popup_caseopen_description">הצג חלון הודעה כאשר מארז המכשיר נפתח (ניסיוני).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">תגובות חלון הודעוה של המכשיר</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Bluetooth כבוי</string>
|
<string name="overview_bluetooth_disabled_label">Bluetooth כבוי</string>
|
||||||
<string name="overview_bluetooth_disabled_description">בלוטות\' מכובה, יש להדליקו ;)</string>
|
<string name="overview_bluetooth_disabled_description">בלוטות\' מכובה, יש להדליקו ;)</string>
|
||||||
<string name="help_translate_label">תרגום</string>
|
<string name="help_translate_label">תרגום</string>
|
||||||
<string name="help_translate_description">עזור לתרגם את זה לשפה האהובה עליך.</string>
|
<string name="help_translate_description">עזרו בתרגום אפליקציה זו לשפה המועדפת עליכם.</string>
|
||||||
<string name="settings_onepod_mode_label">מצב אוזניה בודדת</string>
|
<string name="settings_onepod_mode_label">מצב אוזניה בודדת</string>
|
||||||
<string name="settings_onepod_mode_description">אין צורך לענוד את שני האוזניות, לבישת אוזניה בודדת מספיקה כדי לעורר תגובות.</string>
|
<string name="settings_onepod_mode_description">אין צורך לענוד את שני האוזניות, לבישת אוזניה בודדת מספיקה כדי לעורר תגובות.</string>
|
||||||
<string name="permission_system_alert_window_label">חלון התראות מערכת</string>
|
<string name="permission_system_alert_window_label">חלון התראות מערכת</string>
|
||||||
@@ -133,4 +132,8 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">נתוני BLE לא מפולטרים</string>
|
<string name="settings_blescanner_unfiltered_label">נתוני BLE לא מפולטרים</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">הסר מסננים מסורק BLE כדי להציג את כל נתוני BLE ששודרו. שימושי להוספת תמיכה בסוגי אוזניות חדשים.</string>
|
<string name="settings_blescanner_unfiltered_description">הסר מסננים מסורק BLE כדי להציג את כל נתוני BLE ששודרו. שימושי להוספת תמיכה בסוגי אוזניות חדשים.</string>
|
||||||
<string name="permission_required_title">ההרשאה הבאה נדרשת:</string>
|
<string name="permission_required_title">ההרשאה הבאה נדרשת:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">מצב תאימות</string>
|
||||||
|
<string name="settings_compatibility_mode_description">נטרול אופטימיזציה לשיפור התאימות. נסו את זה אם לא מוצגים נתונים כלל.</string>
|
||||||
|
<string name="translators_thanks_title">מתרגמים</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">AL_Cool_T</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">앱 전체에 영향을 주는 일반적인 설정들입니다.</string>
|
<string name="settings_general_description">앱 전체에 영향을 주는 일반적인 설정들입니다.</string>
|
||||||
<string name="settings_acknowledgements_label">감사의 말</string>
|
<string name="settings_acknowledgements_label">감사의 말</string>
|
||||||
<string name="changelog_label">체인지로그</string>
|
<string name="changelog_label">체인지로그</string>
|
||||||
<string name="settings_support_email_developer_label">개발자에게 메일 보내기</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">개발자에게 메일 보내기</string>
|
||||||
<string name="settings_support_installid_label">설치 ID</string>
|
<string name="settings_support_installid_label">설치 ID</string>
|
||||||
<string name="settings_support_installid_desc">자동 오류 보고는 익명성이 보장됩니다. 개발자가 오류 보고서를 필요로 할 때 설치 ID를 알려주세요.</string>
|
<string name="settings_support_installid_desc">자동 오류 보고는 익명성이 보장됩니다. 개발자가 오류 보고서를 필요로 할 때 설치 ID를 알려주세요.</string>
|
||||||
<string name="settings_support_label">지원</string>
|
<string name="settings_support_label">지원</string>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<string name="settings_monitor_mode_label">모니터링 모드</string>
|
<string name="settings_monitor_mode_label">모니터링 모드</string>
|
||||||
<string name="settings_monitor_mode_description">어떤 상황에서 블루투스 정보를 열람하는지 설정합니다.</string>
|
<string name="settings_monitor_mode_description">어떤 상황에서 블루투스 정보를 열람하는지 설정합니다.</string>
|
||||||
<string name="settings_scanner_mode_label">스캐너 모드</string>
|
<string name="settings_scanner_mode_label">스캐너 모드</string>
|
||||||
<string name="settings_scanner_mode_description">저전력 블루투스 스캐너가 성능과 전력 효율 중 무엇을 우선으로 할 지 선택합니다.</string>
|
<string name="settings_scanner_mode_description">저전력 블루투스 데이터 스캐너가 성능과 전력 효율 중 무엇을 우선으로 할 지 선택합니다.</string>
|
||||||
<string name="settings_monitor_mode_manual_label">앱이 열려 있을 때</string>
|
<string name="settings_monitor_mode_manual_label">앱이 열려 있을 때</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">기기가 연결되어 있을 때</string>
|
<string name="settings_monitor_mode_automatic_label">기기가 연결되어 있을 때</string>
|
||||||
<string name="settings_monitor_mode_always_label">항상</string>
|
<string name="settings_monitor_mode_always_label">항상</string>
|
||||||
@@ -89,11 +89,11 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">균형있게</string>
|
<string name="settings_scanner_mode_balanced_label">균형있게</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">저레이턴시</string>
|
<string name="settings_scanner_mode_lowlatency_label">저레이턴시</string>
|
||||||
<string name="settings_autopause_label">자동 일시정지</string>
|
<string name="settings_autopause_label">자동 일시정지</string>
|
||||||
<string name="settings_autopause_description">기기를 귀에서 뺄 때 음악을 일시정지합니다.</string>
|
<string name="settings_autopause_description">기기를 귀에서 뺄 때 오디오를 일시정지합니다.</string>
|
||||||
<string name="settings_showall_label">모든 기기 보이기</string>
|
<string name="settings_showall_label">모든 기기 보이기</string>
|
||||||
<string name="settings_showall_description">다른 사람의 기기도 보이게 합니다.</string>
|
<string name="settings_showall_description">다른 사람의 기기도 보이게 합니다.</string>
|
||||||
<string name="settings_autopplay_label">자동 재생</string>
|
<string name="settings_autopplay_label">자동 재생</string>
|
||||||
<string name="settings_autoplay_description">귀에 기기를 착용하면 음악을 시작합니다.</string>
|
<string name="settings_autoplay_description">귀에 기기를 착용하면 오디오를 다시 시작합니다.</string>
|
||||||
<string name="settings_fake_data_label">가짜 데이터</string>
|
<string name="settings_fake_data_label">가짜 데이터</string>
|
||||||
<string name="settings_fake_data_description">가짜 기기에 연결하는 것처럼 보이는 등 가짜 정보를 보여줍니다.</string>
|
<string name="settings_fake_data_description">가짜 기기에 연결하는 것처럼 보이는 등 가짜 정보를 보여줍니다.</string>
|
||||||
<string name="settings_debug_label">디버그 설정</string>
|
<string name="settings_debug_label">디버그 설정</string>
|
||||||
@@ -119,11 +119,10 @@
|
|||||||
<string name="upgrade_capod_description">개발자에게 후원하고 추가적 기능도 받습니다.</string>
|
<string name="upgrade_capod_description">개발자에게 후원하고 추가적 기능도 받습니다.</string>
|
||||||
<string name="settings_popup_caseopen_label">팝업 보이기</string>
|
<string name="settings_popup_caseopen_label">팝업 보이기</string>
|
||||||
<string name="settings_popup_caseopen_description">기기 케이스가 열렸을 때 팝업을 보여줍니다. (실험적)</string>
|
<string name="settings_popup_caseopen_description">기기 케이스가 열렸을 때 팝업을 보여줍니다. (실험적)</string>
|
||||||
<string name="notification_channel_reaction_popup_label">팝업을 보일 기기 반응</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">블루투스 꺼져 있음</string>
|
<string name="overview_bluetooth_disabled_label">블루투스 꺼져 있음</string>
|
||||||
<string name="overview_bluetooth_disabled_description">블루투스를 켜야 연결할 수 있어요 ;)</string>
|
<string name="overview_bluetooth_disabled_description">블루투스를 켜야 연결할 수 있어요 ;)</string>
|
||||||
<string name="help_translate_label">번역</string>
|
<string name="help_translate_label">번역</string>
|
||||||
<string name="help_translate_description">앱을 여러분의 언어로 번역하는 것을 도와주세요.</string>
|
<string name="help_translate_description">이 앱을 여러분의 언어로 번역하는 것을 도와주세요.</string>
|
||||||
<string name="settings_onepod_mode_label">한쪽 기기 모드</string>
|
<string name="settings_onepod_mode_label">한쪽 기기 모드</string>
|
||||||
<string name="settings_onepod_mode_description">양쪽 기기를 모두 착용할 필요 없이, 앱에서 한 쪽만 있어도 반응하도록 합니다.</string>
|
<string name="settings_onepod_mode_description">양쪽 기기를 모두 착용할 필요 없이, 앱에서 한 쪽만 있어도 반응하도록 합니다.</string>
|
||||||
<string name="permission_system_alert_window_label">시스템 알림 창</string>
|
<string name="permission_system_alert_window_label">시스템 알림 창</string>
|
||||||
@@ -133,4 +132,8 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">무보정 BLE 데이터</string>
|
<string name="settings_blescanner_unfiltered_label">무보정 BLE 데이터</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">BLE 스캐너에서 보정을 제거해 모든 BLE 정보를 보입니다. 새로운 모델에 대한 지원을 추가하기 좋습니다.</string>
|
<string name="settings_blescanner_unfiltered_description">BLE 스캐너에서 보정을 제거해 모든 BLE 정보를 보입니다. 새로운 모델에 대한 지원을 추가하기 좋습니다.</string>
|
||||||
<string name="permission_required_title">다음 권한을 부여해야 합니다:</string>
|
<string name="permission_required_title">다음 권한을 부여해야 합니다:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">호환성 모드</string>
|
||||||
|
<string name="settings_compatibility_mode_description">최적화 설정들 몇 개를 비활성화해 호환성을 높입니다. 데이터가 보이지 않을 때 사용하세요.</string>
|
||||||
|
<string name="translators_thanks_title">번역가</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">윤지호(annyeong1alt@gmail.com)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Tweak umum yang mempengaruhi keseluruhan apl.</string>
|
<string name="settings_general_description">Tweak umum yang mempengaruhi keseluruhan apl.</string>
|
||||||
<string name="settings_acknowledgements_label">Ucapan terima kasih</string>
|
<string name="settings_acknowledgements_label">Ucapan terima kasih</string>
|
||||||
<string name="changelog_label">Changelog</string>
|
<string name="changelog_label">Changelog</string>
|
||||||
<string name="settings_support_email_developer_label">Pembangun e-mel</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">Pembangun e-mel</string>
|
||||||
<string name="settings_support_installid_label">Pasang ID</string>
|
<string name="settings_support_installid_label">Pasang ID</string>
|
||||||
<string name="settings_support_installid_desc">Laporan ralat automatik adalah tanpa nama. Kongsi ID pemasangan anda jika pembangun perlu mencari laporan ralat anda.</string>
|
<string name="settings_support_installid_desc">Laporan ralat automatik adalah tanpa nama. Kongsi ID pemasangan anda jika pembangun perlu mencari laporan ralat anda.</string>
|
||||||
<string name="settings_support_label">Sokongan</string>
|
<string name="settings_support_label">Sokongan</string>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<string name="settings_monitor_mode_label">Mod monitor</string>
|
<string name="settings_monitor_mode_label">Mod monitor</string>
|
||||||
<string name="settings_monitor_mode_description">Dalam keadaan yang mana apl ini memantau data Bluetooth.</string>
|
<string name="settings_monitor_mode_description">Dalam keadaan yang mana apl ini memantau data Bluetooth.</string>
|
||||||
<string name="settings_scanner_mode_label">Mod pengimbas</string>
|
<string name="settings_scanner_mode_label">Mod pengimbas</string>
|
||||||
<string name="settings_scanner_mode_description">Patutkah pengimbas Tenaga Rendah Bluetooth mengutamakan prestasi atau penjimatan tenaga?</string>
|
<string name="settings_scanner_mode_description">Apakah sepatutnya pengimbas data Tenaga Rendah Bluetooth mengutamakan prestasi atau penjimatan tenaga?</string>
|
||||||
<string name="settings_monitor_mode_manual_label">Apabila apl dibuka</string>
|
<string name="settings_monitor_mode_manual_label">Apabila apl dibuka</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">Apabila peranti disambungkan</string>
|
<string name="settings_monitor_mode_automatic_label">Apabila peranti disambungkan</string>
|
||||||
<string name="settings_monitor_mode_always_label">Sentiasa</string>
|
<string name="settings_monitor_mode_always_label">Sentiasa</string>
|
||||||
@@ -89,13 +89,13 @@
|
|||||||
<string name="settings_scanner_mode_balanced_label">Seimbang</string>
|
<string name="settings_scanner_mode_balanced_label">Seimbang</string>
|
||||||
<string name="settings_scanner_mode_lowlatency_label">Latensi rendah</string>
|
<string name="settings_scanner_mode_lowlatency_label">Latensi rendah</string>
|
||||||
<string name="settings_autopause_label">Auto jeda</string>
|
<string name="settings_autopause_label">Auto jeda</string>
|
||||||
<string name="settings_autopause_description">Jeda muzik apabila peranti dikeluarkan dari telinga anda.</string>
|
<string name="settings_autopause_description">Jeda audio apabila peranti dikeluarkan dari telinga anda.</string>
|
||||||
<string name="settings_showall_label">Tunjukkan semua peranti</string>
|
<string name="settings_showall_label">Tunjukkan semua peranti</string>
|
||||||
<string name="settings_showall_description">Tunjukkan peranti orang lain yang berdekatan dengan anda.</string>
|
<string name="settings_showall_description">Tunjukkan peranti orang lain yang berdekatan dengan anda.</string>
|
||||||
<string name="settings_autopplay_label">Auto main</string>
|
<string name="settings_autopplay_label">Auto main</string>
|
||||||
<string name="settings_autoplay_description">Mulakan muzik main balik muzik apabila memakai peranti.</string>
|
<string name="settings_autoplay_description">Mulakan main balik audio apabila peranti dipakai.</string>
|
||||||
<string name="settings_fake_data_label">Data palsu</string>
|
<string name="settings_fake_data_label">Data palsu</string>
|
||||||
<string name="settings_fake_data_description">Tunjukkan data palsu, i.e. simulasi peranti yang tidak wujud.</string>
|
<string name="settings_fake_data_description">Tunjukkan data palsu, yakni, simulasi peranti yang tidak wujud.</string>
|
||||||
<string name="settings_debug_label">Tetapan nyahpepijat</string>
|
<string name="settings_debug_label">Tetapan nyahpepijat</string>
|
||||||
<string name="settings_debug_description">Tetapan tambahan untuk membantu menyelesaikan isu dengan apl.</string>
|
<string name="settings_debug_description">Tetapan tambahan untuk membantu menyelesaikan isu dengan apl.</string>
|
||||||
<string name="settings_signal_minimum_label">Kualiti isyarat minimum</string>
|
<string name="settings_signal_minimum_label">Kualiti isyarat minimum</string>
|
||||||
@@ -119,11 +119,10 @@
|
|||||||
<string name="upgrade_capod_description">Dapatkan ciri tambahan dan sokongi pemaju.</string>
|
<string name="upgrade_capod_description">Dapatkan ciri tambahan dan sokongi pemaju.</string>
|
||||||
<string name="settings_popup_caseopen_label">Tunjukkan popup</string>
|
<string name="settings_popup_caseopen_label">Tunjukkan popup</string>
|
||||||
<string name="settings_popup_caseopen_description">Tunjukkan popup apabila sarung peranti dibuka (percubaan).</string>
|
<string name="settings_popup_caseopen_description">Tunjukkan popup apabila sarung peranti dibuka (percubaan).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Reaksi peranti popup</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Bluetooth dinyahdayakan</string>
|
<string name="overview_bluetooth_disabled_label">Bluetooth dinyahdayakan</string>
|
||||||
<string name="overview_bluetooth_disabled_description">Bluetooth dinyahdayakan, dayakan ia ;)</string>
|
<string name="overview_bluetooth_disabled_description">Bluetooth dinyahdayakan, dayakan ia ;)</string>
|
||||||
<string name="help_translate_label">Terjemahan</string>
|
<string name="help_translate_label">Terjemahan</string>
|
||||||
<string name="help_translate_description">Bantu menterjemahkan ini ke dalam bahasa kegemaran anda.</string>
|
<string name="help_translate_description">Bantu terjemahkan apl ini ke dalam bahasa kegemaran anda.</string>
|
||||||
<string name="settings_onepod_mode_label">Satu mod pod</string>
|
<string name="settings_onepod_mode_label">Satu mod pod</string>
|
||||||
<string name="settings_onepod_mode_description">Tidak perlu memakai kedua-dua pod, memakai satu pod sudah memadai untuk mencetuskan tindak balas.</string>
|
<string name="settings_onepod_mode_description">Tidak perlu memakai kedua-dua pod, memakai satu pod sudah memadai untuk mencetuskan tindak balas.</string>
|
||||||
<string name="permission_system_alert_window_label">Tetingkap Makluman Sistem</string>
|
<string name="permission_system_alert_window_label">Tetingkap Makluman Sistem</string>
|
||||||
@@ -133,4 +132,8 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">Data BLE tanpa tapisan</string>
|
<string name="settings_blescanner_unfiltered_label">Data BLE tanpa tapisan</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">Alih keluar sebarang tapisan daripada pengimbas BLE untuk menunjukkan semua data BLE yang disiarkan. Berguna bagi menambah sokongan untuk jenis fon kepala baharu.</string>
|
<string name="settings_blescanner_unfiltered_description">Alih keluar sebarang tapisan daripada pengimbas BLE untuk menunjukkan semua data BLE yang disiarkan. Berguna bagi menambah sokongan untuk jenis fon kepala baharu.</string>
|
||||||
<string name="permission_required_title">Kebenaran berikut diperlukan:</string>
|
<string name="permission_required_title">Kebenaran berikut diperlukan:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Mod keserasian</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Nyahdayakan pengoptimuman untuk tingkatkan keserasian. Cuba ini jika anda tidak melihat sebarang data.</string>
|
||||||
|
<string name="translators_thanks_title">Penterjemah</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">bob hasnul(bobhasnul@gmail. com)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<string name="settings_general_description">Algemene aanpassingen die de hele app beïnvloeden.</string>
|
<string name="settings_general_description">Algemene aanpassingen die de hele app beïnvloeden.</string>
|
||||||
<string name="settings_acknowledgements_label">Dankbetuigingen</string>
|
<string name="settings_acknowledgements_label">Dankbetuigingen</string>
|
||||||
<string name="changelog_label">Wijzigingslog</string>
|
<string name="changelog_label">Wijzigingslog</string>
|
||||||
<string name="settings_support_email_developer_label">E-mailontwikkelaar</string>
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">E-mailontwikkelaar</string>
|
||||||
<string name="settings_support_installid_label">Installatie-ID</string>
|
<string name="settings_support_installid_label">Installatie-ID</string>
|
||||||
<string name="settings_support_installid_desc">Automatische foutmeldingen zijn anoniem. Deel uw installatie-ID als de ontwikkelaar uw foutrapporten moet vinden.</string>
|
<string name="settings_support_installid_desc">Automatische foutmeldingen zijn anoniem. Deel uw installatie-ID als de ontwikkelaar uw foutrapporten moet vinden.</string>
|
||||||
<string name="settings_support_label">Ondersteuning</string>
|
<string name="settings_support_label">Ondersteuning</string>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<string name="settings_monitor_mode_label">Monitor modus</string>
|
<string name="settings_monitor_mode_label">Monitor modus</string>
|
||||||
<string name="settings_monitor_mode_description">Onder welke omstandigheden houdt deze app Bluetooth-gegevens bij.</string>
|
<string name="settings_monitor_mode_description">Onder welke omstandigheden houdt deze app Bluetooth-gegevens bij.</string>
|
||||||
<string name="settings_scanner_mode_label">Scannermodus</string>
|
<string name="settings_scanner_mode_label">Scannermodus</string>
|
||||||
<string name="settings_scanner_mode_description">Moet de Bluetooth Low Energy-scanner voorrang geven aan prestaties of energie besparen?</string>
|
<string name="settings_scanner_mode_description">Moet de Bluetooth Low Energy-gegevensscanner prioriteit geven aan prestaties of energie besparen?</string>
|
||||||
<string name="settings_monitor_mode_manual_label">Wanneer app is geopend</string>
|
<string name="settings_monitor_mode_manual_label">Wanneer app is geopend</string>
|
||||||
<string name="settings_monitor_mode_automatic_label">Wanneer het apparaat is aangesloten</string>
|
<string name="settings_monitor_mode_automatic_label">Wanneer het apparaat is aangesloten</string>
|
||||||
<string name="settings_monitor_mode_always_label">Altijd</string>
|
<string name="settings_monitor_mode_always_label">Altijd</string>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
<string name="settings_showall_label">Alle apparaten weergeven</string>
|
<string name="settings_showall_label">Alle apparaten weergeven</string>
|
||||||
<string name="settings_showall_description">Toon apparaten van andere mensen die bij u in de buurt zijn.</string>
|
<string name="settings_showall_description">Toon apparaten van andere mensen die bij u in de buurt zijn.</string>
|
||||||
<string name="settings_autopplay_label">Automatisch afspelen</string>
|
<string name="settings_autopplay_label">Automatisch afspelen</string>
|
||||||
<string name="settings_autoplay_description">Start het afspelen van muziek wanneer u het apparaat draagt.</string>
|
<string name="settings_autoplay_description">Start audioweergave wanneer het apparaat wordt gedragen.</string>
|
||||||
<string name="settings_fake_data_label">Nep gegevens</string>
|
<string name="settings_fake_data_label">Nep gegevens</string>
|
||||||
<string name="settings_fake_data_description">Toon nepgegevens, d.w.z. simuleer apparaten die niet bestaan.</string>
|
<string name="settings_fake_data_description">Toon nepgegevens, d.w.z. simuleer apparaten die niet bestaan.</string>
|
||||||
<string name="settings_debug_label">Foutopsporingsinstellingen</string>
|
<string name="settings_debug_label">Foutopsporingsinstellingen</string>
|
||||||
@@ -119,11 +119,10 @@
|
|||||||
<string name="upgrade_capod_description">Krijg extra functies en ondersteun de ontwikkelaar.</string>
|
<string name="upgrade_capod_description">Krijg extra functies en ondersteun de ontwikkelaar.</string>
|
||||||
<string name="settings_popup_caseopen_label">Pop-up weergeven</string>
|
<string name="settings_popup_caseopen_label">Pop-up weergeven</string>
|
||||||
<string name="settings_popup_caseopen_description">Een pop-up weergeven wanneer de behuizing van het apparaat wordt geopend (experimenteel).</string>
|
<string name="settings_popup_caseopen_description">Een pop-up weergeven wanneer de behuizing van het apparaat wordt geopend (experimenteel).</string>
|
||||||
<string name="notification_channel_reaction_popup_label">Pop-up apparaatreacties</string>
|
|
||||||
<string name="overview_bluetooth_disabled_label">Bluetooth is uitgeschakeld</string>
|
<string name="overview_bluetooth_disabled_label">Bluetooth is uitgeschakeld</string>
|
||||||
<string name="overview_bluetooth_disabled_description">Bluetooth is uitgeschakeld, activeer het ;)</string>
|
<string name="overview_bluetooth_disabled_description">Bluetooth is uitgeschakeld, activeer het ;)</string>
|
||||||
<string name="help_translate_label">Vertaling</string>
|
<string name="help_translate_label">Vertaling</string>
|
||||||
<string name="help_translate_description">Help dit te vertalen naar uw favoriete taal.</string>
|
<string name="help_translate_description">Help deze app te vertalen in uw favoriete taal.</string>
|
||||||
<string name="settings_onepod_mode_label">Eén pod-modus</string>
|
<string name="settings_onepod_mode_label">Eén pod-modus</string>
|
||||||
<string name="settings_onepod_mode_description">Het dragen van beide pods is niet vereist, het dragen van een enkele pod is voldoende om reacties uit te lokken.</string>
|
<string name="settings_onepod_mode_description">Het dragen van beide pods is niet vereist, het dragen van een enkele pod is voldoende om reacties uit te lokken.</string>
|
||||||
<string name="permission_system_alert_window_label">Systeemwaarschuwingsvenster</string>
|
<string name="permission_system_alert_window_label">Systeemwaarschuwingsvenster</string>
|
||||||
@@ -133,4 +132,8 @@
|
|||||||
<string name="settings_blescanner_unfiltered_label">Ongefilterde BLE-gegevens</string>
|
<string name="settings_blescanner_unfiltered_label">Ongefilterde BLE-gegevens</string>
|
||||||
<string name="settings_blescanner_unfiltered_description">Verwijder eventuele filters van de BLE-scanner om alle uitgezonden BLE-gegevens weer te geven. Handig om ondersteuning toe te voegen voor nieuwe typen hoofdtelefoons.</string>
|
<string name="settings_blescanner_unfiltered_description">Verwijder eventuele filters van de BLE-scanner om alle uitgezonden BLE-gegevens weer te geven. Handig om ondersteuning toe te voegen voor nieuwe typen hoofdtelefoons.</string>
|
||||||
<string name="permission_required_title">De volgende toestemming is vereist:</string>
|
<string name="permission_required_title">De volgende toestemming is vereist:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Compatibiliteitsmodus</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Schakel optimalisaties uit om de compatibiliteit te verbeteren. Probeer dit als u geen gegevens ziet.</string>
|
||||||
|
<string name="translators_thanks_title">Vertalers</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">darken</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,2 +1,139 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="app_name">CAPod</string>
|
||||||
|
<string name="app_name_pro">CAPod Pro</string>
|
||||||
|
<string name="app_name_foss">CAPod FOSS</string>
|
||||||
|
<string name="notification_channel_device_status_label">Enhetsstatus</string>
|
||||||
|
<string name="general_error_label">Feil</string>
|
||||||
|
<string name="general_share_action">Del</string>
|
||||||
|
<string name="general_done_action">Ferdig</string>
|
||||||
|
<string name="general_copy_action">Kopier</string>
|
||||||
|
<string name="general_thank_you_label">Tusen takk</string>
|
||||||
|
<string name="general_value_not_available_label">N/A</string>
|
||||||
|
<string name="general_grant_permission_action">Gi tillatelse</string>
|
||||||
|
<string name="general_upgrade_action">Oppgrader</string>
|
||||||
|
<string name="general_check_action">Sjekk</string>
|
||||||
|
<string name="general_close_action">Lukk</string>
|
||||||
|
<string name="debug_debuglog_size_label">Størrelse</string>
|
||||||
|
<string name="debug_debuglog_size_compressed_label">Komprimert størrelse</string>
|
||||||
|
<string name="debug_notification_channel_label">Feilsøkingsvarslinger</string>
|
||||||
|
<string name="debug_debuglog_file_label">Registrert loggfil</string>
|
||||||
|
<string name="debug_debuglog_record_action">Registrer feilsøkingslogg</string>
|
||||||
|
<string name="permission_bluetooth_connect_label">Bluetooth-tilkobling</string>
|
||||||
|
<string name="permission_bluetooth_connect_description">Denne appen må ha \"Bluetooth-tilkobling\"-tillatelsen for å kunne snakke med sammenkoblede enheter og starte tilkoblinger.</string>
|
||||||
|
<string name="permission_bluetooth_scan_label">Bluetooth-skanning</string>
|
||||||
|
<string name="permission_bluetooth_scan_description">\"Bluetooth-skanning\"-tillatelsen lar denne appen oppdage og motta Bluetooth-data fra enheter i nærheten, som for eksempel AirPods.</string>
|
||||||
|
<string name="permission_bluetooth_label">Bluetooth</string>
|
||||||
|
<string name="permission_bluetooth_description">Denne appen må ha \"Bluetooth\"-tillatelsen for å koble til sammenkoblede Bluetooth-enheter.</string>
|
||||||
|
<string name="permission_access_fine_location_label">Forbedret posisjonsnøyaktighet</string>
|
||||||
|
<string name="permission_access_fine_location_description">CAPod bruker tillatelsen \"Forbedret posisjonsnøyaktighet\" for å motta Bluetooth Low Energy-data. Hodetelefonene dine bruker Bluetooth Low Energy-teknologi for å kringkaste statusen. Denne appen bruker IKKE Bluetooth-data til å se posisjonen din.</string>
|
||||||
|
<string name="permission_background_location_label">Bakgrunnsposisjon</string>
|
||||||
|
<string name="permission_background_location_description">CAPod bruker \"Bakgrunnsposisjon\" for å aktivere funksjoner som \"Vis popup\" og \"Autotilkobling\" mens appen er lukket. Tilgang til bakgrunnsposisjon lar appen motta Bluetooth Low Energy-data mens den er i bakgrunnen. Denne appen bruker IKKE Bluetooth-data for å se posisjonen din.</string>
|
||||||
|
<string name="permission_ignore_battery_optimizations_label">Deaktiver batterioptimalisering</string>
|
||||||
|
<string name="permission_ignore_battery_optimizations_description">Batterioptimalisering gjør at denne appen ikke alltid kan motta Bluetooth-data mens den er i bakgrunnen.</string>
|
||||||
|
<string name="pods_dual_left_label">Venstre pod</string>
|
||||||
|
<string name="pods_dual_right_label">Høyre pod</string>
|
||||||
|
<string name="pods_case_label">Deksel</string>
|
||||||
|
<string name="pods_case_status_open_label">Åpen</string>
|
||||||
|
<string name="pods_case_status_closed_label">Lukket</string>
|
||||||
|
<string name="pods_connection_state_disconnected_label">Ikke koblet til en enhet</string>
|
||||||
|
<string name="pods_connection_state_idle_label">Koblet til en enhet, men inaktiv</string>
|
||||||
|
<string name="pods_connection_state_music_label">I musikkmodus</string>
|
||||||
|
<string name="pods_connection_state_call_label">I ringemodus</string>
|
||||||
|
<string name="pods_connection_state_ringing_label">Ringer</string>
|
||||||
|
<string name="pods_connection_state_hanging_up_label">Legger på</string>
|
||||||
|
<string name="pods_connection_state_unknown_label">Ukjent tilkoblingsstatus</string>
|
||||||
|
<string name="pods_unknown_raw_data_label">Rådata</string>
|
||||||
|
<string name="pods_unknown_label">Ukjent enhet</string>
|
||||||
|
<string name="pods_unknown_contact_dev">Dette er en ukjent enhet, men den har en lignende meldingsformat. Vi kan legge til støtte for den, kontakt meg :)</string>
|
||||||
|
<string name="pods_none_label_short">Ingen enhet</string>
|
||||||
|
<string name="pods_charging_label">Lader</string>
|
||||||
|
<string name="pods_inear_label">I øret</string>
|
||||||
|
<string name="pods_microphone_label">Mikrofon</string>
|
||||||
|
<string name="pods_yours">Dine</string>
|
||||||
|
<string name="headset_being_worn_label">Brukes</string>
|
||||||
|
<string name="pods_case_unknown_state">Ukjent status</string>
|
||||||
|
<string name="overview_nomaindevice_label">Ingen primær enhet</string>
|
||||||
|
<string name="overview_nomaindevice_description">Det er usannsynlig at alle oppdagede enheter er dine. Slå på og koble til enheten eller juster innstillingene.</string>
|
||||||
|
<string name="settings_label">Innstillinger</string>
|
||||||
|
<string name="settings_privacy_policy_label">Personvernerklæring</string>
|
||||||
|
<string name="settings_privacy_policy_desc">Håndterer data ansvarlig.</string>
|
||||||
|
<string name="settings_licenses_label">Lisenser</string>
|
||||||
|
<string name="settings_category_other_label">Annet</string>
|
||||||
|
<string name="settings_general_label">Innstillinger</string>
|
||||||
|
<string name="settings_general_description">Generelle justeringer som påvirker hele appen.</string>
|
||||||
|
<string name="settings_acknowledgements_label">Anerkjennelser</string>
|
||||||
|
<string name="changelog_label">Endringslogg</string>
|
||||||
|
<string name="settings_support_email_developer_label" comment="settings_support_email_developer_label Pressing this setting will open your default email app with a template for a mail to me and some device info (e.g. versions).">Send e-post til utvikler</string>
|
||||||
|
<string name="settings_support_installid_label">Installasjons-ID</string>
|
||||||
|
<string name="settings_support_installid_desc">Automatiske feilrapporter er anonyme. Del installasjons-ID-en din hvis utvikleren skal finne feilrapportene dine.</string>
|
||||||
|
<string name="settings_support_label">Brukerstøtte</string>
|
||||||
|
<string name="settings_support_description">Hvis du trenger hjelp med noe.</string>
|
||||||
|
<string name="issue_tracker_label">Problemsporing</string>
|
||||||
|
<string name="issue_tracker_description">En offentlig problemsporing for feilrapporter og funksjonsforespørsler (kun på engelsk).</string>
|
||||||
|
<string name="discord_label">Discord</string>
|
||||||
|
<string name="discord_description">Et sted til å henge og for å stille spørsmål.</string>
|
||||||
|
<string name="settings_support_email_developer_description">Merk at jeg bare kan svare på tysk eller engelsk.</string>
|
||||||
|
<string name="settings_debug_autoreports_label">Automatiske feilrapporter</string>
|
||||||
|
<string name="settings_debug_autoreports_description">Rapporterer problemer automatisk, f.eks. detaljer om en appkrasj slik at jeg kan finne ut hvordan jeg kan fikse det.</string>
|
||||||
|
<string name="settings_debug_mode_label">Feilsøkingsmodus</string>
|
||||||
|
<string name="settings_debug_mode_description">Vis tilleggsinformasjon for å feilsøke problemer.</string>
|
||||||
|
<string name="settings_monitor_mode_label">Overvåkingsmodus</string>
|
||||||
|
<string name="settings_monitor_mode_description">Under hvilke omstendigheter denne appen skal overvåke Bluetooth-data.</string>
|
||||||
|
<string name="settings_scanner_mode_label">Skannermodus</string>
|
||||||
|
<string name="settings_scanner_mode_description">Skal Bluetooth Low Energy data-skanneren prioritere ytelse eller å spare energi?</string>
|
||||||
|
<string name="settings_monitor_mode_manual_label">Når appen er åpen</string>
|
||||||
|
<string name="settings_monitor_mode_automatic_label">Når enheten er tilkoblet</string>
|
||||||
|
<string name="settings_monitor_mode_always_label">Alltid</string>
|
||||||
|
<string name="settings_scanner_mode_lowpower_label">Lavt strømforbruk</string>
|
||||||
|
<string name="settings_scanner_mode_balanced_label">Balansert</string>
|
||||||
|
<string name="settings_scanner_mode_lowlatency_label">Lav forsinkelse</string>
|
||||||
|
<string name="settings_autopause_label">Sett på pause automatisk</string>
|
||||||
|
<string name="settings_autopause_description">Sett lyden på pause når du fjerner enheten fra øret.</string>
|
||||||
|
<string name="settings_showall_label">Vis alle enheter</string>
|
||||||
|
<string name="settings_showall_description">Vis andres enheter som er i nærheten av deg.</string>
|
||||||
|
<string name="settings_autopplay_label">Spill av automatisk</string>
|
||||||
|
<string name="settings_autoplay_description">Spill av lyd når enheten er i bruk.</string>
|
||||||
|
<string name="settings_fake_data_label">Falsk data</string>
|
||||||
|
<string name="settings_fake_data_description">Vis falsk data, dvs. simuler enheter som ikke eksisterer.</string>
|
||||||
|
<string name="settings_debug_label">Feilsøkingsinnstillinger</string>
|
||||||
|
<string name="settings_debug_description">Ytterligere innstillinger til å hjelpe med feilsøking av problemer i appen.</string>
|
||||||
|
<string name="settings_signal_minimum_label">Minimum signalkvalitet</string>
|
||||||
|
<string name="settings_signal_minimum_description">Minimumssignalkvaliteten som en enhet må ha for å anses som din.</string>
|
||||||
|
<string name="settings_autoconnect_label">Autotilkobling</string>
|
||||||
|
<string name="settings_autoconnect_description">Hvis Android ikke kobler til automatisk, kan vi spørre den om å gjøre det. Dette vil sette overvåkingsmodus-innstillingen til \'Alltid\'.</string>
|
||||||
|
<string name="settings_autoconnect_condition_label">Betingelse for autotilkobling</string>
|
||||||
|
<string name="settings_autoconnect_condition_description">Når skal vi prøve å koble til enheten din?</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_maindevice_address_label">Enhetens adresse</string>
|
||||||
|
<string name="settings_maindevice_address_description">Adressen til den sammenkoblede enheten. Appen bruker denne til å finne ut når den er koblet til telefonen din.</string>
|
||||||
|
<string name="settings_maindevice_address_none">Ingen</string>
|
||||||
|
<string name="settings_maindevice_model_label">Enhetens modell</string>
|
||||||
|
<string name="settings_maindevice_model_description">Modellen til hovedenheten din. Dette hjelper appen med å gjenkjenne enheten din når den ikke er koblet til telefonen.</string>
|
||||||
|
<string name="settings_reaction_autoconnect_whenseen_label">Når sett</string>
|
||||||
|
<string name="settings_reaction_autoconnect_caseopen_label">Deksel er åpen</string>
|
||||||
|
<string name="settings_reaction_autoconnect_inear_label">I øret</string>
|
||||||
|
<string name="upgrade_capod_label">Oppgrader CAPod</string>
|
||||||
|
<string name="upgrade_capod_description">Få flere funksjoner og støtt utvikleren.</string>
|
||||||
|
<string name="settings_popup_caseopen_label">Vis popup</string>
|
||||||
|
<string name="settings_popup_caseopen_description">Vis en popup når enhetens deksel åpnes (eksperimentelt).</string>
|
||||||
|
<string name="overview_bluetooth_disabled_label">Bluetooth er deaktivert</string>
|
||||||
|
<string name="overview_bluetooth_disabled_description">Bluetooth er deaktivert, aktiver det ;)</string>
|
||||||
|
<string name="help_translate_label">Oversettelse</string>
|
||||||
|
<string name="help_translate_description">Hjelp til med å oversette denne appen til ditt favorittspråk.</string>
|
||||||
|
<string name="settings_onepod_mode_label">En pod modus</string>
|
||||||
|
<string name="settings_onepod_mode_description">Du trenger kun ha på deg en pod for å utløse reaksjoner, i stedet for begge.</string>
|
||||||
|
<string name="permission_system_alert_window_label">Systemvarslingsvindu</string>
|
||||||
|
<string name="permission_system_alert_window_description">La CAPod tegne over andre apper for å gjøre \"Vis popup\"-funksjonen mulig.</string>
|
||||||
|
<string name="last_seen_x">Sist sett: %s</string>
|
||||||
|
<string name="first_seen_x">Først sett: %s</string>
|
||||||
|
<string name="settings_blescanner_unfiltered_label">Ufiltrert BLE-data</string>
|
||||||
|
<string name="settings_blescanner_unfiltered_description">Fjern eventuelle filtre fra BLE-skanneren for å vise alle kringkastede BLE-data. Nyttig for å kunne støtte nye hodetelefontyper.</string>
|
||||||
|
<string name="permission_required_title">Følgende tillatelse kreves:</string>
|
||||||
|
<string name="settings_compatibility_mode_label">Kompatibilitetsmodus</string>
|
||||||
|
<string name="settings_compatibility_mode_description">Deaktiver optimaliseringer for å forbedre kompatibiliteten. Prøv dette hvis du ikke ser noen data.</string>
|
||||||
|
<string name="translators_thanks_title">Oversettere</string>
|
||||||
|
<string name="translators_thanks_description" comment="translators_thanks_description You can voluntarily add your name here to have it displayed in the app. It will be shown in the Settings>Acknowledgements>Thank you section. Separate names by semicolons and an optional email may be included in brackets, example: darken(darken@darken.eu);John Doe(john@example.com) "darken" is just a placeholder and does not have to be kept if/when you add yours. Be nice to each other!">Kristoffer Vassbø(kristoffervassbo@gmail.com)</string>
|
||||||
|
</resources>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user