2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-31 14:15:14 +00:00

Compare commits

...

155 Commits

Author SHA1 Message Date
Albert Vaca Cintora
ed1dcdab52 Release 1.33.4 2025-05-02 17:24:53 +02:00
Albert Vaca Cintora
e3ccfb1b25 Bump deps 2025-05-02 17:12:15 +02:00
Albert Vaca Cintora
4ae04ae060 Refactor shared code out, apply ratelimit also to TCP 2025-05-02 17:05:55 +02:00
Albert Vaca Cintora
801367458e Improve rate-limit to also limit by IP 2025-05-02 17:05:55 +02:00
Albert Vaca Cintora
26c72fae89 Do not filter logs by PID
So we can see crashes in previous sessions of the app. Also, Android only
lets apps see their own logs anyway (at least in recent versions), so there
should be no privacy concerns from someone sharing those logs.
2025-05-02 17:02:40 +02:00
l10n daemon script
b981f9234b GIT_SILENT made messages (after extraction) 2025-04-29 01:55:52 +00:00
l10n daemon script
7f07e4658f GIT_SILENT made messages (after extraction) 2025-04-28 01:58:08 +00:00
l10n daemon script
f182d27ebe GIT_SILENT made messages (after extraction) 2025-04-27 01:57:46 +00:00
l10n daemon script
3b9d6ac61e GIT_SILENT made messages (after extraction) 2025-04-22 01:56:54 +00:00
l10n daemon script
6f24ac8d25 GIT_SILENT made messages (after extraction) 2025-04-20 01:54:52 +00:00
l10n daemon script
2891ec2092 GIT_SILENT made messages (after extraction) 2025-04-19 01:56:31 +00:00
Albert Vaca Cintora
fc1424c67c Better pairing fragment layout 2025-04-18 19:51:51 +02:00
Albert Vaca Cintora
83efd6b355 Add a warning if multiple devices have the same name 2025-04-18 17:42:08 +00:00
Albert Vaca Cintora
05e14bb81c Remove setting to disable UDP broadcast 2025-04-18 10:30:22 +02:00
l10n daemon script
1236cbe4e3 GIT_SILENT made messages (after extraction) 2025-04-17 01:54:46 +00:00
l10n daemon script
5f9159a13f GIT_SILENT made messages (after extraction) 2025-04-16 01:55:03 +00:00
l10n daemon script
fbd9f8f216 GIT_SILENT made messages (after extraction) 2025-04-15 01:56:01 +00:00
l10n daemon script
e32b6b67e0 GIT_SILENT made messages (after extraction) 2025-04-14 01:55:17 +00:00
Vala Zadeh
63a849b80a Extend offline URL sharing behavior
## Summary

Previously, URLs shared to offline targets via the ShareActivity were
delivered to them once they became online. This change extends this
behavior to direct share targets.

## Test Plan

Test 1

* Make sure a PC device is already paired with the phone. Let's say the name of this device is "PC".
* Make PC unreachable, e.g., close the KDE app on it.
* On the phone, open Chrome and share a couple of webpages to KDE's PC's direct share target.
* Open the KDE app on the PC.
* Observe that the webpages are opened on PC.

Test 2

* Make sure a PC device is already paired with the phone. Let's say the name of this device is "PC".
* Make PC unreachable, e.g., close the KDE app on it.
* On the phone, share a file to KDE's PC's direct share target.
* Open the KDE app on the PC.
* Observe that the file is sent to PC.

Test 3

* Make sure two PC devices are already paired with the phone. Let's say the name of these devices are "PC1" and "PC2".
* Make PC1 and PC2 unreachable, e.g., close the KDE app on them.
* On the phone, open Chrome and share a couple of webpages to KDE's PC1's direct share target.
* Open the KDE app on the PC2.
* Observe that the webpages are NOT opened on PC2.
* Open the KDE app on the PC1.
* Observe that the webpages are opened on PC1.

Test 4

* Make sure a PC device is already paired with the phone. Let's say the name of this device is "PC".
* Make PC reachable, e.g., have the KDE app open on it.
* Try to share a URL from the phone to the KDE's PC's direct share target.
* Observe that the URL opens instantly on the PC.
2025-04-13 00:20:04 +00:00
l10n daemon script
170bb5e717 GIT_SILENT made messages (after extraction) 2025-04-12 01:51:20 +00:00
l10n daemon script
f121e4982e GIT_SILENT made messages (after extraction) 2025-04-10 01:54:33 +00:00
l10n daemon script
937289730d GIT_SILENT made messages (after extraction) 2025-04-09 01:54:22 +00:00
l10n daemon script
624a9302fd GIT_SILENT made messages (after extraction) 2025-04-08 02:00:37 +00:00
l10n daemon script
e6f4b69464 GIT_SILENT made messages (after extraction) 2025-04-07 02:06:50 +00:00
Albert Vaca Cintora
2190c9cdaa Missed updated changelog 2025-04-06 10:32:38 +02:00
Albert Vaca Cintora
864d44cb5b Release 1.33.3 2025-04-06 10:30:22 +02:00
Albert Vaca Cintora
72e958a891 Allow exporting the logs form the app 2025-04-06 10:24:28 +02:00
Albert Vaca Cintora
d4ab2ca6cf Bump deps 2025-04-06 10:24:14 +02:00
Albert Vaca Cintora
fd51ec7c14 Fix linter warnings 2025-04-05 00:44:08 +02:00
Albert Vaca Cintora
28070954a6 Regenerate device ID if the stored ID is not valid 2025-04-05 00:05:56 +02:00
Albert Vaca Cintora
e10f2496de Simplify running git in gradle 2025-04-04 14:06:20 +02:00
Albert Vaca Cintora
95b4c08605 Bump deps 2025-04-04 12:15:11 +02:00
l10n daemon script
51d4de34c4 GIT_SILENT made messages (after extraction) 2025-04-04 02:01:41 +00:00
l10n daemon script
de2001bbe1 GIT_SILENT made messages (after extraction) 2025-03-31 01:55:34 +00:00
Albert Vaca Cintora
9c80cb9a40 Remove old code that used Android IDs as device IDs 2025-03-30 21:01:32 +02:00
Albert Vaca Cintora
0b03a66c37 Generate IDs with only alphanumeric values
As per https://invent.kde.org/network/kdeconnect-meta/-/merge_requests/13
2025-03-30 20:59:38 +02:00
l10n daemon script
6d66d69820 GIT_SILENT made messages (after extraction) 2025-03-27 01:58:41 +00:00
Albert Vaca Cintora
c0fc19baaa Bump version of classindexksp 2025-03-18 12:56:45 +01:00
Albert Vaca Cintora
03ea5eae4c Fix NPE 2025-03-17 14:03:15 +01:00
l10n daemon script
b373c28cdd GIT_SILENT made messages (after extraction) 2025-03-16 01:58:31 +00:00
Albert Vaca Cintora
6c8d22b1ed Release 1.33.2 2025-03-11 17:17:44 +01:00
Albert Vaca Cintora
69adfbfbc2 Do the kdeconnect handshake in a new thread
Some Android versions seem to hang if calling sslSocket.getOutputStream()
from within the HandshakeCompleted callback (maybe because calling it in
on a socket that hasn't finished the SSL handshake is supposed to trigger
the SSL handshake).

BUG: 501241
2025-03-11 17:14:36 +01:00
Albert Vaca Cintora
f80e29538a Do not use BufferedReader to read from socket
Reading the docs, BufferedReader maybe could read and cache more than one
line from the socket, and since we discarded the BufferedReader and
created a new one (up to three times), data could be lost.
2025-03-11 12:44:33 +01:00
l10n daemon script
56dda889d1 GIT_SILENT made messages (after extraction) 2025-03-08 02:05:24 +00:00
Albert Vaca Cintora
0c48f388f4 Release 1.33.1 2025-03-05 15:53:13 +01:00
Albert Vaca Cintora
3eda9d4ef9 Allow hyphens in device ids 2025-03-05 15:47:14 +01:00
Albert Vaca Cintora
5aa6fae03b Bump gradle 2025-03-05 15:47:02 +01:00
Albert Vaca Cintora
228a504b90 Bump deps 2025-03-03 14:42:43 +01:00
Albert Vaca Cintora
34c2c311e2 Fix NPE 2025-03-03 14:41:30 +01:00
l10n daemon script
08fcfc863a GIT_SILENT made messages (after extraction) 2025-03-03 01:58:29 +00:00
l10n daemon script
c550ef4445 GIT_SILENT made messages (after extraction) 2025-03-01 02:08:19 +00:00
l10n daemon script
ec40994d4c GIT_SILENT made messages (after extraction) 2025-02-27 01:53:23 +00:00
Albert Vaca Cintora
43d4f38765 Fix deprecation warning 2025-02-26 21:32:39 +01:00
Albert Vaca Cintora
fbff23a8c0 Release 1.30.0 2025-02-26 21:22:17 +01:00
Albert Vaca Cintora
52ff931c4e Fix build 2025-02-26 21:22:04 +01:00
José Rebelo
0f628d4927 Allow filtering notifications from work profile
BUG: 412188
BUG: 422445
2025-02-26 20:08:50 +00:00
Albert Vaca Cintora
737c333a91 Bump deps 2025-02-26 18:21:58 +01:00
Albert Vaca Cintora
e9e406de88 Deprecate packet id field 2025-02-26 11:10:06 +00:00
l10n daemon script
9b2e4bcf56 GIT_SILENT made messages (after extraction) 2025-02-26 01:56:17 +00:00
l10n daemon script
d3daf20c27 GIT_SILENT made messages (after extraction) 2025-02-25 01:55:19 +00:00
l10n daemon script
7de2817274 GIT_SILENT made messages (after extraction) 2025-02-24 10:45:50 +00:00
Albert Vaca Cintora
6121fa04bc Do not disconnect when there's a version mismatch
Just trust the encrypted packet.
2025-02-23 15:50:11 +00:00
Albert Vaca Cintora
bec807fa63 Catch JSONException when unserializing 2025-02-23 15:50:11 +00:00
Albert Vaca Cintora
fe97750e9a Enforce the protocol doesn't change after the handshake 2025-02-23 15:50:11 +00:00
Albert Vaca Cintora
f8a2d2da03 Fix protocol version comparison 2025-02-23 15:50:11 +00:00
Albert Vaca Cintora
68a0b73e9c Do not unpair automatically on error, just ignore the connection 2025-02-23 15:50:11 +00:00
Albert Vaca Cintora
7a4fb8b584 Make the verification key change every time in protocol v8 2025-02-23 15:50:11 +00:00
Albert Vaca Cintora
b4ee6e30b1 Also compare protocol version to consider device info needs saving 2025-02-23 15:50:11 +00:00
Albert Vaca Cintora
0560071cfb Show protocol version in encryption info 2025-02-23 15:50:11 +00:00
Albert Vaca Cintora
4343ad7e01 Do not allow protocol downgrades 2025-02-23 15:50:11 +00:00
Albert Vaca Cintora
0738710747 Remove support for protocol version < 7 2025-02-23 15:50:11 +00:00
Albert Vaca Cintora
9af8fe791b Protocol version 8: send identity packets encrypted 2025-02-23 15:50:11 +00:00
TPJ Schikhof
a9a99ea7bd Add PeerTube support to formatUriWithSeek function 2025-02-16 21:43:14 +00:00
l10n daemon script
03c2121d57 GIT_SILENT made messages (after extraction) 2025-02-15 02:15:26 +00:00
l10n daemon script
c0c38aab9a GIT_SILENT Sync po/docbooks with svn 2025-02-10 02:18:43 +00:00
l10n daemon script
ab4a6a300b GIT_SILENT Add new file (after extraction) 2025-02-10 01:51:47 +00:00
l10n daemon script
82c434273d GIT_SILENT made messages (after extraction) 2025-02-01 01:54:30 +00:00
Albert Vaca Cintora
0e1842964f Use anonymous functions instead of the callback interface 2025-01-28 00:59:47 +01:00
Albert Vaca Cintora
0a82d303e4 More fixing NPEs and improving nullability handling 2025-01-28 00:51:48 +01:00
Albert Vaca Cintora
c275e26e00 Fix NPEs and improve handling of nullability 2025-01-28 00:22:43 +01:00
Albert Vaca Cintora
d951e3faad Fix NPE 2025-01-25 10:58:56 +01:00
l10n daemon script
144d292948 GIT_SILENT made messages (after extraction) 2025-01-25 01:57:33 +00:00
Albert Vaca Cintora
32d293eb8d Fix "View not attached to window" crash 2025-01-23 12:46:29 +01:00
Albert Vaca Cintora
3e2c077674 Fix NPE crash 2025-01-23 11:58:08 +01:00
Albert Vaca Cintora
49d36d57a6 Update comments 2025-01-19 00:44:07 +01:00
Albert Vaca Cintora
8b6d789c02 Suppress linter issues 2025-01-19 00:38:44 +01:00
Albert Vaca Cintora
de73362624 Remove outdated comment 2025-01-19 00:38:44 +01:00
Albert Vaca Cintora
7bc90fbe85 Simplify regex 2025-01-18 20:42:27 +00:00
Albert Vaca Cintora
818b99774d Add test 2025-01-18 20:42:27 +00:00
Albert Vaca Cintora
13b09ffae8 Enforce format of device IDs 2025-01-18 20:42:27 +00:00
Albert Vaca Cintora
56c96b686d Last round of comment format fixes 2025-01-18 14:58:56 +01:00
Albert Vaca Cintora
3b4f5f83b2 More comment format fixes 2025-01-18 14:55:51 +01:00
TPJ Schikhof
fc18d8a10f Improve SMSPlugin doc comment formatting 2025-01-18 13:51:26 +00:00
Albert Vaca Cintora
d73236ab96 Gitignore files created during tests because of a bug
https://bugs.openjdk.org/browse/JDK-8214300
2025-01-18 14:46:12 +01:00
Albert Vaca Cintora
ecd4bec109 Release 1.32.11 2025-01-18 11:42:02 +01:00
l10n daemon script
bb152c4900 GIT_SILENT made messages (after extraction) 2025-01-15 01:53:11 +00:00
TPJ Schikhof
49a9cd5ea7 Refactoring 2025-01-13 22:35:29 +00:00
TPJ Schikhof
e363a5875a Migrate SMSPlugin to Kotlin 2025-01-13 22:35:29 +00:00
TPJ Schikhof
55d3fd630c Rename .java to .kt 2025-01-13 22:35:29 +00:00
l10n daemon script
a85e6f8057 GIT_SILENT made messages (after extraction) 2025-01-13 01:57:08 +00:00
Albert Vaca Cintora
125c9d54b3 Release 1.32.10 2025-01-12 21:42:05 +01:00
Albert Vaca Cintora
5b937313ff Bump dependencies 2025-01-12 21:34:52 +01:00
l10n daemon script
2ad9f8eeb1 GIT_SILENT made messages (after extraction) 2025-01-12 02:01:35 +00:00
l10n daemon script
b3d84f31f4 GIT_SILENT made messages (after extraction) 2025-01-05 01:55:07 +00:00
l10n daemon script
5ca96fc378 GIT_SILENT made messages (after extraction) 2025-01-04 01:51:55 +00:00
l10n daemon script
05f1cbe136 GIT_SILENT made messages (after extraction) 2025-01-02 01:52:10 +00:00
l10n daemon script
d02e5aabb5 GIT_SILENT made messages (after extraction) 2025-01-01 01:52:54 +00:00
Mash Kyrielight
ae24cd6ca8 Fix insets for android 15
Apps are edge-to-edge by default on devices running Android 15
https://developer.android.com/develop/ui/views/layout/edge-to-edge

Fix: https://bugs.kde.org/show_bug.cgi?id=495999
2024-12-31 18:00:39 +00:00
Albert Vaca Cintora
16414401c0 Honor trusted network for MDNS discovery 2024-12-31 12:58:37 +00:00
Albert Vaca Cintora
3f120fbea8 Move version to build.gradle.kts 2024-12-31 09:24:17 +01:00
l10n daemon script
97806cf6b0 GIT_SILENT made messages (after extraction) 2024-12-31 01:54:17 +00:00
l10n daemon script
a923deee58 GIT_SILENT made messages (after extraction) 2024-12-30 02:01:30 +00:00
Albert Vaca Cintora
0923c8ecda Show number of custom devices in settings fragment 2024-12-29 15:19:22 +00:00
TPJ Schikhof
172822239c Migrate VolumeKeyListener to Kotlin 2024-12-29 10:54:01 +00:00
Albert Vaca Cintora
6a58cc444e Remove old proguard rule 2024-12-29 02:50:57 +01:00
Albert Vaca Cintora
26667e4b78 Simplify proguard-rules 2024-12-29 02:44:12 +01:00
Albert Vaca Cintora
086d366a1c Fix authority not matching manifest in debug builds 2024-12-29 02:34:10 +01:00
Albert Vaca Cintora
84d380aee5 Simplify build.gradle 2024-12-29 02:26:10 +01:00
Albert Vaca Cintora
1ea956f5fb Add en-GB strings for debug (my phone is in GB English) 2024-12-29 02:25:34 +01:00
Albert Vaca Cintora
cfc7242db5 Move "debug" before the name so it's visible in the launcher 2024-12-29 02:25:11 +01:00
l10n daemon script
93b257d46c GIT_SILENT made messages (after extraction) 2024-12-28 02:06:03 +00:00
TPJ Schikhof
fa22722498 Allow for debugging on the same device
This change builds separate debugging app with a different
ID which can be installed alongside the release version.
2024-12-27 18:20:08 +00:00
l10n daemon script
b0c9e46a31 GIT_SILENT made messages (after extraction) 2024-12-27 01:57:15 +00:00
l10n daemon script
53b49163d5 GIT_SILENT made messages (after extraction) 2024-12-25 02:20:51 +00:00
Albert Vaca Cintora
444f5725af Bump deps 2024-12-24 17:35:37 +01:00
TPJ Schikhof
1104baca8f Remove unused SmallEntryItem.kt 2024-12-24 13:00:13 +00:00
Albert Vaca Cintora
c3af9b03f6 Replace classindex with my own implementation that uses KSP instead of KAPT 2024-12-24 12:40:51 +00:00
l10n daemon script
ecb38f2518 GIT_SILENT made messages (after extraction) 2024-12-24 01:52:21 +00:00
TPJ Schikhof
75ddac0bf0 Reworked custom device list
- Solved serialization issue when commas were used
- Validate hosts and show toast message if host is invalid
- Show whether device can be reached over the network
- Show toast message when host already exists
- Code TODO's (including sorting device list)
2024-12-22 19:41:58 +00:00
Mash Kyrielight
553bae4a33 Fix icon color on dark theme 2024-12-16 21:46:31 +00:00
l10n daemon script
7d5f40a3a1 GIT_SILENT made messages (after extraction) 2024-12-10 01:56:00 +00:00
Albert Vaca Cintora
e8c74ec689 Fix format of commented code 2024-12-04 22:47:25 +01:00
Albert Vaca Cintora
c7223a17dc Bump AGP version 2024-12-04 22:47:25 +01:00
Albert Vaca Cintora
2fddd7e24a Gitignore .kotlin 2024-12-04 22:47:25 +01:00
TPJ Schikhof
7920a1a250 Migrate PluginPreference to Kotlin 2024-12-03 08:55:08 +00:00
TPJ Schikhof
a1ce310f65 Rename .java to .kt 2024-12-03 08:55:08 +00:00
TPJ Schikhof
8fea00a843 Migrate list fragments to Kotlin 2024-12-02 22:28:08 +00:00
TPJ Schikhof
7210fd8425 Rename .java to .kt 2024-12-02 22:28:08 +00:00
l10n daemon script
dcb817a805 GIT_SILENT Sync po/docbooks with svn 2024-12-02 03:09:05 +00:00
l10n daemon script
b916d2c972 GIT_SILENT made messages (after extraction) 2024-12-02 02:27:42 +00:00
Albert Vaca Cintora
6b15348677 Bump deps 2024-11-30 16:42:46 +01:00
l10n daemon script
a899f06885 GIT_SILENT made messages (after extraction) 2024-11-24 01:52:13 +00:00
l10n daemon script
4a1a086e0f GIT_SILENT made messages (after extraction) 2024-11-14 01:51:25 +00:00
l10n daemon script
8853f1807f GIT_SILENT Sync po/docbooks with svn 2024-11-13 02:19:46 +00:00
l10n daemon script
0a8bd2bf56 GIT_SILENT made messages (after extraction) 2024-11-13 01:49:45 +00:00
l10n daemon script
c5d1d4a9fa GIT_SILENT made messages (after extraction) 2024-11-10 01:59:34 +00:00
Rocket Aaron
741e24c984 Fix invalid device name condition 2024-11-06 22:51:25 +08:00
l10n daemon script
8b9b99275d GIT_SILENT made messages (after extraction) 2024-11-02 01:49:08 +00:00
l10n daemon script
cfe789fb7e GIT_SILENT made messages (after extraction) 2024-10-31 01:49:58 +00:00
l10n daemon script
7170bdb687 GIT_SILENT made messages (after extraction) 2024-10-28 01:54:26 +00:00
l10n daemon script
53f746cb6a GIT_SILENT made messages (after extraction) 2024-10-27 01:56:57 +00:00
l10n daemon script
35777b4b15 GIT_SILENT made messages (after extraction) 2024-10-26 01:51:18 +00:00
l10n daemon script
a1d0689d50 GIT_SILENT made messages (after extraction) 2024-10-25 01:49:31 +00:00
l10n daemon script
883eca5cf3 GIT_SILENT made messages (after extraction) 2024-10-24 01:47:57 +00:00
l10n daemon script
d91107329a GIT_SILENT made messages (after extraction) 2024-10-23 01:49:27 +00:00
172 changed files with 3741 additions and 2651 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,4 @@
.attach_pid*
local.properties
/.gradle/
/.idea/
@@ -13,3 +14,4 @@ local.properties
.directory
GPUCache/
/release/
/.kotlin/

View File

@@ -7,9 +7,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:versionCode="13209"
android:versionName="1.32.9">
xmlns:tools="http://schemas.android.com/tools">
<uses-feature
android:name="android.hardware.telephony"
@@ -359,7 +357,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="org.kde.kdeconnect_tp.fileprovider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data

View File

@@ -21,37 +21,27 @@ buildscript {
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.kapt)
alias(libs.plugins.ksp)
alias(libs.plugins.dependencyLicenseReport)
alias(libs.plugins.compose.compiler)
}
val licenseResDir = File("$projectDir/build/dependency-license-res")
fun String.runCommand(
workingDir: File = File("."),
timeoutAmount: Long = 60,
timeoutUnit: TimeUnit = TimeUnit.SECONDS
): String = ProcessBuilder(split("\\s(?=(?:[^'\"`]*(['\"`])[^'\"`]*\\1)*[^'\"`]*$)".toRegex()))
.directory(workingDir)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()
.apply { waitFor(timeoutAmount, timeoutUnit) }
.run {
val error = errorStream.bufferedReader().readText().trim()
if (error.isNotEmpty()) {
throw Exception(error)
}
inputStream.bufferedReader().readText().trim()
}
val hashProvider = project.providers.exec {
workingDir = rootDir
commandLine("git", "rev-parse", "--short", "HEAD")
}.standardOutput.asText.map { it.trim() }
android {
namespace = "org.kde.kdeconnect_tp"
compileSdk = 35
defaultConfig {
applicationId = "org.kde.kdeconnect_tp"
minSdk = 21
targetSdk = 35
versionCode = 13304
versionName = "1.33.4"
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
buildFeatures {
@@ -74,16 +64,18 @@ android {
androidResources {
generateLocaleConfig = true
}
sourceSets {
getByName("main") {
manifest.srcFile("AndroidManifest.xml")
java.setSrcDirs(listOf("src"))
resources.setSrcDirs(listOf("resources"))
res.setSrcDirs(listOf(licenseResDir, "res"))
assets.setSrcDirs(listOf("assets"))
setRoot(".") // By default AGP expects all directories under src/main/...
java.srcDir("src") // by default is "java"
res.setSrcDirs(listOf(licenseResDir, "res")) // add licenseResDir
}
getByName("debug") {
res.srcDir("dbg-res")
}
getByName("test") {
java.setSrcDirs(listOf("tests"))
java.srcDir("tests")
}
}
@@ -105,6 +97,8 @@ android {
isMinifyEnabled = false
isShrinkResources = false
signingConfig = signingConfigs.getByName("debug")
applicationIdSuffix = ".debug"
versionNameSuffix = "-debug"
}
getByName("release") {
isMinifyEnabled = true
@@ -127,8 +121,7 @@ android {
// Default output filename is "${project.name}-${v.name}.apk". We want
// the Git commit short-hash to be added onto that default filename.
try {
val hash = "git rev-parse --short HEAD".runCommand(workingDir = rootDir)
val newName = "${project.name}-${variant.name}-${hash}.apk"
val newName = "${project.name}-${variant.name}-${hashProvider.get()}.apk"
logger.quiet(" Found an output file ${output.outputFile.name}, renaming to $newName")
output.outputFileName = newName
} catch (ignored: Exception) {
@@ -254,6 +247,10 @@ abstract class FixCollectionsClassVisitorFactory :
interface Params : InstrumentationParameters
}
ksp {
arg("com.albertvaka.classindexksp.annotations", "org.kde.kdeconnect.Plugins.PluginFactory.LoadablePlugin")
}
androidComponents {
onVariants { variant ->
variant.instrumentation.transformClassesWith(
@@ -304,11 +301,9 @@ dependencies {
implementation(libs.apache.sshd.mina)
implementation(libs.apache.mina.core)
//implementation("com.github.bright:slf4android:0.1.6") { transitive = true } // For org.apache.sshd debugging
implementation(libs.bcpkix.jdk15on) //For SSL certificate generation
implementation(libs.classindex)
kapt(libs.classindex)
ksp(libs.classindexksp)
// The android-smsmms library is the only way I know to handle MMS in Android
// (Shouldn't a phone OS make phone things easy?)

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <background android:drawable="@drawable/ic_launcher_background"/>-->
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <background android:drawable="@drawable/ic_launcher_banner_background"/>-->
<foreground android:drawable="@drawable/ic_launcher_banner_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <background android:drawable="@drawable/ic_launcher_background"/>-->
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="kde_connect">Debug KDE Connect</string>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="kde_connect">Debug KDE Connect</string>
</resources>

View File

@@ -0,0 +1,21 @@
يوفر كِيدِي المتّصل مجموعة من الميزات لدمج سير عملك عبر الأجهزة:
- نقل الملفات بين أجهزتك.
- الوصول إلى الملفات الموجودة على هاتفك من جهاز الكمبيوتر الخاص بك، دون أسلاك.
- الحافظة المشتركة: النسخ واللصق بين أجهزتك.
- الحصول على إشعارات للمكالمات والرسائل الواردة على جهاز الكمبيوتر الخاص بك.
- لوحة اللمس الافتراضية: استخدم شاشة هاتفك كلوحة لمس لجهاز الكمبيوتر الخاص بك.
- مزامنة الإشعارات: الوصول إلى إشعارات هاتفك من جهاز الكمبيوتر الخاص بك والرد على الرسائل.
- التحكم عن بعد في الوسائط المتعددة: استخدم هاتفك كجهاز تحكم عن بعد لمشغلات الوسائط لينكس.
- اتصال WiFi: لا حاجة إلى سلك USB أو بلوتوث.
- تشفير TLS من البداية إلى النهاية: معلوماتك آمنة.
يرجى ملاحظة أنك ستحتاج إلى تثبيت كِيدِي المتّصل على حاسوبك حتى يعمل هذا التطبيق، والحفاظ على تحديث إصدار سطح المكتب بإصدار أندوريد حتى تعمل أحدث الميزات.
معلومات الأذونات الحساسة:
* إذن إمكانية الوصول: مطلوب لتلقي إدخال من جهاز آخر للتحكم في هاتف أندرويد خاص بك، إذا كنت تستخدم ميزة الإدخال عن بُعد.
* إذن تحديد الموقع في الخلفية: مطلوب لمعرفة شبكة واي فاي التي تتصل بها، إذا كنت تستخدم ميزة الشبكات الموثوقة.
لا يرسل كِيدِي المتّصل أي معلومات إلى كيدي أو إلى أي طرف ثالث. يرسل كِيدِي المتّصل البيانات من جهاز إلى آخر مباشرةً باستخدام الشبكة المحلية، وليس عبر الإنترنت، وباستخدام التشفير من البداية إلى النهاية.
هذا التطبيق جزء من مشروع مفتوح المصدر وهو موجود بفضل جميع الأشخاص الذين ساهموا فيه. قم بزيارة الموقع الإلكتروني للحصول على الكود المصدر.

View File

@@ -0,0 +1 @@
يقوم كِيدِي المتّصل بدمج هاتفك الذكي والحاسوب

View File

@@ -0,0 +1 @@
KDE Connect

View File

@@ -0,0 +1,14 @@
1.32.10
* Fixed app showing behind the notifications bar in Android 15
* Fixed file transfers showing as failed when they succeeded
* Fixed plugin list not updating after granting permissions
1.32.3
* Fix trusted devices list
1.32.2
* Handle expired certificates
* Support doubletap drag in remote mouse
1.32.1
* Fixed a crash when opening the presentation remote

View File

@@ -0,0 +1,6 @@
1.33.0
* Add support for PeerTube links
* Allow filtering notifications from work profile
* Fix bug where devices would unpair without user interaction
* Verification key now changes every second (only if both devices support it)
* Fix crashes

View File

@@ -0,0 +1,9 @@
1.33.1
* Fix compatibility with GSConnect
1.33.0
* Add support for PeerTube links
* Allow filtering notifications from work profile
* Fix bug where devices would unpair without user interaction
* Verification key now changes every second (only if both devices support it)
* Fix crashes

View File

@@ -0,0 +1,12 @@
1.33.2
* Fix connection issues on some devices
1.33.1
* Fix compatibility with GSConnect
1.33.0
* Add support for PeerTube links
* Allow filtering notifications from work profile
* Fix bug where devices would unpair without user interaction
* Verification key now changes every second (only if both devices support it)
* Fix crashes

View File

@@ -0,0 +1,16 @@
1.33.3
* Fix more connection issues. Pairing again might be needed in some setups.
* Add a setting to export the application logs.
1.33.2
* Fix connection issues on some devices.
1.33.1
* Fix compatibility with GSConnect.
1.33.0
* Add support for PeerTube links.
* Allow filtering notifications from work profile.
* Fix bug where devices would unpair without user interaction.
* Verification key now changes every second (only if both devices support it).
* Fix crashes.

View File

@@ -0,0 +1,16 @@
1.33.4
* Extend offline URL sharing behavior to direct share targets.
* Improve paring screen.
1.33.3
* Fix connection issues. Pairing again might be needed in some cases.
* Add a setting to export the application logs.
1.33.1
* Fix compatibility with GSConnect.
1.33.0
* Add support for PeerTube links.
* Allow filtering notifications from work profile.
* Fix bug where devices would unpair without user interaction.
* Verification key now changes every second (if both devices support it).

View File

@@ -1,4 +1,4 @@
KDE 連線提供許多功能讓您整合您跨裝置的作業流程:
KDE Connect 提供許多功能讓您整合您跨裝置的作業流程:
- 在您的裝置之間傳輸檔案。
- 從您的電腦無線存取您的手機上的檔案。
@@ -10,12 +10,12 @@ KDE 連線提供許多功能讓您整合您跨裝置的作業流程:
- WiFi 連線:不需要 USB 線或是藍牙連線。
- 點對點 TLS 加密:您的資訊是安全的。
請注意,這個應用程式需要您在電腦上也安裝 KDE 連線才能正常運作;最新功能也會需要電腦的版本跟 Android 的版本一樣新才能正常運作。
請注意,這個應用程式需要您在電腦上也安裝 KDE Connect 才能正常運作;最新功能也會需要電腦的版本跟 Android 的版本一樣新才能正常運作。
敏感權限資訊:
* 協助工具權限:如果您使用「遠端輸入」功能,需要它來從另一個裝置接收輸入後控制您的 Android 裝置。
* 背景位置權限:如果您使用「信任網路」功能,需要它來得知您目前連線的 WiFi 網路。
KDE 連線不會傳送任何資訊給 KDE 或任何第三方。KDE 連線利用本地網路直接從一個裝置傳送資料到另一個裝置,不會透過網際網路,並且同時使用點對點加密。
KDE Connect 不會傳送任何資訊給 KDE 或任何第三方。KDE Connect 利用本地網路直接從一個裝置傳送資料到另一個裝置,不會透過網際網路,並且同時使用點對點加密。
這個應用程式是一個開源專案的一部分,它的存在歸功於所有貢獻者。可造訪網站取得原始碼。

View File

@@ -1 +1 @@
KDE 連線整合了您的智慧型手機與電腦
KDE Connect 整合了您的智慧型手機與電腦

View File

@@ -1,40 +1,41 @@
[versions]
activityCompose = "1.9.3"
androidDesugarJdkLibs = "2.1.2"
androidGradlePlugin = "8.7.1"
activityCompose = "1.10.1"
androidDesugarJdkLibs = "2.1.5"
androidGradlePlugin = "8.9.2"
androidSmsmms = "kdeconnect-1-21-0"
appcompat = "1.7.0"
bcpkixJdk15on = "1.70"
classindex = "3.13"
commonsCollections4 = "4.4"
commonsIo = "2.17.0"
classindexksp = "1.2"
commonsCollections4 = "4.5.0"
commonsIo = "2.19.0"
commonsLang3 = "3.17.0"
constraintlayoutCompose = "1.0.1"
coreKtx = "1.13.1"
dependencyLicenseReport = "2.7"
constraintlayoutCompose = "1.1.1"
coreKtx = "1.16.0"
dependencyLicenseReport = "2.9"
disklrucache = "2.0.2"
documentfile = "1.0.1"
gridlayout = "1.0.0"
gridlayout = "1.1.0"
jsonassert = "1.5.3"
junit = "4.13.2"
kotlin = "2.0.21"
kotlinxCoroutinesCore = "1.9.0"
kotlin = "2.1.20"
kspPlugin = "2.1.20-1.0.32"
kotlinxCoroutinesCore = "1.10.2"
lifecycleExtensions = "2.2.0"
lifecycleRuntimeKtx = "2.8.6"
lifecycleRuntimeKtx = "2.8.7"
logger = "1.0.3"
material = "1.12.0"
material3 = "1.3.0"
material3 = "1.3.2"
media = "1.7.0"
minaCore = "2.2.3"
mockitoCore = "5.14.2"
minaCore = "2.2.4"
mockitoCore = "5.17.0"
preferenceKtx = "1.2.1"
reactiveStreams = "1.0.4"
recyclerview = "1.3.2"
recyclerview = "1.4.0"
rxjava = "2.2.21"
sl4j = "2.0.13"
sshdCore = "2.14.0"
sshdCore = "2.15.0"
swiperefreshlayout = "1.1.0"
uiToolingPreview = "1.7.4"
uiToolingPreview = "1.8.0"
univocityParsers = "2.9.1"
[libraries]
@@ -58,7 +59,7 @@ androidx-preference-ktx = { module = "androidx.preference:preference-ktx", versi
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" }
androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "swiperefreshlayout" }
bcpkix-jdk15on = { module = "org.bouncycastle:bcpkix-jdk15on", version.ref = "bcpkixJdk15on" }
classindex = { module = "org.atteo.classindex:classindex", version.ref = "classindex" }
classindexksp = { module = "com.github.albertvaka:classindexksp", version.ref = "classindexksp" }
commons-collections4 = { module = "org.apache.commons:commons-collections4", version.ref = "commonsCollections4" }
commons-io = { module = "commons-io:commons-io", version.ref = "commonsIo" }
commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commonsLang3" }
@@ -87,5 +88,5 @@ slf4j-handroid = { group = "com.gitlab.mvysny.slf4j", name = "slf4j-handroid", v
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "kspPlugin" }
dependencyLicenseReport = { id = "com.github.jk1.dependency-license-report", version.ref = "dependencyLicenseReport" }

View File

@@ -1,7 +1,7 @@
#Sat Sep 28 01:39:16 AM EDT 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -0,0 +1,84 @@
# SPDX-FileCopyrightText: 2025 Zayed Al-Saidi <zayed.alsaidi@gmail.com>
#. extracted from ./metadata/android/en-US/full_description.txt
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-05 12:31+0000\n"
"PO-Revision-Date: 2025-02-09 17:40+0400\n"
"Last-Translator: Zayed Al-Saidi <zayed.alsaidi@gmail.com>\n"
"Language-Team: ar\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
"X-Generator: Lokalize 23.08.5\n"
msgid ""
"KDE Connect provides a set of features to integrate your workflow across "
"devices:\n"
"\n"
"- Transfer files between your devices.\n"
"- Access files on your phone from your computer, without wires.\n"
"- Shared clipboard: copy and paste between your devices.\n"
"- Get notifications for incoming calls and messages on your computer.\n"
"- Virtual touchpad: Use your phone screen as your computer's touchpad.\n"
"- Notifications sync: Access your phone notifications from your computer and "
"reply to messages.\n"
"- Multimedia remote control: Use your phone as a remote for Linux media "
"players.\n"
"- WiFi connection: no USB wire or bluetooth needed.\n"
"- End-to-end TLS encryption: your information is safe.\n"
"\n"
"Please note you will need to install KDE Connect on your computer for this "
"app to work, and keep the desktop version up-to-date with the Android "
"version for the latest features to work.\n"
"\n"
"Sensitive permissions information:\n"
"* Accessibility permission: Required to receive input from another device to "
"control your Android phone, if you use the Remote Input feature.\n"
"* Background location permission: Required to know to which WiFi network you "
"are connected to, if you use the Trusted Networks feature.\n"
"\n"
"KDE Connect never sends any information to KDE nor to any third party. KDE "
"Connect sends data from one device to the other directly using the local "
"network, never through the internet, and using end to end encryption.\n"
"\n"
"This app is part of an open source project and it exists thanks to all the "
"people who contributed to it. Visit the website to grab the source code.\n"
msgstr ""
"يوفر كِيدِي المتّصل مجموعة من الميزات لدمج سير عملك عبر الأجهزة:\n"
"\n"
"- نقل الملفات بين أجهزتك.\n"
"- الوصول إلى الملفات الموجودة على هاتفك من جهاز الكمبيوتر الخاص بك، دون "
"أسلاك.\n"
"- الحافظة المشتركة: النسخ واللصق بين أجهزتك.\n"
"- الحصول على إشعارات للمكالمات والرسائل الواردة على جهاز الكمبيوتر الخاص "
"بك.\n"
"- لوحة اللمس الافتراضية: استخدم شاشة هاتفك كلوحة لمس لجهاز الكمبيوتر الخاص "
"بك.\n"
"- مزامنة الإشعارات: الوصول إلى إشعارات هاتفك من جهاز الكمبيوتر الخاص بك "
"والرد على الرسائل.\n"
"- التحكم عن بعد في الوسائط المتعددة: استخدم هاتفك كجهاز تحكم عن بعد لمشغلات "
"الوسائط لينكس.\n"
"- اتصال WiFi: لا حاجة إلى سلك USB أو بلوتوث.\n"
"- تشفير TLS من البداية إلى النهاية: معلوماتك آمنة.\n"
"\n"
"يرجى ملاحظة أنك ستحتاج إلى تثبيت كِيدِي المتّصل على حاسوبك حتى يعمل هذا "
"التطبيق، والحفاظ على تحديث إصدار سطح المكتب بإصدار أندوريد حتى تعمل أحدث "
"الميزات.\n"
"\n"
"معلومات الأذونات الحساسة:\n"
"* إذن إمكانية الوصول: مطلوب لتلقي إدخال من جهاز آخر للتحكم في هاتف أندرويد "
"خاص بك، إذا كنت تستخدم ميزة الإدخال عن بُعد.\n"
"* إذن تحديد الموقع في الخلفية: مطلوب لمعرفة شبكة واي فاي التي تتصل بها، إذا "
"كنت تستخدم ميزة الشبكات الموثوقة.\n"
"\n"
"لا يرسل كِيدِي المتّصل أي معلومات إلى كيدي أو إلى أي طرف ثالث. يرسل كِيدِي المتّصل "
"البيانات من جهاز إلى آخر مباشرةً باستخدام الشبكة المحلية، وليس عبر الإنترنت، "
"وباستخدام التشفير من البداية إلى النهاية.\n"
"\n"
"هذا التطبيق جزء من مشروع مفتوح المصدر وهو موجود بفضل جميع الأشخاص الذين "
"ساهموا فيه. قم بزيارة الموقع الإلكتروني للحصول على الكود المصدر.\n"

View File

@@ -0,0 +1,20 @@
# SPDX-FileCopyrightText: 2025 Zayed Al-Saidi <zayed.alsaidi@gmail.com>
#. extracted from ./metadata/android/en-US/short_description.txt
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-05 12:31+0000\n"
"PO-Revision-Date: 2025-02-09 17:40+0400\n"
"Last-Translator: Zayed Al-Saidi <zayed.alsaidi@gmail.com>\n"
"Language-Team: ar\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
"X-Generator: Lokalize 23.08.5\n"
msgid "KDE Connect integrates your smartphone and computer"
msgstr "يقوم كِيدِي المتّصل بدمج هاتفك الذكي والحاسوب"

View File

@@ -13,7 +13,6 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 22.12.3\n"
msgid ""
"KDE Connect provides a set of features to integrate your workflow across "

View File

@@ -13,7 +13,6 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 22.12.3\n"
msgid "KDE Connect integrates your smartphone and computer"
msgstr "KDE Connect eheyttää älypuhelimen ja tietokoneen"

View File

@@ -1,19 +1,20 @@
# Kisaragi Hiu <mail@kisaragi-hiu.com>, 2023.
# taijuin <taijuin@gmail.com>, 2024.
#. extracted from ./metadata/android/en-US/full_description.txt
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-05 12:31+0000\n"
"PO-Revision-Date: 2023-12-09 17:51+0900\n"
"Last-Translator: Kisaragi Hiu <mail@kisaragi-hiu.com>\n"
"PO-Revision-Date: 2024-11-12 19:04+0800\n"
"Last-Translator: taijuin <taijuin@gmail.com>\n"
"Language-Team: Traditional Chinese <zh-l10n@lists.slat.org>\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Lokalize 24.01.80\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.5\n"
msgid ""
"KDE Connect provides a set of features to integrate your workflow across "
@@ -48,7 +49,7 @@ msgid ""
"This app is part of an open source project and it exists thanks to all the "
"people who contributed to it. Visit the website to grab the source code.\n"
msgstr ""
"KDE 連線提供許多功能讓您整合您跨裝置的作業流程:\n"
"KDE Connect 提供許多功能讓您整合您跨裝置的作業流程:\n"
"\n"
"- 在您的裝置之間傳輸檔案。\n"
"- 從您的電腦無線存取您的手機上的檔案。\n"
@@ -60,8 +61,8 @@ msgstr ""
"- WiFi 連線:不需要 USB 線或是藍牙連線。\n"
"- 點對點 TLS 加密:您的資訊是安全的。\n"
"\n"
"請注意,這個應用程式需要您在電腦上也安裝 KDE 連線才能正常運作;最新功能也會需"
"要電腦的版本跟 Android 的版本一樣新才能正常運作。\n"
"請注意,這個應用程式需要您在電腦上也安裝 KDE Connect 才能正常運作;最新功能也"
"會需要電腦的版本跟 Android 的版本一樣新才能正常運作。\n"
"\n"
"敏感權限資訊:\n"
"* 協助工具權限:如果您使用「遠端輸入」功能,需要它來從另一個裝置接收輸入後控"
@@ -69,8 +70,8 @@ msgstr ""
"* 背景位置權限:如果您使用「信任網路」功能,需要它來得知您目前連線的 WiFi 網"
"路。\n"
"\n"
"KDE 連線不會傳送任何資訊給 KDE 或任何第三方。KDE 連線利用本地網路直接從一個裝"
"置傳送資料到另一個裝置,不會透過網際網路,並且同時使用點對點加密。 \n"
"KDE Connect 不會傳送任何資訊給 KDE 或任何第三方。KDE Connect 利用本地網路直接"
"從一個裝置傳送資料到另一個裝置,不會透過網際網路,並且同時使用點對點加密。 \n"
"\n"
"這個應用程式是一個開源專案的一部分,它的存在歸功於所有貢獻者。可造訪網站取得"
"原始碼。\n"

View File

@@ -1,19 +1,20 @@
# Kisaragi Hiu <mail@kisaragi-hiu.com>, 2023.
# taijuin <taijuin@gmail.com>, 2024.
#. extracted from ./metadata/android/en-US/short_description.txt
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-05 12:31+0000\n"
"PO-Revision-Date: 2023-12-09 17:39+0900\n"
"Last-Translator: Kisaragi Hiu <mail@kisaragi-hiu.com>\n"
"PO-Revision-Date: 2024-11-12 19:00+0800\n"
"Last-Translator: taijuin <taijuin@gmail.com>\n"
"Language-Team: Traditional Chinese <zh-l10n@lists.slat.org>\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Lokalize 24.01.80\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.5\n"
msgid "KDE Connect integrates your smartphone and computer"
msgstr "KDE 連線整合了您的智慧型手機與電腦"
msgstr "KDE Connect 整合了您的智慧型手機與電腦"

25
proguard-rules.pro vendored
View File

@@ -17,29 +17,10 @@
#}
-dontobfuscate
-dontwarn org.spongycastle.**
-dontwarn org.apache.sshd.**
-dontwarn org.apache.mina.**
-dontwarn org.slf4j.**
-dontwarn io.netty.**
-keepattributes SourceFile,LineNumberTable,Signature,*Annotation*
-keep class org.spongycastle.** {*;}
# SSHd requires mina, and mina uses reflection so some classes would get deleted
-keep class org.apache.mina.** {*;}
-keep class org.apache.sshd.** {*;}
-keep class org.kde.kdeconnect.** {*;}
-dontwarn org.mockito.**
-dontwarn sun.reflect.**
-dontwarn android.test.**
-dontwarn java.lang.management.**
-dontwarn javax.**
# SSHd requires mina, and mina uses reflection so some classes would get deleted
-keep class org.apache.sshd.** {*;}
-dontwarn org.apache.sshd.**
-dontwarn android.net.ConnectivityManager
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn android.net.LinkProperties

View File

@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#000000"
android:fillColor="?colorControlNormal"
android:pathData="M12,3v10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55 -2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4V7h4V3h-6z"/>
</vector>

View File

@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:fillColor="?attr/colorControlNormal"
android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/>
</vector>

View File

@@ -6,8 +6,6 @@
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:fillColor="?attr/colorControlNormal"
android:pathData="M7 9v6h4l5 5V4l-5 5H7z" />
<path
android:pathData="M0 0h24v24H0z" />
</vector>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2023 Albert Vaca Cintora <albertvaka@gmail.com>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:drawablePadding="8dp"
android:paddingTop="16dp"
android:paddingBottom="12dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:text="@string/pairing_duplicate_names"
app:drawableStartCompat="@drawable/ic_warning"
app:drawableTint="?attr/colorControlNormal">
</TextView>

View File

@@ -21,6 +21,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:clipToPadding="false"
android:id="@+id/scroll_view"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout

View File

@@ -26,6 +26,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
tools:listitem="@layout/custom_device_item"/>
<TextView

View File

@@ -30,7 +30,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:id="@+id/device_view"
android:descendantFocusability="afterDescendants"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:clipToPadding="false">
<!-- Shown when the device is paired and reachable -->
<androidx.compose.ui.platform.ComposeView

View File

@@ -20,5 +20,6 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:id="@+id/licenses_text"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
android:clipToPadding="false"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -17,7 +17,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<!-- Keep in sync with toolbar.xml, copied here because it needs the nested TabLayout -->
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"

View File

@@ -57,6 +57,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:dividerHeight="0dp"
android:orientation="vertical"
android:paddingTop="8dp"
android:clipToPadding="false"
tools:context=".MainActivity" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -24,7 +24,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
app:drawableEndCompat="@drawable/ic_delete"
app:drawableStartCompat="@drawable/ic_delete" />
<FrameLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/swipeableView"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -32,17 +32,30 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<TextView
android:id="@+id/deviceNameOrIP"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="?android:selectableItemBackground"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingEnd="?android:attr/listPreferredItemPaddingRight"
android:paddingStart="?android:attr/listPreferredItemPaddingLeft"
android:paddingEnd="?android:attr/listPreferredItemPaddingRight"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:visibility="visible"
tools:text="192.168.0.1"/>
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="192.168.0.1" />
</FrameLayout>
<TextView
android:id="@+id/connectionStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:paddingStart="?android:attr/listPreferredItemPaddingLeft"
android:paddingEnd="?android:attr/listPreferredItemPaddingRight"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@@ -22,6 +22,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:descendantFocusability="afterDescendants"
android:dividerHeight="12dp"
android:orientation="vertical"
android:clipToPadding="false"
tools:listitem="@layout/list_card_entry"
tools:context=".MainActivity" />

View File

@@ -11,7 +11,9 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fillViewport="true">
android:fillViewport="true"
android:clipToPadding="false"
android:id="@+id/scroll_view">
<LinearLayout
android:id="@+id/about_layout"

View File

@@ -49,7 +49,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:background="@android:color/transparent"
android:contentDescription="@string/mute"
android:scaleType="fitXY"
android:src="@drawable/ic_volume_black"/>
android:src="@drawable/ic_volume"/>
<SeekBar
android:id="@+id/systemvolume_seek"

View File

@@ -198,7 +198,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:layout_weight="0"
android:contentDescription="@string/mpris_volume"
android:maxWidth="30dip"
android:src="@drawable/ic_volume_black"/>
android:src="@drawable/ic_volume"/>
<SeekBar

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2023 Albert Vaca Cintora <albertvaka@gmail.com>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:drawablePadding="8dp"
android:paddingTop="16dp"
android:paddingBottom="12dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:text="@string/pairing_duplicate_names"
app:drawableStartCompat="@drawable/ic_warning"
app:drawableLeftCompat="@drawable/ic_warning">
</TextView>

View File

@@ -19,12 +19,6 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:visibility="gone"
tools:visibility="visible">
<ProgressBar
android:id="@+id/pair_progress"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<TextView
android:id="@+id/pair_message"
android:layout_width="wrap_content"
@@ -33,6 +27,13 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:text="@string/device_not_paired"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/pairing_explanation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="12dip"
android:text="@string/pairing_explanation" />
<TextView
android:id="@+id/pair_verification"
android:layout_width="wrap_content"
@@ -43,6 +44,12 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:textAppearance="?android:attr/textAppearanceMedium"
app:drawableStartCompat="@drawable/ic_key" />
<ProgressBar
android:id="@+id/pair_progress"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<com.google.android.material.button.MaterialButton
android:id="@+id/pair_button"
android:layout_width="match_parent"

View File

@@ -17,6 +17,7 @@
<string name="pref_plugin_clipboard_sent">أرسل الحافظة</string>
<string name="pref_plugin_mousepad">الدّخل البعيد</string>
<string name="pref_plugin_mousepad_desc">استخدم الهاتف أو اللوحيّ كفأرة ولوحة مفاتيح</string>
<string name="pref_plugin_presenter">متحكم العرض التقديمي</string>
<string name="pref_plugin_mpris">تحكّمات الوسائط المتعدّدة</string>
<string name="pref_plugin_mpris_desc">توفّر تحكّمًا بعيدًا لمشغّل الوسائط</string>
<string name="pref_plugin_runcommand">شغّل أمرًا</string>
@@ -76,6 +77,7 @@
<string name="device_menu_plugins">إعدادات الملحقة</string>
<string name="device_menu_unpair">ألغِ الاقتران</string>
<string name="pair_new_device">اقرن جهازًا جديدًا</string>
<string name="cancel_pairing">ألغ الاقتران</string>
<string name="unknown_device">جهاز مجهول</string>
<string name="error_not_reachable">الجهاز غير قابل الوصول</string>
<string name="error_already_paired">الجهاز مقترن بالفعل</string>
@@ -83,8 +85,11 @@
<string name="error_canceled_by_user">ألغاه المستخدم</string>
<string name="error_canceled_by_other_peer">ألغاه ندّ آخر</string>
<string name="encryption_info_title">معلومات التّعمية</string>
<string name="my_device_fingerprint">بصمة SHA256 لشهادة جهازك هي:</string>
<string name="remote_device_fingerprint">بصمة SHA256 لشهادة الجهاز البعيد هي:</string>
<string name="pair_requested">طُلب الاقتران</string>
<string name="pair_succeeded">نجح الاقتران</string>
<string name="pairing_request_from">اطلب اقتران من \'%1s\'</string>
<string name="tap_to_open">اطرق لتفتح</string>
<string name="received_file_text">المس لفتح \'%1s\'</string>
<string name="tap_to_answer">المس للإجابة</string>
@@ -173,6 +178,7 @@
<string name="clipboard_toast">نُسخ إلى الحافظة</string>
<string name="runcommand_notreachable">الجهاز غير قابل الوصول</string>
<string name="runcommand_notpaired">الجهاز غير مقترن</string>
<string name="runcommand_category_device_controls_title">متحكمات الجهاز</string>
<string name="pref_plugin_findremotedevice">اعثر على جهاز بعيد</string>
<string name="pref_plugin_findremotedevice_desc">رنّ على الجهاز البعيد</string>
<string name="ring">رّن</string>
@@ -183,6 +189,8 @@
<string name="settings_rename">اسم الجهاز</string>
<string name="settings_dark_mode">سمة مظلمة</string>
<string name="settings_more_settings_title">المزيد من الإعدادات</string>
<string name="setting_persistent_notification_oreo">الإخطارات المستمرّة</string>
<string name="extra_options">الخيارات الإضافية</string>
<string name="privacy_options">خيارات الخصوصية</string>
<string name="set_privacy_options">حدد خيارات الخصوصية</string>
<string name="block_contents">امنح محتويات الإخطارات</string>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">Устройството е недостъпно</string>
<string name="error_already_paired">Устройството вече е сдвоено</string>
<string name="error_timed_out">Просрочка</string>
<string name="error_clocks_not_match">Часовниците на устройствата не са синхронизирани</string>
<string name="error_canceled_by_user">Отхвърлена от потребителя</string>
<string name="error_canceled_by_other_peer">Отказана от другата страна</string>
<string name="encryption_info_title">Информация за криптиране</string>
@@ -192,11 +193,13 @@
<string name="share_to">Споделяне към...</string>
<string name="unreachable_device">%s (не е достъпно)</string>
<string name="unreachable_device_url_share_text">URL адресите, споделени към недостъпно устройство, ще бъдат доставени до него, когато то стане достъпно.\n\n</string>
<string name="protocol_version">Версия на протокол:</string>
<string name="protocol_version_newer">Това устройство използва по-нова версия на протокола</string>
<string name="plugin_settings_with_name">%s настройки</string>
<string name="invalid_device_name">Невалидно име на устройство</string>
<string name="shareplugin_text_saved">Получен текст, запазен в клипборда</string>
<string name="custom_devices_settings">Списък с потребителски устройства</string>
<string name="custom_devices_settings_summary">%d устройства, добавени ръчно</string>
<string name="custom_device_list">Добавяне на устройства по IP адрес</string>
<string name="custom_device_deleted">Изтрито потребителско устройство</string>
<string name="custom_device_list_help">Ако устройството ви не е открито автоматично, можете да добавите неговия IP адрес или име на хост, като щракнете върху плаващия бутон за действие</string>
@@ -306,6 +309,8 @@
<string name="devices">Устройства</string>
<string name="settings_rename">Име на устройство</string>
<string name="settings_dark_mode">Тъмна тема</string>
<string name="settings_export_logs">Експортиране на дневниците на KDE Connect</string>
<string name="settings_export_logs_text">Генерирайте файл с информация за изпълнени команди, която може да помогне за отстраняването на проблеми.</string>
<string name="settings_more_settings_title">Още настройки</string>
<string name="settings_more_settings_text">Настройките за всяко устройство могат да бъдат намерени в раздел \"Настройки на плъгина\" в рамките на устройство.</string>
<string name="setting_persistent_notification">Показване на постоянна нотификация</string>
@@ -326,7 +331,7 @@
<string name="empty_trusted_networks_list_text">Все още не сте добавили надеждна мрежа</string>
<string name="allow_all_networks_text">Allow all</string>
<string name="location_permission_needed_title">Изисква се разрешение</string>
<string name="bluetooth_permission_needed_desc">Предоставете разрешения за Bluetooth, за да направите устройства, сдвоени чрез Bluetooth, налични в KDE Connect.</string>
<string name="bluetooth_permission_needed_desc">KDE Connect се нуждае от разрешение за свързване с устройства наблизо, за да направи устройства, сдвоени чрез Bluetooth, достъпни в KDE Connect.</string>
<string name="location_permission_needed_desc">KDE Connect се нуждае от разрешение за местоположението във фонов режим, за да познава WiFi към която сте свързани, дори когато приложението е във фонов режим. Това е така, защото имената на WiFi мрежите около вас могат да бъдат използвани за намиране на вашето местоположение, дори когато KDE Connect не прави това.</string>
<string name="clipboard_android_x_incompat">Android 10 премахна достъпа до клипборда за всички приложения. Тази приставка ще бъде деактивирана.</string>
<string name="mpris_open_url">Продължаване на възпроизвеждането тук</string>
@@ -420,4 +425,9 @@
<string name="mpris_keepwatching_settings_title">Продължаване на възпроизвеждането</string>
<string name="mpris_keepwatching_settings_summary">Показване на безшумно известие за продължаване на възпроизвеждането на това устройство след затваряне на медия</string>
<string name="notification_channel_keepwatching">Продължаване на възпроизвеждането</string>
<string name="ping_result">Извършен е пинг за %1$d милисекунди</string>
<string name="ping_failed">Устройството не можа да изпрати пинг</string>
<string name="ping_in_progress">Изпращане на пинг…</string>
<string name="device_host_invalid">Хостът е невалиден. Използвайте валидно име на хост, IPv4 или IPv6</string>
<string name="device_host_duplicate">Хостът вече е в списъка</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">No es pot accedir al dispositiu</string>
<string name="error_already_paired">El dispositiu ja està aparellat</string>
<string name="error_timed_out">Ha excedit el temps</string>
<string name="error_clocks_not_match">Els rellotges dels dispositius no estan sincronitzats</string>
<string name="error_canceled_by_user">Cancel·lat per l\'usuari</string>
<string name="error_canceled_by_other_peer">Cancel·lat per l\'altre parell</string>
<string name="encryption_info_title">Informació de l\'encriptatge</string>
@@ -164,9 +165,11 @@
<string name="middle_click">Envia un clic del mig</string>
<string name="show_keyboard">Mostra el teclat</string>
<string name="device_not_paired">El dispositiu no està aparellat</string>
<string name="pairing_duplicate_names">Precaució: hi ha diversos dispositius amb el mateix nom.</string>
<string name="request_pairing">Demana aparellar</string>
<string name="pairing_accept">Accepta</string>
<string name="pairing_reject">Rebutja</string>
<string name="pairing_explanation">L\'aparellament de dos dispositius els donarà accés l\'un a l\'altre. Només aparelleu els vostres propis dispositius.</string>
<string name="settings">Arranjament</string>
<string name="mpris_play">Reprodueix</string>
<string name="mpris_pause">Pausa</string>
@@ -191,12 +194,15 @@
<string name="mpris_notification_settings_summary">Permet controlar els reproductors multimèdia sense obrir el KDE Connect</string>
<string name="share_to">Comparteix amb…</string>
<string name="unreachable_device">%s (no s\'hi pot accedir)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">Els URL compartits amb un dispositiu no accessible es lliuraran un cop s\'hi pugui accedir.\n\n</string>
<string name="protocol_version">Versió del protocol:</string>
<string name="protocol_version_newer">Aquest dispositiu usa una versió nova del protocol</string>
<string name="plugin_settings_with_name">Configuració del %s</string>
<string name="invalid_device_name">El nom del dispositiu no és vàlid</string>
<string name="shareplugin_text_saved">S\'ha rebut text i s\'ha desat al porta-retalls</string>
<string name="custom_devices_settings">Llista personalitzada de dispositius</string>
<string name="custom_devices_settings_summary">S\'han afegir %d dispositius manualment</string>
<string name="custom_device_list">Afegeix dispositius per la IP</string>
<string name="custom_device_deleted">S\'ha suprimit un dispositiu personalitzat</string>
<string name="custom_device_list_help">Si el dispositiu no es detecta automàticament, podeu afegir la seva adreça IP o el nom de la màquina fent clic al botó flotant d\'acció</string>
@@ -306,6 +312,8 @@
<string name="devices">Dispositius</string>
<string name="settings_rename">Nom del dispositiu</string>
<string name="settings_dark_mode">Tema fosc</string>
<string name="settings_export_logs">Exporta els registres del KDE Connect</string>
<string name="settings_export_logs_text">Genera un fitxer amb informació d\'execució que pot ajudar a resoldre problemes.</string>
<string name="settings_more_settings_title">Més opcions</string>
<string name="settings_more_settings_text">La configuració per dispositiu es pot trobar a «Arranjament dels connectors» des d\'un dispositiu.</string>
<string name="setting_persistent_notification">Mostra les notificacions persistents</string>
@@ -326,7 +334,7 @@
<string name="empty_trusted_networks_list_text">Encara no heu afegit cap xarxa de confiança</string>
<string name="allow_all_networks_text">Permet totes</string>
<string name="location_permission_needed_title">Es requereix permís</string>
<string name="bluetooth_permission_needed_desc">Atorgueu els permisos de Bluetooth per a fer que els dispositius aparellats per Bluetooth estiguin disponibles al KDE Connect.</string>
<string name="bluetooth_permission_needed_desc">El KDE Connect necessita permís per a connectar als dispositius propers per a fer que els dispositius aparellats per Bluetooth estiguin disponibles al KDE Connect.</string>
<string name="location_permission_needed_desc">El KDE Connect necessita el permís d\'ubicació en segon pla per a conèixer la xarxa Wi-Fi a la qual esteu connectat fins i tot quan l\'aplicació està en segon pla. Això és perquè el nom de les xarxes Wi-Fi que hi ha al voltant es podria utilitzar per a trobar la vostra ubicació, fins i tot quan això no és el que fa el KDE Connect.</string>
<string name="clipboard_android_x_incompat">L\'Android 10 ha tret l\'accés al porta-retalls a totes les aplicacions. Aquest connector estarà inhabilitat.</string>
<string name="mpris_open_url">Continua reproduint aquí</string>
@@ -420,4 +428,9 @@
<string name="mpris_keepwatching_settings_title">Continua reproduint</string>
<string name="mpris_keepwatching_settings_summary">Mostra una notificació silenciosa per a continuar reproduint en aquest dispositiu després de tancar l\'element multimèdia</string>
<string name="notification_channel_keepwatching">Continua reproduint</string>
<string name="ping_result">S\'ha fet «ping» en %1$d mil·lisegons</string>
<string name="ping_failed">No s\'ha pogut fer «ping» al dispositiu</string>
<string name="ping_in_progress">S\'està fent «ping»…</string>
<string name="device_host_invalid">L\'ordinador no és vàlid. Useu un nom d\'ordinador, IPv4 o IPv6 vàlids</string>
<string name="device_host_duplicate">L\'ordinador ja existeix a la llista</string>
</resources>

View File

@@ -326,7 +326,7 @@
<string name="empty_trusted_networks_list_text">You have not added any trusted network yet</string>
<string name="allow_all_networks_text">Allow all</string>
<string name="location_permission_needed_title">Permission required</string>
<string name="bluetooth_permission_needed_desc">Grant Bluetooth permissions to make devices paired using Bluetooth available in KDE Connect.</string>
<string name="bluetooth_permission_needed_desc">KDE Connect needs permission to connect to nearby devices to make devices paired using Bluetooth available in KDE Connect.</string>
<string name="location_permission_needed_desc">KDE Connect needs the background location permission to know the WiFi network you are connected to even when the app is in the background. This is because the name of the WiFi networks around you could be used to find your location, even when this is not what KDE Connect does.</string>
<string name="clipboard_android_x_incompat">Android 10 has removed clipboard access to all apps. This plugin will be disabled.</string>
<string name="mpris_open_url">Continue playing here</string>

View File

@@ -17,7 +17,7 @@
<string name="pref_plugin_clipboard_desc">Kunhavigi la enhavon de la tondujo</string>
<string name="pref_plugin_clipboard_sent">Clipboard Sendita</string>
<string name="pref_plugin_mousepad">Fora enigo</string>
<string name="pref_plugin_mousepad_desc">Uzu vian telefonon aŭ tablojdon kiel tuŝplaton kaj klavaron</string>
<string name="pref_plugin_mousepad_desc">Uzu vian telefonon aŭ tabuleton kiel tuŝplaton kaj klavaron</string>
<string name="pref_plugin_presenter">Prezento fora</string>
<string name="pref_plugin_presenter_desc">Uzu vian aparaton por ŝanĝi lumbildojn en prezento</string>
<string name="pref_plugin_remotekeyboard">Ricevi forajn klavojn</string>
@@ -25,7 +25,7 @@
<string name="pref_plugin_mpris">Plurmedia regiloj</string>
<string name="pref_plugin_mpris_desc">Provizas teleregilon por via plurmedia ludilo</string>
<string name="pref_plugin_runcommand">Lanĉi Komandon</string>
<string name="pref_plugin_runcommand_desc">Ekigi forajn komandojn de via telefono aŭ tablojdo</string>
<string name="pref_plugin_runcommand_desc">Ekigi forajn komandojn de via telefono aŭ tabuleto</string>
<string name="pref_plugin_contacts">Sinkronigilo de Kontaktoj</string>
<string name="pref_plugin_contacts_desc">Permesi sinkronigi la kontaktlibron de la aparato</string>
<string name="pref_plugin_ping">Ping</string>
@@ -115,6 +115,7 @@
<string name="error_not_reachable">Aparato ne atingebla</string>
<string name="error_already_paired">Aparato jam parigita</string>
<string name="error_timed_out">Tempo elĉerpita</string>
<string name="error_clocks_not_match">Aparataj horloĝoj estas malsinkronaj</string>
<string name="error_canceled_by_user">Nuligite de uzanto</string>
<string name="error_canceled_by_other_peer">Nuligite de alia kunulo</string>
<string name="encryption_info_title">Ĉifrada Informo</string>
@@ -192,11 +193,13 @@
<string name="share_to">Kunhavigi al…</string>
<string name="unreachable_device">%s (Neatingebla)</string>
<string name="unreachable_device_url_share_text">URL-oj kundividitaj al neatingebla aparato estos liveritaj al ĝi post kiam ĝi fariĝos atingebla.\n\n</string>
<string name="protocol_version">Protokolversio:</string>
<string name="protocol_version_newer">Ĉi tiu aparato uzas pli novan protokolversion</string>
<string name="plugin_settings_with_name">%s agordoj</string>
<string name="invalid_device_name">Nevalida aparato nomo</string>
<string name="shareplugin_text_saved">Ricevita teksto, konservita en tondujo</string>
<string name="custom_devices_settings">Propra aparato listo</string>
<string name="custom_devices_settings_summary">%d aparatoj aldoniĝis permane</string>
<string name="custom_device_list">Aldoni aparatojn per IP</string>
<string name="custom_device_deleted">Propra aparato forigita</string>
<string name="custom_device_list_help">Se via aparato ne estas aŭtomate detektita, vi povas aldoni ĝian IP-adreson aŭ gastigan nomon alklakante la Ŝveban Ago-Butonon</string>
@@ -326,6 +329,7 @@
<string name="empty_trusted_networks_list_text">Vi ankoraŭ ne aldonis neniun fidindan reton</string>
<string name="allow_all_networks_text">Permesi ĉion</string>
<string name="location_permission_needed_title">Permeso bezonata</string>
<string name="bluetooth_permission_needed_desc">KDE Connect bezonas permeson por konekti al proksimaj aparatoj por fari aparatojn parigitaj per Bluetooth disponebla en KDE Connect.</string>
<string name="location_permission_needed_desc">KDE Connect bezonas la fonlokan permeson por scii la WiFi-reton al kiu vi estas konektita eĉ kiam la programo estas en la fono. Ĉi tio estas ĉar la nomo de la WiFi-retoj ĉirkaŭ vi povus esti uzata por trovi vian lokon, eĉ kiam tion ne faras KDE Connect.</string>
<string name="clipboard_android_x_incompat">Android 10 forigis aliron al tondujo al ĉiuj aplikaĵoj. Ĉi tiu kromaĵo estos malŝaltita.</string>
<string name="mpris_open_url">Daŭre ludi ĉi tie</string>
@@ -389,6 +393,8 @@
<string name="send_compose">Sendi</string>
<string name="compose_send_title">Verki sendon</string>
<string name="open_compose_send">Verki tekston</string>
<string name="double_tap_to_drag">Duoble frapetu por treni</string>
<string name="hold_to_drag">Teni por treni</string>
<string name="about_kde_about">&lt;h1&gt;Pri&lt;/h1&gt; &lt;p&gt;KDE estas tutmonda komunumo de softvar-inĝenieroj, artistoj, verkistoj, tradukistoj kaj kreintoj kiuj engaĝiĝas al &lt;a href=https://www.gnu.org/philosophy/free -sw.html&gt;Disvolvado de Libera Programaro&lt;/a&gt;. KDE produktas la Plasma labortablan medion, centojn da aplikaĵoj, kaj la multajn programarajn bibliotekojn kiuj subtenas ilin.&lt;/p&gt; &lt;/p&gt;KDE estas kunlabora entrepreno: neniu unuopa ento stiras ĝian direkton aŭ produktojn. Anstataŭe, ni kunlaboras por atingi la komunan celon konstrui la plej bonan Liberan Programaron de la mondo. Ĉiuj bonvenas &lt;a href=https://community.kde.org/Get_Involved&gt;aliiĝi kaj kontribui&lt;/a&gt; al KDE, inkluzive de vi.&lt;/p&gt; Vizitu &lt;a href=https://www.kde.org/&gt;https://www.kde.org/&lt;/a&gt; por pliaj informoj pri la KDE-komunumo kaj la programaro, kiun ni produktas.</string>
<string name="about_kde_report_bugs_or_wishes">&lt;h1&gt;Raporti Cimojn aŭ Dezirojn&lt;/h1&gt; &lt;p&gt;Softvaro ĉiam povas esti plibonigita kaj la KDE-teamo pretas fari tion. Tamen, vi - la uzanto - devas diri al ni se io ne funkcias kiel atendite aŭ povus esti farata pli bone.&lt;/p&gt; &lt;p&gt;KDE havas cimraportan sistemon. Vizitu &lt;a href=https://bugs.kde.org/&gt;https://bugs.kde.org/&lt;/a&gt; aŭ uzu la butonon \"Raporti Cimon\" el la Pri-ekrano por raporti cimojn.&lt;/p&gt; Se vi havas sugeston por plibonigo, vi estas bonvena uzi la cimtrakan sistemon pro registri vian deziron. Certigu, ke vi uzas la severecon nomita \"Wishlist\".</string>
<string name="about_kde_join_kde">&lt;h1&gt;Kuniĝu al KDE&lt;/h1&gt; &lt;p&gt;Vi ne devas esti programisto por esti membro de la teamo KDE. Vi povas aliĝi al la lingvoteamoj kiuj tradukas program-interfacojn. Vi povas provizi grafikaĵojn, etosojn, sonojn, kaj plibonigitan dokumentadon. Vi decidas!&lt;/p&gt; &lt;p&gt;Vizitu &lt;a href=https://community.kde.org/Get_Involved&gt;https://community.kde.org/Get_Involved&lt;/a&gt; por informo pri iuj projektoj en kiuj vi povas partopreni.&lt;/p&gt; Se vi bezonas plian informon aŭ dorkmentadon, vizito al &lt;a href=https://techbase.kde.org/&gt;https://techbase.kde.org/&lt;/a&gt; provizos al vi kion vi bezonas.</string>
@@ -403,11 +409,13 @@
<string name="maxim_leshchenko_task">UI-plibonigoj kaj ĉi tiu pri paĝo</string>
<string name="holger_kaelberer_task">Fora klavara kromaĵo kaj korektoj de cimoj</string>
<string name="saikrishna_arcot_task">Subteno por uzi la klavaron en la fora eniga kromaĵo, korektoj de cimoj kaj ĝeneralaj plibonigoj</string>
<string name="shellwen_chen_task">Plibonigi la sekurecon de SFTP, plibonigi la funkciteneblon de ĉi projekto, cimkorektoj kaj ĝeneralaj plibonigoj</string>
<string name="everyone_else">Ĉiuj aliaj, kiuj kontribuis al KDE Connect tra la jaroj</string>
<string name="send_clipboard">Sendi tondujon</string>
<string name="tap_to_execute">Frapi por plenumi</string>
<string name="plugin_stats">Statistiko de kromprogramoj</string>
<string name="enable_udp_broadcast">Ebligi UDP-aparatan malkovron</string>
<string name="enable_bluetooth">Ŝalti bluetooth (beta)</string>
<string name="receive_notifications_permission_explanation">Sciigoj devas esti permesitaj ricevi ilin de aliaj aparatoj</string>
<string name="findmyphone_notifications_explanation">La sciiga permeso estas necesa por ke la telefono povu sonori kiam la app estas en la fono</string>
<string name="no_notifications">Sciigoj estas malŝaltitaj, vi ne ricevos alvenantajn parajn sciigojn.</string>
@@ -415,4 +423,9 @@
<string name="mpris_keepwatching_settings_title">Daŭrigi ludadon</string>
<string name="mpris_keepwatching_settings_summary">Montri silentan sciigon por daŭrigi ludadon en ĉi tiu aparato post fermo de datumportilo</string>
<string name="notification_channel_keepwatching">Daŭrigi ludadon</string>
<string name="ping_result">Eĥosondis en %1$d milisekundoj</string>
<string name="ping_failed">Ne eblis eĥosondi aparaton</string>
<string name="ping_in_progress">Eĥosondante…</string>
<string name="device_host_invalid">Gastiganto estas nevalida. Uzu validan gastigantnomon, IPv4, aŭ IPv6</string>
<string name="device_host_duplicate">Gastiganto jam ekzistas en la listo</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">No se encuentra el dispositivo</string>
<string name="error_already_paired">Dispositivo ya vinculado</string>
<string name="error_timed_out">Se ha agotado el tiempo</string>
<string name="error_clocks_not_match">Los relojes de los dispositivos no están sincronizados</string>
<string name="error_canceled_by_user">Cancelado por el usuario</string>
<string name="error_canceled_by_other_peer">Cancelado por la otra parte</string>
<string name="encryption_info_title">Información de cifrado</string>
@@ -192,11 +193,13 @@
<string name="share_to">Compartir con...</string>
<string name="unreachable_device">%s (no accesible)</string>
<string name="unreachable_device_url_share_text">Las URLs compartidas con dispositivos no accesibles se entregarán una vez que vuelvan a estar accesibles.\n\n</string>
<string name="protocol_version">Versión del protocolo:</string>
<string name="protocol_version_newer">Este dispositivo usa una versión más reciente del protocolo</string>
<string name="plugin_settings_with_name">Preferencias de %s</string>
<string name="invalid_device_name">Nombre de dispositivo no válido</string>
<string name="shareplugin_text_saved">Texto recibido y guardado en el portapapeles</string>
<string name="custom_devices_settings">Lista de dispositivos personalizada</string>
<string name="custom_devices_settings_summary">%d dispositivos añadidos manualmente</string>
<string name="custom_device_list">Añadir dispositivos por IP</string>
<string name="custom_device_deleted">Dispositivo personalizado borrado</string>
<string name="custom_device_list_help">Si su dispositivo no es detectado automáticamente puede añadir su dirección IP o nombre pulsando el botón de acción flotante</string>
@@ -326,7 +329,7 @@
<string name="empty_trusted_networks_list_text">No ha añadido ninguna red confiable de momento</string>
<string name="allow_all_networks_text">Permitir todas</string>
<string name="location_permission_needed_title">Permisos requeridos</string>
<string name="bluetooth_permission_needed_desc">Añadir permisos Bluetooth para que los dispositivos vinculados por esta tecnología estén disponibles en KDE Connect.</string>
<string name="bluetooth_permission_needed_desc">KDE Connect necesitas permisos para conectar a dispositivos cercanos para mostrar como disponibles en KDE Connect dispositivos vinculados por Bluetooth.</string>
<string name="location_permission_needed_desc">KDE Connect requiere permisos de localización para saber a que red está conectado incluso cuando la aplicación está en segundo plano. Esto es así porque el nombre de las redes WiFi a su alrededor se pueden usar para encontrar su localización, aunque no es esto lo que KDE Connect hace.</string>
<string name="clipboard_android_x_incompat">Android 10 ha eliminado el acceso al portapapeles para todas las aplicaciones. Este complemento se desactivará.</string>
<string name="mpris_open_url">Continuar reproduciendo aquí</string>
@@ -420,4 +423,9 @@
<string name="mpris_keepwatching_settings_title">Continuar reproduciendo</string>
<string name="mpris_keepwatching_settings_summary">Mostrar una notificación silenciosa para continuar reproduciendo en este dispositivo tras cerrar el reproductor.</string>
<string name="notification_channel_keepwatching">Continuar reproduciendo</string>
<string name="ping_result">Conectado en %1$d mili-segundos</string>
<string name="ping_failed">No se pudo contactar con el dispositivo</string>
<string name="ping_in_progress">Conectando</string>
<string name="device_host_invalid">El servidor es inválido. Use un nombre válido de servidor, IPv4 o IPv6</string>
<string name="device_host_duplicate">El servidor ya existe en la lista</string>
</resources>

View File

@@ -197,6 +197,7 @@
<string name="invalid_device_name">Gailuaren izen baliogabea</string>
<string name="shareplugin_text_saved">Testua jaso da, arbelean kopiatu da</string>
<string name="custom_devices_settings">Gailuen zerrenda pertsonalizatua</string>
<string name="custom_devices_settings_summary">%d gailua eskuz gehitu dira</string>
<string name="custom_device_list">Gehitu gailuak IP bidez</string>
<string name="custom_device_deleted">Norberak finkatutako gailua ezabatu da</string>
<string name="custom_device_list_help">Zure gailua ez bada automatikoki detektatzen bere IP helbidea edo ostalari-izena gehitu dezakezu ekintza botoi mugikorrean klik eginez</string>
@@ -326,6 +327,7 @@
<string name="empty_trusted_networks_list_text">Oraindik ez duzu gehitu konfiantza duen sarerik</string>
<string name="allow_all_networks_text">Baimendu guztiak</string>
<string name="location_permission_needed_title">Baimena beharrezkoa da</string>
<string name="bluetooth_permission_needed_desc">KDE Connect-ek hurbileko gailuetara konektatzeko baimena behar du, Bluetooth bidez parekatutako gailuak KDE Connect-en erabilgarri ipintzeko.</string>
<string name="location_permission_needed_desc">KDE Connect-ek konektatuta zauden Wi-Fi sarea zein den jakiteko atzeko planoko kokapen baimena behar du, baita aplikazioa atzeko planoan dagoenean ere. Hori horrela da, zure inguruko Wi-Fi sareen izenak zure kokalekua aurkitzeko erabil daitezkeelako, nahiz eta hori ez izan KDE Connect-ek egiten duena.</string>
<string name="clipboard_android_x_incompat">Android 10ek arbela atzitzeko aukera kendu die aplikazio guztiei. Plugin hau desgaitu egingo da.</string>
<string name="mpris_open_url">Jarraitu hemen jotzen</string>
@@ -419,4 +421,9 @@
<string name="mpris_keepwatching_settings_title">Jarraitu jotzen</string>
<string name="mpris_keepwatching_settings_summary">Hedabidea itxi ondoren, gailu honetan jotzen jarraitzeko jakinarazpen ixil bat erakutsi.</string>
<string name="notification_channel_keepwatching">Jarraitu jotzen</string>
<string name="ping_result">«Ping» %1$d milisegundotan egin da</string>
<string name="ping_failed">Ezin izan dio gailuari «ping» egin</string>
<string name="ping_in_progress">«Ping» egiten...</string>
<string name="device_host_invalid">Ostalaria baliogabea da. Erabili balio duen ostalari-izen bat, IPv4, edo IPv6</string>
<string name="device_host_duplicate">Ostalaria jada zerrendan dago</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">Laite tavoittamattomissa</string>
<string name="error_already_paired">Laite on jo kytketty pariksi</string>
<string name="error_timed_out">Aikakatkaisu</string>
<string name="error_clocks_not_match">Laitteiden kelloja ei ole tahdistettu</string>
<string name="error_canceled_by_user">Käyttäjä perui</string>
<string name="error_canceled_by_other_peer">Vertaiskäyttäjä perui</string>
<string name="encryption_info_title">Salaustiedot</string>
@@ -122,6 +123,7 @@
<string name="remote_device_fingerprint">Etälaitteen varmenteen SHA256-sormenjälki on:</string>
<string name="pair_requested">Paripyyntö</string>
<string name="pair_succeeded">Paritus onnistui</string>
<string name="pairing_request_from">Parituspyyntö laitteesta ”%1s”</string>
<plurals name="incoming_file_title">
<item quantity="one">Vastaanotetaan %1$d tiedosto lähettäjältä %2$s</item>
<item quantity="other">Vastaanotetaan %1$d tiedostoa lähettäjältä %2$s</item>
@@ -188,11 +190,16 @@
<string name="mpris_notifications_explanation">Ilmoituskäyttöoikeus vaaditaan etämedian näyttämiseksi ilmoitussovelmassa</string>
<string name="mpris_notification_settings_title">Näytä mediasäädinilmoitukset</string>
<string name="mpris_notification_settings_summary">Sallii mediasoitintesi hallinnan KDE Connectia avaamatta</string>
<string name="share_to">Jaa…</string>
<string name="unreachable_device">%s (tavoittamattomissa)</string>
<string name="unreachable_device_url_share_text">Tavoittamattomissa olevalle laitteelle jaetut verkko-osoitteet välitetään heti kun laite tavoitetaan.\n\n</string>
<string name="protocol_version">Yhteyskäytäntöversio:</string>
<string name="protocol_version_newer">Laite käyttää uudempaa yhteyskäytäntöversiota</string>
<string name="plugin_settings_with_name">%s-asetukset</string>
<string name="invalid_device_name">Virheellinen laitenimi</string>
<string name="shareplugin_text_saved">Vastaanotettiin tekstiä, tallennettiin leikepöydälle</string>
<string name="custom_devices_settings">Omien laitteiden luettelo</string>
<string name="custom_devices_settings_summary">Käyttäjä lisäsi %d laitetta</string>
<string name="custom_device_list">Lisää laitteita IP:llä</string>
<string name="custom_device_deleted">Poistettiin mukautettu laite</string>
<string name="custom_device_list_help">Ellei laitetta tunnisteta automaattisesti, sen IP-osoitteen tai konenimen voi lisätä napsauttamalla kelluvaa toimintopainiketta</string>
@@ -322,6 +329,7 @@
<string name="empty_trusted_networks_list_text">Luotettuja verkkoja ei ole vielä lisätty</string>
<string name="allow_all_networks_text">Salli kaikki</string>
<string name="location_permission_needed_title">Käyttöoikeus vaaditaan</string>
<string name="bluetooth_permission_needed_desc">KDE Connect vaatii oikeuden yhdistää lähellä oleviin laitteisiin, jotta voisi kytkeä niitä Bluetoothilla pariksi.</string>
<string name="location_permission_needed_desc">KDE Connect tarvitsee taustasijaintioikeudet tietääkseen myös sovelluksen olleessa taustalla, mihin langattomaan verkkoon on kirjauduttu. Ympärilläsi olevien langattomien verkkojen nimiä voi käyttää sijaintisi selvittämiseen, vaikka KDE Connect ei tietoa siihen käytäkään.</string>
<string name="clipboard_android_x_incompat">Android 10 on poistanut kaikkien sovellusten leikepöytäkäytön. Liitännäinen poistetaan käytöstä.</string>
<string name="mpris_open_url">Jatka toistoa tästä</string>
@@ -385,6 +393,8 @@
<string name="send_compose">Lähetä</string>
<string name="compose_send_title">Kirjoita teksti</string>
<string name="open_compose_send">Kirjoita teksti</string>
<string name="double_tap_to_drag">Vedä kaksoisnapauttamalla</string>
<string name="hold_to_drag">Vedä pitämällä pohjassa</string>
<string name="about_kde_about">&lt;h1&gt;Tietoa&lt;/h1&gt; &lt;p&gt;KDE on ohjelmoijien, taiteilijoiden, kirjoittajien, kääntäjien ja muiden sisällönluojien kansainvälinen yhteisö, joka on sitoutunut &lt;a href=https://www.gnu.org/philosophy/free-sw.html&gt;vapaiden ohjelmien&lt;/a&gt; kehitykseen. KDE tuottaa Plasma-työpöytäympäristöä, satoja sovelluksia ja monia niitä tukevia ohjelmakirjastoja.&lt;/p&gt; &lt;p&gt;KDE pyrkii yhteistyöhön: mikään yksittäinen toimija ei hallitse sen suuntaa tai tuotteita, vaan teemme yhdessä työtä yhteisen päämäärän hyväksi: tuottaaksemme maailman hienointa vapaata ohjelmistoa. Kaikki ovat tervetulleita &lt;a href=https://community.kde.org/Get_Involved&gt;liittymään ja avustamaan&lt;/a&gt; KDE:ta myös sinä.&lt;/p&gt; Sivulta &lt;a href=https://www.kde.org/&gt;https://www.kde.org/&lt;/a&gt; löytyy KDE-yhteisöstä ja tuottamistamme ohjelmista lisätietoa.</string>
<string name="about_kde_report_bugs_or_wishes">&lt;h1&gt;Ilmoita ohjelmavirheistä tai -toiveista&lt;/h1&gt; &lt;p&gt;Ohjelmia voi aina parantaa, ja KDE-yhteisö on siihen valmis. Sinun käyttäjän on kuitenkin kerrottava meille, kun jokin ei toimi odotetusti tai voisi toimia paremmin.&lt;/p&gt; &lt;p&gt;KDE:lla on virheenseurantajärjestelmä. Käy sivulla &lt;a href=https://bugs.kde.org/&gt;https://bugs.kde.org/&lt;/a&gt; tai käytä Tietoa-sivun painiketta ”Ilmoita ohjelmavirheestä”.&lt;/p&gt; Parannusehdotuksissakin olet tervetullut käyttämään virheenseurantajärjestelmää kirjataksesi toiveesi. Varmista, että käytät vakavuustasoa ”Wishlist”.</string>
<string name="about_kde_join_kde">&lt;h1&gt;Liity KDE:hen&lt;/h1&gt; &lt;p&gt;KDE-työryhmän jäseneksi tullakseen ei tarvitse olla ohjelmoija. Ohjelmien käyttöliittymien kääntämiseksi voi liittyä johonkin kansalliseen ryhmään, tuottaa grafiikkaa, teemoja tai ääniä tai parantaa ohjeistusta. Sinä päätät!&lt;/p&gt; &lt;p&gt;Sivulta &lt;a href=https://community.kde.org/Get_Involved&gt;https://community.kde.org/Get_Involved&lt;/a&gt; löytyy tietoa projekteista, joihin osallistua.&lt;/p&gt; Kaikki tarvittava lisätieto ja ohjeet löytyvät sivulta &lt;a href=https://techbase.kde.org/&gt;https://techbase.kde.org/&lt;/a&gt;.</string>
@@ -399,12 +409,23 @@
<string name="maxim_leshchenko_task">Käyttöliittymäparannukset ja tämä tietosivu</string>
<string name="holger_kaelberer_task">Etänäppäimistöliitännäinen ja virheenkorjaukset</string>
<string name="saikrishna_arcot_task">Tuki näppäimistön käytölle etäsyöteliitännäisessä, virheenkorjaukset ja yleisparannukset</string>
<string name="shellwen_chen_task">Parantaa SFTP:n tietoturvaa ja tämän projektin ylläpidettävyyttä, korjaa virheitä ja yleisesti parantaa asioita</string>
<string name="everyone_else">Kaikki muut vuosien varrella KDE Connectia avustaneet</string>
<string name="send_clipboard">Lähetä leikepöytä</string>
<string name="tap_to_execute">Suorita napauttamalla</string>
<string name="plugin_stats">Liitännäisen tilastot</string>
<string name="enable_udp_broadcast">Käytä UDP-laitehakua</string>
<string name="enable_bluetooth">Käytä Bluetoothia (beeta)</string>
<string name="receive_notifications_permission_explanation">Ilmoitukset tulee sallia, jotta niitä voi vastaanottaa muilta laitteilta</string>
<string name="findmyphone_notifications_explanation">Ilmoituskäyttöoikeus vaaditaan, jotta puhelin voisi soida sovelluksen toimiessa taustalla</string>
<string name="no_notifications">Ilmoitukset eivät ole käytössä, joten paritusilmoituksia ei vastaanoteta.</string>
<string name="mpris_keepwatching">Jatka toistoa</string>
<string name="mpris_keepwatching_settings_title">Jatka toistoa</string>
<string name="mpris_keepwatching_settings_summary">Näytä hiljainen ilmoitus toiston jatkamisesta laitteella median sulkeuduttua</string>
<string name="notification_channel_keepwatching">Jatka toistoa</string>
<string name="ping_result">Pingattiin %1$d millisekunnissa</string>
<string name="ping_failed">Laitetta ei voitu pingata</string>
<string name="ping_in_progress">Pingataan…</string>
<string name="device_host_invalid">Konenimi on virheellinen. Käytä kelvollista konenimeä tai IPv4- tai IPv6-osoitetta.</string>
<string name="device_host_duplicate">Konenimi löytyy jo luettelosta</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">Périphérique inaccessible</string>
<string name="error_already_paired">Périphérique déjà associé</string>
<string name="error_timed_out">Délai expiré</string>
<string name="error_clocks_not_match">Les horloges du périphérique ne sont pas synchronisées.</string>
<string name="error_canceled_by_user">Annulé par l\'utilisateur</string>
<string name="error_canceled_by_other_peer">Annulé par un autre homologue</string>
<string name="encryption_info_title">Informations de chiffrement</string>
@@ -164,9 +165,11 @@
<string name="middle_click">Envoyer un clic central</string>
<string name="show_keyboard">Afficher le clavier</string>
<string name="device_not_paired">Périphérique non associé</string>
<string name="pairing_duplicate_names">Attention : Il existe plusieurs périphériques portant le même nom.</string>
<string name="request_pairing">Demande d\'association</string>
<string name="pairing_accept">Accepter</string>
<string name="pairing_reject">Rejeter</string>
<string name="pairing_explanation">L\'association de deux périphériques leur donnera un accès réciproque. Veuillez n\'associer que vos propres périphériques.</string>
<string name="settings">Configuration</string>
<string name="mpris_play">Lire</string>
<string name="mpris_pause">Pause</string>
@@ -191,12 +194,15 @@
<string name="mpris_notification_settings_summary">Vous permet de contrôler vos lecteurs multimédia sans ouvrir KDEConnect.</string>
<string name="share_to">Partager vers…</string>
<string name="unreachable_device">%s (Inaccessible)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">Les URL partagées vers un appareil inaccessible lui seront transmises une fois qu\'il re-deviendra accessible.\n\n</string>
<string name="protocol_version">Version de protocole :</string>
<string name="protocol_version_newer">Le périphérique utilise une version plus récente du protocole</string>
<string name="plugin_settings_with_name">Configuration %s</string>
<string name="invalid_device_name">Nom de périphérique non valable</string>
<string name="shareplugin_text_saved">Texte reçu et enregistré dans le presse-papiers</string>
<string name="custom_devices_settings">Liste personnalisée de périphériques</string>
<string name="custom_devices_settings_summary">%d périphériques ajoutés de façon manuelle</string>
<string name="custom_device_list">Ajouter des périphériques par IP</string>
<string name="custom_device_deleted">Périphérique personnalisé supprimé</string>
<string name="custom_device_list_help">Si votre périphérique n\'est pas détecté automatiquement, vous pouvez ajouter son adresse IP ou son nom d\'hôte en cliquant sur le bouton d\'action flottant</string>
@@ -306,6 +312,8 @@
<string name="devices">Périphériques</string>
<string name="settings_rename">Nom du périphérique</string>
<string name="settings_dark_mode">Thème sombre</string>
<string name="settings_export_logs">Exporter les journaux de KDEConnect</string>
<string name="settings_export_logs_text">Générez un fichier avec des informations d\'exécution pouvant aider à résoudre les problèmes.</string>
<string name="settings_more_settings_title">Plus de paramètres</string>
<string name="settings_more_settings_text">Les paramètres par appareil sont disponibles dans la rubrique « Paramètres des modules externes » sur l\'appareil.</string>
<string name="setting_persistent_notification">Afficher une notification persistante</string>
@@ -326,7 +334,7 @@
<string name="empty_trusted_networks_list_text">Vous n\'avez pas encore ajouté de réseau de confiance</string>
<string name="allow_all_networks_text">Tout autoriser</string>
<string name="location_permission_needed_title">Permissions requises</string>
<string name="bluetooth_permission_needed_desc">Accordez des autorisations « Bluetooth » pour que les appareils couplés à l\'aide de Bluetooth soient disponibles dans KDEConnect.</string>
<string name="bluetooth_permission_needed_desc">KDEConnect a besoin d\'autorisations pour se connecter aux périphériques proches afin que les périphériques couplés à l\'aide de Bluetooth soient disponibles dans KDEConnect.</string>
<string name="location_permission_needed_desc">KDEConnect a besoin de la permission d\'accéder à la localisation en arrière-plan pour connaître le réseau Wifi sur lequel vous êtes connecté, même si l\'application est en arrière-plan. En effet, le nom des réseaux Wifi autour de vous pourrait être utilisé pour trouver votre emplacement, même si ce n\'est pas ce que KDEConnect fait.</string>
<string name="clipboard_android_x_incompat">Android 10 a supprimé l\'accès des applications au presse-papier. Ce module externe sera désactivé.</string>
<string name="mpris_open_url">Continuer la lecture ici</string>
@@ -420,4 +428,9 @@
<string name="mpris_keepwatching_settings_title">Continuer la lecture</string>
<string name="mpris_keepwatching_settings_summary">Afficher une notification silencieuse pour continuer à jouer sur ce périphérique après la fermeture du média.</string>
<string name="notification_channel_keepwatching">Continuer la lecture</string>
<string name="ping_result">Interrogé en %1$d millisecondes</string>
<string name="ping_failed">Il est impossible d\'interroger un périphérique (Par ping)</string>
<string name="ping_in_progress">Interrogation par ping en cours...</string>
<string name="device_host_invalid">L\'hôte est non valable. Veuillez utiliser un nom d\'hôte valable, IPv4 ou IPv6</string>
<string name="device_host_duplicate">L\'hôte existe déjà dans la liste.</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">O dispositivo está inaccesíbel.</string>
<string name="error_already_paired">O dispositivo xa está emparellado.</string>
<string name="error_timed_out">Esgotouse o tempo límite</string>
<string name="error_clocks_not_match">Os reloxos do dispositivos non están sincronizados.</string>
<string name="error_canceled_by_user">Cancelouno a persoa usuaria.</string>
<string name="error_canceled_by_other_peer">Cancelouse remotamente</string>
<string name="encryption_info_title">Información do cifrado</string>
@@ -192,11 +193,13 @@
<string name="share_to">Compartir con…</string>
<string name="unreachable_device">%s (inaccesíbel)</string>
<string name="unreachable_device_url_share_text">Os URL que se compartan cun dispositivo inaccesíbel entregaranse cando o dispositivo estea accesíbel.\n\n</string>
<string name="protocol_version">Versión do protocolo:</string>
<string name="protocol_version_newer">Este dispositivo usa unha versión máis nova do protocolo.</string>
<string name="plugin_settings_with_name">Configuración de %s</string>
<string name="invalid_device_name">Nome de dispositivo incorrecto</string>
<string name="shareplugin_text_saved">Recibiuse un texto e gardouse no portapapeis</string>
<string name="custom_devices_settings">Lista de dispositivos personalizada</string>
<string name="custom_devices_settings_summary">%d dispositivos engadidos manualmente</string>
<string name="custom_device_list">Engadir dispositivos por IP</string>
<string name="custom_device_deleted">Eliminouse o dispositivo personalizado</string>
<string name="custom_device_list_help">Se o seu dispositivo non se detecta automaticamente pode engadir o seu enderezo IP ou nome de máquina premendo o botón flotante de acción</string>
@@ -326,6 +329,7 @@
<string name="empty_trusted_networks_list_text">Aínda non engadiu ningunha rede de confianza</string>
<string name="allow_all_networks_text">Permitilas todas</string>
<string name="location_permission_needed_title">Require permiso</string>
<string name="bluetooth_permission_needed_desc">KDE Connect require permisos para conectarse a dispositivos próximos para poñer dispositivos emparellados mediante Bluetooth a disposición de KDE Connect.</string>
<string name="location_permission_needed_desc">KDE Connect necesita o permiso de localización en segundo planto para saber a que rede WiFi se conectou incluso cando a aplicación está en segundo plano. Isto é porque o nome das redes WiFi ao redor seu podería usarse para descubrir a súa localización, aínda que KDE Connect non faga tal cousa.</string>
<string name="clipboard_android_x_incompat">Android 10 retirou o acceso ao portapapeis a todas as aplicacións. Desactivarase este complemento.</string>
<string name="mpris_open_url">Continuar reproducindo aquí</string>
@@ -419,4 +423,9 @@
<string name="mpris_keepwatching_settings_title">Continuar reproducindo</string>
<string name="mpris_keepwatching_settings_summary">Amosar unha notificación silenciosa para continuar reproducindo neste dispositivo tras pechar o contido multimedia.</string>
<string name="notification_channel_keepwatching">Continuar reproducindo</string>
<string name="ping_result">Enviouse un ping en %1$d milisegundos</string>
<string name="ping_failed">Non foi posíbel enviar un ping ao dispositivo.</string>
<string name="ping_in_progress">Enviando un ping…</string>
<string name="device_host_invalid">O servidor non é válido. Use un nome de servidor, enderezo IPv4 ou enderezo IPv6 válido.</string>
<string name="device_host_duplicate">O servidor xa existe na lista.</string>
</resources>

View File

@@ -185,11 +185,14 @@
<string name="mpris_notification_settings_summary">Gerir kleift að stýra margmiðlunarspilurunum þínum án þess að opna KDE-tengingar</string>
<string name="share_to">Deila með…</string>
<string name="unreachable_device">%s (ekki aðgengilegt)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="protocol_version">Útgáfa samskiptamáta:</string>
<string name="protocol_version_newer">Þetta tæki notar nýrri útgáfu samskiptastaðals</string>
<string name="plugin_settings_with_name">Stillingar %s</string>
<string name="invalid_device_name">Ógilt heiti tækis</string>
<string name="shareplugin_text_saved">Tók við texta, vistaði á klippispjald</string>
<string name="custom_devices_settings">Listi yfir sérsniðin tæki</string>
<string name="custom_devices_settings_summary">%d tækjum bætt við handvirkt</string>
<string name="custom_device_list">Bæta við tækjum eftir auðkennum</string>
<string name="custom_device_deleted">Sérsniðnu tæki eytt</string>
<string name="custom_device_fab_hint">Bæta við tæki</string>
@@ -279,6 +282,7 @@
<string name="devices">Tæki</string>
<string name="settings_rename">Heiti tækis</string>
<string name="settings_dark_mode">Dökkt þema</string>
<string name="settings_export_logs">Flytja út atvikaskrár KDE Connect</string>
<string name="settings_more_settings_title">Fleiri stillingar</string>
<string name="setting_persistent_notification">Birta viðvarandi tilkynningu</string>
<string name="setting_persistent_notification_oreo">Viðvarandi tilkynning</string>
@@ -380,4 +384,7 @@
<string name="mpris_keepwatching">Halda áfram spilun</string>
<string name="mpris_keepwatching_settings_title">Halda áfram spilun</string>
<string name="notification_channel_keepwatching">Halda áfram spilun</string>
<string name="ping_failed">Gat ekki pikkað í tæki</string>
<string name="device_host_invalid">Ógilt vélarheiti. Notaðu gilt vélarheiti, IPv4 eða IPv6</string>
<string name="device_host_duplicate">Hýsivélin er nú þegar á listanum</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">Dispositivo fuori portata</string>
<string name="error_already_paired">Dispositivo già associato</string>
<string name="error_timed_out">Richiesta scaduta</string>
<string name="error_clocks_not_match">Gli orologi dei dispositivi non sono sincronizzati</string>
<string name="error_canceled_by_user">Annullata dall\'utente</string>
<string name="error_canceled_by_other_peer">Annullata dal dispositivo remoto</string>
<string name="encryption_info_title">Informazioni di cifratura</string>
@@ -164,9 +165,11 @@
<string name="middle_click">Invia clic tasto centrale</string>
<string name="show_keyboard">Mostra tastiera</string>
<string name="device_not_paired">Dispositivo non associato</string>
<string name="pairing_duplicate_names">Attenzione: ci sono più dispositivi con lo stesso nome.</string>
<string name="request_pairing">Richiedi associazione</string>
<string name="pairing_accept">Accetta</string>
<string name="pairing_reject">Rifiuta</string>
<string name="pairing_explanation">L\'associazione di due dispositivi consentirà loro l\'accesso reciproco. Associa solo i tuoi dispositivi.</string>
<string name="settings">Impostazioni</string>
<string name="mpris_play">Riproduci</string>
<string name="mpris_pause">Pausa</string>
@@ -191,12 +194,15 @@
<string name="mpris_notification_settings_summary">Consenti di controllare i lettori multimediali senza aprire KDE Connect</string>
<string name="share_to">Condividi con…</string>
<string name="unreachable_device">%s (non raggiungibile)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">Gli URL condivisi su un dispositivo irraggiungibile saranno recapitati una volta che sarà tornato raggiungibile.\n\n</string>
<string name="protocol_version">Versione del protocollo:</string>
<string name="protocol_version_newer">Questo dispositivo usa una nuova versione del protocollo di rete</string>
<string name="plugin_settings_with_name">Impostazioni di %s</string>
<string name="invalid_device_name">Nome dispositivo non valido</string>
<string name="shareplugin_text_saved">Testo ricevuto, salvato negli appunti</string>
<string name="custom_devices_settings">Elenco dispositivi personalizzati</string>
<string name="custom_devices_settings_summary">%d dispositivi aggiunti manualmente</string>
<string name="custom_device_list">Aggiungi dispositivi per IP</string>
<string name="custom_device_deleted">Dispositivo personalizzato eliminato</string>
<string name="custom_device_list_help">Se il tuo dispositivo non è rilevato automaticamente, puoi aggiungere il suo indirizzo IP o il nome host facendo clic sul pulsante Azione</string>
@@ -306,6 +312,8 @@
<string name="devices">Dispositivi</string>
<string name="settings_rename">Nome dispositivo</string>
<string name="settings_dark_mode">Tema scuro</string>
<string name="settings_export_logs">Esporta i registri di KDE Connect</string>
<string name="settings_export_logs_text">Genera un file con informazioni di esecuzione che possono aiutare a risolvere i problemi.</string>
<string name="settings_more_settings_title">Altre impostazioni</string>
<string name="settings_more_settings_text">Le impostazioni per dispositivo sono disponibili sotto «Impostazioni estensioni» dall\'interno del dispositivo.</string>
<string name="setting_persistent_notification">Mostra notifica persistente</string>
@@ -326,7 +334,7 @@
<string name="empty_trusted_networks_list_text">Non hai aggiunto ancora alcuna rete affidabile</string>
<string name="allow_all_networks_text">Consenti tutte</string>
<string name="location_permission_needed_title">Permesso richiesto</string>
<string name="bluetooth_permission_needed_desc">Concedi i permessi Bluetooth per rendere disponibili in KDE Connect i dispositivi associati tramite Bluetooth.</string>
<string name="bluetooth_permission_needed_desc">KDE Connect necessita dell\'autorizzazione per connettersi ai dispositivi nelle vicinanze per rendere disponibili in KDE Connect i dispositivi associati tramite Bluetooth.</string>
<string name="location_permission_needed_desc">KDE Connect necessita dell\'autorizzazione alla posizione in background per conoscere la rete Wi-Fi a cui sei connesso anche quando l\'applicazione è in esecuzione sullo sfondo. Questo perché il nome delle reti Wi-Fi nelle tue vicinanze potrebbe essere utilizzata per trovare la tua posizione, anche se questo non è un utilizzo previsto da KDE Connect.</string>
<string name="clipboard_android_x_incompat">Android 10 ha rimosso l\'accesso agli appunti a tutte le applicazioni. Questa estensione sarà disabilitata.</string>
<string name="mpris_open_url">Continua qui la riproduzione</string>
@@ -420,4 +428,9 @@
<string name="mpris_keepwatching_settings_title">Continua la riproduzione</string>
<string name="mpris_keepwatching_settings_summary">Mostra una notifica silenziosa per continuare a giocare su questo dispositivo dopo aver chiuso il supporto multimediale</string>
<string name="notification_channel_keepwatching">Continua la riproduzione</string>
<string name="ping_result">Ping effettuato in %1$d millisecondi</string>
<string name="ping_failed">Impossibile effettuare il ping del dispositivo</string>
<string name="ping_in_progress">Ping in corso…</string>
<string name="device_host_invalid">L\'host non è valido. Utilizza un nome host valido, IPv4 o IPv6</string>
<string name="device_host_duplicate">L\'host esiste già nell\'elenco</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">המכשיר לא זמין</string>
<string name="error_already_paired">המכשיר כבר מצומד</string>
<string name="error_timed_out">נגמר הזמן</string>
<string name="error_clocks_not_match">שעוני המכשירים לא תואמים</string>
<string name="error_canceled_by_user">בוטל על ידי המשתמש</string>
<string name="error_canceled_by_other_peer">בוטל מהצד השני</string>
<string name="encryption_info_title">פרטי הצפנה</string>
@@ -180,9 +181,11 @@
<string name="middle_click">שליחת לחיצה אמצעית (גלגלת)</string>
<string name="show_keyboard">הצגת מקלדת</string>
<string name="device_not_paired">המכשיר לא מצומד</string>
<string name="pairing_duplicate_names">אזהרה: יש כמה מכשירים שונים באותו השם.</string>
<string name="request_pairing">בקשת צימוד</string>
<string name="pairing_accept">אישור</string>
<string name="pairing_reject">דחייה</string>
<string name="pairing_explanation">צימוד שני מכשירים יעניק להם גישה מאחד לשני ולהפך. יש לצמד רק אם המכשירים הם שלך.</string>
<string name="settings">הגדרות</string>
<string name="mpris_play">נגינה</string>
<string name="mpris_pause">השהיה</string>
@@ -207,12 +210,15 @@
<string name="mpris_notification_settings_summary">לאפשר שליטה בנגני המדיה שלך מבלי לפתוח את KDE Connect</string>
<string name="share_to">שיתוף אל…</string>
<string name="unreachable_device">%s (לא נגיש)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">כתובות שותפו להתקן בלתי נגיש והן תועברנה אליו ברגע שישוב להיות נגיש.\n\n</string>
<string name="protocol_version">גרסת פרוטוקול:</string>
<string name="protocol_version_newer">המכשיר משתמש בגרסה חדשה יותר</string>
<string name="plugin_settings_with_name">הגדרות %s</string>
<string name="invalid_device_name">שם המכשיר שגוי</string>
<string name="shareplugin_text_saved">התקבל טקסט, נשמר ללוח הגזירים</string>
<string name="custom_devices_settings">רשימת מכשירים מותאמת אישית</string>
<string name="custom_devices_settings_summary">%d התקנים נוספו ידנית</string>
<string name="custom_device_list">הוספת מכשירים לפי IP</string>
<string name="custom_device_deleted">מכשיר מותאם אישית נמחק</string>
<string name="custom_device_list_help">אם המכשיר שלך לא מזוהה אוטומטית אפשר להוסיף את כתובת ה־IP או את שם המארח שלו בלחיצה על כפתור הפעולה הצף</string>
@@ -252,7 +258,7 @@
<string name="pairing_description">מכשירים אחרים שמריצים KDE Connect ברשת הנוכחית צריכים להופיע פה.</string>
<string name="device_rename_title">שינוי שם מכשיר</string>
<string name="device_rename_confirm">שינוי שם</string>
<string name="refresh">רענון</string>
<string name="refresh">ריענון</string>
<string name="unreachable_description">ההתקן המצומד לא זמין, כדאי לוודא שהוא מחובר לאותה רשת כמוך.</string>
<string name="no_wifi">לא התחברת לאף רשת אלחוטית, לכן אין לך אפשרות לראות מכשירים כלשהם. לחיצה כאן תפעיל את הרשת האלחוטית.</string>
<string name="on_non_trusted_message">לא רשת מהימנה: גילוי אוטומטי מושבת.</string>
@@ -322,6 +328,8 @@
<string name="devices">מכשירים</string>
<string name="settings_rename">שם המכשיר</string>
<string name="settings_dark_mode">ערכת עיצוב כהה</string>
<string name="settings_export_logs">ייצוא היומנים של KDE Connect</string>
<string name="settings_export_logs_text">ליצור קובץ עם פרטי הפעלה שיכול לסייע בפתרון תקלות.</string>
<string name="settings_more_settings_title">הגדרות נוספות</string>
<string name="settings_more_settings_text">אפשר למצוא הגדרות נקודתיות למכשיר תחת ‚הגדרות תוסף’ מתוך המכשיר.</string>
<string name="setting_persistent_notification">הצגת התראה קבועה</string>
@@ -342,7 +350,7 @@
<string name="empty_trusted_networks_list_text">עדיין לא הוספת רשתות מהימנות</string>
<string name="allow_all_networks_text">לאפשר הכול</string>
<string name="location_permission_needed_title">נדרשת הרשאה</string>
<string name="bluetooth_permission_needed_desc">יש להעניק גישה לבלוטות׳ כדי שהתקנים שצומדו עם בלוטות׳ יהיו זמינים ב־KDE Connect.</string>
<string name="bluetooth_permission_needed_desc">KDE Connect זקוק להרשאה להתחבר להתקנים קרובים כדי שהתקנים שצומדו עם בלוטות׳ יהיו זמינים ב־KDE Connect.</string>
<string name="location_permission_needed_desc">KDE Connect צריך הרשאת איתור מקום ברקע כדי לדעת לאיזו רשת אלחוטית התחברת, אפילו אם היישום ברקע. מצב זה נחוץ כיוון ששם הרשתות האלחוטיות מסביבך יכולים לשמש לאיתור המקום שלך, אפילו אם זה לא מה ש־KDE Connect תוכנן לעשות.</string>
<string name="clipboard_android_x_incompat">ב־Android 10 הוסרה הגישה ללוח הגזירים לכל היישומונים. התוסף הזה יושבת.</string>
<string name="mpris_open_url">להמשיך לנגן מכאן</string>
@@ -436,4 +444,9 @@
<string name="mpris_keepwatching_settings_title">להמשיך לנגן</string>
<string name="mpris_keepwatching_settings_summary">הצגת התראה שקטה כדי להמשיך לנגן בהתקן הזה לאחר סגירת המדיה</string>
<string name="notification_channel_keepwatching">להמשיך לנגן</string>
<string name="ping_result">הפינג ארך %1$d מילישניות</string>
<string name="ping_failed">לא ניתן לשלוח פינג להתקן</string>
<string name="ping_in_progress">נשלח פינג…</string>
<string name="device_host_invalid">המארח שגוי. נא להשתמש בשם מארח, IPv4 או IPv6 תקניים.</string>
<string name="device_host_duplicate">המארח כבר קיים ברשימה</string>
</resources>

View File

@@ -89,15 +89,12 @@
<string name="error_not_reachable">მოწყობილობა მიუწვდოელია</string>
<string name="error_already_paired">მოწყობილობა უკვე დაწყვილებულია</string>
<string name="error_timed_out">ვადა გავიდა</string>
<string name="error_clocks_not_match">მოწყობილობის საათების სინქრონიზაცია დარღვეულია</string>
<string name="error_canceled_by_user">გაუქმებულია მომხმარებლის მიერ</string>
<string name="error_canceled_by_other_peer">გაუქმებულია პარტნიორის მიერ</string>
<string name="encryption_info_title">დაშიფვრის ინფორმაცია</string>
<string name="pair_requested">დაწყვილების მოთხოვნა</string>
<string name="pair_succeeded">დაწყვილება წარმატებულია</string>
<plurals name="incoming_files_text">
<item quantity="one">File: %1s</item>
<item quantity="other">(File %2$d of %3$d) : %1$s</item>
</plurals>
<plurals name="outgoing_files_text">
<item quantity="one">ფაილი: %1$s</item>
<item quantity="other">(ფაილი %2$d of %3$d) : %1$s</item>
@@ -134,6 +131,7 @@
</string-array>
<string name="share_to">გაზიარება…</string>
<string name="unreachable_device">%s (მიუწვდომელია)</string>
<string name="protocol_version">პროტოკოლის ვერსია:</string>
<string name="protocol_version_newer">მოწყობილობა პროტოკოლის უფრო ახალ ვერსიას იყენებს</string>
<string name="plugin_settings_with_name">%s-ის მორგება</string>
<string name="invalid_device_name">მოწყობილობის არასწორი სახელი</string>
@@ -217,6 +215,7 @@
<string name="devices">მოწყობილობები</string>
<string name="settings_rename">მოწყობილობის სახელი</string>
<string name="settings_dark_mode">ბნელი თემა</string>
<string name="settings_export_logs">KDE Connect-ის ჟურნალის გატანა</string>
<string name="settings_more_settings_title">მეტი პარამეტრი</string>
<string name="extra_options">დამატებითი პარამეტრები</string>
<string name="privacy_options">კონფიდენციალობის პარამეტრები</string>
@@ -292,4 +291,5 @@
<string name="send_clipboard">ბუფერის გაგზავნა</string>
<string name="tap_to_execute">ქმედების შესასრულებლად დაატყაპუნეთ</string>
<string name="plugin_stats">მოდულის სტატისტიკა</string>
<string name="ping_failed">მოწყობილობა არ იპინგება</string>
</resources>

View File

@@ -108,21 +108,22 @@
<string name="category_not_paired_devices">사용 가능한 장치</string>
<string name="category_remembered_devices">기억하는 장치</string>
<string name="device_menu_plugins">플러그인 설정</string>
<string name="device_menu_unpair">연결 해제</string>
<string name="pair_new_device">새 장치 연결</string>
<string name="device_menu_unpair">페어링 해제</string>
<string name="pair_new_device">새 장치 페어링</string>
<string name="cancel_pairing">페어링 취소</string>
<string name="unknown_device">알 수 없는 장치</string>
<string name="error_not_reachable">장치에 접근할 수 없음</string>
<string name="error_already_paired">장치가 이미 연결</string>
<string name="error_already_paired">장치가 이미 페어링</string>
<string name="error_timed_out">시간 초과됨</string>
<string name="error_clocks_not_match">장치 시계가 맞지 않음</string>
<string name="error_canceled_by_user">사용자가 취소함</string>
<string name="error_canceled_by_other_peer">다른 쪽에서 취소함</string>
<string name="encryption_info_title">암호화 정보</string>
<string name="my_device_fingerprint">내 장치 인증서의 SHA256 지문:</string>
<string name="remote_device_fingerprint">원격 장치 인증서의 SHA256 지문:</string>
<string name="pair_requested">연결 요청됨</string>
<string name="pair_succeeded">연결 성공</string>
<string name="pairing_request_from">\'%1s\'에서 연결 요청</string>
<string name="pair_requested">페어링 요청됨</string>
<string name="pair_succeeded">페어링 성공</string>
<string name="pairing_request_from">\'%1s\'에서 페어링 요청</string>
<plurals name="incoming_file_title">
<item quantity="other">%2$s에서 보낸 파일 %1$d개 받음</item>
</plurals>
@@ -155,10 +156,12 @@
<string name="right_click">오른쪽 단추 클릭 신호 보내기</string>
<string name="middle_click">가운데 단추 클릭 신호 보내기</string>
<string name="show_keyboard">키보드 표시</string>
<string name="device_not_paired">장치가 연결되지 않음</string>
<string name="request_pairing">연결 요청</string>
<string name="device_not_paired">장치가 페어링되지 않음</string>
<string name="pairing_duplicate_names">경고: 이름이 같은 장치가 여러 대 있습니다.</string>
<string name="request_pairing">페어링 요청</string>
<string name="pairing_accept">수락</string>
<string name="pairing_reject">거부</string>
<string name="pairing_explanation">두 장치를 페어링하면 서로간의 접근을 허용합니다. 내 장치끼리만 페어링하십시오.</string>
<string name="settings">설정</string>
<string name="mpris_play">재생</string>
<string name="mpris_pause">일시 정지</string>
@@ -183,12 +186,15 @@
<string name="mpris_notification_settings_summary">KDE Connect를 열지 않고 미디어 재생기 제어</string>
<string name="share_to">다음으로 공유…</string>
<string name="unreachable_device">%s(접근할 수 없음)</string>
<string name="unreachable_device_dynamic_shortcut">%s(✕)</string>
<string name="unreachable_device_url_share_text">접근할 수 없는 장치와 공유한 URL은 장치에 다시 접근할 수 있게 될 때 전달됩니다.\n\n</string>
<string name="protocol_version">프로토콜 버전:</string>
<string name="protocol_version_newer">이 장치의 프로토콜 버전이 더 새롭습니다</string>
<string name="plugin_settings_with_name">%s 설정</string>
<string name="invalid_device_name">잘못된 장치 이름</string>
<string name="shareplugin_text_saved">텍스트 수신, 클립보드에 복사됨</string>
<string name="custom_devices_settings">사용자 정의 장치 목록</string>
<string name="custom_devices_settings_summary">장치 %d개를 수동으로 추가함</string>
<string name="custom_device_list">IP로 장치 추가</string>
<string name="custom_device_deleted">사용자 정의 장치 삭제됨</string>
<string name="custom_device_list_help">장치가 자동으로 감지되지 않았다면 떠 다니는 동작 단추를 클릭해서 IP 주소나 호스트 이름으로 장치를 수동으로 추가할 수 있습니다</string>
@@ -229,7 +235,7 @@
<string name="device_rename_title">장치 이름 바꾸기</string>
<string name="device_rename_confirm">이름 바꾸기</string>
<string name="refresh">새로 고침</string>
<string name="unreachable_description">연결된 장치에 접근할 수 없습니다. 같은 네트워크에 있는지 확인하십시오.</string>
<string name="unreachable_description">페어링된 장치에 접근할 수 없습니다. 같은 네트워크에 있는지 확인하십시오.</string>
<string name="no_wifi">Wi-Fi 네트워크에 연결된 것 같지 않습니다. 다른 장치를 볼 수 없습니다. 여기를 클릭하면 Wi-Fi를 활성화합니다.</string>
<string name="on_non_trusted_message">신뢰할 수 없는 네트워크: 자동 발견을 비활성화했습니다.</string>
<string name="no_file_browser">설치된 파일 탐색기가 없습니다.</string>
@@ -281,7 +287,7 @@
<string name="copy_url_to_clipboard">클립보드로 URL 복사</string>
<string name="clipboard_toast">클립보드에 복사됨</string>
<string name="runcommand_notreachable">장치에 접근할 수 없음</string>
<string name="runcommand_notpaired">장치가 연결되지 않음</string>
<string name="runcommand_notpaired">장치가 페어링되지 않음</string>
<string name="runcommand_nosuchdevice">장치가 없음</string>
<string name="runcommand_noruncommandplugin">이 장치에서 명령 실행 플러그인이 활성화되어 있지 않음</string>
<string name="runcommand_category_device_controls_title">장치 제어</string>
@@ -298,6 +304,8 @@
<string name="devices">장치</string>
<string name="settings_rename">장치 이름</string>
<string name="settings_dark_mode">어두운 테마</string>
<string name="settings_export_logs">KDE Connect 로그 내보내기</string>
<string name="settings_export_logs_text">문제 해결을 위해서 실행 정보를 포함하는 파일을 생성합니다.</string>
<string name="settings_more_settings_title">더 많은 설정</string>
<string name="settings_more_settings_text">장치별 설정은 각각 장치의 \'플러그인 설정\'에서 확인할 수 있습니다.</string>
<string name="setting_persistent_notification">항상 표시되는 알림 표시</string>
@@ -318,6 +326,7 @@
<string name="empty_trusted_networks_list_text">신뢰할 수 있는 네트워크를 추가하지 않았습니다</string>
<string name="allow_all_networks_text">모두 허용</string>
<string name="location_permission_needed_title">권한이 필요함</string>
<string name="bluetooth_permission_needed_desc">KDE Connect에서 블루투스를 사용하여 페어링된 장치를 사용하려면 근처 장치에 연결할 수 있는 권한이 필요합니다.</string>
<string name="location_permission_needed_desc">KDE Connect에서 현재 연결된 Wi-Fi 네트워크 정보를 얻으려면 앱이 백그라운드에서 실행 중일 때에도 백그라운드 권한이 필요합니다. KDE Connect에서는 사용자의 위치를 찾지 않지만, 내 주변에 있는 Wi-Fi 네트워크의 이름으로도 위치를 찾을 수 있기 때문입니다.</string>
<string name="clipboard_android_x_incompat">안드로이드 10부터는 앱에서 클립보드에 접근할 수 없습니다. 이 플러그인이 비활성화되었습니다.</string>
<string name="mpris_open_url">여기에서 계속 재생</string>
@@ -381,6 +390,8 @@
<string name="send_compose">보내기</string>
<string name="compose_send_title">텍스트 보내기</string>
<string name="open_compose_send">텍스트 작성</string>
<string name="double_tap_to_drag">두 번 탭하면 드래그</string>
<string name="hold_to_drag">누르고 있으면 드래그</string>
<string name="about_kde_about">&lt;h1&gt;정보&lt;h1&gt; &lt;p&gt;KDE는 &lt;a href=https://www.gnu.org/philosophy/free-sw.html&gt;자유 소프트웨어&lt;/a&gt;를 개발하려고 모인 소프트웨어 개발자, 예술가, 집필가, 번역가 및 기타 인원의 모임입니다. KDE 커뮤니티에서는 Plasma 데스크톱 환경, 다양한 앱 및 지원 라이브러리를 개발합니다.&lt;p&gt; &lt;p&gt;KDE는 협동 조합입니다. 어떠한 단일 집단도 방향이나 제품을 결정하지 않습니다. 우리는 전 세계에서 가장 뛰어난 자유 소프트웨어 개발이라는 공통 목표를 향해 함께 힘을 모으고 있습니다. KDE에는 이 글을 읽는 여러분과 같은 누구나 &lt;a href=https://community.kde.org/Get_Involved&gt;참여하고 기여&lt;/a&gt;할 수 있습니다.&lt;p&gt; &lt;a href=https://www.kde.org/&gt;https://www.kde.org/&lt;/a&gt; 페이지를 방문하셔서 KDE 커뮤니티와 소프트웨어에 대해 알아 보십시오.</string>
<string name="about_kde_report_bugs_or_wishes">"&lt;h1&gt;버그나 요구 사항 보고&lt;/h1&gt; &lt;p&gt;소프트웨어는 항상 개선되며, KDE 팀도 그럴 준비가 되어 있습니다. 따라서 사용자 여러분은 무언가가 예상한 대로 작동하지 않거나 더 잘 작동하기를 바라면 개발자에게 알려 주십시오.&lt;/p&gt; &lt;p&gt;KDE는 버그 추적 시스템을 가지고 있습니다. &lt;a href=https://bugs.kde.org/&gt;https://bugs.kde.org/&lt;/a&gt;를 방문하시거나 \"도움말\" 메뉴의 \"버그 보고...\" 대화 상자를 이용하셔서 버그를 보고해 주십시오.&lt;/p&gt; 개선 사항 제안을 하고 싶으시다면 버그 보고 시스템을 통해서 알려 주십시오. 이 경우 심각성 항목에서 \"Wishlist\"를 선택하셔야 합니다."</string>
<string name="about_kde_join_kde">&lt;h1&gt;KDE에 참여하기&lt;/h1&gt; &lt;p&gt;소프트웨어 개발자만이 KDE에 참가할 수 있는 것은 아닙니다. 프로그램 인터페이스를 번역하는 각 언어 번역팀을 도울 수도 있습니다. 또한 그래픽, 테마, 소리, 더 나은 문서 등을 기여할 수도 있습니다. 직접 결정하십시오!&lt;/p&gt; &lt;p&gt;&lt;a href=https://community.kde.org/Get_Involved&gt;https://community.kde.org/Get_Involved&lt;/a&gt; 페이지를 방문하셔서 참여할 수 있는 프로젝트를 찾아 보십시오.&lt;/p&gt; 만약 더 많은 정보나 문서가 필요하다면, &lt;a href=https://techbase.kde.org/&gt;https://techbase.kde.org/&lt;/a&gt; 사이트를 방문하셔서 원하는 정보를 찾으십시오.</string>
@@ -401,6 +412,7 @@
<string name="tap_to_execute">실행하려면 누르십시오</string>
<string name="plugin_stats">플러그인 통계</string>
<string name="enable_udp_broadcast">UDP 서비스 발견 활성화</string>
<string name="enable_bluetooth">블루투스 활성화(베타)</string>
<string name="receive_notifications_permission_explanation">다른 장치에서 알림을 받으려면 알림을 허용해야 합니다</string>
<string name="findmyphone_notifications_explanation">앱이 백그라운드에서 실행 중일 때 장치를 울리게 하려면 알림 권한이 필요합니다</string>
<string name="no_notifications">알림이 비활성화되어 있습니다. 들어오는 페어링 알림을 받을 수 없습니다</string>
@@ -408,4 +420,9 @@
<string name="mpris_keepwatching_settings_title">계속 재생</string>
<string name="mpris_keepwatching_settings_summary">미디어를 닫은 후 이 장치에서 계속 재생할 수 있는 조용한 알림 표시</string>
<string name="notification_channel_keepwatching">계속 재생</string>
<string name="ping_result">핑 시간: %1$d 밀리초</string>
<string name="ping_failed">장치에 핑을 보낼 수 없음</string>
<string name="ping_in_progress">핑 진행 중…</string>
<string name="device_host_invalid">호스트가 잘못되었습니다. 올바른 호스트 이름, IPv4, IPv6 주소를 지정하십시오</string>
<string name="device_host_duplicate">호스트가 목록에 이미 있음</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">Apparaat niet bereikbaar</string>
<string name="error_already_paired">Apparaat is al gepaard</string>
<string name="error_timed_out">Tijdslimiet overschreden</string>
<string name="error_clocks_not_match">Klokken op apparaten lopen niet gelijk</string>
<string name="error_canceled_by_user">Geannuleerd door gebruiker</string>
<string name="error_canceled_by_other_peer">Geannuleerd door andere kant</string>
<string name="encryption_info_title">Versleutelde informatie</string>
@@ -164,9 +165,11 @@
<string name="middle_click">Verstuur een middelste muisklik</string>
<string name="show_keyboard">Toetsenbord tonen</string>
<string name="device_not_paired">Apparaat is niet gepaard</string>
<string name="pairing_duplicate_names">Voorzichtig: er zijn meerdere apparaten met dezelfde naam.</string>
<string name="request_pairing">Verzoek voor maken van paar</string>
<string name="pairing_accept">Accepteren</string>
<string name="pairing_reject">Afwijzen</string>
<string name="pairing_explanation">Twee apparaten paren zal ze toegang geven tot elkaar. Paar alleen uw eigen apparaten.</string>
<string name="settings">Instellingen</string>
<string name="mpris_play">Afspelen</string>
<string name="mpris_pause">Pauzeren</string>
@@ -191,12 +194,15 @@
<string name="mpris_notification_settings_summary">Staat besturing van uw mediaspelers toe zonder KDE Connect te openen</string>
<string name="share_to">Delen met…</string>
<string name="unreachable_device">%s (niet bereikbaar)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">URL\'s gedeeld met een niet bereikbaar apparaat zullen er afgeleverd worden wanneer deze bereikbaar wordt.\n\n</string>
<string name="protocol_version">Protocolversie:</string>
<string name="protocol_version_newer">Dit apparaat gebruikt een nieuwere protocolversie</string>
<string name="plugin_settings_with_name">Instellingen van %s</string>
<string name="invalid_device_name">Ongeldige apparaatnaam</string>
<string name="shareplugin_text_saved">Oontvangen tekst, opgeslagen op klembord</string>
<string name="custom_devices_settings">Aangepaste lijst apparaten</string>
<string name="custom_devices_settings_summary">%d apparaten handmatig toegevoegd</string>
<string name="custom_device_list">Voeg apparaten toe per IP-adres</string>
<string name="custom_device_deleted">Aangepaste apparaat verwijderd</string>
<string name="custom_device_list_help">Als uw apparaat niet automatisch wordt gedetecteerd kunt u zijn IP-adres of hostnaam toevoegen door te klikken op de knop Zwevende actie</string>
@@ -306,6 +312,8 @@
<string name="devices">Apparaten</string>
<string name="settings_rename">Apparaatnaam</string>
<string name="settings_dark_mode">Donker thema</string>
<string name="settings_export_logs">Logs van KDE Connect exporteren</string>
<string name="settings_export_logs_text">Genereert een bestand met uitvoeringsinformatie die kan helpen problemen op te lossen.</string>
<string name="settings_more_settings_title">Meer instellingen</string>
<string name="settings_more_settings_text">Instellingen per apparaat kunnen gevonden worden onder \'Plug-in-instellingen\' vanuit een apparaat.</string>
<string name="setting_persistent_notification">Blijvende melding tonen</string>
@@ -326,7 +334,7 @@
<string name="empty_trusted_networks_list_text">U hebt nog geen vertrouwd netwerk toegevoegd</string>
<string name="allow_all_networks_text">Allen toestaan</string>
<string name="location_permission_needed_title">Toestemming vereist</string>
<string name="bluetooth_permission_needed_desc">Geeft Bluetooth rechten om apparaten te laten paren met Bluetooth beschikbaar in KDE Connect.</string>
<string name="bluetooth_permission_needed_desc">KDE Connect heeft rechten nodig om te verbinden met apparaten dichtbij om apparaten te laten paren met Bluetooth beschikbaar in KDE Connect.</string>
<string name="location_permission_needed_desc">KDE Connect heeft de permissie achtergrondlocatie nodig om het WiFi-netwerk te weten waarmee u bent verbonden zelfs wanneer de toepassing in de achtergrond is. Dit vanwege dat de naam van de WiFi-netwerken om u heen gebruikt zouden kunnen worden om uw locatie te vinden, zelfs wanneer dit niet is wat KDE Connect doet.</string>
<string name="clipboard_android_x_incompat">Android 10 heeft toegang tot het klembord naar alle toepassingen verwijderd. Deze plug-in zal uitgeschakeld worden.</string>
<string name="mpris_open_url">Hier doorgaan met afspelen</string>
@@ -420,4 +428,9 @@
<string name="mpris_keepwatching_settings_title">Doorgaan met afspelen</string>
<string name="mpris_keepwatching_settings_summary">Een stille melding tonen om door te gaan met afspelen op dit apparaat na sluiten van het medium</string>
<string name="notification_channel_keepwatching">Doorgaan met afspelen</string>
<string name="ping_result">Ping verkregen in %1$d milliseconden</string>
<string name="ping_failed">Kreeg geen antwoord op ping van apparaat</string>
<string name="ping_in_progress">Ping wordt verstuurt</string>
<string name="device_host_invalid">Host is ongeldig. Gebruik een geldige hostnaam, IPv4 of IPv6</string>
<string name="device_host_duplicate">Host bestaat al in de lijst</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">Urządzenie nieosiągalne</string>
<string name="error_already_paired">Urządzenie już sparowano</string>
<string name="error_timed_out">Upłynął czas na odpowiedź</string>
<string name="error_clocks_not_match">Zegary urządzenia nie są zsynchronizowane</string>
<string name="error_canceled_by_user">Użytkownik zaniechał</string>
<string name="error_canceled_by_other_peer">Inny uczestnik zaniechał</string>
<string name="encryption_info_title">Dane o szyfrowaniu</string>
@@ -208,11 +209,13 @@
<string name="share_to">Udostępnij urządzeniu...</string>
<string name="unreachable_device">%s (nieosiągalne)</string>
<string name="unreachable_device_url_share_text">Adres URL udostępniony nieosiągalnemu urządzeniu zostanie do niego dostarczony zaraz po tym jak stanie się osiągalne.\n\n</string>
<string name="protocol_version">Wersja protokołu:</string>
<string name="protocol_version_newer">Urządzenie to używa nowszej wersji protokołu</string>
<string name="plugin_settings_with_name">Ustawienia %s</string>
<string name="invalid_device_name">Nieprawidłowa nazwa urządzenia</string>
<string name="shareplugin_text_saved">Otrzymano tekst, zapisano do schowka</string>
<string name="custom_devices_settings">Lista własnych urządzeń</string>
<string name="custom_devices_settings_summary">%d urządzeń dodanych ręcznie</string>
<string name="custom_device_list">Dodaj urządzenie po adresie IP</string>
<string name="custom_device_deleted">Usunięto własne urządzenie</string>
<string name="custom_device_list_help">Jeśli twoje urządzenie nie zostało wykryte samoczynnie, to możesz dodać je ręcznie po wpisaniu jego adresu IP lub nazwy gospodarza. Aby to zrobić, naciśnij pomarańczowy przycisk u dołu ekranu.</string>
@@ -342,7 +345,7 @@
<string name="empty_trusted_networks_list_text">Nie dodałeś jeszcze żadnej zaufanej sieci</string>
<string name="allow_all_networks_text">Zezwól wszystkim</string>
<string name="location_permission_needed_title">Wymagana zgoda</string>
<string name="bluetooth_permission_needed_desc">Udziel uprawnień do Bluetooth, aby urządzenia sparowane przy jego pomocy były widoczne w KDE Connect.</string>
<string name="bluetooth_permission_needed_desc">KDE Connect wymaga pozwolenia na łączenie do sąsiednich urządzeń, aby urządzenia sparowane przy pomocy Bluetooth były widoczne w KDE Connect.</string>
<string name="location_permission_needed_desc">KDE Connect potrzebuje uprawnień do sprawdzania twojego położenia w tle, aby móc poznać sieć WiFi, do której jesteś podłączony także wtedy, gdy aplikacja działa w tle. Jest tak dlatego, że nazwy sieci WiFi wokół ciebie mogą zostać użyte do ustalenia twojego położenia, mimo że KDE Connect nie robi tego w ten sposób.</string>
<string name="clipboard_android_x_incompat">Android 10 odebrał dostęp do schowka wszystkim programom. Ta wtyczka pozostanie wyłączona.</string>
<string name="mpris_open_url">Kontynuuj odtwarzanie tutaj</string>
@@ -436,4 +439,9 @@
<string name="mpris_keepwatching_settings_title">Kontynuuj odtwarzanie</string>
<string name="mpris_keepwatching_settings_summary">Pokaż ciche powiadomienie, aby kontynuować odtwarzanie na tym urządzeniu po zamknięciu mediów</string>
<string name="notification_channel_keepwatching">Kontynuuj odtwarzanie</string>
<string name="ping_result">Odpowiedział w %1$d milisekund</string>
<string name="ping_failed">Nie można wysłać pingu do urządzenia</string>
<string name="ping_in_progress">Wysyłanie pingu…</string>
<string name="device_host_invalid">Nazwa gospodarza jest nieprawidłowa. Użyj prawidłowej nazwy, adresu IPv4 lub IPv6</string>
<string name="device_host_duplicate">Nazwa gospodarza już znajduje się na liście</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">Naprava ni dosegljiva</string>
<string name="error_already_paired">Naprava je že uparjena</string>
<string name="error_timed_out">Čas je potekel</string>
<string name="error_clocks_not_match">Ure naprave niso sinhronizirane</string>
<string name="error_canceled_by_user">Preklical uporabnik</string>
<string name="error_canceled_by_other_peer">Preklican od drugega vrstnika</string>
<string name="encryption_info_title">Informacija o šifriranju</string>
@@ -130,10 +131,10 @@
<item quantity="other">Prejemanje %1$d datotek od %2$s</item>
</plurals>
<plurals name="incoming_files_text">
<item quantity="one">(Datotek %2$d od %3$d) : %1$s</item>
<item quantity="one">(Datoteka %2$d od %3$d) : %1$s</item>
<item quantity="two">(Datoteka %2$d od %3$d) : %1$s</item>
<item quantity="few">(Datoteki %2$d od %3$d) : %1$s</item>
<item quantity="other">(Datoteke %2$d od %3$d) : %1$s</item>
<item quantity="few">(Datoteka %2$d od %3$d) : %1$s</item>
<item quantity="other">(Datoteka %2$d od %3$d) : %1$s</item>
</plurals>
<plurals name="outgoing_file_title">
<item quantity="one">Pošiljanje %1$d datotek na %2$s</item>
@@ -180,9 +181,11 @@
<string name="middle_click">Pošlji sredinski klik</string>
<string name="show_keyboard">Pokaži tipkovnico</string>
<string name="device_not_paired">Naprava ni uparjena</string>
<string name="pairing_duplicate_names">POZOR: Obstaja več naprav z istim imenom.</string>
<string name="request_pairing">Zahtevaj uparjanje</string>
<string name="pairing_accept">Sprejmi</string>
<string name="pairing_reject">Zavrni</string>
<string name="pairing_explanation">Uparjanje dveh naprav jim bo omogočilo dostop ene do druge. Uparjajte samo svoje lastne naprave.</string>
<string name="settings">Nastavitve</string>
<string name="mpris_play">Predvajaj</string>
<string name="mpris_pause">Premor</string>
@@ -207,12 +210,15 @@
<string name="mpris_notification_settings_summary">Dovoli nadzor nad predvajalniki medijev, ne da bi odprli KDE Connect</string>
<string name="share_to">Deli z…</string>
<string name="unreachable_device">%s (Nedosegljiva)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">URL-ji, ki so v skupni rabi z nedosegljivo napravo, ji bodo dostavljeni, ko postane dosegljiva.\n\n</string>
<string name="protocol_version">Protokol različice:</string>
<string name="protocol_version_newer">Ta naprava uporablja novejšo različico protokola</string>
<string name="plugin_settings_with_name">Nastavitve %s</string>
<string name="invalid_device_name">Neveljavno ime naprave</string>
<string name="shareplugin_text_saved">Prejeto besedilo shranjeno na odložišče</string>
<string name="custom_devices_settings">Seznam naprav po meri</string>
<string name="custom_devices_settings_summary">%d naprav, dodanih ročno</string>
<string name="custom_device_list">Dodaj naprave po IP</string>
<string name="custom_device_deleted">Zbrisana naprava po meri</string>
<string name="custom_device_list_help">Če vaša naprava ni samodejno zaznana, lahko dodate njen IP naslov ali ime gostitelja s klikom na gumb Plavajoče dejanje</string>
@@ -322,6 +328,8 @@
<string name="devices">Naprave</string>
<string name="settings_rename">Ime naprave</string>
<string name="settings_dark_mode">Temna tema</string>
<string name="settings_export_logs">Izvozi dnevnike KDE Connect</string>
<string name="settings_export_logs_text">Ustvari datoteko z informacijami o izvajanju, ki lahko pomagajo pri odpravljanju težav.</string>
<string name="settings_more_settings_title">Več nastavitev</string>
<string name="settings_more_settings_text">Nastavitve posamezne naprave najdete v razdelku \'Nastavitve vtičnikov\' v napravi.</string>
<string name="setting_persistent_notification">Prikazuj trajno obvestilo</string>
@@ -342,7 +350,7 @@
<string name="empty_trusted_networks_list_text">Niste še dodali nobenega zaupanja vrednega omrežja</string>
<string name="allow_all_networks_text">Dovoli vse</string>
<string name="location_permission_needed_title">Zahtevano dovoljenje</string>
<string name="bluetooth_permission_needed_desc">Dodeli dovoljenja za Bluetooth, da bodo naprave, seznanjene z Bluetoothom, na voljo v KDE Connect.</string>
<string name="bluetooth_permission_needed_desc">KDE Connect potrebuje dovoljenje za povezavo z bližnjimi napravami, da bodo naprave, seznanjene z Bluetoothom, na voljo v KDE Connect.</string>
<string name="location_permission_needed_desc">"KDE Connect potrebuje dovoljenje omrežja, da pozna WiFi omrežje, s katerim ste povezani, tudi če je aplikacija v ozadju. To je zato, ker se ime omrežja wifi lahko uporabi za iskanje svoje lokacije, četudi to ne počne KDE Connect."</string>
<string name="clipboard_android_x_incompat">Android 10 je odstranil dostop do odložišča za vse aplikacije. Ta vtičnik bo onemogočen.</string>
<string name="mpris_open_url">Nadaljuj s predvajanjem tukaj</string>
@@ -436,4 +444,9 @@
<string name="mpris_keepwatching_settings_title">Nadaljuj s predvajanjem</string>
<string name="mpris_keepwatching_settings_summary">Pokaži tiho obvestilo za nadaljevanje predvajanja v tej napravi po zaprtju predstavnosti</string>
<string name="notification_channel_keepwatching">Nadaljuj s predvajanjem</string>
<string name="ping_result">Ping-an v %1$d milisekundah</string>
<string name="ping_failed">Ni bilo mogoče pingati naprave</string>
<string name="ping_in_progress">Pinganje…</string>
<string name="device_host_invalid">Gostitelj ni veljaven. Uporabite veljavno ime gostitelja, IPv4 ali IPv6</string>
<string name="device_host_duplicate">Gostitelj že obstaja na seznamu</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">Apparaten kan inte nås</string>
<string name="error_already_paired">Apparat redan parkopplad</string>
<string name="error_timed_out">Tidsgräns överskriden</string>
<string name="error_clocks_not_match">Apparaternas klockor är inte synkroniserade</string>
<string name="error_canceled_by_user">Avbruten av användaren</string>
<string name="error_canceled_by_other_peer">Avbruten av motparten</string>
<string name="encryption_info_title">Krypteringsinformation</string>
@@ -192,11 +193,13 @@
<string name="share_to">Dela med…</string>
<string name="unreachable_device">%s (kan inte nås)</string>
<string name="unreachable_device_url_share_text">Webbadress som delas med en apparat som inte kan nås levereras till den när den väl blir möjlig att nå.\n\n</string>
<string name="protocol_version">Protokollversion:</string>
<string name="protocol_version_newer">Apparaten använder en nyare protokollversion</string>
<string name="plugin_settings_with_name">Inställningar av %s</string>
<string name="invalid_device_name">Ogiltigt apparatnamn</string>
<string name="shareplugin_text_saved">Tog emot text, spara på klippbordet</string>
<string name="custom_devices_settings">Egen apparatlista</string>
<string name="custom_devices_settings_summary">%d apparater manuellt tillagda</string>
<string name="custom_device_list">Lägg till apparater enligt IP-adress</string>
<string name="custom_device_deleted">Egen apparat borttagen</string>
<string name="custom_device_list_help">Om apparaten inte detekteras automatiskt kan dess IP-adress eller värddatornamn läggas till genom att klicka på den lösa åtgärdsknappen.</string>
@@ -326,7 +329,7 @@
<string name="empty_trusted_networks_list_text">Du har inte lagt till några pålitliga nätverk ännu</string>
<string name="allow_all_networks_text">Tillåt alla</string>
<string name="location_permission_needed_title">Rättighet krävs</string>
<string name="bluetooth_permission_needed_desc">Ge Blåtand behörighet att göra apparater som är parkopplade med Bluetooth tillgängliga i KDE-anslut.</string>
<string name="bluetooth_permission_needed_desc">KDE-anslut behöver behörighet för att ansluta till närliggande apparater för att göra apparater som är parkopplade med Blåtand tillgängliga i KDE-anslut.</string>
<string name="location_permission_needed_desc">KDE-anslut behöver rättigheter för bakgrundsplats för att känna till WIFI-nätverket du är ansluten med även när programmet är i bakgrunden. Det beror på att namnen på WIFI-nätverk omkring dig skulle kunna användas för att ta reda på var du befinner dig, även om det inte är vad KDE-anslut gör.</string>
<string name="clipboard_android_x_incompat">Android 10 har tagit bort åtkomst till klippbordet för alla applikationer. Det här insticksprogrammet kommer att inaktiveras.</string>
<string name="mpris_open_url">Fortsätt spela här</string>
@@ -420,4 +423,9 @@
<string name="mpris_keepwatching_settings_title">Fortsätt spela</string>
<string name="mpris_keepwatching_settings_summary">Visa en tyst underrättelse för att fortsätta spela på apparaten efter att media har stängts.</string>
<string name="notification_channel_keepwatching">Fortsätt spela</string>
<string name="ping_result">Skickade paket på %1$d millisekunder</string>
<string name="ping_failed">Kunde inte skicka paket till apparaten</string>
<string name="ping_in_progress">Skickar paket…</string>
<string name="device_host_invalid">Värddatorn är ogiltig. Använd ett giltigt värddatornamn, IPv4 eller IPv6</string>
<string name="device_host_duplicate">Värddatorn finns redan i listan</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">Aygıt ulaşılabilir değil</string>
<string name="error_already_paired">Aygıt zaten eşleşmiş</string>
<string name="error_timed_out">Zaman aşımı</string>
<string name="error_clocks_not_match">Aygıt saatleri eşzamanlı değil</string>
<string name="error_canceled_by_user">Kullanıcı tarafından iptal edildi</string>
<string name="error_canceled_by_other_peer">Diğer eş tarafından iptal edildi</string>
<string name="encryption_info_title">Şifreleme Bilgisi</string>
@@ -129,7 +130,7 @@
</plurals>
<plurals name="incoming_files_text">
<item quantity="one">Dosya: %1s</item>
<item quantity="other">(Dosya %2$d %3$d) : %1$s</item>
<item quantity="other">(Dosya %2$d/%3$d) : %1$s</item>
</plurals>
<plurals name="outgoing_file_title">
<item quantity="one">%1$d dosya %2$s gönderiliyor</item>
@@ -164,9 +165,11 @@
<string name="middle_click">Orta Tık Gönder</string>
<string name="show_keyboard">Klavyeyi Göster</string>
<string name="device_not_paired">Aygıt eşleşmemiş</string>
<string name="pairing_duplicate_names">Dikkat: Aynı adlı birden çok aygıt var.</string>
<string name="request_pairing">Eşleşme isteği</string>
<string name="pairing_accept">Onayla</string>
<string name="pairing_reject">Reddet</string>
<string name="pairing_explanation">İki aygıtı eşleştirmek, onlara birbirlerine erişim hakkını verecektir. Yalnızca kendi aygıtlarınızı eşleştirin.</string>
<string name="settings">Ayarlar</string>
<string name="mpris_play">Oynat</string>
<string name="mpris_pause">Duraklat</string>
@@ -191,12 +194,15 @@
<string name="mpris_notification_settings_summary">KDE Bağlanı açmadan ortam oynatıcılarınızı denetlemenize izin verin</string>
<string name="share_to">Şuraya Paylaş…</string>
<string name="unreachable_device">%s (Erişilebilir değil)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">Erişilemeyen bir aygıta gönderilen URLler, aygıt erişilebilir olduğunda teslim edilir.\n\n</string>
<string name="protocol_version">Protokol sürümü:</string>
<string name="protocol_version_newer">Bu aygıt, daha yeni bir protokol sürümü kullanıyor</string>
<string name="plugin_settings_with_name">%s ayarları</string>
<string name="invalid_device_name">Geçersiz aygıt adı</string>
<string name="shareplugin_text_saved">Gelen ileti, panoya kaydet</string>
<string name="custom_devices_settings">Özel aygıt listesi</string>
<string name="custom_devices_settings_summary">%d aygıt elle eklendi</string>
<string name="custom_device_list">IPye göre aygıtları ekle</string>
<string name="custom_device_deleted">Özel aygıt silindi</string>
<string name="custom_device_list_help">Aygıtınız kendiliğinden algılanmazsa İşlem Düğmesine tıklayarak IP adresini veya ana bilgisayar adını ekleyebilirsiniz</string>
@@ -306,6 +312,8 @@
<string name="devices">Aygıtlar</string>
<string name="settings_rename">Aygıt adı</string>
<string name="settings_dark_mode">Karanlık tema</string>
<string name="settings_export_logs">KDE Bağlan Günlüklerini Dışa Aktar</string>
<string name="settings_export_logs_text">Sorun tanılama konusunda yandımcı olabilecek yürütme bilgisini içeren bir dosya üretin.</string>
<string name="settings_more_settings_title">Daha fazla ayar</string>
<string name="settings_more_settings_text">Aygıt başına ayarlar, bir aygıt içinden “Eklenti Ayarları” altında bulunabilir.</string>
<string name="setting_persistent_notification">Kalıcı bildirim göster</string>
@@ -326,7 +334,7 @@
<string name="empty_trusted_networks_list_text">Henüz herhangi bir güvenilen ağ eklemediniz</string>
<string name="allow_all_networks_text">Hepsine izin ver</string>
<string name="location_permission_needed_title">İzin gerekli</string>
<string name="bluetooth_permission_needed_desc">Bluetooth kullanılarak eşleştirilen aygıtların KDE Bağlanda kullanılabilir olmasını sağlamak için Bluetooth iznini verin.</string>
<string name="bluetooth_permission_needed_desc">KDE Bağlan, Bluetooth kullanarak eşleştirilmiş aygıtların KDE Bağlanda görülebilir olmasını sağlamak için yakındaki aygıtlara bağlanma iznine gereksinim duyar.</string>
<string name="location_permission_needed_desc">KDE Bağlan, uygulama arka planda olsa bile bağlı olduğunuz Wi-Fi ağını bilmek için arka plan konumu iznine gereksinim duyar. Bunun nedeni, çevrenizdeki Wi-Fi ağlarının adının, KDE Bağlanın yaptığı bu olmasa bile konumunuzu bulmak için kullanılabilmesidir.</string>
<string name="clipboard_android_x_incompat">Android 10, tüm uygulamalara pano erişimini kaldırdı. Bu eklenti devre dışı bırakılacak.</string>
<string name="mpris_open_url">Oynamayı burada sürdürün</string>
@@ -396,7 +404,7 @@
<string name="about_kde_report_bugs_or_wishes">&lt;h1&gt;Hataları veya İsteklerinizi Bildirin&lt;/h1&gt; &lt;p&gt;Yazılımlar her zaman iyileştirilebilir ve KDE takımın bunu yapmaya hazırdır. Ancak siz de bir şey beklendiği gibi gitmezse veya hata verirse bize bildirin.&lt;/p&gt; &lt;p&gt;KDEnin bir hata takip sistemi vardır. &lt;a href=https://bugs.kde.org/&gt;https://bugs.kde.org/&lt;/a&gt; adresini ziyaret edin veya hakkında ekranının Hata Bildir düğmesini kullanarak hataları bildirin.&lt;/p&gt; Bir iyileştirme için öneriniz varsa bunu bildirmek için hata takip sistemini kullanabilirsiniz; yalnızca “Wishlist” önceliğini kullandığınızdan emin olun.</string>
<string name="about_kde_join_kde">"&lt;h1&gt;KDEye Katılın&lt;/h1&gt; &lt;p&gt;KDE takımının bir üyesi olmak için yazılım geliştirici olmanıza gerek yoktur. Program arayüzlerini çeviren dil takımlarına katılabilirsiniz. Grafikler, temalar, sesler ve iyileştirilmiş belgelendirme sağlayabilirsiniz. Karar sizin!&lt;/p&gt; &lt;p&gt;Katılabileceğiniz bazı projeler hakkında bilgi almak için &lt;a href=https://community.kde.org/Get_Involved&gt;https://community.kde.org/Get_Involved&lt;/a&gt; sayfasını ziyaret edin.&lt;/p&gt; Daha fazla bilgiye veya belgeye gereksiniminiz varsa &lt;a href=https://techbase.kde.org/&gt;https://techbase.kde.org/&lt;/a&gt; sayfasında aradığınızı bulabilirsiniz."</string>
<string name="about_kde_support_kde">"&lt;h1&gt;KDEyi Destekleyin&lt;/h1&gt; &lt;p&gt;KDE yazılımları her zaman ücretsiz kalmayı sürdürecektir; ancak bunu oluşturmak bedava değildir. &lt;/p&gt; &lt;p&gt;Geliştirmeyi desteklemek için KDE topluluğu, kar amacı gütmeyen bir kuruluş olan KDE e.V.yi kurmuştur, bu topluluk KDE topluğunu yasal ve finansal konularda temsil eder. KDE e.V. hakkında daha fazla bilgi için &lt;a href=https://ev.kde.org/&gt;https://ev.kde.org/&lt;/a&gt; adresini ziyaret edin.&lt;/p&gt; &lt;p&gt;KDE, finansal da dahil olmak üzere her türlü katkıdan yarar sağlar. Maddi kaynaklarımızla, geliştiricilerimizin ve diğerlerinin katkıda bulunurken oluşan masraflarını karşılıyoruz. Ayrıca yasal destek ve konferanslar ve toplantılar için de kullanılmaktadır.&lt;/p&gt; &lt;p&gt;Emeklerimizi, finansal destekle desteklemeniz için &lt;a href=https://www.kde.org/community/donations/&gt;https://www.kde.org/community/donations/&lt;/a&gt; adresinde bulunan yollardan birini kullanabilirsiniz.&lt;/p&gt; Desteğiniz için şimdiden teşekkürler."</string>
<string name="maintainer_and_developer">Projeyi sürdüren ve geliştirici</string>
<string name="maintainer_and_developer">Bakımcı ve geliştirici</string>
<string name="developer">Geliştirici</string>
<string name="apple_support">macOS ve iOS desteği üzerinde çalışılmaktadır.</string>
<string name="bug_fixes_and_general_improvements">Hata düzeltmeleri ve genel iyileştirmeler</string>
@@ -420,4 +428,9 @@
<string name="mpris_keepwatching_settings_title">Oynamayı Sürdür</string>
<string name="mpris_keepwatching_settings_summary">Ortamı kapattıktan sonra bu aygıtta oynatmayı sürdürmek için sessiz bir bildirim göster</string>
<string name="notification_channel_keepwatching">Oynamayı Sürdür</string>
<string name="ping_result">%1$d milisaniye içinde pinglendi</string>
<string name="ping_failed">Aygıt pinglenemedi</string>
<string name="ping_in_progress">Pingleniyor…</string>
<string name="device_host_invalid">Makine geçersiz. Geçerli bir makine adı kullanın; IPv4 veya IPv6 gibi</string>
<string name="device_host_duplicate">Makine listede halihazırda var</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">Немає доступу до пристрою</string>
<string name="error_already_paired">Пристрій вже пов’язано</string>
<string name="error_timed_out">Час очікування вичерпано</string>
<string name="error_clocks_not_match">Годинник пристрою не синхронізовано</string>
<string name="error_canceled_by_user">Скасовано користувачем</string>
<string name="error_canceled_by_other_peer">Скасовано з іншого вузла пов’язування</string>
<string name="encryption_info_title">Дані щодо шифрування</string>
@@ -180,9 +181,11 @@
<string name="middle_click">Надіслати клацання лівою кнопкою</string>
<string name="show_keyboard">Показати клавіатуру</string>
<string name="device_not_paired">Пристрій не пов’язано</string>
<string name="pairing_duplicate_names">Попередження: маємо декілька пристроїв із однією назвою.</string>
<string name="request_pairing">Надіслати запит щодо пов’язування</string>
<string name="pairing_accept">Прийняти</string>
<string name="pairing_reject">Відмовити</string>
<string name="pairing_explanation">Пов\'язування двох пристроїв надасть їм взаємний доступ. Пов\'язуйте між собою лише ваші власні пристрої.</string>
<string name="settings">Параметри</string>
<string name="mpris_play">Пуск</string>
<string name="mpris_pause">Пауза</string>
@@ -207,12 +210,15 @@
<string name="mpris_notification_settings_summary">Уможливлює керування відтворенням мультимедійних даних без відкриття KDE Connect</string>
<string name="share_to">Оприлюднити на…</string>
<string name="unreachable_device">%s (недоступний)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">Адреси, які оприлюднено на недоступному пристрої, буде надіслано, щойно пристрій стане доступним.\n\n</string>
<string name="protocol_version">Версія протоколу:</string>
<string name="protocol_version_newer">На цьому пристрої використовується новіша версія протоколу</string>
<string name="plugin_settings_with_name">Параметри %s</string>
<string name="invalid_device_name">Некоректна назва пристрою</string>
<string name="shareplugin_text_saved">Отримано текст, збережено до буфера обміну даними</string>
<string name="custom_devices_settings">Список нетипових пристроїв</string>
<string name="custom_devices_settings_summary">%d пристроїв додано вручну</string>
<string name="custom_device_list">Додати пристрої за IP</string>
<string name="custom_device_deleted">Нетиповий пристрій вилучено</string>
<string name="custom_device_list_help">Якщо ваш пристрій не було виявлено автоматично, ви можете додати його IP-адресу або назву вузла, натиснувши рухому кнопку дій.</string>
@@ -322,6 +328,8 @@
<string name="devices">Пристрої</string>
<string name="settings_rename">Назва пристрою</string>
<string name="settings_dark_mode">Темна тема</string>
<string name="settings_export_logs">Експортувати журнал KDE Connect</string>
<string name="settings_export_logs_text">Створити файл з даними щодо виконання, які можуть допомогти у діагностиці вад.</string>
<string name="settings_more_settings_title">Додаткові параметри</string>
<string name="settings_more_settings_text">Окремі параметри пристроїв наведено на сторінці «Параметри додатків» сторінки пристрою.</string>
<string name="setting_persistent_notification">Показувати постійне сповіщення</string>
@@ -342,7 +350,7 @@
<string name="empty_trusted_networks_list_text">Вами ще не додано надійних мереж</string>
<string name="allow_all_networks_text">Дозволити всі</string>
<string name="location_permission_needed_title">Потрібні права доступу</string>
<string name="bluetooth_permission_needed_desc">Надання прав доступу Bluetooth для сполучення пристроїв за допомогою доступного у KDE Connect Bluetooth.</string>
<string name="bluetooth_permission_needed_desc">KDE Connect потрібні права доступу до з\'єднання із сусідніми пристроями, щоб зробити пов\'язування пристроїв за допомогою Bluetooth доступним у KDE Connect.</string>
<string name="location_permission_needed_desc">KDE Connect потрібні права на визначення місця перебування у фоновому режимі для роботи з мережею WiFi, з якою встановлено з\'єднання, навіть якщо програма працює у фоновому режимі. Причина полягає у тому, що назви сусідніх мереж WiFi може бути використано для визначення місця перебування, навіть якщо це не робить сама KDE Connect.</string>
<string name="clipboard_android_x_incompat">У Android 10 вилучено доступ до буфера даних для усіх програм. Цей додаток буде вимкнено.</string>
<string name="mpris_open_url">Продовжити відтворення тут</string>
@@ -436,4 +444,9 @@
<string name="mpris_keepwatching_settings_title">Продовжити відтворення</string>
<string name="mpris_keepwatching_settings_summary">Показати беззвучне сповіщення для продовження відтворення на цьому пристрої після закриття носія</string>
<string name="notification_channel_keepwatching">Продовжити відтворення</string>
<string name="ping_result">Виконано зондування за %1$d мілісекунд</string>
<string name="ping_failed">Не вдалося зондувати пристрій</string>
<string name="ping_in_progress">Зондування…</string>
<string name="device_host_invalid">Вузол є некоректним. Скористайтеся коректною назвою вузла, IPv4 або IPv6</string>
<string name="device_host_duplicate">Запис вузла вже є у списку</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="error_not_reachable">设备不可及</string>
<string name="error_already_paired">设备已配对</string>
<string name="error_timed_out">超时</string>
<string name="error_clocks_not_match">设备时钟不同步</string>
<string name="error_canceled_by_user">已被用户取消</string>
<string name="error_canceled_by_other_peer">已被其他对等点取消</string>
<string name="encryption_info_title">加密信息</string>
@@ -156,9 +157,11 @@
<string name="middle_click">发送中键点击</string>
<string name="show_keyboard">显示键盘</string>
<string name="device_not_paired">设备未配对</string>
<string name="pairing_duplicate_names">注意:存在多个同名设备。</string>
<string name="request_pairing">请求配对</string>
<string name="pairing_accept">接受</string>
<string name="pairing_reject">拒绝</string>
<string name="pairing_explanation">两个设备在配对后即可相互访问。请只配对您自己的设备。</string>
<string name="settings">设置</string>
<string name="mpris_play">播放</string>
<string name="mpris_pause">暂停</string>
@@ -183,12 +186,15 @@
<string name="mpris_notification_settings_summary">不打开 KDE Connect 也能在常驻通知中控制媒体播放器</string>
<string name="share_to">分享到…</string>
<string name="unreachable_device">%s (无法访问)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">URL 被分享到了不可访问的设备。它将在设备能够访问时自动传输到该设备。\n</string>
<string name="protocol_version">协议版本:</string>
<string name="protocol_version_newer">此设备使用较新版本的协议</string>
<string name="plugin_settings_with_name">%s设置</string>
<string name="invalid_device_name">无效的设备名</string>
<string name="shareplugin_text_saved">已收到文本,存至剪贴板</string>
<string name="custom_devices_settings">自定义设备列表</string>
<string name="custom_devices_settings_summary">手动添加了 %d 个设备</string>
<string name="custom_device_list">通过 IP 添加设备</string>
<string name="custom_device_deleted">自定义设备已删除</string>
<string name="custom_device_list_help">如果您的设备未被自动检测到,您点击浮动操作按钮可以添加它的 IP 地址或主机名。</string>
@@ -298,6 +304,8 @@
<string name="devices">设备</string>
<string name="settings_rename">设备名</string>
<string name="settings_dark_mode">深色主题</string>
<string name="settings_export_logs">导出 KDE Connect 日志</string>
<string name="settings_export_logs_text">生成一个包含程序执行信息的文件,有助于排查故障。</string>
<string name="settings_more_settings_title">更多设置</string>
<string name="settings_more_settings_text">每个设备的独立设置可以在设备页内的“插件设置”下找到。</string>
<string name="setting_persistent_notification">启用常驻通知栏</string>
@@ -318,7 +326,7 @@
<string name="empty_trusted_networks_list_text">您还没有添加任何可信的网络</string>
<string name="allow_all_networks_text">允许所有</string>
<string name="location_permission_needed_title">需要权限</string>
<string name="bluetooth_permission_needed_desc">授予蓝牙权限以通过 KDE Connect 配对可用设备。</string>
<string name="bluetooth_permission_needed_desc">KDE Connect 需要权限才能使用蓝牙连接并配对附近的设备。</string>
<string name="location_permission_needed_desc">KDE Connect 需要后台位置权限才能在后台检测您连接到的 WiFi 网络。后台位置权限是一个敏感权限,这是因为该权限可以让应用程序通过您周围的 WiFi 网络名称来查找您的位置。尽管 KDE Connect 申请了该权限,但它不会对您进行定位。</string>
<string name="clipboard_android_x_incompat">Android 10 已删除所有应用的剪贴板访问权限。此插件将被禁用。</string>
<string name="mpris_open_url">继续在此播放</string>
@@ -412,4 +420,9 @@
<string name="mpris_keepwatching_settings_title">继续播放</string>
<string name="mpris_keepwatching_settings_summary">关闭媒体后显示一条用于继续在此设备上播放的静音通知</string>
<string name="notification_channel_keepwatching">继续播放</string>
<string name="ping_result">Ping 的响应时间是 %1$d 毫秒</string>
<string name="ping_failed">无法 ping 设备</string>
<string name="ping_in_progress">正在执行 ping 命令…</string>
<string name="device_host_invalid">主机无效。请使用有效的主机名、IPv4 或 IPv6 地址</string>
<string name="device_host_duplicate">主机已在列表中</string>
</resources>

View File

@@ -1,105 +1,105 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="kde_connect">KDE 連線</string>
<string name="kde_connect">KDE Connect</string>
<string name="manifest_label_share">傳送到裝置</string>
<string name="foreground_notification_no_devices">沒有連線到任何裝置</string>
<string name="foreground_notification_devices">已連線到%s</string>
<string name="foreground_notification_no_devices">未與任何裝置產生連結</string>
<string name="foreground_notification_devices">已連%s</string>
<string name="foreground_notification_send_clipboard">傳送剪貼簿</string>
<string name="pref_plugin_telephony">電話通知器</string>
<string name="pref_plugin_telephony_desc">傳送來電通知</string>
<string name="pref_plugin_battery">電池報告</string>
<string name="pref_plugin_battery_desc">定期回報電池狀態</string>
<string name="pref_plugin_connectivity_report">報告</string>
<string name="pref_plugin_connectivity_report_desc">回報網路訊號強度狀態</string>
<string name="pref_plugin_connectivity_report">通性報告</string>
<string name="pref_plugin_connectivity_report_desc">回報網路訊號強度狀態</string>
<string name="pref_plugin_sftp">顯示檔案系統</string>
<string name="pref_plugin_sftp_desc">同意讓遠端可以瀏覽檔案系統</string>
<string name="pref_plugin_clipboard">同步剪貼簿</string>
<string name="pref_plugin_clipboard_desc">享剪貼簿的內容</string>
<string name="pref_plugin_clipboard_sent">已傳送剪貼簿</string>
<string name="pref_plugin_sftp_desc">允許遠端瀏覽此裝置的檔案系統</string>
<string name="pref_plugin_clipboard">剪貼簿同步</string>
<string name="pref_plugin_clipboard_desc">享剪貼簿的內容</string>
<string name="pref_plugin_clipboard_sent">已傳送剪貼簿內容</string>
<string name="pref_plugin_mousepad">遠端輸入</string>
<string name="pref_plugin_mousepad_desc">使用您的智慧型手機或平板來模擬觸碰板與鍵盤</string>
<string name="pref_plugin_mousepad_desc">使用手機或平板電腦作為觸控板和鍵盤</string>
<string name="pref_plugin_presenter">簡報遙控</string>
<string name="pref_plugin_presenter_desc">使用您的裝置來切換簡報中的投影片</string>
<string name="pref_plugin_remotekeyboard">接收遠端按鍵輸入</string>
<string name="pref_plugin_remotekeyboard_desc">從遠端裝置接收按鍵輸入活動</string>
<string name="pref_plugin_mpris">多媒體控制</string>
<string name="pref_plugin_mpris_desc">成為您媒體播放器的遙控器</string>
<string name="pref_plugin_runcommand">執行</string>
<string name="pref_plugin_runcommand_desc">您的智慧型手機或平板當中觸發遠端裝置上的命令</string>
<string name="pref_plugin_contacts">同步聯絡人工具</string>
<string name="pref_plugin_mpris_desc">成為您媒體播放器的遙控器</string>
<string name="pref_plugin_runcommand">執行</string>
<string name="pref_plugin_runcommand_desc">從手機或平板電腦觸發遠端命令</string>
<string name="pref_plugin_contacts">聯絡人同步</string>
<string name="pref_plugin_contacts_desc">允許同步裝置的通訊錄</string>
<string name="pref_plugin_ping">Ping 回應封包</string>
<string name="pref_plugin_ping_desc">傳送接收 Ping 回應封包</string>
<string name="pref_plugin_notifications">同步通知</string>
<string name="pref_plugin_notifications_desc">存取其他裝置的通知</string>
<string name="pref_plugin_ping">Ping 測試</string>
<string name="pref_plugin_ping_desc">傳送接收連線測試封包</string>
<string name="pref_plugin_notifications">通知同步</string>
<string name="pref_plugin_notifications_desc">其他裝置存取您的通知</string>
<string name="pref_plugin_receive_notifications">接收通知</string>
<string name="pref_plugin_receive_notifications_desc">在 Android 上顯示從其他裝置收到的通知</string>
<string name="pref_plugin_sharereceiver">分享接收</string>
<string name="pref_plugin_sharereceiver_desc">兩個裝置當中互相分享URL網址與檔案</string>
<string name="pref_plugin_receive_notifications_desc">接收來自其他裝置的通知並將其顯示在 Android 上</string>
<string name="pref_plugin_sharereceiver">分享接收</string>
<string name="pref_plugin_sharereceiver_desc">裝置之間分享檔案和網址 (URL)</string>
<string name="device_list_empty">沒有裝置</string>
<string name="ok">確認</string>
<string name="sad_ok">好吧 :(</string>
<string name="cancel">取消</string>
<string name="open_settings">開啟設定</string>
<string name="no_permissions">需要授予存取通知的權限</string>
<string name="no_permission_mprisreceiver">為了要能控制您的媒體播放器,您需要提供「通知的權限</string>
<string name="no_permissions_remotekeyboard">若要接收鍵盤按鍵事件,您需要啟用 KDE 連線遠端鍵盤功能</string>
<string name="send_ping">傳送 Ping 回應封包</string>
<string name="no_permissions">必須給予存取通知的權限</string>
<string name="no_permission_mprisreceiver">為了要能控制您的媒體播放器,您必須給予存取通知的權限</string>
<string name="no_permissions_remotekeyboard">若要接收鍵盤按鍵輸入活動,您必須啟用 KDE Connect 的遠端鍵盤功能</string>
<string name="send_ping">傳送 Ping 測試封包</string>
<string name="open_mpris_controls">多媒體控制</string>
<string name="remotekeyboard_editing_only_title">編輯時處理遠端按鍵</string>
<string name="remotekeyboard_not_connected">這裡沒有建立在 kdeconnect 之上的使用中遠端鍵盤連線。</string>
<string name="remotekeyboard_connected">遠端鍵盤連線啟用狀態</string>
<string name="remotekeyboard_multiple_connections">這裡有兩個以上的遠端鍵盤連結,選擇一個裝置以設定</string>
<string name="remotekeyboard_editing_only_title">僅在編輯時處理遠端按鍵</string>
<string name="remotekeyboard_not_connected">沒有作用中的遠端鍵盤連線,請在 KDE Connect 中建立一個</string>
<string name="remotekeyboard_connected">遠端鍵盤連線啟用</string>
<string name="remotekeyboard_multiple_connections">遠端鍵盤連線有多個,請選擇裝置進行設定</string>
<string name="open_mousepad">遠端輸入</string>
<string name="mousepad_info">您的智慧型手機螢幕上移動手指來控制電腦螢幕的游標。按一下表示滑鼠的左鍵,使用兩/三手指頭按一下來表示滑鼠的右鍵/中鍵。使用兩隻手指捲動。長按則表示要拖拉。可以在外掛程式設定啟用陀螺儀滑鼠功能</string>
<string name="mousepad_info_no_gestures">在螢幕上移動手指移動滑鼠游標,輕點來進行點擊</string>
<string name="mousepad_info">在手機螢幕上移動手指即可移動滑鼠游標。點擊一次,然後使用兩/三手指操作右側和中間按鈕。使用 2 根手指捲動頁面。長按進行拖放。可從右上角選單的外掛程式設定啟用陀螺儀滑鼠功能以更靈活的操控滑鼠游標</string>
<string name="mousepad_info_no_gestures">在螢幕上移動手指就可以移動滑鼠游標,手指輕點就代表點擊一下</string>
<string name="mousepad_keyboard_input_not_supported">配對裝置不支援鍵盤輸入</string>
<string name="mousepad_single_tap_settings_title">設定單指輕點的動作</string>
<string name="mousepad_double_tap_settings_title">設定兩隻手指頭按一下的動作</string>
<string name="mousepad_triple_tap_settings_title">設定三隻手指頭按一下的動作</string>
<string name="mousepad_sensitivity_settings_title">設定觸碰板的靈敏度</string>
<string name="mousepad_double_tap_settings_title">設定兩指輕點的動作</string>
<string name="mousepad_triple_tap_settings_title">設定三指輕點的動作</string>
<string name="mousepad_sensitivity_settings_title">設定觸控板靈敏度</string>
<string name="mousepad_mouse_buttons_title">顯示滑鼠按鈕</string>
<string name="mousepad_acceleration_profile_settings_title">設定指針加速度</string>
<string name="mousepad_scroll_direction_title">動方向相反</string>
<string name="mousepad_acceleration_profile_settings_title">設定滑鼠游標加速度</string>
<string name="mousepad_scroll_direction_title">反向捲動方向</string>
<string name="mousepad_scroll_sensitivity_title">捲動靈敏度</string>
<string name="gyro_mouse_enabled_title">啟用陀螺儀滑鼠</string>
<string name="gyro_mouse_sensitivity_title">陀螺儀靈敏度</string>
<string-array name="mousepad_tap_entries">
<item>點擊左鍵</item>
<item>點擊右鍵</item>
<item>點擊中鍵</item>
<item>左鍵點擊</item>
<item>右鍵點擊</item>
<item>中鍵點擊</item>
<item></item>
</string-array>
<string-array name="mousepad_sensitivity_entries">
<item></item>
<item>最慢</item>
<item></item>
<item>預設</item>
<item>高於預設值</item>
<item></item>
<item>最快</item>
</string-array>
<string-array name="mousepad_acceleration_profile_entries">
<item>沒有加速</item>
<item></item>
<item></item>
<item>沒有加速</item>
<item>最弱</item>
<item></item>
<item>中等</item>
<item>安全</item>
<item>安全</item>
<item>較強</item>
<item></item>
</string-array>
<string name="sendkeystrokes_send_to">傳送鍵盤輸入</string>
<string name="sendkeystrokes_textbox_hint">傳送鍵盤輸入主機</string>
<string name="sendkeystrokes_disabled_toast">已停用傳送鍵盤輸入的功能——請至「設定」裡啟動</string>
<string name="sendkeystrokes_wrong_data">無效的檔案類型——需為 text/x-keystrokes</string>
<string name="sendkeystrokes_sent_text">傳送按鍵組合 %1$s 裝置 %2$s</string>
<string name="sendkeystrokes_pref_category_summary">這個模組讓其他應用程式可以分享文字片段,並作為鍵盤輸入傳送至連線的主機</string>
<string name="sendkeystrokes_send_to">鍵盤輸入傳送到</string>
<string name="sendkeystrokes_textbox_hint">鍵盤輸入傳送到主機</string>
<string name="sendkeystrokes_disabled_toast">傳送鍵盤輸入的功能已停用 - 可在「設定」中啟用</string>
<string name="sendkeystrokes_wrong_data">無效的 mime 類型 - 必須為「text/x-keystrokes</string>
<string name="sendkeystrokes_sent_text">按鍵組合 %1$s 傳送到裝置 %2$s</string>
<string name="sendkeystrokes_pref_category_summary">此模組允許其他應用程式分享文字片段如同鍵盤輸入,並將其傳送到已連結的主機</string>
<string name="sendkeystrokes_pref_category_title">傳送鍵盤輸入</string>
<string name="sendkeystrokes_pref_enabled">啟用鍵盤輸入傳送</string>
<string name="sendkeystrokes_pref_enabled_summary">接收 MIME 類型為 \'text/x-keystrokes\' 的資料</string>
<string name="sendkeystrokes_safe_text_enabled">馬上傳送安全文字</string>
<string name="sendkeystrokes_safe_text_enabled_summary">不另行確認直接傳送簡短而只有數字字串</string>
<string name="sendkeystrokes_safe_text_enabled_summary">傳送短的純數字字串而不進行確認</string>
<string name="pref_plugin_mousepad_send_keystrokes">作為鍵盤輸入傳送</string>
<string name="mouse_receiver_plugin_description">接收遠端滑鼠移動</string>
<string name="mouse_receiver_plugin_name">滑鼠接收</string>
<string name="mouse_receiver_no_permissions">要接收遠端觸控輸入,您需要提供完全控制裝置的協助工具權限</string>
<string name="mouse_receiver_plugin_name">滑鼠接收</string>
<string name="mouse_receiver_no_permissions">若要遠端接收觸控輸入,您必須給予輔助功能權限以完全控制您的裝置</string>
<string name="view_status_title">狀態</string>
<string name="battery_status_format">電池:%d%%</string>
<string name="battery_status_low_format">電池:%d%% 低電量</string>
@@ -112,9 +112,10 @@
<string name="pair_new_device">配對新裝置</string>
<string name="cancel_pairing">取消配對</string>
<string name="unknown_device">不明的裝置</string>
<string name="error_not_reachable">裝置無法連結</string>
<string name="error_not_reachable">裝置無法存取</string>
<string name="error_already_paired">裝置已經配對</string>
<string name="error_timed_out">逾時</string>
<string name="error_clocks_not_match">裝置時鐘不同步</string>
<string name="error_canceled_by_user">使用者中斷</string>
<string name="error_canceled_by_other_peer">被其他同等功能應用中斷</string>
<string name="encryption_info_title">加密資訊</string>
@@ -142,18 +143,18 @@
<item quantity="other">無法從 %1$s 接收到 %2$d/%3$d 個檔案</item>
</plurals>
<plurals name="sent_files_title">
<item quantity="other">已將 %2$d 傳送至 %1$s</item>
<item quantity="other">已將 %2$d 個檔案傳送至 %1$s</item>
</plurals>
<plurals name="send_files_fail_title">
<item quantity="other">無法將第 %2$d (共 %3$d) 個檔案傳送至 %1$s</item>
</plurals>
<string name="tap_to_open">按一下開啟</string>
<string name="received_file_text">按一下開啟 \'%1s\'</string>
<string name="tap_to_open">點擊以開啟</string>
<string name="received_file_text">點擊以開啟「%1s</string>
<string name="cannot_create_file">無法建立 %s 檔案</string>
<string name="tap_to_answer">按一下即可回應</string>
<string name="left_click">傳送左鍵按一下</string>
<string name="right_click">傳送右鍵按一下</string>
<string name="middle_click">傳送中鍵按一下</string>
<string name="tap_to_answer">點擊即可回應</string>
<string name="left_click">傳送左鍵點擊</string>
<string name="right_click">傳送右鍵點擊</string>
<string name="middle_click">傳送中鍵點擊</string>
<string name="show_keyboard">顯示鍵盤</string>
<string name="device_not_paired">裝置未配對</string>
<string name="request_pairing">請求配對</string>
@@ -169,8 +170,8 @@
<string name="mpris_loop">重複播放</string>
<string name="mpris_shuffle">隨機播放</string>
<string name="mpris_volume">音量</string>
<string name="mpris_time_settings_title">往前/往後按鍵</string>
<string name="mpris_time_settings_summary">調整按下時往前 / 往後的時間</string>
<string name="mpris_time_settings_title">快轉 / 倒轉按鈕</string>
<string name="mpris_time_settings_summary">調整按下時快轉 / 倒轉的時間</string>
<string-array name="mpris_time_entries">
<item>10 秒鐘</item>
<item>20 秒鐘</item>
@@ -178,98 +179,100 @@
<item>1 分鐘</item>
<item>2 分鐘</item>
</string-array>
<string name="mpris_notifications_explanation">需要通知權限在通知欄顯示遠端媒體</string>
<string name="mpris_notification_settings_title">顯示媒體控制通知</string>
<string name="mpris_notification_settings_summary">允許控制您的媒體播放器而不需要開啟 KDE 連線</string>
<string name="mpris_notifications_explanation">需要通知權限才能在通知欄顯示遠端媒體</string>
<string name="mpris_notification_settings_title">顯示媒體控制通知</string>
<string name="mpris_notification_settings_summary">無需開啟 KDE Connect 即可控制您的媒體播放器</string>
<string name="share_to">分享給…</string>
<string name="unreachable_device">%s無法連線</string>
<string name="unreachable_device_url_share_text">分享給無法連線的裝置的網址會在該裝置重新連線後傳送給它。\n\n</string>
<string name="protocol_version_newer">此裝置使用較新的通訊協定</string>
<string name="plugin_settings_with_name">%s 設定</string>
<string name="unreachable_device">%s無法存取</string>
<string name="unreachable_device_url_share_text">分享網址 (URL) 到無法存取的裝置,將在該裝置變得可存取後再傳送過去。\n\n</string>
<string name="protocol_version">協定版本:</string>
<string name="protocol_version_newer">此裝置使用較新的通訊協定版本</string>
<string name="plugin_settings_with_name">%s的設定</string>
<string name="invalid_device_name">無效的裝置名稱</string>
<string name="shareplugin_text_saved">已接收文字,並且儲存到剪貼簿</string>
<string name="custom_devices_settings">自訂裝置列表</string>
<string name="custom_device_list">以 IP 新增裝置</string>
<string name="custom_device_deleted">已刪除自訂裝置</string>
<string name="custom_device_list_help">若未自動偵測到您的裝置,您可透過點選「浮動動作按鈕」來新增該裝置的 IP 位址或主機名稱</string>
<string name="custom_devices_settings_summary">已成功加入 %d 台裝置</string>
<string name="custom_device_list">透過 IP 新增裝置</string>
<string name="custom_device_deleted">自訂裝置已刪除</string>
<string name="custom_device_list_help">如果未自動偵測到您的裝置,您可以透過點擊「浮動操作按鈕」來新增其 IP 位址或主機名稱</string>
<string name="custom_device_fab_hint">新增裝置</string>
<string name="undo">復原</string>
<string name="share_notification_preference">通知方式</string>
<string name="share_notification_preference_summary">接收檔案時發出振動以及播放聲音</string>
<string name="share_destination_customize">自訂目標路徑</string>
<string name="share_destination_customize_summary_disabled">收到的檔案將會在 Downloads 上顯示。</string>
<string name="share_destination_customize_summary_enabled">檔案將儲存在下方所示的資料夾</string>
<string name="share_destination_folder_preference">目標路徑</string>
<string name="share_notification_preference_summary">接收檔案時振動並播放聲音</string>
<string name="share_destination_customize">自訂目標資料夾</string>
<string name="share_destination_customize_summary_disabled">收到的檔案將出現在「下載」資料夾中</string>
<string name="share_destination_customize_summary_enabled">檔案將儲存在下資料夾</string>
<string name="share_destination_folder_preference">目標資料夾</string>
<string name="share">分享</string>
<string name="share_received_file">分享「%s」</string>
<string name="title_activity_notification_filter">通知過濾器</string>
<string name="filter_apps_info">將會同步選取 App 的通知</string>
<string name="show_notification_if_screen_off">在螢幕關閉時傳送通知</string>
<string name="filter_apps_info">所選應用程式的通知將被同步</string>
<string name="show_notification_if_screen_off">在螢幕關閉時傳送通知</string>
<string name="add_device_dialog_title">新增裝置</string>
<string name="add_device_hint">主機名稱或 IP 位址</string>
<string name="sftp_preference_configured_storage_locations">設定儲存空間位置</string>
<string name="sftp_preference_add_storage_location_title">新增儲存空間位置</string>
<string name="sftp_preference_edit_storage_location">編輯儲存空間位置</string>
<string name="sftp_storage_preference_storage_location">儲存空間位置</string>
<string name="sftp_preference_configured_storage_locations">設定存放位置</string>
<string name="sftp_preference_add_storage_location_title">新增存放位置</string>
<string name="sftp_preference_edit_storage_location">編輯存放位置</string>
<string name="sftp_storage_preference_storage_location">存放位置</string>
<string name="sftp_storage_preference_storage_location_already_configured">此位置已被設定</string>
<string name="sftp_storage_preference_click_to_select">按一下選擇</string>
<string name="sftp_storage_preference_click_to_select">點擊以選擇</string>
<string name="sftp_storage_preference_display_name">顯示名稱</string>
<string name="sftp_storage_preference_display_name_already_used">此顯示名稱已被使用</string>
<string name="sftp_storage_preference_display_name_cannot_be_empty">顯示名稱不空白</string>
<string name="sftp_storage_preference_display_name_cannot_be_empty">顯示名稱不能為空白</string>
<string name="sftp_action_mode_menu_delete">刪除</string>
<string name="sftp_no_storage_locations_configured">未設定儲存空間位置</string>
<string name="sftp_saf_permission_explanation">要遠端存取檔案,您需先設定儲存空間位置</string>
<string name="sftp_manage_storage_permission_explanation">要允許遠端存取裝置的檔案,您需要允許 KDE 連線管理儲存裝置</string>
<string name="no_players_connected">沒有發現播放器</string>
<string name="sftp_no_storage_locations_configured">未設定存放位置</string>
<string name="sftp_saf_permission_explanation">要遠端存取檔案,您必須設定存放位置</string>
<string name="sftp_manage_storage_permission_explanation">要允許遠端存取裝置的檔案,您需要允許 KDE Connect 可以管理儲存空間</string>
<string name="no_players_connected">沒有找到播放器</string>
<string name="send_files">傳送檔案</string>
<string name="block_notification_contents">阻擋通知內容</string>
<string name="block_notification_images">阻擋通知圖片</string>
<string name="pairing_title">KDE 連線裝置</string>
<string name="pairing_description">您相同網域當中,有其他有執行KDE連線的裝置會出現在這裡</string>
<string name="pairing_title">KDE Connect 裝置</string>
<string name="pairing_description">同一網路中執行 KDE Connect 的其他裝置應該會出現在</string>
<string name="device_rename_title">重新命名裝置</string>
<string name="device_rename_confirm">變更名稱</string>
<string name="device_rename_confirm">重新命名</string>
<string name="refresh">重新整理</string>
<string name="unreachable_description">無法連結此配對裝置。請確保它連結到與您相同的網</string>
<string name="no_wifi">您尚未連線 Wi-Fi 網路,因此您可能無法看到任何裝置。按一下這裡啟用 Wi-Fi。</string>
<string name="unreachable_description">無法此配對裝置連結。請確保它連線至與您相同的網</string>
<string name="no_wifi">您尚未連線 Wi-Fi 網路,因此您可能無法看到任何裝置。點擊這裡啟用 Wi-Fi。</string>
<string name="on_non_trusted_message">不在信任網路:自動探索已停用。</string>
<string name="no_file_browser">沒有安裝檔案瀏覽程式</string>
<string name="no_file_browser">沒有安裝檔案瀏覽器。</string>
<string name="pref_plugin_telepathy">傳送簡訊</string>
<string name="pref_plugin_telepathy_desc">傳送文字訊到您的電腦桌面</string>
<string name="pref_plugin_telepathy_desc">傳送文字訊到您的電腦桌面</string>
<string name="pref_plugin_telepathy_mms">傳送 MMS</string>
<string name="pref_plugin_telepathy_mms_desc">要能夠從 KDE 連線傳送 MMS 您需要先將其設為預設簡訊應用程式。</string>
<string name="pref_plugin_telepathy_mms_desc">要能夠從 KDE Connect 傳送 MMS 您必須先將其設為預設簡訊應用程式。</string>
<string name="findmyphone_title">尋找我的手機</string>
<string name="findmyphone_title_tablet">尋找我的平板</string>
<string name="findmyphone_title_tv">尋找我的電視</string>
<string name="findmyphone_description">這個裝置發出聲響讓您能找到它</string>
<string name="findmyphone_description">裝置發出聲響以便您可以找到它</string>
<string name="findmyphone_found">找到裝置</string>
<string name="open">開啟</string>
<string name="close">關閉</string>
<string name="plugins_need_permission">部份的外掛程式需要權限才能運作(按一下以取得更多資訊)</string>
<string name="plugins_need_permission">部份的外掛程式需要權限才能運作(點擊以取得更多資訊)</string>
<string name="permission_explanation">這外掛程式需要權限以運作</string>
<string name="all_permissions_granted">提供所有權限 🎉</string>
<string name="optional_permission_explanation">你需要授予延伸的權限以啟用所有功能</string>
<string name="plugins_need_optional_permission">部份的外掛程式因為缺乏權限,而導致功能被停用。(按一下以了解更多資訊</string>
<string name="share_optional_permission_explanation">要接收檔案您需要允許存取儲存裝置</string>
<string name="share_notifications_explanation">要能夠看到傳送或接收檔案時的進度您需要允許通知</string>
<string name="telepathy_permission_explanation">為了要在您的個人電腦上讀取與撰寫簡訊,你需要提供簡訊權限</string>
<string name="telephony_permission_explanation">為了要在桌面上檢視手機通話,您需要提供手機通話記錄及手機狀態的權限</string>
<string name="telephony_optional_permission_explanation">為了要讓聯絡人名稱取代手機號碼,您需要提供手機通訊錄的權限</string>
<string name="contacts_permission_explanation">為了要與電腦分享您的通訊錄,您必須提供「聯絡人」的權限</string>
<string name="contacts_per_device_confirmation">您的電話通訊錄將會被複製到這個裝置,讓它們能夠被 KDE 連線簡訊應用程式和其他應用程式使用。</string>
<string name="all_permissions_granted">給予所有權限 🎉</string>
<string name="optional_permission_explanation">您必須給予額外權限才能啟用所有功能</string>
<string name="plugins_need_optional_permission">某些外掛程式由於缺乏權限功能被停用(點擊以了解更多):</string>
<string name="share_optional_permission_explanation">要接收檔案您必須允許存取儲存裝置</string>
<string name="share_notifications_explanation">要能夠看到傳送或接收檔案時的進度您必須允許通知</string>
<string name="telepathy_permission_explanation">要從電腦端傳送和讀取簡訊,您必須給予簡訊權限</string>
<string name="telephony_permission_explanation">要在電腦上查看手機通話,您必須給予電話通話紀錄和電話狀態的權限</string>
<string name="telephony_optional_permission_explanation">要查看聯絡人姓名而不是電話號碼,您必須給予存取手機聯絡人的權限</string>
<string name="contacts_permission_explanation">為了要與電腦分享您的通訊錄,您必須給予「聯絡人」的權限</string>
<string name="contacts_per_device_confirmation">您的電話通訊錄將會被複製到這個裝置,讓它們能夠被 KDE Connect 的簡訊應用程式和其他應用程式使用。</string>
<string name="select_ringtone">選擇一個鈴聲</string>
<string name="telephony_pref_blocked_title">封鎖號碼</string>
<string name="telephony_pref_blocked_dialog_desc">不顯示這些號碼的來電簡訊。請在一行指定一個電話號碼。</string>
<string name="mpris_coverart_description">目前媒體的專輯圖像</string>
<string name="telephony_pref_blocked_title">封鎖號碼</string>
<string name="telephony_pref_blocked_dialog_desc">不顯示這些號碼的來電簡訊。請行指定一個數字</string>
<string name="mpris_coverart_description">目前媒體的專輯封面</string>
<string name="settings_icon_description">設定圖示</string>
<string name="presenter_fullscreen">全螢幕</string>
<string name="presenter_exit">離開簡報模式</string>
<string name="presenter_lock_tip">您能鎖定裝置並使用音量鍵前往上 / 下一張投影片</string>
<string name="add_command">增加一行</string>
<string name="addcommand_explanation">沒有註冊的</string>
<string name="addcommand_explanation2">現在可以在 KDE 連線系統設定增加新的指</string>
<string name="add_command_description">您可以在電腦上增加</string>
<string name="add_command">增加一行</string>
<string name="addcommand_explanation">沒有註冊的</string>
<string name="addcommand_explanation2">您可以在 KDE Connect 系統設定中新增命</string>
<string name="add_command_description">您可以在電腦上增加</string>
<string name="pref_plugin_mprisreceiver">控制媒體播放器</string>
<string name="pref_plugin_mprisreceiver_desc">從另一個裝置操控您手機的媒體播放器</string>
<string name="pref_plugin_mprisreceiver_desc">從另一個裝置控製手機的媒體播放器</string>
<string name="notification_channel_default">其他通知</string>
<string name="notification_channel_persistent">持續性指示器</string>
<string name="notification_channel_media_control">多媒體控制</string>
@@ -278,16 +281,16 @@
<string name="notification_channel_filetransfer_error">檔案傳輸錯誤</string>
<string name="notification_channel_high_priority">高優先度</string>
<string name="mpris_stop">停止目前播放器</string>
<string name="copy_url_to_clipboard">複製 URL 剪貼簿</string>
<string name="copy_url_to_clipboard"> URL 複製到剪貼簿</string>
<string name="clipboard_toast">已複製到剪貼簿</string>
<string name="runcommand_notreachable">無法聯絡裝置</string>
<string name="runcommand_notreachable">裝置無法存取</string>
<string name="runcommand_notpaired">裝置未配對</string>
<string name="runcommand_nosuchdevice">此處沒有裝置</string>
<string name="runcommand_noruncommandplugin">裝置未啟用「執行令外掛程式」</string>
<string name="runcommand_nosuchdevice">沒有這樣的裝置</string>
<string name="runcommand_noruncommandplugin">裝置未啟用「執行令外掛程式」</string>
<string name="runcommand_category_device_controls_title">裝置控制</string>
<string name="runcommand_device_controls_summary">如果您的裝置支援「裝置控制」,您已設定的令將會出現在那裡。</string>
<string name="runcommand_device_controls_summary">如果您的裝置支援「裝置控制」,您已設定的令將會出現在那裡。</string>
<string name="set_runcommand_name_as_title">set_runcommand_name_as_title</string>
<string name="runcommand_name_as_title_title">將名稱為標題顯示</string>
<string name="runcommand_name_as_title_title">將名稱顯示為標題</string>
<string name="pref_plugin_findremotedevice">尋找遠端裝置</string>
<string name="pref_plugin_findremotedevice_desc">使遠端裝置響鈴</string>
<string name="ring">響鈴</string>
@@ -298,11 +301,13 @@
<string name="devices">裝置</string>
<string name="settings_rename">裝置名稱</string>
<string name="settings_dark_mode">暗色主題</string>
<string name="settings_export_logs">匯出 KDE Connect 紀錄</string>
<string name="settings_export_logs_text">產生包含執行資訊的檔案來幫助發現問題。</string>
<string name="settings_more_settings_title">更多設定</string>
<string name="settings_more_settings_text">各裝置設定可在裝置內的「外掛程式設定」底下找到。</string>
<string name="setting_persistent_notification">顯示一致設定</string>
<string name="setting_persistent_notification_oreo">一致化通知</string>
<string name="setting_persistent_notification_description">按一下以在「通知設定」啟用或停用</string>
<string name="setting_persistent_notification_description">點擊以在「通知設定」啟用或停用</string>
<string name="extra_options">延伸選項</string>
<string name="privacy_options">隱私權選項</string>
<string name="set_privacy_options">設定隱私權選項</string>
@@ -310,15 +315,16 @@
<string name="block_images">阻擋通知中的圖片</string>
<string name="notification_channel_receivenotification">其他裝置上的通知</string>
<string name="no_app_for_opening">找不到適合用來開啟此檔案的應用程式</string>
<string name="remote_keyboard_service">KDE 連線遠端鍵盤</string>
<string name="presenter_pointer">指標裝置</string>
<string name="trusted_networks">信任網路</string>
<string name="remote_keyboard_service">KDE Connect 遠端鍵盤</string>
<string name="presenter_pointer">滑鼠游標</string>
<string name="trusted_networks">信任網路</string>
<string name="trusted_networks_desc">限制只對已知網路自動探索</string>
<string name="add_trusted_network">加入 %1s</string>
<string name="empty_trusted_networks_list_text">您尚未加入任何信任網路</string>
<string name="empty_trusted_networks_list_text">您尚未加入任何信任網路</string>
<string name="allow_all_networks_text">全部允許</string>
<string name="location_permission_needed_title">需要權限</string>
<string name="location_permission_needed_desc">KDE 連線需要背景位置權限,才能在背景執行時也能知道您目前所連線的 WiFi 網路。這是因為您週遭的 WiFi 網路名稱可以被用來推斷您的位置,即使這不是 KDE 連線在做的事情</string>
<string name="bluetooth_permission_needed_desc">KDE Connect 需要連線到附近裝置的權限,以便在 KDE Connect 中使用藍牙進行配對</string>
<string name="location_permission_needed_desc">KDE Connect 需要背景位置權限,才能在背景執行時也能知道您目前所連線的 WiFi 網路。這是因為您週遭的 WiFi 網路名稱可以被用來推斷您的位置,即使這不是 KDE Connect 在做的事情。</string>
<string name="clipboard_android_x_incompat">Android 10 已移除所有應用程式的剪貼簿存取權限。此外掛程式將停用。</string>
<string name="mpris_open_url">繼續在此播放</string>
<string name="cant_open_url">無法開啟 URL 以繼續播放</string>
@@ -329,12 +335,12 @@
<string name="bigscreen_right"></string>
<string name="bigscreen_down"></string>
<string name="bigscreen_mic">麥克風</string>
<string name="pref_plugin_bigscreen">全覽螢幕遠端</string>
<string name="pref_plugin_bigscreen_desc">裝置作為 Plasma 全覽螢幕的遠端控制</string>
<string name="bigscreen_optional_permission_explanation">為了與電腦共享手機麥克風端的音效輸入,需要您允許本軟體存取手機的音輸入權限</string>
<string name="pref_plugin_bigscreen">大螢幕遙控器</string>
<string name="pref_plugin_bigscreen_desc">使用您的裝置作為 Plasma Bigscreen 的遙控</string>
<string name="bigscreen_optional_permission_explanation">為了與電腦共享手機麥克風端的音效輸入,需要您允許本軟體存取手機的音輸入權限</string>
<string name="bigscreen_speech_extra_prompt">聲控功能</string>
<string name="message_reply_label">回覆</string>
<string name="mark_as_read_label">為已讀</string>
<string name="mark_as_read_label">為已讀</string>
<string name="user_display_name"></string>
<string name="set_default_sms_app_title">傳送 MMS</string>
<string name="set_group_message_as_mms_title">傳送群組 MMS</string>
@@ -367,7 +373,7 @@
<string name="authors">作者群</string>
<string name="thanks_to">感謝</string>
<string name="easter_egg">Easter Egg</string>
<string name="email_contributor">發信給貢獻者\n%s</string>
<string name="email_contributor">傳送電子郵件給貢獻者\n%s</string>
<string name="visit_contributors_homepage">造訪貢獻者的首頁\n%s</string>
<string name="version">版本 %s</string>
<string name="about_kde">關於 KDE</string>
@@ -376,13 +382,13 @@
<string name="konqi">Konqi</string>
<string name="rise_up">往上</string>
<string name="rise_down">往下</string>
<string name="click_here_to_type">這裡打字</string>
<string name="click_here_to_type">點擊這裡打字</string>
<string name="clear_compose">清除</string>
<string name="send_compose">傳送</string>
<string name="compose_send_title">撰寫傳送</string>
<string name="open_compose_send">撰寫簡訊</string>
<string name="double_tap_to_drag">雙擊拖曳</string>
<string name="hold_to_drag">按住拖曳</string>
<string name="double_tap_to_drag">雙擊拖曳</string>
<string name="hold_to_drag">按住拖曳</string>
<string name="about_kde_about">&lt;h1&gt;關於&lt;/h1&gt;&lt;p&gt;KDE 是一個由眾多軟體工程師、藝術作業者、文字作業者、翻譯人員和其他有志於&lt;a href=https://www.gnu.org/philosophy/free-sw.html&gt;自由軟體&lt;/a&gt;事業的人們組成的世界性社群。KDE 做出了 Plasma 桌面環境、數百個應用程式和支援它們的軟體函式庫。&lt;/p&gt;&lt;p&gt;KDE 團隊不受任何單獨的團體、公司或機構控制。我們的目標是一同為製作世界上最好的自由軟體而努力。我們歡迎任何人&lt;a href=https://community.kde.org/Get_Involved&gt;加入並作出貢獻&lt;/a&gt;——包含您。&lt;/p&gt;請造訪 &lt;a href=&amp;quot;https://www.kde.org/&amp;quot;&gt;https://www.kde.org/&lt;/a&gt; 來了解有關 KDE 社群與我們所做的軟體的更多資訊。</string>
<string name="about_kde_report_bugs_or_wishes">&lt;h1&gt;回報問題或希望功能&lt;/h1&gt;&lt;p&gt;軟體總是可以改善,而 KDE 團隊準備好繼續此項工作。不過您 — 作為使用者 — 需要在有東西沒有正常運作或是可以更好的時候告訴我們。&lt;/p&gt;&lt;p&gt;KDE 有一個問題追蹤系統。請造訪 &lt;a href=https://bugs.kde.org/&gt;https://bugs.kde.org/&lt;/a&gt; 或是從關於頁面使用「回報問題」按鈕來回報問題。&lt;/p&gt;如果您有改善的建議您也可以使用問題追蹤系統來寫下您的希望。此時請使用「Wishlist」願望清單作為問題的嚴重程度。</string>
<string name="about_kde_join_kde">&lt;h1&gt;加入 KDE&lt;/h1&gt;&lt;p&gt;您不需要是軟體工程師也能加入 KDE 團隊。您可以加入翻譯團隊來翻譯程式的介面。您可以提供圖形、佈景主題、音效,或幫忙撰寫文件,看您喜歡做哪一項。&lt;/p&gt;&lt;p&gt;請參考 &lt;a href=https://community.kde.org/Get_Involved&gt;https://community.kde.org/Get_Involved&lt;/a&gt; 上的資訊看看您能幫上什麼忙。&lt;/p&gt;如果您需要更多資訊或說明文件,請參照 &lt;a href=https://techbase.kde.org/&gt;https://techbase.kde.org/&lt;/a&gt;,上面會有一些能幫忙您的資訊。</string>
@@ -394,21 +400,26 @@
<string name="samoilenko_yuri_task">SFTP 的實作、錯誤修正與一般改進</string>
<string name="aniket_kumar_task">簡訊外掛程式的改善</string>
<string name="alex_fiestas_task">聯絡人外掛程式的改善</string>
<string name="maxim_leshchenko_task">使用者介面的改善,以及這個關於頁面</string>
<string name="maxim_leshchenko_task">使用者介面的改善,以及此「關於頁面</string>
<string name="holger_kaelberer_task">遠端鍵盤外掛程式與問題修正</string>
<string name="saikrishna_arcot_task">在遠端輸入外掛程式中對於鍵盤的支援、錯誤修正一般改進</string>
<string name="shellwen_chen_task">改善 SFTP 的安全性、改善專案的維護性錯誤修正一般改進</string>
<string name="everyone_else">其他所有這些年來 KDE 連線貢獻的人們</string>
<string name="saikrishna_arcot_task">支援在遠端輸入外掛程式中使用鍵盤、錯誤修正一般改進</string>
<string name="shellwen_chen_task">改善 SFTP 的安全性、改善專案的維護性錯誤修正一般改進</string>
<string name="everyone_else">這些年來 KDE Connect 做出貢獻的所有其他人</string>
<string name="send_clipboard">傳送剪貼簿</string>
<string name="tap_to_execute">按一下執行</string>
<string name="tap_to_execute">點擊以執行</string>
<string name="plugin_stats">外掛程式統計</string>
<string name="enable_udp_broadcast">啟用 UDP 裝置探索</string>
<string name="enable_bluetooth">啟用藍牙 (beta)</string>
<string name="receive_notifications_permission_explanation">需要允許通知才能接收來自其他裝置通知</string>
<string name="findmyphone_notifications_explanation">需要通知權限應用程式在背景時也能讓手機響鈴</string>
<string name="no_notifications">通知已停用,您不會收到送來的配對請求</string>
<string name="receive_notifications_permission_explanation">需要允許其他裝置收到通知</string>
<string name="findmyphone_notifications_explanation">需要通知權限,以便當應用程式在背景時手機可以響鈴</string>
<string name="no_notifications">通知已停用,您不會收到傳入的配對通知</string>
<string name="mpris_keepwatching">繼續播放</string>
<string name="mpris_keepwatching_settings_title">繼續播放</string>
<string name="mpris_keepwatching_settings_summary">關閉媒體後在此裝置顯示繼續播放用的靜音通知</string>
<string name="mpris_keepwatching_settings_summary">顯示無聲通知以在關閉媒體後繼續在此裝置上播放</string>
<string name="notification_channel_keepwatching">繼續播放</string>
<string name="ping_result">成功傳送測試封包,花費 %1$d 毫秒</string>
<string name="ping_failed">無法向裝置傳送測試封包</string>
<string name="ping_in_progress">正在傳送測試封包…</string>
<string name="device_host_invalid">主機是無效的。請使用有效的主機名稱、IPv4 位址或 IPv6 位址</string>
<string name="device_host_duplicate">主機已在清單中</string>
</resources>

View File

@@ -176,6 +176,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="error_not_reachable">Device not reachable</string>
<string name="error_already_paired">Device already paired</string>
<string name="error_timed_out">Timed out</string>
<string name="error_clocks_not_match">Device clocks are out of sync</string>
<string name="error_canceled_by_user">Canceled by user</string>
<string name="error_canceled_by_other_peer">Canceled by other peer</string>
<string name="encryption_info_title">Encryption Info</string>
@@ -226,9 +227,11 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="middle_click">Send Middle Click</string>
<string name="show_keyboard">Show Keyboard</string>
<string name="device_not_paired">Device not paired</string>
<string name="pairing_duplicate_names">Caution: There are multiple devices with the same name.</string>
<string name="request_pairing">Request pairing</string>
<string name="pairing_accept">Accept</string>
<string name="pairing_reject">Reject</string>
<string name="pairing_explanation">Pairing two devices will give them access to each other. Only pair together your own devices.</string>
<string name="settings">Settings</string>
<string name="mpris_play">Play</string>
<string name="mpris_pause">Pause</string>
@@ -263,12 +266,15 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="mpris_notification_key" translatable="false">mpris_notification_enabled</string>
<string name="share_to">Share to…</string>
<string name="unreachable_device">%s (Unreachable)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">URLs shared to an unreachable device will be delivered to it once it becomes reachable.\n\n</string>
<string name="protocol_version">Protocol version:</string>
<string name="protocol_version_newer">This device uses a newer protocol version</string>
<string name="plugin_settings_with_name">%s settings</string>
<string name="invalid_device_name">Invalid device name</string>
<string name="shareplugin_text_saved">Received text, saved to clipboard</string>
<string name="custom_devices_settings">Custom device list</string>
<string name="custom_devices_settings_summary">%d devices added manually</string>
<string name="custom_device_list">Add devices by IP</string>
<string name="custom_device_deleted">Custom device deleted</string>
<string name="custom_device_list_help">If your device is not automatically detected you can add its IP address or hostname by clicking on the Floating Action Button</string>
@@ -398,6 +404,9 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="settings_rename">Device name</string>
<string name="settings_dark_mode">Dark theme</string>
<string name="settings_export_logs">Export KDE Connect logs</string>
<string name="settings_export_logs_text">Generate a file with execution information that can help troubleshoot issues.</string>
<string name="settings_more_settings_title">More settings</string>
<string name="settings_more_settings_text">Per-device settings can be found under \'Plugin settings\' from within a device.</string>
<string name="setting_persistent_notification">Show persistent notification</string>
@@ -581,4 +590,11 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="mpris_keepwatching_settings_summary">Show a silent notification to continue playing on this device after closing media</string>
<string name="notification_channel_keepwatching">Continue playing</string>
<string name="ping_result">Pinged in %1$d milliseconds</string>
<string name="ping_failed">Could not ping device</string>
<string name="ping_in_progress">Pinging…</string>
<string name="device_host_invalid">Host is invalid. Use a valid hostname, IPv4, or IPv6</string>
<string name="device_host_duplicate">Host already exists in the list</string>
</resources>

View File

@@ -3,11 +3,9 @@ pluginManagement {
gradlePluginPortal()
google()
mavenCentral()
/* Needed for org.apache.sshd debugging
maven {
url = uri("https://jitpack.io")
}
*/
}
}
dependencyResolutionManagement {

View File

@@ -24,13 +24,16 @@ import java.io.Reader
import java.util.UUID
import kotlin.text.Charsets.UTF_8
class BluetoothLink(context: Context?, connection: ConnectionMultiplexer, input: InputStream, output: OutputStream, remoteAddress: BluetoothDevice, deviceInfo: DeviceInfo, linkProvider: BluetoothLinkProvider) : BaseLink(context!!, linkProvider) {
private val connection: ConnectionMultiplexer?
private val input: InputStream
private val output: OutputStream
private val remoteAddress: BluetoothDevice
private val linkProvider: BluetoothLinkProvider
private val deviceInfo: DeviceInfo
class BluetoothLink(
context: Context?,
connection: ConnectionMultiplexer,
val input: InputStream,
val output: OutputStream,
val remoteAddress: BluetoothDevice,
val theDeviceInfo: DeviceInfo,
val linkProvider: BluetoothLinkProvider
) : BaseLink(context!!, linkProvider) {
private val connection: ConnectionMultiplexer? = connection
private var continueAccepting = true
private val receivingThread = Thread(object : Runnable {
override fun run() {
@@ -64,8 +67,7 @@ class BluetoothLink(context: Context?, connection: ConnectionMultiplexer, input:
}
private fun processMessage(message: String) {
val np: NetworkPacket
np = try {
val np = try {
NetworkPacket.unserialize(message)
} catch (e: JSONException) {
Log.e("BluetoothLink/receiving", "Unable to parse message.", e)
@@ -84,15 +86,6 @@ class BluetoothLink(context: Context?, connection: ConnectionMultiplexer, input:
}
})
init {
this.connection = connection
this.input = input
this.output = output
this.deviceInfo = deviceInfo
this.remoteAddress = remoteAddress
this.linkProvider = linkProvider
}
fun startListening() {
receivingThread.start()
}
@@ -102,7 +95,7 @@ class BluetoothLink(context: Context?, connection: ConnectionMultiplexer, input:
}
override fun getDeviceInfo(): DeviceInfo {
return deviceInfo
return theDeviceInfo
}
override fun disconnect() {

View File

@@ -35,6 +35,7 @@ import java.io.Reader
import java.security.cert.CertificateException
import java.util.UUID
import kotlin.text.Charsets.UTF_8
import androidx.core.content.edit
class BluetoothLinkProvider(private val context: Context) : BaseLinkProvider() {
private val visibleDevices: MutableMap<String, BluetoothLink> = HashMap()
@@ -138,9 +139,9 @@ class BluetoothLinkProvider(private val context: Context) : BaseLinkProvider() {
} catch (e: SecurityException) {
Log.e("KDEConnect", "Security Exception for CONNECT", e)
val prefenceEditor = PreferenceManager.getDefaultSharedPreferences(context).edit()
prefenceEditor.putBoolean(SettingsFragment.KEY_BLUETOOTH_ENABLED, false)
prefenceEditor.apply()
PreferenceManager.getDefaultSharedPreferences(context).edit {
putBoolean(SettingsFragment.KEY_BLUETOOTH_ENABLED, false)
}
return
}

View File

@@ -21,7 +21,7 @@ import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
private class ChannelInputStream constructor(val channel: Channel) : InputStream(), Closeable {
private class ChannelInputStream(val channel: Channel) : InputStream(), Closeable {
override fun available(): Int {
return channel.available()
}
@@ -49,7 +49,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
}
}
private class ChannelOutputStream constructor(val channel: Channel) : OutputStream(), Closeable {
private class ChannelOutputStream(val channel: Channel) : OutputStream(), Closeable {
@Throws(IOException::class)
override fun close() {
channel.close()
@@ -78,7 +78,7 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
}
}
private class Channel constructor(val multiplexer: ConnectionMultiplexer, val id: UUID) : Closeable {
private class Channel(val multiplexer: ConnectionMultiplexer, val id: UUID) : Closeable {
val readBuffer: ByteBuffer = ByteBuffer.allocate(BUFFER_SIZE)
val lock = ReentrantLock()
var lockCondition: Condition = lock.newCondition()
@@ -371,14 +371,9 @@ class ConnectionMultiplexer(socket: BluetoothSocket) : Closeable {
}
}
private inner class ListenRunnable constructor(socket: BluetoothSocket) : Runnable {
var input: InputStream
var output: OutputStream
init {
input = socket.inputStream
output = socket.outputStream
}
private inner class ListenRunnable(socket: BluetoothSocket) : Runnable {
var input: InputStream = socket.inputStream
var output: OutputStream = socket.outputStream
@Throws(IOException::class)
private fun readBuffer(buffer: ByteArray, len: Int) {

View File

@@ -10,8 +10,8 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.net.Network;
import android.os.Build;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.Pair;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@@ -19,20 +19,17 @@ import androidx.annotation.WorkerThread;
import org.json.JSONException;
import org.kde.kdeconnect.Backends.BaseLink;
import org.kde.kdeconnect.Backends.BaseLinkProvider;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.DeviceHost;
import org.kde.kdeconnect.DeviceInfo;
import org.kde.kdeconnect.Helpers.DeviceHelper;
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
import org.kde.kdeconnect.Helpers.ThreadHelper;
import org.kde.kdeconnect.Helpers.TrustedNetworkHelper;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.NetworkPacket;
import org.kde.kdeconnect.UserInterface.CustomDevicesActivity;
import org.kde.kdeconnect.UserInterface.SettingsFragment;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
@@ -58,7 +55,7 @@ import kotlin.text.Charsets;
* WiFi network. The first packet sent over a socket must be an
* {@link DeviceInfo#toIdentityPacket()}.
*
* @see #identityPacketReceived(NetworkPacket, Socket, LanLink.ConnectionStarted)
* @see #identityPacketReceived(NetworkPacket, Socket, LanLink.ConnectionStarted, boolean)
*/
public class LanLinkProvider extends BaseLinkProvider {
@@ -67,20 +64,23 @@ public class LanLinkProvider extends BaseLinkProvider {
final static int MAX_PORT = 1764;
final static int PAYLOAD_TRANSFER_MIN_PORT = 1739;
final static int MAX_IDENTITY_PACKET_SIZE = 1024 * 512;
final static int MAX_UDP_PACKET_SIZE = 1024 * 512;
final static long MILLIS_DELAY_BETWEEN_CONNECTIONS_TO_SAME_DEVICE = 500L;
final static long MILLIS_DELAY_BETWEEN_CONNECTIONS_TO_SAME_DEVICE = 1000L;
private final Context context;
final HashMap<String, LanLink> visibleDevices = new HashMap<>(); // Links by device id
final ConcurrentHashMap<String, Long> lastConnectionTime = new ConcurrentHashMap<>();
final static int MAX_RATE_LIMIT_ENTRIES = 255;
final ConcurrentHashMap<String, Long> lastConnectionTimeByDeviceId = new ConcurrentHashMap<>();
final ConcurrentHashMap<InetAddress, Long> lastConnectionTimeByIp = new ConcurrentHashMap<>();
private ServerSocket tcpServer;
private DatagramSocket udpServer;
private MdnsDiscovery mdnsDiscovery;
private final MdnsDiscovery mdnsDiscovery;
private long lastBroadcast = 0;
private final static long delayBetweenBroadcasts = 200;
@@ -93,30 +93,115 @@ public class LanLinkProvider extends BaseLinkProvider {
super.onConnectionLost(link);
}
Pair<NetworkPacket, Boolean> unserializeReceivedIdentityPacket(String message) {
NetworkPacket identityPacket;
try {
identityPacket = NetworkPacket.unserialize(message);
} catch (JSONException e) {
Log.w("KDE/LanLinkProvider", "Invalid identity packet received: " + e.getMessage());
return null;
}
if (!DeviceInfo.isValidIdentityPacket(identityPacket)) {
Log.w("KDE/LanLinkProvider", "Invalid identity packet received.");
return null;
}
final String deviceId = identityPacket.getString("deviceId");
String myId = DeviceHelper.getDeviceId(context);
if (deviceId.equals(myId)) {
//Ignore my own broadcast
return null;
}
if (rateLimitByDeviceId(deviceId)) {
Log.i("LanLinkProvider", "Discarding second packet from the same device " + deviceId + " received too quickly");
return null;
}
boolean deviceTrusted = isDeviceTrusted(deviceId);
if (!deviceTrusted && !TrustedNetworkHelper.isTrustedNetwork(context)) {
Log.i("KDE/LanLinkProvider", "Ignoring identity packet because the device is not trusted and I'm not on a trusted network.");
return null;
}
return new Pair<>(identityPacket, deviceTrusted);
}
//They received my UDP broadcast and are connecting to me. The first thing they send should be their identity packet.
@WorkerThread
private void tcpPacketReceived(Socket socket) throws IOException {
NetworkPacket networkPacket;
InetAddress address = socket.getInetAddress();
if (rateLimitByIp(address)) {
Log.i("LanLinkProvider", "Discarding second TCP packet from the same ip " + address + " received too quickly");
return;
}
String message;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String message = reader.readLine();
networkPacket = NetworkPacket.unserialize(message);
//Log.e("TcpListener", "Received TCP packet: " + networkPacket.serialize());
message = readSingleLine(socket);
//Log.e("TcpListener", "Received TCP packet: " + identityPacket.serialize());
} catch (Exception e) {
Log.e("KDE/LanLinkProvider", "Exception while receiving TCP packet", e);
return;
}
Log.i("KDE/LanLinkProvider", "identity packet received from a TCP connection from " + networkPacket.getString("deviceName"));
boolean deviceTrusted = isDeviceTrusted(networkPacket.getString("deviceId"));
if (!deviceTrusted && !TrustedNetworkHelper.isTrustedNetwork(context)) {
Log.i("KDE/LanLinkProvider", "Ignoring identity packet because the device is not trusted and I'm not on a trusted network.");
final Pair<NetworkPacket, Boolean> pair = unserializeReceivedIdentityPacket(message);
if (pair == null) {
return;
}
final NetworkPacket identityPacket = pair.first;
final boolean deviceTrusted = pair.second;
identityPacketReceived(networkPacket, socket, LanLink.ConnectionStarted.Locally, deviceTrusted);
Log.i("KDE/LanLinkProvider", "identity packet received from a TCP connection from " + identityPacket.getString("deviceName"));
identityPacketReceived(identityPacket, socket, LanLink.ConnectionStarted.Locally, deviceTrusted);
}
/**
* Read a single line from a socket without consuming anything else from the input.
*/
private String readSingleLine(Socket socket) throws IOException {
InputStream stream = socket.getInputStream();
StringBuilder line = new StringBuilder(MAX_IDENTITY_PACKET_SIZE);
int ch;
while ((ch = stream.read()) != -1) {
line.append((char) ch);
if (ch == '\n') {
return line.toString();
}
if (line.length() >= MAX_IDENTITY_PACKET_SIZE) {
break;
}
}
throw new IOException("Couldn't read a line from the socket");
}
boolean rateLimitByIp(InetAddress address) {
long now = System.currentTimeMillis();
Long last = lastConnectionTimeByIp.get(address);
if (last != null && (last + MILLIS_DELAY_BETWEEN_CONNECTIONS_TO_SAME_DEVICE > now)) {
return true;
}
lastConnectionTimeByIp.put(address, now);
if (lastConnectionTimeByIp.size() > MAX_RATE_LIMIT_ENTRIES) {
lastConnectionTimeByIp.entrySet().removeIf(e -> e.getValue() + MILLIS_DELAY_BETWEEN_CONNECTIONS_TO_SAME_DEVICE < now);
}
return false;
}
boolean rateLimitByDeviceId(String deviceId) {
long now = System.currentTimeMillis();
Long last = lastConnectionTimeByDeviceId.get(deviceId);
if (last != null && (last + MILLIS_DELAY_BETWEEN_CONNECTIONS_TO_SAME_DEVICE > now)) {
return true;
}
lastConnectionTimeByDeviceId.put(deviceId, now);
if (lastConnectionTimeByDeviceId.size() > MAX_RATE_LIMIT_ENTRIES) {
lastConnectionTimeByDeviceId.entrySet().removeIf(e -> e.getValue() + MILLIS_DELAY_BETWEEN_CONNECTIONS_TO_SAME_DEVICE < now);
}
return false;
}
//I've received their broadcast and should connect to their TCP socket and send my identity.
@@ -125,28 +210,21 @@ public class LanLinkProvider extends BaseLinkProvider {
final InetAddress address = packet.getAddress();
if (rateLimitByIp(address)) {
Log.i("LanLinkProvider", "Discarding second UDP packet from the same ip " + address + " received too quickly");
return;
}
String message = new String(packet.getData(), Charsets.UTF_8);
final NetworkPacket identityPacket = NetworkPacket.unserialize(message);
if (!DeviceInfo.isValidIdentityPacket(identityPacket)) {
Log.w("KDE/LanLinkProvider", "Invalid identity packet received.");
final Pair<NetworkPacket, Boolean> pair = unserializeReceivedIdentityPacket(message);
if (pair == null) {
return;
}
final NetworkPacket identityPacket = pair.first;
final boolean deviceTrusted = pair.second;
final String deviceId = identityPacket.getString("deviceId");
String myId = DeviceHelper.getDeviceId(context);
if (deviceId.equals(myId)) {
//Ignore my own broadcast
return;
}
long now = System.currentTimeMillis();
Long last = lastConnectionTime.get(deviceId);
if (last != null && (last + MILLIS_DELAY_BETWEEN_CONNECTIONS_TO_SAME_DEVICE > now)) {
Log.i("LanLinkProvider", "Discarding second UDP packet from the same device " + deviceId + " received too quickly");
return;
}
lastConnectionTime.put(deviceId, now);
Log.i("KDE/LanLinkProvider", "Broadcast identity packet received from " + identityPacket.getString("deviceName"));
int tcpPort = identityPacket.getInt("tcpPort", MIN_PORT);
if (tcpPort < MIN_PORT || tcpPort > MAX_PORT) {
@@ -154,14 +232,6 @@ public class LanLinkProvider extends BaseLinkProvider {
return;
}
Log.i("KDE/LanLinkProvider", "Broadcast identity packet received from " + identityPacket.getString("deviceName"));
boolean deviceTrusted = isDeviceTrusted(identityPacket.getString("deviceId"));
if (!deviceTrusted && !TrustedNetworkHelper.isTrustedNetwork(context)) {
Log.i("KDE/LanLinkProvider", "Ignoring identity packet because the device is not trusted and I'm not on a trusted network.");
return;
}
SocketFactory socketFactory = SocketFactory.getDefault();
Socket socket = socketFactory.createSocket(address, tcpPort);
configureSocket(socket);
@@ -192,12 +262,7 @@ public class LanLinkProvider extends BaseLinkProvider {
/**
* Called when a new 'identity' packet is received. Those are passed here by
* {@link #tcpPacketReceived(Socket)} and {@link #udpPacketReceived(DatagramPacket)}.
* <p>
* Should be called on a new thread since it blocks until the handshake is completed.
* </p><p>
* If the remote device should be connected, this calls {@link #addLink}.
* Otherwise, if there was an Exception, we unpair from that device.
* </p>
*
* @param identityPacket identity of a remote device
* @param socket a new Socket, which should be used to receive packets from the remote device
@@ -206,52 +271,60 @@ public class LanLinkProvider extends BaseLinkProvider {
*/
@WorkerThread
private void identityPacketReceived(final NetworkPacket identityPacket, final Socket socket, final LanLink.ConnectionStarted connectionStarted, final boolean deviceTrusted) throws IOException {
if (!DeviceInfo.isValidIdentityPacket(identityPacket)) {
Log.w("KDE/LanLinkProvider", "Invalid identity packet received.");
return;
}
String myId = DeviceHelper.getDeviceId(context);
final String deviceId = identityPacket.getString("deviceId");
if (deviceId.equals(myId)) {
Log.e("KDE/LanLinkProvider", "Somehow I'm connected to myself, ignoring. This should not happen.");
int protocolVersion = identityPacket.getInt("protocolVersion");
if (deviceTrusted && isProtocolDowngrade(deviceId, protocolVersion)) {
Log.w("KDE/LanLinkProvider", "Refusing to connect to a device using an older protocol version:" + protocolVersion);
return;
}
// If I'm the TCP server I will be the SSL client and viceversa.
final boolean clientMode = (connectionStarted == LanLink.ConnectionStarted.Locally);
if (deviceTrusted && !SslHelper.isCertificateStored(context, deviceId)) {
//Device paired with and old version, we can't use it as we lack the certificate
Device device = KdeConnect.getInstance().getDevice(deviceId);
if (device == null) {
return;
}
device.unpair();
//Retry as unpaired
identityPacketReceived(identityPacket, socket, connectionStarted, deviceTrusted);
Log.e("KDE/LanLinkProvider", "Device trusted but no cert stored. This should not happen.");
return;
}
String deviceName = identityPacket.getString("deviceName", "unknown");
Log.i("KDE/LanLinkProvider", "Starting SSL handshake with " + deviceName + " trusted:" + deviceTrusted);
// If I'm the TCP server I will be the SSL client and viceversa.
final boolean clientMode = (connectionStarted == LanLink.ConnectionStarted.Locally);
final SSLSocket sslSocket = SslHelper.convertToSslSocket(context, socket, deviceId, deviceTrusted, clientMode);
sslSocket.addHandshakeCompletedListener(event -> {
String mode = clientMode ? "client" : "server";
try {
Certificate certificate = event.getPeerCertificates()[0];
DeviceInfo deviceInfo = DeviceInfo.fromIdentityPacketAndCert(identityPacket, certificate);
Log.i("KDE/LanLinkProvider", "Handshake as " + mode + " successful with " + deviceName + " secured with " + event.getCipherSuite());
addOrUpdateLink(sslSocket, deviceInfo);
} catch (IOException e) {
Log.e("KDE/LanLinkProvider", "Handshake as " + mode + " failed with " + deviceName, e);
Device device = KdeConnect.getInstance().getDevice(deviceId);
if (device == null) {
return;
// Start a new thread because some Android versions don't allow calling sslSocket.getOutputStream() from the callback
ThreadHelper.execute(() -> {
String mode = clientMode ? "client" : "server";
try {
NetworkPacket secureIdentityPacket;
if (protocolVersion >= 8) {
DeviceInfo myDeviceInfo = DeviceHelper.getDeviceInfo(context);
NetworkPacket myIdentity = myDeviceInfo.toIdentityPacket();
OutputStream writer = sslSocket.getOutputStream();
writer.write(myIdentity.serialize().getBytes(Charsets.UTF_8));
writer.flush();
String line = readSingleLine(sslSocket);
// Do not trust the identity packet we received unencrypted
secureIdentityPacket = NetworkPacket.unserialize(line);
if (!DeviceInfo.isValidIdentityPacket(secureIdentityPacket)) {
throw new JSONException("Invalid identity packet");
}
int newProtocolVersion = secureIdentityPacket.getInt("protocolVersion");
if (newProtocolVersion != protocolVersion) {
Log.w("KDE/LanLinkProvider", "Protocol version changed half-way through the handshake: " + protocolVersion + " ->" + newProtocolVersion);
}
} else {
secureIdentityPacket = identityPacket;
}
Certificate certificate = event.getPeerCertificates()[0];
DeviceInfo deviceInfo = DeviceInfo.fromIdentityPacketAndCert(secureIdentityPacket, certificate);
Log.i("KDE/LanLinkProvider", "Handshake as " + mode + " successful with " + deviceName + " secured with " + event.getCipherSuite());
addOrUpdateLink(sslSocket, deviceInfo);
} catch (JSONException e) {
Log.e("KDE/LanLinkProvider", "Remote device doesn't correctly implement protocol version 8", e);
} catch (IOException e) {
Log.e("KDE/LanLinkProvider", "Handshake as " + mode + " failed with " + deviceName, e);
}
device.unpair();
}
});
});
//Handshake is blocking, so do it on another thread and free this thread to keep receiving new connection
@@ -260,6 +333,12 @@ public class LanLinkProvider extends BaseLinkProvider {
Log.d("LanLinkProvider", "Handshake done");
}
private boolean isProtocolDowngrade(String deviceId, int protocolVersion) {
SharedPreferences devicePrefs = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE);
int lastKnownProtocolVersion = devicePrefs.getInt("protocolVersion", 0);
return lastKnownProtocolVersion > protocolVersion;
}
/**
* Add or update a link in the {@link #visibleDevices} map.
*
@@ -377,26 +456,20 @@ public class LanLinkProvider extends BaseLinkProvider {
}
private void broadcastUdpIdentityPacket(@Nullable Network network) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if (!preferences.getBoolean(SettingsFragment.KEY_UDP_BROADCAST_ENABLED, true)) {
Log.i("LanLinkProvider", "UDP broadcast is disabled in settings. Skipping.");
return;
}
ThreadHelper.execute(() -> {
List<String> ipStringList = CustomDevicesActivity
.getCustomDeviceList(PreferenceManager.getDefaultSharedPreferences(context));
List<DeviceHost> hostList = CustomDevicesActivity
.getCustomDeviceList(context);
if (TrustedNetworkHelper.isTrustedNetwork(context)) {
ipStringList.add("255.255.255.255"); //Default: broadcast.
hostList.add(DeviceHost.BROADCAST); //Default: broadcast.
} else {
Log.i("LanLinkProvider", "Current network isn't trusted, not broadcasting");
}
ArrayList<InetAddress> ipList = new ArrayList<>();
for (String ip : ipStringList) {
for (DeviceHost host : hostList) {
try {
ipList.add(InetAddress.getByName(ip));
ipList.add(InetAddress.getByName(host.toString()));
} catch (UnknownHostException e) {
e.printStackTrace();
}
@@ -417,6 +490,8 @@ public class LanLinkProvider extends BaseLinkProvider {
return;
}
// TODO: In protocol version 8 this packet doesn't need to contain identity info
// since it will be exchanged after the socket is encrypted.
DeviceInfo myDeviceInfo = DeviceHelper.getDeviceInfo(context);
NetworkPacket identity = myDeviceInfo.toIdentityPacket();
identity.set("tcpPort", tcpServer.getLocalPort());
@@ -470,7 +545,9 @@ public class LanLinkProvider extends BaseLinkProvider {
setupTcpListener();
mdnsDiscovery.startDiscovering();
mdnsDiscovery.startAnnouncing();
if (TrustedNetworkHelper.isTrustedNetwork(context)) {
mdnsDiscovery.startAnnouncing();
}
broadcastUdpIdentityPacket(null);
}

View File

@@ -41,7 +41,7 @@ public class MdnsDiscovery {
this.lanLinkProvider = lanLinkProvider;
this.mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
this.mNsdResolveQueue = new NsdResolveQueue(this.mNsdManager);
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
multicastLock = wifiManager.createMulticastLock("kdeConnectMdnsMulticastLock");
}
@@ -132,7 +132,7 @@ public class MdnsDiscovery {
// Also, on Android Lollipop those fields aren't resolved.
String deviceName = DeviceHelper.getDeviceName(context);
String deviceType = DeviceHelper.getDeviceType().toString();
String protocolVersion = Integer.toString(DeviceHelper.ProtocolVersion);
String protocolVersion = Integer.toString(DeviceHelper.PROTOCOL_VERSION);
serviceInfo.setAttribute("id", deviceId);
serviceInfo.setAttribute("name", deviceName);
serviceInfo.setAttribute("type", deviceType);
@@ -216,6 +216,9 @@ public class MdnsDiscovery {
// Let the LanLinkProvider handle the connection
InetAddress remoteAddress = serviceInfo.getHost();
// TODO: In protocol version 8 we should be able to call "identityPacketReceived"
// here, since we already have all the info we need to start a connection
// and the remaining identity info will be exchanged later.
lanLinkProvider.sendUdpIdentityPacket(Collections.singletonList(remoteAddress), null);
}
};

View File

@@ -50,7 +50,7 @@ import org.kde.kdeconnect_tp.R
class BackgroundService : Service() {
private lateinit var applicationInstance: KdeConnect
private val linkProviders = ArrayList<BaseLinkProvider>()
private val linkProviders = mutableListOf<BaseLinkProvider>()
private val connectedToNonCellularNetwork = MutableLiveData<Boolean>()
/** Indicates whether device is connected over wifi / usb / bluetooth / (anything other than cellular) */
@@ -67,7 +67,7 @@ class BackgroundService : Service() {
private fun registerLinkProviders() {
linkProviders.add(LanLinkProvider(this))
// linkProviders.add(new LoopbackLinkProvider(this));
//linkProviders.add(LoopbackLinkProvider(this))
linkProviders.add(BluetoothLinkProvider(this))
}
@@ -148,8 +148,8 @@ class BackgroundService : Service() {
private fun createForegroundNotification(): Notification {
// Why is this needed: https://developer.android.com/guide/components/services#Foreground
val connectedDevices = ArrayList<String>()
val connectedDeviceIds = ArrayList<String>()
val connectedDevices = mutableListOf<String>()
val connectedDeviceIds = mutableListOf<String>()
for (device in applicationInstance.devices.values) {
if (device.isReachable && device.isPaired) {
connectedDeviceIds.add(device.deviceId)

View File

@@ -33,7 +33,6 @@ import org.kde.kdeconnect.DeviceStats.countReceived
import org.kde.kdeconnect.DeviceStats.countSent
import org.kde.kdeconnect.Helpers.DeviceHelper
import org.kde.kdeconnect.Helpers.NotificationHelper
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper
import org.kde.kdeconnect.PairingHandler.PairingCallback
import org.kde.kdeconnect.Plugins.Plugin
import org.kde.kdeconnect.Plugins.Plugin.Companion.getPluginKey
@@ -46,6 +45,7 @@ import java.util.Vector
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentMap
import java.util.concurrent.CopyOnWriteArrayList
import androidx.core.content.edit
class Device : PacketReceiver {
@@ -150,25 +150,27 @@ class Device : PacketReceiver {
val deviceType: DeviceType
get() = deviceInfo.type
val protocolVersion: Int
get() = deviceInfo.protocolVersion
val deviceId: String
get() = deviceInfo.id
val certificate: Certificate
get() = deviceInfo.certificate
val verificationKey: String?
get() = pairingHandler.verificationKey()
// Returns 0 if the version matches, < 0 if it is older or > 0 if it is newer
fun compareProtocolVersion(): Int =
deviceInfo.protocolVersion - DeviceHelper.ProtocolVersion
deviceInfo.protocolVersion - DeviceHelper.PROTOCOL_VERSION
val isPaired: Boolean
get() = pairingHandler.state == PairingHandler.PairState.Paired
val isPairRequested: Boolean
get() = pairingHandler.state == PairingHandler.PairState.Requested
val isPairRequestedByPeer: Boolean
get() = pairingHandler.state == PairingHandler.PairState.RequestedByPeer
val pairStatus : PairingHandler.PairState
get() = pairingHandler.state
fun addPairingCallback(callback: PairingCallback) = pairingCallbacks.add(callback)
@@ -207,7 +209,7 @@ class Device : PacketReceiver {
// Store as trusted device
val preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE)
preferences.edit().putBoolean(deviceInfo.id, true).apply()
preferences.edit { putBoolean(deviceInfo.id, true) }
try {
reloadPluginsFromSettings()
@@ -226,10 +228,10 @@ class Device : PacketReceiver {
override fun unpaired() {
Log.i("Device", "unpaired, removing from trusted devices list")
val preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE)
preferences.edit().remove(deviceInfo.id).apply()
preferences.edit { remove(deviceInfo.id) }
val devicePreferences = context.getSharedPreferences(deviceInfo.id, Context.MODE_PRIVATE)
devicePreferences.edit().clear().apply()
devicePreferences.edit { clear() }
pairingCallbacks.forEach(PairingCallback::unpaired)
@@ -286,8 +288,6 @@ class Device : PacketReceiver {
val notificationManager = ContextCompat.getSystemService(context, NotificationManager::class.java)!!
val verificationKey = SslHelper.getVerificationKey(SslHelper.certificate, deviceInfo.certificate)
val noti = NotificationCompat.Builder(context, NotificationHelper.Channels.DEFAULT)
.setContentTitle(res.getString(R.string.pairing_request_from, name))
.setContentText(res.getString(R.string.pairing_verification_code, verificationKey))
@@ -358,10 +358,11 @@ class Device : PacketReceiver {
fun updateDeviceInfo(newDeviceInfo: DeviceInfo): Boolean {
var hasChanges = false
if (deviceInfo.name != newDeviceInfo.name || deviceInfo.type != newDeviceInfo.type) {
if (deviceInfo.name != newDeviceInfo.name || deviceInfo.type != newDeviceInfo.type || deviceInfo.protocolVersion != newDeviceInfo.protocolVersion) {
hasChanges = true
deviceInfo.name = newDeviceInfo.name
deviceInfo.type = newDeviceInfo.type
deviceInfo.protocolVersion = newDeviceInfo.protocolVersion
if (isPaired) {
deviceInfo.saveInSettings(settings)
}
@@ -595,7 +596,7 @@ class Device : PacketReceiver {
}
fun setPluginEnabled(pluginKey: String, value: Boolean) {
settings.edit().putBoolean(pluginKey, value).apply()
settings.edit { putBoolean(pluginKey, value) }
reloadPluginsFromSettings()
}

View File

@@ -0,0 +1,65 @@
package org.kde.kdeconnect
import org.kde.kdeconnect.Helpers.ThreadHelper
import java.net.InetAddress
class DeviceHost private constructor(private val host: String) {
// Wrapper because Kotlin doesn't allow nested nullability
data class PingResult(val latency: Long?)
/** The amount of milliseconds the ping request took or null it's in progress */
var ping: PingResult? = null
private set
/**
* Checks if the host can be reached over the network.
* @param callback Callback for updating UI elements
*/
fun checkReachable(callback: () -> Unit) {
ThreadHelper.execute {
try {
val address = InetAddress.getByName(this.host)
val startTime = System.currentTimeMillis()
val pingable = address.isReachable(PING_TIMEOUT)
val delayMillis = System.currentTimeMillis() - startTime
val pingResult = PingResult(if (pingable) delayMillis else null)
ping = pingResult
}
catch (_: Exception) {
ping = PingResult(null)
}
callback()
}
}
init {
require(isValidDeviceHost(host)) { "Invalid host" }
}
override fun toString(): String {
return this.host
}
companion object {
/** Ping timeout */
private const val PING_TIMEOUT = 3_000
private val hostnameValidityPattern = Regex("^[0-9A-Za-z._-]+$")
@JvmStatic
fun isValidDeviceHost(host: String): Boolean {
return hostnameValidityPattern.matches(host)
}
@JvmStatic
fun toDeviceHostOrNull(host: String): DeviceHost? {
return if (isValidDeviceHost(host)) {
DeviceHost(host)
} else {
null
}
}
@JvmField
val BROADCAST: DeviceHost = DeviceHost("255.255.255.255")
}
}

View File

@@ -44,6 +44,7 @@ class DeviceInfo(
putString("certificate", encodedCertificate)
putString("deviceName", name)
putString("deviceType", type.toString())
putInt("protocolVersion", protocolVersion)
apply()
}
} catch (e: CertificateEncodingException) {
@@ -58,12 +59,12 @@ class DeviceInfo(
*/
fun toIdentityPacket(): NetworkPacket =
NetworkPacket(NetworkPacket.PACKET_TYPE_IDENTITY).also { np ->
np.set("deviceId", id)
np.set("deviceName", name)
np.set("protocolVersion", protocolVersion)
np.set("deviceType", type.toString())
np.set("incomingCapabilities", incomingCapabilities!!)
np.set("outgoingCapabilities", outgoingCapabilities!!)
np["deviceId"] = id
np["deviceName"] = name
np["protocolVersion"] = protocolVersion
np["deviceType"] = type.toString()
np["incomingCapabilities"] = incomingCapabilities!!
np["outgoingCapabilities"] = outgoingCapabilities!!
}
companion object {
@@ -79,7 +80,8 @@ class DeviceInfo(
id = deviceId,
name = getString("deviceName", "unknown")!!,
type = DeviceType.fromString(getString("deviceType", "desktop")!!),
certificate = SslHelper.getDeviceCertificate(context, deviceId)
certificate = SslHelper.getDeviceCertificate(context, deviceId),
protocolVersion = getInt("protocolVersion", 0),
)
}
@@ -105,8 +107,13 @@ class DeviceInfo(
fun isValidIdentityPacket(identityPacket: NetworkPacket): Boolean = with(identityPacket) {
type == NetworkPacket.PACKET_TYPE_IDENTITY &&
DeviceHelper.filterName(getString("deviceName", "")).isNotBlank() &&
getString("deviceId", "").isNotBlank()
isValidDeviceId(getString("deviceId", ""))
}
private val DEVICE_ID_REGEX = "^[a-zA-Z0-9_-]{32,38}$".toRegex()
@JvmStatic
fun isValidDeviceId(deviceId: String): Boolean = deviceId.matches(DEVICE_ID_REGEX)
}
}

View File

@@ -115,7 +115,7 @@ object DeviceStats {
val entry = iterator.next()
val events = entry.value
var index = Collections.binarySearch(events, cutoutTimestamp)
var index = events.binarySearch(cutoutTimestamp)
if (index < 0) {
index = -(index + 1) // Convert the negative index to insertion point
}

View File

@@ -91,7 +91,7 @@ public final class CollectionsBackport {
}
static boolean eq(Object o1, Object o2) {
return o1 == null ? o2 == null : o1.equals(o2);
return Objects.equals(o1, o2);
}
static class UnmodifiableNavigableSetBackport<E>

View File

@@ -214,7 +214,7 @@ public class ContactsHelper {
Map<uID, Map<String, String>> databaseValue = accessContactsDatabase(context, projection, selection, selectionArgs, null);
if (databaseValue.size() == 0) {
if (databaseValue.isEmpty()) {
throw new ContactNotFoundException("Querying for contact with id " + contactID + " returned no results.");
}

View File

@@ -0,0 +1,27 @@
package org.kde.kdeconnect.Helpers
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.activity.result.contract.ActivityResultContract
data class CreateFileParams(
val fileMimeType: String,
val suggestedFileName: String,
)
class CreateFileResultContract : ActivityResultContract<CreateFileParams, Uri?>() {
override fun createIntent(context: Context, input: CreateFileParams): Intent =
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
setTypeAndNormalize(input.fileMimeType)
putExtra(Intent.EXTRA_TITLE, input.suggestedFileName)
}
override fun parseResult(resultCode: Int, intent: Intent?): Uri? = when (resultCode) {
Activity.RESULT_OK -> intent?.data
else -> null
}
}

View File

@@ -11,7 +11,6 @@ import android.content.res.Configuration
import android.content.res.Resources
import android.os.Build
import android.preference.PreferenceManager
import android.provider.Settings
import android.util.Log
import com.univocity.parsers.common.TextParsingException
import com.univocity.parsers.csv.CsvParser
@@ -26,9 +25,10 @@ import java.io.InputStreamReader
import java.net.URL
import java.nio.charset.StandardCharsets
import java.util.UUID
import androidx.core.content.edit
object DeviceHelper {
const val ProtocolVersion = 7
const val PROTOCOL_VERSION = 8
const val KEY_DEVICE_NAME_PREFERENCE = "device_name_preference"
private const val KEY_DEVICE_NAME_FETCHED_FROM_THE_INTERNET = "device_name_downloaded_preference"
@@ -85,7 +85,7 @@ object DeviceHelper {
// If we get here we managed to download the file. Mark that as done so we don't try again even if we don't end up finding a name.
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
preferences.edit().putBoolean(KEY_DEVICE_NAME_FETCHED_FROM_THE_INTERNET, true).apply()
preferences.edit { putBoolean(KEY_DEVICE_NAME_FETCHED_FROM_THE_INTERNET, true) }
BufferedReader(
InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_16)
@@ -124,26 +124,17 @@ object DeviceHelper {
fun setDeviceName(context: Context, name: String) {
val filteredName = filterName(name)
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
preferences.edit().putString(KEY_DEVICE_NAME_PREFERENCE, filteredName).apply()
preferences.edit { putString(KEY_DEVICE_NAME_PREFERENCE, filteredName) }
}
fun initializeDeviceId(context: Context) {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val preferenceKeys: Set<String> = preferences.all.keys
if (preferenceKeys.contains(KEY_DEVICE_ID_PREFERENCE)) {
val deviceId = preferences.getString(KEY_DEVICE_ID_PREFERENCE, "")!!
if (DeviceInfo.isValidDeviceId(deviceId)) {
return // We already have an ID
}
@SuppressLint("HardwareIds")
val deviceName = if (preferenceKeys.isEmpty()) {
// For new installations, use random IDs
Log.i("DeviceHelper","No device ID found and this looks like a new installation, creating a random ID")
UUID.randomUUID().toString().replace('-', '_')
} else {
// Use the ANDROID_ID as device ID for existing installations, for backwards compatibility
Log.i("DeviceHelper", "No device ID found but this seems an existing installation, using the Android ID")
Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
}
preferences.edit().putString(KEY_DEVICE_ID_PREFERENCE, deviceName).apply()
val deviceName = UUID.randomUUID().toString().replace("-", "")
preferences.edit { putString(KEY_DEVICE_ID_PREFERENCE, deviceName) }
}
@JvmStatic
@@ -159,12 +150,12 @@ object DeviceHelper {
SslHelper.certificate,
getDeviceName(context),
deviceType,
ProtocolVersion,
PROTOCOL_VERSION,
PluginFactory.incomingCapabilities,
PluginFactory.outgoingCapabilities
)
}
@JvmStatic
fun filterName(input: String): String = input.replace(NAME_INVALID_CHARACTERS_REGEX, "").take(MAX_DEVICE_NAME_LENGTH)
fun filterName(input: String): String = input.replace(NAME_INVALID_CHARACTERS_REGEX, "").trim().take(MAX_DEVICE_NAME_LENGTH)
}

View File

@@ -97,7 +97,7 @@ object FilesHelper {
fun contentResolverExtract(): Triple<String?, Long, Long?> {
// Since we used Intent.CATEGORY_OPENABLE, these two columns are the only ones we are guaranteed to have: https://developer.android.com/reference/android/provider/OpenableColumns
val proj = arrayOf(OpenableColumns.SIZE, OpenableColumns.DISPLAY_NAME,)
val proj = arrayOf(OpenableColumns.SIZE, OpenableColumns.DISPLAY_NAME)
try {
contentResolver.query(uri, proj, null, null, null).use { cursor ->

View File

@@ -11,7 +11,6 @@ import android.content.ContentUris
import android.content.Context
import android.database.ContentObserver
import android.database.sqlite.SQLiteException
import android.graphics.Bitmap
import android.media.MediaMetadataRetriever
import android.media.ThumbnailUtils
import android.net.Uri
@@ -23,6 +22,8 @@ import android.telephony.TelephonyManager
import android.util.Log
import android.util.Pair
import androidx.annotation.RequiresApi
import androidx.core.graphics.scale
import androidx.core.net.toUri
import com.google.android.mms.pdu_alt.MultimediaMessagePdu
import com.google.android.mms.pdu_alt.PduPersister
import com.google.android.mms.util_alt.PduCache
@@ -37,13 +38,11 @@ import org.kde.kdeconnect.Helpers.TelephonyHelper.LocalPhoneNumber
import org.kde.kdeconnect.Plugins.SMSPlugin.MimeType
import org.kde.kdeconnect.Plugins.SMSPlugin.SmsMmsUtils
import java.io.IOException
import java.util.Arrays
import java.util.Objects
import java.util.SortedMap
import java.util.TreeMap
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
import java.util.stream.Collectors
import kotlin.text.Charsets.UTF_8
@SuppressLint("InlinedApi")
@@ -52,8 +51,7 @@ object SMSHelper {
private const val THUMBNAIL_WIDTH = 100
// The constant Telephony.Mms.Part.CONTENT_URI was added in API 29
@JvmField
val mMSPartUri : Uri = Uri.parse("content://mms/part/")
val mMSPartUri : Uri = "content://mms/part/".toUri()
/**
* Get the base address for all message conversations
@@ -68,14 +66,14 @@ object SMSHelper {
if ("Samsung".equals(Build.MANUFACTURER, ignoreCase = true)) {
Log.i("SMSHelper", "This appears to be a Samsung device. This may cause some features to not work properly.")
}
return Uri.parse("content://mms-sms/conversations?simple=true")
return "content://mms-sms/conversations?simple=true".toUri()
}
private fun getCompleteConversationsUri(): Uri {
// This glorious - but completely undocumented - content URI gives us all messages, both MMS and SMS,
// in all conversations
// See https://stackoverflow.com/a/36439630/3723163
return Uri.parse("content://mms-sms/complete-conversations")
return "content://mms-sms/complete-conversations".toUri()
}
/**
@@ -94,10 +92,7 @@ object SMSHelper {
* @param context android.content.Context running the request
* @return Timestamp of the oldest known message.
*/
@JvmStatic
fun getNewestMessageTimestamp(
context: Context
): Long {
fun getNewestMessageTimestamp(context: Context): Long {
var oldestMessageTimestamp = Long.MIN_VALUE
val newestMessage = getMessagesInRange(context, null, Long.MAX_VALUE, 1L, true)
// There should only be one, but in case for some reason there are more, take the latest
@@ -117,12 +112,7 @@ object SMSHelper {
* @param numberToGet Number of messages to return. Pass null for "all"
* @return List of all messages in the thread
*/
@JvmStatic
fun getMessagesInThread(
context: Context,
threadID: ThreadID,
numberToGet: Long?
): List<Message> {
fun getMessagesInThread(context: Context, threadID: ThreadID, numberToGet: Long?): List<Message> {
return getMessagesInRange(context, threadID, Long.MAX_VALUE, numberToGet, true)
}
@@ -136,7 +126,6 @@ object SMSHelper {
* @param getMessagesOlderStartTime If true, get messages with timestamps before the startTimestamp. If false, get newer messages
* @return Some messages in the requested conversation
*/
@JvmStatic
@SuppressLint("NewApi")
fun getMessagesInRange(
context: Context,
@@ -441,10 +430,7 @@ object SMSHelper {
* @param context android.content.Context running the request
* @return Non-blocking iterable of the first message in each conversation
*/
@JvmStatic
fun getConversations(
context: Context
): Sequence<Message> {
fun getConversations(context: Context): Sequence<Message> {
val uri = getConversationUri()
// Used to avoid spewing logs in case there is an overall problem with fetching thread IDs
@@ -507,14 +493,10 @@ object SMSHelper {
}
threadTimestampPair.add(Pair(threadID, messageDate))
}
threadIds = threadTimestampPair.stream()
.sorted { left: Pair<ThreadID, Long>, right: Pair<ThreadID, Long> ->
right.second.compareTo(
left.second
)
} // Sort most-recent to least-recent (largest to smallest)
threadIds = threadTimestampPair
// Sort most-recent to least-recent (largest to smallest)
.sortedWith { left: Pair<ThreadID, Long>, right: Pair<ThreadID, Long> -> right.second.compareTo(left.second) }
.map { threadTimestampPairElement: Pair<ThreadID, Long> -> threadTimestampPairElement.first }
.collect(Collectors.toList())
}
// Step 2: Get the actual message object from each thread ID
@@ -538,25 +520,16 @@ object SMSHelper {
}
}
private fun addEventFlag(
oldEvent: Int,
eventFlag: Int
): Int {
private fun addEventFlag(oldEvent: Int, eventFlag: Int): Int {
return oldEvent or eventFlag
}
/**
* Parse all parts of an SMS into a Message
*/
private fun parseSMS(
context: Context,
messageInfo: Map<String, String?>
): Message {
var event = Message.EVENT_UNKNOWN
event = addEventFlag(event, Message.EVENT_TEXT_MESSAGE)
val address = listOf(
Address(context, messageInfo[Telephony.Sms.ADDRESS]!!)
)
private fun parseSMS(context: Context, messageInfo: Map<String, String?>): Message {
val event = addEventFlag(Message.EVENT_UNKNOWN, Message.EVENT_TEXT_MESSAGE)
val address = listOf(Address(context, messageInfo[Telephony.Sms.ADDRESS]!!))
val maybeBody = messageInfo.getOrDefault(Message.BODY, "")
val body = maybeBody ?: ""
val date = NumberUtils.toLong(messageInfo.getOrDefault(Message.DATE, null))
@@ -569,28 +542,14 @@ object SMSHelper {
)
)
val uID = NumberUtils.toLong(messageInfo.getOrDefault(Message.U_ID, null))
val subscriptionID =
NumberUtils.toInt(messageInfo.getOrDefault(Message.SUBSCRIPTION_ID, null))
val subscriptionID = NumberUtils.toInt(messageInfo.getOrDefault(Message.SUBSCRIPTION_ID, null))
// Examine all the required SMS columns and emit a log if something seems amiss
val anyNulls = Arrays.stream(
arrayOf(
Telephony.Sms.ADDRESS,
Message.BODY,
Message.DATE,
Message.TYPE,
Message.READ,
Message.THREAD_ID,
Message.U_ID
)
)
val anyNulls = arrayOf(Telephony.Sms.ADDRESS, Message.BODY, Message.DATE, Message.TYPE, Message.READ, Message.THREAD_ID, Message.U_ID)
.map { key: String -> messageInfo.getOrDefault(key, null) }
.anyMatch { obj: String? -> Objects.isNull(obj) }
.any { obj: String? -> Objects.isNull(obj) }
if (anyNulls) {
Log.e(
"parseSMS",
"Some fields were invalid. This indicates either a corrupted SMS database or an unsupported device."
)
Log.e("parseSMS", "Some fields were invalid. This indicates either a corrupted SMS database or an unsupported device.")
}
return Message(
address,
@@ -610,11 +569,7 @@ object SMSHelper {
* Parse all parts of the MMS message into a message
* Original implementation from https://stackoverflow.com/a/6446831/3723163
*/
private fun parseMMS(
context: Context,
messageInfo: Map<String, String?>,
userPhoneNumbers: List<LocalPhoneNumber>
): Message {
private fun parseMMS(context: Context, messageInfo: Map<String, String?>, userPhoneNumbers: List<LocalPhoneNumber>): Message {
var event = Message.EVENT_UNKNOWN
var body = ""
val read = NumberUtils.toInt(messageInfo[Message.READ])
@@ -695,12 +650,7 @@ object SMSHelper {
)
val videoThumbnail = retriever.frameAtTime
val encodedThumbnail = SmsMmsUtils.bitMapToBase64(
Bitmap.createScaledBitmap(
videoThumbnail!!,
THUMBNAIL_WIDTH,
THUMBNAIL_HEIGHT,
true
)
videoThumbnail!!.scale(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT)
)
attachments.add(
Attachment(
@@ -747,8 +697,8 @@ object SMSHelper {
val to = SmsMmsUtils.getMmsTo(context, msg)
val addresses: MutableList<Address> = ArrayList()
if (from != null) {
val isLocalPhoneNumber = userPhoneNumbers.stream()
.anyMatch { localPhoneNumber: LocalPhoneNumber ->
val isLocalPhoneNumber = userPhoneNumbers
.any { localPhoneNumber: LocalPhoneNumber ->
localPhoneNumber.isMatchingPhoneNumber(from.getAddress())
}
if (!isLocalPhoneNumber && from.toString() != "insert-address-token") {
@@ -757,8 +707,8 @@ object SMSHelper {
}
if (to != null) {
for (toAddress in to) {
val isLocalPhoneNumber = userPhoneNumbers.stream()
.anyMatch { localPhoneNumber: LocalPhoneNumber ->
val isLocalPhoneNumber = userPhoneNumbers
.any { localPhoneNumber: LocalPhoneNumber ->
localPhoneNumber.isMatchingPhoneNumber(toAddress.getAddress())
}
if (!isLocalPhoneNumber && toAddress.toString() != "insert-address-token") {
@@ -837,16 +787,8 @@ object SMSHelper {
*
* @param observer ContentObserver to alert on Message changes
*/
@JvmStatic
fun registerObserver(
observer: ContentObserver,
context: Context
) {
context.contentResolver.registerContentObserver(
getConversationUri(),
true,
observer
)
fun registerObserver(observer: ContentObserver, context: Context) {
context.contentResolver.registerContentObserver(getConversationUri(), true, observer)
}
/**
@@ -862,10 +804,7 @@ object SMSHelper {
* ...
* ]
</String></String></String></Attachment> */
@JvmStatic
fun jsonArrayToAttachmentsList(
jsonArray: JSONArray?
): List<Attachment> {
fun jsonArrayToAttachmentsList(jsonArray: JSONArray?): List<Attachment> {
if (jsonArray == null) {
return emptyList()
}
@@ -887,11 +826,7 @@ object SMSHelper {
/**
* converts a given JSONArray into List<Address>
</Address> */
@JvmStatic
fun jsonArrayToAddressList(context: Context, jsonArray: JSONArray?): List<Address>? {
if (jsonArray == null) {
return null
}
fun jsonArrayToAddressList(context: Context, jsonArray: JSONArray): List<Address> {
val addresses: MutableList<Address> = ArrayList()
try {
for (i in 0 until jsonArray.length()) {
@@ -909,13 +844,9 @@ object SMSHelper {
* Represent an ID used to uniquely identify a message thread
*/
class ThreadID(val threadID: Long) {
override fun toString(): String {
return threadID.toString()
}
override fun toString(): String = threadID.toString()
override fun hashCode(): Int {
return java.lang.Long.hashCode(threadID)
}
override fun hashCode(): Int = java.lang.Long.hashCode(threadID)
override fun equals(other: Any?): Boolean {
return other!!.javaClass.isAssignableFrom(ThreadID::class.java) && (other as ThreadID?)!!.threadID == threadID
@@ -933,9 +864,9 @@ object SMSHelper {
class Attachment(
private val partID: Long,
@JvmField val mimeType: String,
@JvmField val base64EncodedFile: String?,
@JvmField val uniqueIdentifier: String
val mimeType: String,
val base64EncodedFile: String?,
val uniqueIdentifier: String
) {
@Throws(JSONException::class)
@@ -1020,7 +951,7 @@ object SMSHelper {
class Message internal constructor(
private val addresses: List<Address>,
val body: String,
@JvmField val date: Long,
val date: Long,
val type: Int,
val read: Int,
private val threadID: ThreadID,
@@ -1149,7 +1080,7 @@ object SMSHelper {
* Since this means a thread has to be spawned, this method might block until that thread is
* ready to serve requests
*/
@JvmStatic
@JvmStatic // required for ConnectivityReportPlugin.java
fun getLooper(): Looper? {
if (singleton == null) {
looperReadyLock.lock()

View File

@@ -6,6 +6,7 @@
package org.kde.kdeconnect.Helpers.SecurityHelpers;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@@ -23,7 +24,6 @@ import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.util.Arrays;
import org.kde.kdeconnect.Helpers.DeviceHelper;
import org.kde.kdeconnect.Helpers.RandomHelper;
import org.kde.kdeconnect.KdeConnect;
@@ -62,7 +62,7 @@ import javax.security.auth.x500.X500Principal;
public class SslHelper {
public static Certificate certificate; //my device's certificate
private static CertificateFactory factory;
private static final CertificateFactory factory;
static {
try {
factory = CertificateFactory.getInstance("X.509");
@@ -71,20 +71,14 @@ public class SslHelper {
}
}
private final static TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
@SuppressLint({"CustomX509TrustManager", "TrustAllX509TrustManager"})
private final static TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
private final X509Certificate[] issuers = new X509Certificate[0];
@Override public X509Certificate[] getAcceptedIssuers() { return issuers; }
@Override public void checkClientTrusted(X509Certificate[] certs, String authType) { }
@Override public void checkServerTrusted(X509Certificate[] certs, String authType) { }
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
public static void initialiseCertificate(Context context) {
@@ -287,31 +281,4 @@ public class SslHelper {
return IETFUtils.valueToString(rdn.getFirst().getValue());
}
public static String getVerificationKey(Certificate certificateA, Certificate certificateB) {
try {
byte[] a = certificateA.getPublicKey().getEncoded();
byte[] b = certificateB.getPublicKey().getEncoded();
if (Arrays.compareUnsigned(a, b) < 0) {
// Swap them so on both devices they are in the same order
byte[] aux = a;
a = b;
b = aux;
}
byte[] concat = new byte[a.length + b.length];
System.arraycopy(a, 0, concat, 0, a.length);
System.arraycopy(b, 0, concat, a.length, b.length);
byte[] hash = MessageDigest.getInstance("SHA-256").digest(concat);
Formatter formatter = new Formatter();
for (byte value : hash) {
formatter.format("%02x", value);
}
return formatter.toString().substring(0,8).toUpperCase(Locale.ROOT);
} catch(Exception e) {
e.printStackTrace();
return "error";
}
}
}

View File

@@ -6,7 +6,6 @@
package org.kde.kdeconnect.Helpers
import android.net.Uri
import android.provider.DocumentsContract
object StorageHelper {
fun getDisplayName(treeUri: Uri): String {

View File

@@ -13,6 +13,7 @@ import android.net.wifi.WifiManager
import android.preference.PreferenceManager
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.core.content.edit
class TrustedNetworkHelper(private val context: Context) {
@@ -22,19 +23,19 @@ class TrustedNetworkHelper(private val context: Context) {
return serializedNetworks.split(NETWORK_SSID_DELIMITER, "#_#" /* TODO remove old delimiter in 2025 */).filter { it.isNotEmpty() }
}
set(value) {
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putString(KEY_CUSTOM_TRUSTED_NETWORKS, value.joinToString(NETWORK_SSID_DELIMITER))
.apply()
PreferenceManager.getDefaultSharedPreferences(context).edit {
putString(
KEY_CUSTOM_TRUSTED_NETWORKS,
value.joinToString(NETWORK_SSID_DELIMITER)
)
}
}
var allNetworksAllowed: Boolean
get() = !hasPermissions || PreferenceManager.getDefaultSharedPreferences(context).getBoolean(KEY_CUSTOM_TRUST_ALL_NETWORKS, true)
set(value) = PreferenceManager
.getDefaultSharedPreferences(context)
.edit()
.putBoolean(KEY_CUSTOM_TRUST_ALL_NETWORKS, value)
.apply()
set(value) = PreferenceManager.getDefaultSharedPreferences(context).edit {
putBoolean(KEY_CUSTOM_TRUST_ALL_NETWORKS, value)
}
val hasPermissions: Boolean
get() = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED

View File

@@ -13,6 +13,9 @@ object VideoUrlsHelper {
private const val MINUTES_IN_HOUR = 60
private const val SECONDS_IN_HOUR = SECONDS_IN_MINUTE * MINUTES_IN_HOUR
/** PeerTube uses a Flickr Base58 encoded short UUID (alphanumeric, but 0, O, I, and l are excluded) with a length of 22 characters **/
private val peerTubePathPattern = Regex("^/w/[1-9a-km-zA-HJ-NP-Z]{22}(\\?.+)?$")
@Throws(MalformedURLException::class)
fun formatUriWithSeek(address: String, position: Long): URL {
val positionSeconds = position / 1000 // milliseconds to seconds
@@ -33,7 +36,10 @@ object VideoUrlsHelper {
url.editParameter("start", Regex("\\d+")) { "$positionSeconds" }
}
host.contains("twitch.tv") -> {
url.editParameter("t", Regex("(\\d+[hH])?(\\d+[mM])?\\d+[sS]")) { positionSeconds.formatTimestampHMS() }
url.editParameter("t", Regex("(\\d+[hH])?(\\d+[mM])?\\d+[sS]")) { formatTimestampHMS(positionSeconds) }
}
url.path.matches(peerTubePathPattern) -> {
url.editParameter("start", Regex("(\\d+[hH])?(\\d+[mM])?\\d+[sS]")) { formatTimestampHMS(positionSeconds) }
}
else -> url
}
@@ -62,13 +68,16 @@ object VideoUrlsHelper {
return URL("${urlBase}?${modifiedUrlQuery}") // -> "https://www.youtube.com/watch?v=ovX5G0O5ZvA&t=14"
}
/** Formats timestamp to e.g. 01h02m34s */
private fun Long.formatTimestampHMS(): String {
if (this == 0L) return "0s"
/**
* @param timestamp in seconds
* @return timestamp formatted as e.g. "01h02m34s"
* */
private fun formatTimestampHMS(timestamp: Long): String {
if (timestamp == 0L) return "0s"
val seconds: Long = this % SECONDS_IN_MINUTE
val minutes: Long = (this / SECONDS_IN_MINUTE) % MINUTES_IN_HOUR
val hours: Long = this / SECONDS_IN_HOUR
val seconds: Long = timestamp % SECONDS_IN_MINUTE
val minutes: Long = (timestamp / SECONDS_IN_MINUTE) % MINUTES_IN_HOUR
val hours: Long = timestamp / SECONDS_IN_HOUR
fun pad(s: String) = s.padStart(3, '0')
val hoursText = if (hours > 0) pad("${hours}h") else ""

View File

@@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2024 Mash Kyrielight <fiepi@live.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
package org.kde.kdeconnect.Helpers
import android.view.View
import org.kde.kdeconnect.extensions.setupBottomMargin
import org.kde.kdeconnect.extensions.setupBottomPadding
object WindowHelper {
// for java only
@JvmStatic
fun setupBottomPadding(view: View) {
view.setupBottomPadding()
}
// for java only
@JvmStatic
fun setupBottomMargin(view: View) {
view.setupBottomMargin()
}
}

View File

@@ -25,6 +25,7 @@ import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import java.util.Date
import java.util.concurrent.ConcurrentHashMap
import androidx.core.content.edit
/*
* This class holds all the active devices and makes them accessible from every other class.
@@ -116,7 +117,7 @@ class KdeConnect : Application() {
"KdeConnect",
"Couldn't load the certificate for a remembered device. Removing from trusted list.", e
)
preferences.edit().remove(it).apply()
preferences.edit { remove(it) }
}
}
}
@@ -127,7 +128,7 @@ class KdeConnect : Application() {
trustedDevices.filter { preferences.getBoolean(it, false) }
.forEach {
Log.d("KdeConnect", "Removing devices: $it")
preferences.edit().remove(it).apply()
preferences.edit { remove(it) }
}
}

View File

@@ -11,19 +11,15 @@ import org.json.JSONObject
import java.io.ByteArrayInputStream
import java.io.IOException
import java.io.InputStream
import java.lang.RuntimeException
import java.net.Socket
import kotlin.concurrent.Volatile
class NetworkPacket private constructor(
val id: Long,
val type: String,
private val mBody: JSONObject,
var payload: Payload?,
var payloadTransferInfo: JSONObject,
) {
constructor(type: String) : this(
id = System.currentTimeMillis(),
type = type,
mBody = JSONObject(),
payload = null,
@@ -209,7 +205,7 @@ class NetworkPacket private constructor(
@Throws(JSONException::class)
fun serialize(): String {
val jo = JSONObject()
jo.put("id", id)
jo.put("id", System.currentTimeMillis())
jo.put("type", type)
jo.put("body", mBody)
if (hasPayload()) {
@@ -285,14 +281,13 @@ class NetworkPacket private constructor(
@Throws(JSONException::class)
fun unserialize(s: String): NetworkPacket {
val jo = JSONObject(s)
val id = jo.getLong("id")
val type = jo.getString("type")
val mBody = jo.getJSONObject("body")
val hasPayload = jo.has("payloadSize")
val payloadTransferInfo = if (hasPayload) jo.getJSONObject("payloadTransferInfo") else JSONObject()
val payload = if (hasPayload) Payload(jo.getLong("payloadSize")) else null
return NetworkPacket(id, type, mBody, payload, payloadTransferInfo)
return NetworkPacket(type, mBody, payload, payloadTransferInfo)
}
}
}

View File

@@ -8,7 +8,13 @@ package org.kde.kdeconnect
import android.util.Log
import androidx.annotation.VisibleForTesting
import kotlinx.coroutines.*
import org.bouncycastle.util.Arrays
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper
import org.kde.kdeconnect_tp.R
import java.security.MessageDigest
import java.security.cert.Certificate
import java.util.Formatter
import kotlin.math.abs
import kotlin.time.Duration.Companion.seconds
class PairingHandler(private val device: Device, private val callback: PairingCallback, var state: PairState) {
@@ -31,6 +37,7 @@ class PairingHandler(private val device: Device, private val callback: PairingCa
private val pairingJob = SupervisorJob()
private val pairingScope = CoroutineScope(Dispatchers.IO + pairingJob)
private var pairingTimestamp = 0L
fun packetReceived(np: NetworkPacket) {
cancelTimer()
@@ -50,10 +57,26 @@ class PairingHandler(private val device: Device, private val callback: PairingCa
Log.w("PairingHandler", "Received pairing request from a device we already trusted.")
// It would be nice to auto-accept the pairing request here, but since the pairing accept and pairing request
// messages are identical, this could create an infinite loop if both devices are "accepting" each other pairs.
// Instead, unpair and handle as if "NotPaired".
// Instead, unpair and handle as if "NotPaired". TODO: No longer true in protocol version 8
state = PairState.NotPaired
callback.unpaired()
}
if (device.protocolVersion >= 8) {
pairingTimestamp = np.getLong("timestamp", -1L)
if (pairingTimestamp == -1L) {
state = PairState.NotPaired
callback.unpaired()
return
}
val currentTimestamp = System.currentTimeMillis() / 1000L
if (abs(pairingTimestamp - currentTimestamp) > allowedTimestampDifferenceSeconds) {
state = PairState.NotPaired
callback.pairingFailed(device.context.getString(R.string.error_clocks_not_match))
return
}
}
state = PairState.RequestedByPeer
pairingScope.launch {
@@ -85,6 +108,18 @@ class PairingHandler(private val device: Device, private val callback: PairingCa
}
}
fun verificationKey(): String? {
return if (device.protocolVersion >= 8) {
if (state != PairState.Requested && state != PairState.RequestedByPeer) {
return null
} else {
getVerificationKey(SslHelper.certificate, device.certificate, pairingTimestamp)
}
} else {
getVerificationKeyV7(SslHelper.certificate, device.certificate)
}
}
fun requestPairing() {
cancelTimer()
@@ -126,6 +161,8 @@ class PairingHandler(private val device: Device, private val callback: PairingCa
}
val np = NetworkPacket(NetworkPacket.PACKET_TYPE_PAIR)
np["pair"] = true
pairingTimestamp = System.currentTimeMillis() / 1000L
np["timestamp"] = pairingTimestamp
device.sendPacket(np, statusCallback)
}
@@ -181,4 +218,36 @@ class PairingHandler(private val device: Device, private val callback: PairingCa
private fun cancelTimer() {
pairingJob.cancelChildren()
}
companion object {
private const val allowedTimestampDifferenceSeconds = 1_800 // 30 minutes
// Concatenate in a deterministic order so on both devices the result is the same
private fun sortedConcat(a: ByteArray, b: ByteArray): ByteArray {
return if (Arrays.compareUnsigned(a, b) < 0) {
b + a
} else {
a + b
}
}
private fun humanReadableHash(bytes: ByteArray): String {
val hash = MessageDigest.getInstance("SHA-256").digest(bytes)
val formatter = Formatter()
for (value in hash) {
formatter.format("%02x", value)
}
return formatter.toString().substring(0, 8).uppercase()
}
fun getVerificationKey(certificateA: Certificate, certificateB: Certificate, timestamp: Long): String {
val certsConcat = sortedConcat(certificateA.publicKey.encoded, certificateB.publicKey.encoded)
return humanReadableHash(certsConcat + timestamp.toString().toByteArray())
}
fun getVerificationKeyV7(certificateA: Certificate, certificateB: Certificate): String {
val certsConcat = sortedConcat(certificateA.publicKey.encoded, certificateB.publicKey.encoded)
return humanReadableHash(certsConcat)
}
}
}

View File

@@ -15,37 +15,46 @@ import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.annotation.NonNull;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.MainActivity;
import org.kde.kdeconnect.UserInterface.PermissionsAlertDialogFragment;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityBigscreenBinding;
import java.util.ArrayList;
import java.util.Objects;
public class BigscreenActivity extends AppCompatActivity {
import kotlin.Lazy;
import kotlin.LazyKt;
public class BigscreenActivity extends BaseActivity<ActivityBigscreenBinding> {
private static final int REQUEST_SPEECH = 100;
private final Lazy<ActivityBigscreenBinding> lazyBinding = LazyKt.lazy(() -> ActivityBigscreenBinding.inflate(getLayoutInflater()));
@NonNull
@Override
protected ActivityBigscreenBinding getBinding() {
return lazyBinding.getValue();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActivityBigscreenBinding binding = ActivityBigscreenBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbarLayout.toolbar);
setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
final String deviceId = getIntent().getStringExtra("deviceId");
if (!SpeechRecognizer.isRecognitionAvailable(this)) {
binding.micButton.setEnabled(false);
binding.micButton.setVisibility(View.INVISIBLE);
getBinding().micButton.setEnabled(false);
getBinding().micButton.setVisibility(View.INVISIBLE);
}
BigscreenPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, BigscreenPlugin.class);
@@ -54,13 +63,13 @@ public class BigscreenActivity extends AppCompatActivity {
return;
}
binding.leftButton.setOnClickListener(v -> plugin.sendLeft());
binding.rightButton.setOnClickListener(v -> plugin.sendRight());
binding.upButton.setOnClickListener(v -> plugin.sendUp());
binding.downButton.setOnClickListener(v -> plugin.sendDown());
binding.selectButton.setOnClickListener(v -> plugin.sendSelect());
binding.homeButton.setOnClickListener(v -> plugin.sendHome());
binding.micButton.setOnClickListener(v -> {
getBinding().leftButton.setOnClickListener(v -> plugin.sendLeft());
getBinding().rightButton.setOnClickListener(v -> plugin.sendRight());
getBinding().upButton.setOnClickListener(v -> plugin.sendUp());
getBinding().downButton.setOnClickListener(v -> plugin.sendDown());
getBinding().selectButton.setOnClickListener(v -> plugin.sendSelect());
getBinding().homeButton.setOnClickListener(v -> plugin.sendHome());
getBinding().micButton.setOnClickListener(v -> {
if (plugin.hasMicPermission()) {
activateSTT();
} else {

View File

@@ -25,8 +25,6 @@ import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.Plugins.PluginFactory;
import org.kde.kdeconnect_tp.R;
import java.util.Objects;
@PluginFactory.LoadablePlugin
public class BigscreenPlugin extends Plugin {

View File

@@ -25,8 +25,6 @@ import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.Plugins.PluginFactory;
import org.kde.kdeconnect_tp.R;
import java.util.Objects;
@PluginFactory.LoadablePlugin
public class ClipboardPlugin extends Plugin {

View File

@@ -10,26 +10,35 @@ import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import androidx.appcompat.app.AppCompatActivity;
import androidx.annotation.NonNull;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.databinding.ActivityFindMyPhoneBinding;
import java.util.Objects;
public class FindMyPhoneActivity extends AppCompatActivity {
import kotlin.Lazy;
import kotlin.LazyKt;
public class FindMyPhoneActivity extends BaseActivity<ActivityFindMyPhoneBinding> {
static final String EXTRA_DEVICE_ID = "deviceId";
String deviceId;
private final Lazy<ActivityFindMyPhoneBinding> lazyBinding = LazyKt.lazy(() -> ActivityFindMyPhoneBinding.inflate(getLayoutInflater()));
@NonNull
@Override
protected ActivityFindMyPhoneBinding getBinding() {
return lazyBinding.getValue();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActivityFindMyPhoneBinding binding = ActivityFindMyPhoneBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbarLayout.toolbar);
setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
@@ -47,7 +56,7 @@ public class FindMyPhoneActivity extends AppCompatActivity {
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
);
binding.bFindMyPhone.setOnClickListener(view -> finish());
getBinding().bFindMyPhone.setOnClickListener(view -> finish());
}
@Override

View File

@@ -37,7 +37,6 @@ import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
import org.kde.kdeconnect_tp.R;
import java.io.IOException;
import java.util.Objects;
@PluginFactory.LoadablePlugin
public class FindMyPhonePlugin extends Plugin {

View File

@@ -30,6 +30,7 @@ import org.kde.kdeconnect.UserInterface.compose.KdeTextButton
import org.kde.kdeconnect.UserInterface.compose.KdeTextField
import org.kde.kdeconnect.UserInterface.compose.KdeTheme
import org.kde.kdeconnect.UserInterface.compose.KdeTopAppBar
import org.kde.kdeconnect.extensions.safeDrawPadding
import org.kde.kdeconnect_tp.R
private const val INPUT_CACHE_KEY = "compose_send_input_cache"
@@ -91,6 +92,7 @@ class ComposeSendActivity : AppCompatActivity() {
private fun ComposeSendScreen() {
KdeTheme(this) {
Scaffold(
modifier = Modifier.safeDrawPadding(),
topBar = {
KdeTopAppBar(
title = stringResource(R.string.compose_send_title),

Some files were not shown because too many files have changed in this diff Show More