2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-09-04 16:15:09 +00:00

Compare commits

..

3 Commits

Author SHA1 Message Date
Albert Vaca Cintora
4d4f63723e Fix build 2025-07-02 21:14:34 +02:00
Albert Vaca Cintora
568a8e623b Tweaks 2025-07-02 20:31:48 +02:00
Aleix Pol
c3e51d13fe virtual-monitor: Make it possible for the device to act as an rdp host 2025-07-02 19:29:28 +02:00
35 changed files with 403 additions and 264 deletions

View File

@@ -268,7 +268,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name="org.kde.kdeconnect.Plugins.MousePadPlugin.BigscreenActivity" android:name="org.kde.kdeconnect.Plugins.BigscreenPlugin.BigscreenActivity"
android:configChanges="orientation|keyboardHidden|screenSize" android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/pref_plugin_bigscreen" android:label="@string/pref_plugin_bigscreen"
android:exported="true" android:exported="true"
@@ -298,7 +298,6 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:name="android.support.PARENT_ACTIVITY" android:name="android.support.PARENT_ACTIVITY"
android:value="org.kde.kdeconnect.Plugins.MousePadPlugin.MousePadActivity" /> android:value="org.kde.kdeconnect.Plugins.MousePadPlugin.MousePadActivity" />
</activity> </activity>
<!-- TODO: Remove? This is only used by https://github.com/andOTP/andOTP, which is unmaintained since 2021. Do people use forks or can we remove this? -->
<activity <activity
android:name="org.kde.kdeconnect.Plugins.MousePadPlugin.SendKeystrokesToHostActivity" android:name="org.kde.kdeconnect.Plugins.MousePadPlugin.SendKeystrokesToHostActivity"
android:label="@string/pref_plugin_mousepad_send_keystrokes" android:label="@string/pref_plugin_mousepad_send_keystrokes"

View File

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

View File

@@ -1,9 +1,9 @@
[versions] [versions]
activityCompose = "1.10.1" activityCompose = "1.10.1"
androidDesugarJdkLibs = "2.1.5" androidDesugarJdkLibs = "2.1.5"
androidGradlePlugin = "8.11.0" androidGradlePlugin = "8.10.1"
androidSmsmms = "kdeconnect-1-21-0" androidSmsmms = "kdeconnect-1-21-0"
appcompat = "1.7.1" appcompat = "1.7.0"
bcpkixJdk15on = "1.70" bcpkixJdk15on = "1.70"
classindexksp = "1.2" classindexksp = "1.2"
commonsCollections4 = "4.5.0" commonsCollections4 = "4.5.0"
@@ -17,11 +17,11 @@ documentfile = "1.1.0"
gridlayout = "1.1.0" gridlayout = "1.1.0"
jsonassert = "1.5.3" jsonassert = "1.5.3"
junit = "4.13.2" junit = "4.13.2"
kotlin = "2.2.0" kotlin = "2.1.21"
kspPlugin = "2.2.0-2.0.2" kspPlugin = "2.1.21-2.0.1"
kotlinxCoroutinesCore = "1.10.2" kotlinxCoroutinesCore = "1.10.2"
lifecycleExtensions = "2.2.0" lifecycleExtensions = "2.2.0"
lifecycleRuntimeKtx = "2.9.1" lifecycleRuntimeKtx = "2.9.0"
logger = "1.0.3" logger = "1.0.3"
material = "1.12.0" material = "1.12.0"
material3 = "1.3.2" material3 = "1.3.2"
@@ -35,7 +35,7 @@ rxjava = "2.2.21"
sl4j = "2.0.13" sl4j = "2.0.13"
sshdCore = "2.15.0" sshdCore = "2.15.0"
swiperefreshlayout = "1.1.0" swiperefreshlayout = "1.1.0"
uiToolingPreview = "1.8.3" uiToolingPreview = "1.8.2"
univocityParsers = "2.9.1" univocityParsers = "2.9.1"
[libraries] [libraries]

View File

@@ -5,7 +5,7 @@ msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-05 12:31+0000\n" "POT-Creation-Date: 2023-11-05 12:31+0000\n"
"PO-Revision-Date: 2025-08-20 21:20+0400\n" "PO-Revision-Date: 2025-05-31 17:29+0400\n"
"Last-Translator: Zayed Al-Saidi <zayed.alsaidi@gmail.com>\n" "Last-Translator: Zayed Al-Saidi <zayed.alsaidi@gmail.com>\n"
"Language-Team: ar\n" "Language-Team: ar\n"
"Language: ar\n" "Language: ar\n"
@@ -13,7 +13,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" "&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
"X-Generator: Lokalize 23.08.5\n" "X-Generator: Lokalize 23.08.5\n"
msgid "" msgid ""
@@ -55,12 +55,12 @@ msgstr ""
"- الوصول إلى الملفات الموجودة على هاتفك من حاسوبك، دون أسلاك.\n" "- الوصول إلى الملفات الموجودة على هاتفك من حاسوبك، دون أسلاك.\n"
"- الحافظة المشتركة: النسخ واللصق بين أجهزتك.\n" "- الحافظة المشتركة: النسخ واللصق بين أجهزتك.\n"
"- الحصول على إشعارات للمكالمات والرسائل الواردة على حاسوبك.\n" "- الحصول على إشعارات للمكالمات والرسائل الواردة على حاسوبك.\n"
"- لوحة اللمس افتراضية: استخدم شاشة هاتفك كلوحة لمس لحاسوبك.\n" "- لوحة اللمس الافتراضية: استخدم شاشة هاتفك كلوحة لمس لحاسوبك.\n"
"- مزامنة الإشعارات: الوصول إلى إشعارات هاتفك من حاسوبك والرد على الرسائل.\n" "- مزامنة الإشعارات: الوصول إلى إشعارات هاتفك من حاسوبك والرد على الرسائل.\n"
"- التحكم عن بعد في الوسائط المتعددة: استخدم هاتفك كجهاز تحكم عن بعد لمشغلات " "- التحكم عن بعد في الوسائط المتعددة: استخدم هاتفك كجهاز تحكم عن بعد لمشغلات "
"الوسائط لينكس.\n" "الوسائط لينكس.\n"
"- اتصال واي فاي: لا حاجة إلى سلك يو اس بي أو بلوتوث.\n" "- اتصال واي فاي: لا حاجة إلى سلك USB أو بلوتوث.\n"
"- تعمية TLS من البداية إلى النهاية: معلوماتك آمنة.\n" "- تشفير TLS من البداية إلى النهاية: معلوماتك آمنة.\n"
"\n" "\n"
"يرجى ملاحظة أنك ستحتاج إلى تثبيت جسر كِيدِي على حاسوبك حتى يعمل هذا التطبيق، " "يرجى ملاحظة أنك ستحتاج إلى تثبيت جسر كِيدِي على حاسوبك حتى يعمل هذا التطبيق، "
"والحفاظ على تحديث إصدار سطح المكتب بإصدار أندوريد حتى تعمل أحدث الميزات.\n" "والحفاظ على تحديث إصدار سطح المكتب بإصدار أندوريد حتى تعمل أحدث الميزات.\n"
@@ -73,7 +73,7 @@ msgstr ""
"\n" "\n"
"لا يرسل جسر كِيدِي أي معلومات إلى كيدي أو إلى أي طرف ثالث. يرسل جسر كِيدِي " "لا يرسل جسر كِيدِي أي معلومات إلى كيدي أو إلى أي طرف ثالث. يرسل جسر كِيدِي "
"البيانات من جهاز إلى آخر مباشرةً باستخدام الشبكة المحلية، وليس عبر الإنترنت، " "البيانات من جهاز إلى آخر مباشرةً باستخدام الشبكة المحلية، وليس عبر الإنترنت، "
"وباستخدام التعمية من البداية إلى النهاية.\n" "وباستخدام التشفير من البداية إلى النهاية.\n"
"\n" "\n"
"هذا التطبيق جزء من مشروع مفتوح المصدر وهو موجود بفضل جميع الأشخاص الذين " "هذا التطبيق جزء من مشروع مفتوح المصدر وهو موجود بفضل جميع الأشخاص الذين "
"ساهموا فيه. زر الموقع الإلكتروني للحصول على الشفرة المصدرية.\n" "ساهموا فيه. قم بزيارة الموقع الإلكتروني للحصول على الشفرة المصدرية.\n"

View File

@@ -13,7 +13,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" "&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
"X-Generator: Lokalize 23.08.5\n" "X-Generator: Lokalize 23.08.5\n"
msgid "KDE Connect integrates your smartphone and computer" msgid "KDE Connect integrates your smartphone and computer"

View File

@@ -1,5 +1,5 @@
# SPDX-FileCopyrightText: 2023 Frederik Schwarzer <schwarzer@kde.org> # Frederik Schwarzer <schwarzer@kde.org>, 2023.
# SPDX-FileCopyrightText: 2024 tobi <onewayme001@posteo.de> # tobi <onewayme001@posteo.de>, 2024.
#. extracted from ./metadata/android/en-US/full_description.txt #. extracted from ./metadata/android/en-US/full_description.txt
msgid "" msgid ""
msgstr "" msgstr ""

View File

@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 Frederik Schwarzer <schwarzer@kde.org> # Frederik Schwarzer <schwarzer@kde.org>, 2023.
#. extracted from ./metadata/android/en-US/short_description.txt #. extracted from ./metadata/android/en-US/short_description.txt
msgid "" msgid ""
msgstr "" msgstr ""

View File

@@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M360,840L600,840Q600,840 600,840Q600,840 600,840L600,640Q575,659 544.5,669.5Q514,680 480,680Q446,680 415.5,669.5Q385,659 360,640L360,840Q360,840 360,840Q360,840 360,840ZM480,600Q530,600 565,565Q600,530 600,480Q600,430 565,395Q530,360 480,360Q430,360 395,395Q360,430 360,480Q360,530 395,565Q430,600 480,600ZM360,320Q385,301 415.5,290.5Q446,280 480,280Q514,280 544.5,290.5Q575,301 600,320L600,120Q600,120 600,120Q600,120 600,120L360,120Q360,120 360,120Q360,120 360,120L360,320ZM360,920Q327,920 303.5,896.5Q280,873 280,840L280,120Q280,87 303.5,63.5Q327,40 360,40L600,40Q633,40 656.5,63.5Q680,87 680,120L680,840Q680,873 656.5,896.5Q633,920 600,920L360,920ZM480,540Q455,540 437.5,522.5Q420,505 420,480Q420,455 437.5,437.5Q455,420 480,420Q505,420 522.5,437.5Q540,455 540,480Q540,505 522.5,522.5Q505,540 480,540ZM480,240Q497,240 508.5,228.5Q520,217 520,200Q520,183 508.5,171.5Q497,160 480,160Q463,160 451.5,171.5Q440,183 440,200Q440,217 451.5,228.5Q463,240 480,240ZM480,680Q480,680 480,680Q480,680 480,680L480,680Q480,680 480,680Q480,680 480,680Q480,680 480,680Q480,680 480,680L480,680Q480,680 480,680Q480,680 480,680ZM480,280L480,280Q480,280 480,280Q480,280 480,280L480,280Q480,280 480,280Q480,280 480,280L480,280Q480,280 480,280Q480,280 480,280Q480,280 480,280Q480,280 480,280Z"/>
</vector>

View File

@@ -12,7 +12,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context="org.kde.kdeconnect.Plugins.MousePadPlugin.BigscreenActivity"> tools:context="org.kde.kdeconnect.Plugins.BigscreenPlugin.BigscreenActivity">
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" /> <include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:kdeconnect="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_use_mouse_and_keyboard"
android:icon="@drawable/touchpad_plugin_action_24dp"
android:title="@string/show_mouse_and_keyboard"
kdeconnect:iconTint="?colorOnBackground"
kdeconnect:showAsAction="ifRoom" />
</menu>

View File

@@ -6,7 +6,7 @@
<string name="foreground_notification_devices">متّصل بـ: %s</string> <string name="foreground_notification_devices">متّصل بـ: %s</string>
<string name="foreground_notification_send_clipboard">أرسل الحافظة</string> <string name="foreground_notification_send_clipboard">أرسل الحافظة</string>
<string name="pref_plugin_telephony">مُخطِر المهاتفة</string> <string name="pref_plugin_telephony">مُخطِر المهاتفة</string>
<string name="pref_plugin_telephony_desc">أرسل إشعارات للمكالمات الواردة</string> <string name="pref_plugin_telephony_desc">أرسل إخطارات للمكالمات الواردة</string>
<string name="pref_plugin_battery">تقرير البطّاريّة</string> <string name="pref_plugin_battery">تقرير البطّاريّة</string>
<string name="pref_plugin_battery_desc">بلّغ عن حالة البطّاريّة دوريًّا</string> <string name="pref_plugin_battery_desc">بلّغ عن حالة البطّاريّة دوريًّا</string>
<string name="pref_plugin_connectivity_report">تقرير الاتصال</string> <string name="pref_plugin_connectivity_report">تقرير الاتصال</string>
@@ -42,7 +42,7 @@
<string name="cancel">ألغِ</string> <string name="cancel">ألغِ</string>
<string name="open_settings">افتح الإعدادات</string> <string name="open_settings">افتح الإعدادات</string>
<string name="no_permissions">عليك إعطاء التّطبيق صلاحيّات للنّفاذ إلى الإشعارات</string> <string name="no_permissions">عليك إعطاء التّطبيق صلاحيّات للنّفاذ إلى الإشعارات</string>
<string name="no_permission_mprisreceiver">لتكون قادرًا على التحكم في مشغلات الوسائط الخاصة بك، تحتاج إلى منح حق الوصول إلى الإشعارات</string> <string name="no_permission_mprisreceiver">لتكون قادرًا على التحكم في مشغلات الوسائط الخاصة بك ، تحتاج إلى منح حق الوصول إلى الإشعارات</string>
<string name="no_permissions_remotekeyboard">لتلقي ضغطات المفاتيح تحتاج إلى تنشيط لوحة المفاتيح البعيدة لجسر كِيدِي</string> <string name="no_permissions_remotekeyboard">لتلقي ضغطات المفاتيح تحتاج إلى تنشيط لوحة المفاتيح البعيدة لجسر كِيدِي</string>
<string name="send_ping">أرسل وخزة ping</string> <string name="send_ping">أرسل وخزة ping</string>
<string name="open_mpris_controls">متحكّمات الوسائط المتعدّدة</string> <string name="open_mpris_controls">متحكّمات الوسائط المتعدّدة</string>
@@ -113,7 +113,7 @@
<string name="cancel_pairing">ألغ الاقتران</string> <string name="cancel_pairing">ألغ الاقتران</string>
<string name="unknown_device">جهاز مجهول</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_already_paired">الجهاز مقترن بالفعل</string>
<string name="error_timed_out">انتهت المهلة</string> <string name="error_timed_out">انتهت المهلة</string>
<string name="error_clocks_not_match">ساعات الجهاز غير متزامنة</string> <string name="error_clocks_not_match">ساعات الجهاز غير متزامنة</string>
<string name="error_canceled_by_user">ألغاه المستخدم</string> <string name="error_canceled_by_user">ألغاه المستخدم</string>
@@ -201,7 +201,7 @@
<string name="request_pairing">اطلب الاقتران</string> <string name="request_pairing">اطلب الاقتران</string>
<string name="pairing_accept">اقبل</string> <string name="pairing_accept">اقبل</string>
<string name="pairing_reject">ارفض</string> <string name="pairing_reject">ارفض</string>
<string name="pairing_explanation">سيؤدي إقران جهازين إلى منحهما إمكانية الوصول إلى بعضهما البعض. أقرن أجهزتك الخاصة بك فقط.</string> <string name="pairing_explanation">سيؤدي إقران جهازين إلى منحهما إمكانية الوصول إلى بعضهما البعض. قم بإقران أجهزتك الخاصة بك فقط.</string>
<string name="settings">إعدادات</string> <string name="settings">إعدادات</string>
<string name="mpris_play">شغّل</string> <string name="mpris_play">شغّل</string>
<string name="mpris_pause">ألبث</string> <string name="mpris_pause">ألبث</string>
@@ -236,10 +236,10 @@
<string name="custom_devices_settings_summary">%d أجهزة مضافة يدوياً</string> <string name="custom_devices_settings_summary">%d أجهزة مضافة يدوياً</string>
<string name="custom_device_list">أضف أجهزة بعنوان IP</string> <string name="custom_device_list">أضف أجهزة بعنوان IP</string>
<string name="custom_device_deleted">حُذف الجهاز المخصّص</string> <string name="custom_device_deleted">حُذف الجهاز المخصّص</string>
<string name="custom_device_list_help">إذا لم يُكتشف جهازك آليّاً يمكنك إضافة عنوان IP الخاص به أو اسم المضيف الخاص به من خلال النقر على زر الإجراء العائم</string> <string name="custom_device_list_help">إذا لم يُكتشف جهازك آلياً يمكنك إضافة عنوان IP الخاص به أو اسم المضيف الخاص به من خلال النقر على زر الإجراء العائم</string>
<string name="custom_device_fab_hint">أضف جهازاً</string> <string name="custom_device_fab_hint">أضف جهازاً</string>
<string name="undo">تراجع</string> <string name="undo">تراجع</string>
<string name="share_notification_preference">إشعارات مزعجة</string> <string name="share_notification_preference">إخطارات مزعجة</string>
<string name="share_notification_preference_summary">اهتزّ وشغّل صوتًا عند استقبال ملفّ</string> <string name="share_notification_preference_summary">اهتزّ وشغّل صوتًا عند استقبال ملفّ</string>
<string name="share_destination_customize">خصص مجلد المقصد</string> <string name="share_destination_customize">خصص مجلد المقصد</string>
<string name="share_destination_customize_summary_disabled">ستظهر الملفات المستلمة في التنزيلات</string> <string name="share_destination_customize_summary_disabled">ستظهر الملفات المستلمة في التنزيلات</string>
@@ -247,9 +247,9 @@
<string name="share_destination_folder_preference">مجلد الوجهة</string> <string name="share_destination_folder_preference">مجلد الوجهة</string>
<string name="share">شارك</string> <string name="share">شارك</string>
<string name="share_received_file">شارك \"%s\"</string> <string name="share_received_file">شارك \"%s\"</string>
<string name="title_activity_notification_filter">مرشّح الإشعارات</string> <string name="title_activity_notification_filter">مرشّح الإخطارات</string>
<string name="filter_apps_info">ستُزامن الإشعارات من التّطبيقات المحدّدة.</string> <string name="filter_apps_info">ستُزامن الإخطارات من التّطبيقات المحدّدة.</string>
<string name="show_notification_if_screen_off">أرسل إشعارات فقط إذا كانت الشاشة مغلقة</string> <string name="show_notification_if_screen_off">أرسل تنبيهات فقط إذا كانت الشاشة مغلقة</string>
<string name="add_device_dialog_title">أضف جهازاً</string> <string name="add_device_dialog_title">أضف جهازاً</string>
<string name="add_device_hint">اسم المضيف أو عنوان IP</string> <string name="add_device_hint">اسم المضيف أو عنوان IP</string>
<string name="sftp_preference_configured_storage_locations">أماكن التّخزين المضبوطة</string> <string name="sftp_preference_configured_storage_locations">أماكن التّخزين المضبوطة</string>
@@ -276,7 +276,7 @@
<string name="refresh">حدّث</string> <string name="refresh">حدّث</string>
<string name="unreachable_description">الجهاز المقترن هذا لا يمكن الوصول إليه. تأكّد من اتّصاله بنفس الشّبكة.</string> <string name="unreachable_description">الجهاز المقترن هذا لا يمكن الوصول إليه. تأكّد من اتّصاله بنفس الشّبكة.</string>
<string name="no_wifi">أنت غير متصل بشبكة واي فاي، لذلك قد لا تتمكن من رؤية أي أجهزة. انقر هنا لتمكين واي فاي.</string> <string name="no_wifi">أنت غير متصل بشبكة واي فاي، لذلك قد لا تتمكن من رؤية أي أجهزة. انقر هنا لتمكين واي فاي.</string>
<string name="on_non_trusted_message">ليس على شبكة موثوق بها: الاكتشاف الآليّ معطل.</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">أرسل رسالة نصية قصيرة</string>
<string name="pref_plugin_telepathy_desc">أرسل رسائل نصّيّة من سطح المكتب</string> <string name="pref_plugin_telepathy_desc">أرسل رسائل نصّيّة من سطح المكتب</string>
@@ -347,27 +347,27 @@
<string name="settings_export_logs_text">أنشئ ملفًا يحتوي على معلومات التنفيذ التي يمكن أن تساعد في استكشاف المشكلات وإصلاحها.</string> <string name="settings_export_logs_text">أنشئ ملفًا يحتوي على معلومات التنفيذ التي يمكن أن تساعد في استكشاف المشكلات وإصلاحها.</string>
<string name="settings_more_settings_title">المزيد من الإعدادات</string> <string name="settings_more_settings_title">المزيد من الإعدادات</string>
<string name="settings_more_settings_text">يمكن العثور على إعدادات لكل جهاز ضمن ”إعدادات الملحقة“ من داخل الجهاز.</string> <string name="settings_more_settings_text">يمكن العثور على إعدادات لكل جهاز ضمن ”إعدادات الملحقة“ من داخل الجهاز.</string>
<string name="setting_persistent_notification">أظهر الإشعارات المستمرّة</string> <string name="setting_persistent_notification">أظهر الإخطارات المستمرّة</string>
<string name="setting_persistent_notification_oreo">الإشعارات المستمرّة</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="extra_options">الخيارات الإضافية</string>
<string name="privacy_options">خيارات الخصوصية</string> <string name="privacy_options">خيارات الخصوصية</string>
<string name="set_privacy_options">حدد خيارات الخصوصية</string> <string name="set_privacy_options">حدد خيارات الخصوصية</string>
<string name="block_contents">امنح محتويات الإشعارات</string> <string name="block_contents">امنح محتويات الإخطارات</string>
<string name="block_images">امنع الصور في الإشعارات</string> <string name="block_images">امنع الصور في الإخطارات</string>
<string name="notification_channel_receivenotification">إشعارات من أجهزة أخرى</string> <string name="notification_channel_receivenotification">إخطارات من أجهزة أخرى</string>
<string name="no_app_for_opening">لا يوجد تطبيق مناسب لفتح هذا الملف</string> <string name="no_app_for_opening">لا يوجد تطبيق مناسب لفتح هذا الملف</string>
<string name="remote_keyboard_service">لوحة مفاتيح بعيده لجسر كِيدِي</string> <string name="remote_keyboard_service">لوحة مفاتيح بعيده لجسر كِيدِي</string>
<string name="presenter_pointer">المؤشر</string> <string name="presenter_pointer">المؤشر</string>
<string name="trusted_networks">الشّبكات الموثوقة</string> <string name="trusted_networks">الشّبكات الموثوقة</string>
<string name="trusted_networks_desc">اقَصْر الاكتشاف الآليّ على الشبكات المعروفة</string> <string name="trusted_networks_desc">اقَصْر الاكتشاف التلقائي على الشبكات المعروفة</string>
<string name="add_trusted_network">أضف %1s</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="allow_all_networks_text">اسمح للكل</string>
<string name="location_permission_needed_title">الإذن مطلوب</string> <string name="location_permission_needed_title">الإذن مطلوب</string>
<string name="bluetooth_permission_needed_desc">يحتاج جسر كِيدِي إلى إذن للاتصال بالأجهزة القريبة لإتاحة الأجهزة المقترنة باستخدام البلوتوث في جسر كِيدِي.</string> <string name="bluetooth_permission_needed_desc">يحتاج جسر كِيدِي إلى إذن للاتصال بالأجهزة القريبة لإتاحة الأجهزة المقترنة باستخدام البلوتوث في جسر كِيدِي.</string>
<string name="location_permission_needed_desc">يحتاج جسر كِيدِي إلى إذن الموقع في الخلفية لمعرفة شبكة الواي فاي التي تتصل بها حتى عندما يكون التطبيق في الخلفية. وذلك لأنه يمكن استخدام اسم شبكات الواي فاي من حولك للعثور على موقعك، حتى وإن لم يكن هذا ما يفعله جسر كِيدِي.</string> <string name="location_permission_needed_desc">يحتاج جسر كِيدِي إلى إذن الموقع في الخلفية لمعرفة شبكة الواي فاي التي تتصل بها حتى عندما يكون التطبيق في الخلفية. وذلك لأنه يمكن استخدام اسم شبكات الواي فاي من حولك للعثور على موقعك، حتى وإن لم يكن هذا ما يفعله جسر كِيدِي.</string>
<string name="clipboard_android_x_incompat">أزال أندرويد 10 الوصول للحافظة إلى جميع التطبيقات. ستعطل هذه الملحقة.</string> <string name="clipboard_android_x_incompat">قام أندرويد 10 بإزالة وصول للحافظة إلى جميع التطبيقات. ستعطل هذه الملحقة.</string>
<string name="mpris_open_url">استمر في التشغيل هنا</string> <string name="mpris_open_url">استمر في التشغيل هنا</string>
<string name="cant_open_url">تعذر فتح العنوان للاستمرار في التشغيل</string> <string name="cant_open_url">تعذر فتح العنوان للاستمرار في التشغيل</string>
<string name="bigscreen_home">المنزل</string> <string name="bigscreen_home">المنزل</string>
@@ -416,7 +416,7 @@
<string name="thanks_to">الشكر إلى</string> <string name="thanks_to">الشكر إلى</string>
<string name="easter_egg">بيض الفصح</string> <string name="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="visit_contributors_homepage">زر صفحة المساهم الرئيسية\n%s</string>
<string name="version">الإصدار %s</string> <string name="version">الإصدار %s</string>
<string name="about_kde">عن كِيدِي</string> <string name="about_kde">عن كِيدِي</string>
<string name="kde_be_free">كِيدِي- كن حرًّا!</string> <string name="kde_be_free">كِيدِي- كن حرًّا!</string>
@@ -425,16 +425,16 @@
<string name="rise_up">ارفع</string> <string name="rise_up">ارفع</string>
<string name="rise_down">اخفض</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="clear_compose">امسح</string>
<string name="send_compose">أرسل</string> <string name="send_compose">أرسل</string>
<string name="compose_send_title">اكتب أرسل</string> <string name="compose_send_title">اكتب أرسل</string>
<string name="open_compose_send">اكتب نصًا</string> <string name="open_compose_send">اكتب نصًا</string>
<string name="double_tap_to_drag">طرق مزدوج للسحب</string> <string name="double_tap_to_drag">طرق مزدوج للسحب</string>
<string name="hold_to_drag">اضغط مع الاستمرار للسحب</string> <string name="hold_to_drag">اضغط مع الاستمرار للسحب</string>
<string name="about_kde_about"><h1>حول</h1>" "<p>كيدي مجتمع عالمي من مهندسي البرمجيات والفنانين والكتاب والمترجمين والمبدعين الملتزمين بتطوير البرمجيات الحرة. تُنتج كيدي بيئة سطح المكتب بلازما، ومئات التطبيقات، والعديد من مكتبات البرمجيات التي تدعمها.</p>" "<p>كيدي مشروع تعاوني: لا تتحكم جهة واحدة في توجهاته أو منتجاته. بل نعمل معًا لتحقيق هدفنا المشترك المتمثل في بناء أفضل برمجيات حرة في العالم. الجميع مدعوون للانضمام والمساهمة في كيدي، بمن فيهم أنت.</p>" زر &lt;a href=https://www.kde.org/&gt;https://www.kde.org/&lt;/a&gt; للحصول على مزيد من المعلومات حول مجتمع كيدي والبرمجيات التي ننتجها"</string> <string name="about_kde_about"><h1>حول</h1>" "<p>كيدي مجتمع عالمي من مهندسي البرمجيات والفنانين والكتاب والمترجمين والمبدعين الملتزمين بتطوير البرمجيات الحرة. تُنتج كيدي بيئة سطح المكتب بلازما، ومئات التطبيقات، والعديد من مكتبات البرمجيات التي تدعمها.</p>" "<p>كيدي مشروع تعاوني: لا تتحكم جهة واحدة في توجهاته أو منتجاته. بل نعمل معًا لتحقيق هدفنا المشترك المتمثل في بناء أفضل برمجيات حرة في العالم. الجميع مدعوون للانضمام والمساهمة في كيدي، بمن فيهم أنت.</p>" قم بزيارة &lt;a href=https://www.kde.org/&gt;https://www.kde.org/&lt;/a&gt; للحصول على مزيد من المعلومات حول مجتمع كيدي والبرمجيات التي ننتجها"</string>
<string name="about_kde_report_bugs_or_wishes">&lt;h1&gt;الإبلاغ عن الأخطاء أو الرغبات&lt;/h1&gt; &lt;p&gt;يمكن دائمًا تحسين البرامج، وفريق كيدي مستعدٌّ لذلك. ومع ذلك، يجب عليك - كمستخدم - إبلاغنا عندما لا يعمل شيءٌ ما كما هو متوقع أو عندما يكون من الممكن تحسينه.&lt;/p&gt; &lt;p&gt;تحتوي كيدي على نظام تتبع للأخطاء. تفضل بزيارة &lt;a href=https://bugs.kde.org/&gt;https://bugs.kde.org/&lt;/a&gt; أو استخدم زر \"الإبلاغ عن خطأ\" من شاشة \"حول\" للإبلاغ عن الأخطاء.&lt;/p&gt; إذا كانت لديك أي اقتراحات للتحسين، فنرحب بك باستخدام نظام تتبع الأخطاء لتسجيل رغبتك. تأكد من استخدام مستوى الخطورة المسمى \"قائمة الأمنيات\".</string> <string name="about_kde_report_bugs_or_wishes">&lt;h1&gt;الإبلاغ عن الأخطاء أو الرغبات&lt;/h1&gt; &lt;p&gt;يمكن دائمًا تحسين البرامج، وفريق كيدي مستعدٌّ لذلك. ومع ذلك، يجب عليك - كمستخدم - إبلاغنا عندما لا يعمل شيءٌ ما كما هو متوقع أو عندما يكون من الممكن تحسينه.&lt;/p&gt; &lt;p&gt;تحتوي كيدي على نظام تتبع للأخطاء. تفضل بزيارة &lt;a href=https://bugs.kde.org/&gt;https://bugs.kde.org/&lt;/a&gt; أو استخدم زر \"الإبلاغ عن خطأ\" من شاشة \"حول\" للإبلاغ عن الأخطاء.&lt;/p&gt; إذا كانت لديك أي اقتراحات للتحسين، فنرحب بك باستخدام نظام تتبع الأخطاء لتسجيل رغبتك. تأكد من استخدام مستوى الخطورة المسمى \"قائمة الأمنيات\".</string>
<string name="about_kde_join_kde">&lt;h1&gt;انضم إلى كيدي&lt;/h1&gt; &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> <string name="about_kde_join_kde">&lt;h1&gt;انضم إلى كيدي&lt;/h1&gt; &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>
<string name="about_kde_support_kde">"&lt;h1&gt;دعم كيدي&lt;/h1&gt; &lt;p&gt;برامج كيدي متاحة دائمًا بالمجان، ولكن إنشاءها ليس مجانيًا.&lt;/p&gt; &lt;p&gt;لدعم التطوير، أسس مجتمع كيدي KDE e.V.، وهي منظمة غير ربحية تأسست بشكل قانوني في ألمانيا. تمثل KDE e.V. مجتمع كيدي في الشؤون القانونية والمالية. انظر &lt;a href=https://ev.kde.org/&gt;https://ev.kde.org/&lt;/a&gt; للحصول على معلومات حول KDE e.V.&lt;/p&gt; &lt;p&gt;تستفيد كيدي من العديد من أنواع المساهمات، بما في ذلك المساهمات المالية. نحن نستخدم الأموال لتعويض الأعضاء وغيرهم عن النفقات التي يتكبد عند المساهمة. وتستخدم الأموال للدعم القانوني وتنظيم المؤتمرات والاجتماعات.&lt;/p&gt; &lt;p&gt;نود أن نشجعكم على دعم جهودنا من خلال التبرع المالي، باستخدام إحدى الطرق الموضحة في &lt;a href=https://www.kde.org/community/donations/&gt;https://www.kde.org/community/donations/&lt;/a&gt;.&lt;/p&gt; نشكركم جزيل الشكر مقدمًا على دعمكم."</string> <string name="about_kde_support_kde">&lt;h1&gt;دعم كيدي&lt;/h1&gt; &lt;p&gt;برامج كيدي متاحة دائمًا بالمجان، ولكن إنشاءها ليس مجانيًا.&lt;/p&gt; &lt;p&gt;لدعم التطوير، قام مجتمع كيدي بتأسيس KDE e.V.، وهي منظمة غير ربحية تأسست بشكل قانوني في ألمانيا. تمثل KDE e.V. مجتمع كيدي في الشؤون القانونية والمالية. انظر &lt;a href=https://ev.kde.org/&gt;https://ev.kde.org/&lt;/a&gt; للحصول على معلومات حول KDE e.V.&lt;/p&gt; &lt;p&gt;يستفيد كيدي من العديد من أنواع المساهمات، بما في ذلك المساهمات المالية. نحن نستخدم الأموال لتعويض الأعضاء وغيرهم عن النفقات التي يتكبدونها عند المساهمة. ويتم استخدام المزيد من الأموال للدعم القانوني وتنظيم المؤتمرات والاجتماعات.&lt;/p&gt; &lt;p&gt;نود أن نشجعكم على دعم جهودنا من خلال التبرع المالي، باستخدام إحدى الطرق الموضحة في &lt;a href=https://www.kde.org/community/donations/&gt;https://www.kde.org/community/donations/&lt;/a&gt;.&lt;/p&gt; نشكركم جزيل الشكر مقدمًا على دعمكم.</string>
<string name="maintainer_and_developer">الصائن ومطوّر</string> <string name="maintainer_and_developer">الصائن ومطوّر</string>
<string name="developer">مطوّر</string> <string name="developer">مطوّر</string>
<string name="apple_support">دعم ماك أو إس. العمل على دعم iOS</string> <string name="apple_support">دعم ماك أو إس. العمل على دعم iOS</string>
@@ -451,7 +451,7 @@
<string name="tap_to_execute">اطرق لتنفيذه</string> <string name="tap_to_execute">اطرق لتنفيذه</string>
<string name="plugin_stats">ملحقة الإحصائيات</string> <string name="plugin_stats">ملحقة الإحصائيات</string>
<string name="enable_udp_broadcast">مكّن اكتشاف الجهاز عن طريق UDP</string> <string name="enable_udp_broadcast">مكّن اكتشاف الجهاز عن طريق UDP</string>
<string name="enable_bluetooth">مكّن بلوتوث (بيتا)</string> <string name="enable_bluetooth">فعّل بلوتوث (بيتا)</string>
<string name="receive_notifications_permission_explanation">يجب السماح بتلقي الإشعارات من الأجهزة الأخرى</string> <string name="receive_notifications_permission_explanation">يجب السماح بتلقي الإشعارات من الأجهزة الأخرى</string>
<string name="findmyphone_notifications_explanation">إذن الإشعارات مطلوب حتى يتمكن الهاتف من الرنين عندما يكون التطبيق في الخلفية</string> <string name="findmyphone_notifications_explanation">إذن الإشعارات مطلوب حتى يتمكن الهاتف من الرنين عندما يكون التطبيق في الخلفية</string>
<string name="no_notifications">الإشعارات معطلة، لن تتلقى إشعارات الأزواج الواردة.</string> <string name="no_notifications">الإشعارات معطلة، لن تتلقى إشعارات الأزواج الواردة.</string>

View File

@@ -397,7 +397,7 @@
<string name="send_compose">Envia</string> <string name="send_compose">Envia</string>
<string name="compose_send_title">Títol de l\'enviament</string> <string name="compose_send_title">Títol de l\'enviament</string>
<string name="open_compose_send">Redacta text</string> <string name="open_compose_send">Redacta text</string>
<string name="double_tap_to_drag">Toc doble per a arrossegar</string> <string name="double_tap_to_drag">Dos tocs per a arrossegar</string>
<string name="hold_to_drag">Mantenir premut per a arrossegar</string> <string name="hold_to_drag">Mantenir premut per a arrossegar</string>
<string name="about_kde_about">&lt;h1&gt;Quant al&lt;/h1&gt; &lt;p&gt;KDE és una comunitat mundial d\'enginyers, artistes, escriptors, traductors i creadors de programari compromesos amb el desenvolupament de &lt;a href=https://www.gnu.org/philosophy/free-sw.html&gt;programari lliure&lt;/a&gt;. KDE produeix l\'entorn d\'escriptori Plasma, centenars d\'aplicacions i moltes biblioteques de programari que els donen suport.&lt;/p&gt; &lt;p&gt;KDE és una empresa en cooperativa: cap entitat controla la seva direcció o els productes. En el seu lloc, treballem junts per a aconseguir l\'objectiu comú de construir el millor programari lliure del món. Tothom hi és benvingut a &lt;a href=https://community.kde.org/Get_Involved&gt;unir-se i contribuir&lt;/a&gt; a KDE, inclosos vosaltres.&lt;/p&gt; Visiteu &lt;a href=https://www.kde.org/ca/&gt;https://www.kde.org/ca/&lt;/a&gt; per a obtenir més informació sobre la comunitat KDE i el programari que produïm.</string> <string name="about_kde_about">&lt;h1&gt;Quant al&lt;/h1&gt; &lt;p&gt;KDE és una comunitat mundial d\'enginyers, artistes, escriptors, traductors i creadors de programari compromesos amb el desenvolupament de &lt;a href=https://www.gnu.org/philosophy/free-sw.html&gt;programari lliure&lt;/a&gt;. KDE produeix l\'entorn d\'escriptori Plasma, centenars d\'aplicacions i moltes biblioteques de programari que els donen suport.&lt;/p&gt; &lt;p&gt;KDE és una empresa en cooperativa: cap entitat controla la seva direcció o els productes. En el seu lloc, treballem junts per a aconseguir l\'objectiu comú de construir el millor programari lliure del món. Tothom hi és benvingut a &lt;a href=https://community.kde.org/Get_Involved&gt;unir-se i contribuir&lt;/a&gt; a KDE, inclosos vosaltres.&lt;/p&gt; Visiteu &lt;a href=https://www.kde.org/ca/&gt;https://www.kde.org/ca/&lt;/a&gt; per a obtenir més informació sobre la comunitat KDE i el programari que produïm.</string>
<string name="about_kde_report_bugs_or_wishes">&lt;h1&gt;Informeu dels errors o desitjos&lt;/h1&gt; &lt;p&gt;El programari sempre es pot millorar, i l\'equip del KDE està a punt per a fer-ho. No obstant això, l\'usuari, ha de dir-nos quan alguna cosa no funciona com s\'esperava o si podria fer-se millor.&lt;/p&gt; &lt;p&gt;El KDE té un sistema de seguiment d\'errors. Per a informar-ne d\'un, visiteu &lt;a href=https://bugs.kde.org/&gt;https://bugs.kde.org/&lt;/a&gt; o useu el botó «Informeu d\'un error» des de la pantalla Quant al.&lt;/p&gt; Si teniu un suggeriment de millora, podeu usar el sistema de seguiment d\'errors per a enregistrar el vostre desig. Assegureu-vos d\'usar la severitat anomenada «Llista de desitjos» (Wishlist).</string> <string name="about_kde_report_bugs_or_wishes">&lt;h1&gt;Informeu dels errors o desitjos&lt;/h1&gt; &lt;p&gt;El programari sempre es pot millorar, i l\'equip del KDE està a punt per a fer-ho. No obstant això, l\'usuari, ha de dir-nos quan alguna cosa no funciona com s\'esperava o si podria fer-se millor.&lt;/p&gt; &lt;p&gt;El KDE té un sistema de seguiment d\'errors. Per a informar-ne d\'un, visiteu &lt;a href=https://bugs.kde.org/&gt;https://bugs.kde.org/&lt;/a&gt; o useu el botó «Informeu d\'un error» des de la pantalla Quant al.&lt;/p&gt; Si teniu un suggeriment de millora, podeu usar el sistema de seguiment d\'errors per a enregistrar el vostre desig. Assegureu-vos d\'usar la severitat anomenada «Llista de desitjos» (Wishlist).</string>

View File

@@ -94,7 +94,6 @@
<string name="sendkeystrokes_pref_category_title">Tastendrücke senden</string> <string name="sendkeystrokes_pref_category_title">Tastendrücke senden</string>
<string name="sendkeystrokes_pref_enabled">Senden von Tastendrücken aktivieren</string> <string name="sendkeystrokes_pref_enabled">Senden von Tastendrücken aktivieren</string>
<string name="sendkeystrokes_pref_enabled_summary">Auf Daten mit dem MIME-Typ „text/x-keystrokes“ warten</string> <string name="sendkeystrokes_pref_enabled_summary">Auf Daten mit dem MIME-Typ „text/x-keystrokes“ warten</string>
<string name="sendkeystrokes_safe_text_enabled_summary">Kurze Ziffernfolgen ohne Bestätigung senden</string>
<string name="pref_plugin_mousepad_send_keystrokes">Als Tastendruck senden</string> <string name="pref_plugin_mousepad_send_keystrokes">Als Tastendruck senden</string>
<string name="mouse_receiver_plugin_description">Empfänger für entfernte Mauseingaben</string> <string name="mouse_receiver_plugin_description">Empfänger für entfernte Mauseingaben</string>
<string name="mouse_receiver_plugin_name">Maus-Empfänger</string> <string name="mouse_receiver_plugin_name">Maus-Empfänger</string>
@@ -113,7 +112,6 @@
<string name="error_not_reachable">Das Gerät ist nicht erreichbar</string> <string name="error_not_reachable">Das Gerät ist nicht erreichbar</string>
<string name="error_already_paired">Das Gerät ist bereits verbunden</string> <string name="error_already_paired">Das Gerät ist bereits verbunden</string>
<string name="error_timed_out">Zeitüberschreitung</string> <string name="error_timed_out">Zeitüberschreitung</string>
<string name="error_clocks_not_match">Uhren der Geräte sind nicht synchron</string>
<string name="error_canceled_by_user">Abbruch durch Benutzer</string> <string name="error_canceled_by_user">Abbruch durch Benutzer</string>
<string name="error_canceled_by_other_peer">Abbruch durch Gegenstelle</string> <string name="error_canceled_by_other_peer">Abbruch durch Gegenstelle</string>
<string name="encryption_info_title">Verschlüsselungsinformationen</string> <string name="encryption_info_title">Verschlüsselungsinformationen</string>
@@ -163,11 +161,9 @@
<string name="middle_click">Mittelklick senden</string> <string name="middle_click">Mittelklick senden</string>
<string name="show_keyboard">Tastatur anzeigen</string> <string name="show_keyboard">Tastatur anzeigen</string>
<string name="device_not_paired">Das Gerät ist nicht verbunden</string> <string name="device_not_paired">Das Gerät ist nicht verbunden</string>
<string name="pairing_duplicate_names">Achtung: Es gibt mehrere Geräte mit dem gleichen Namen.</string>
<string name="request_pairing">Kopplung anfordern</string> <string name="request_pairing">Kopplung anfordern</string>
<string name="pairing_accept">Annehmen</string> <string name="pairing_accept">Annehmen</string>
<string name="pairing_reject">Ablehnen</string> <string name="pairing_reject">Ablehnen</string>
<string name="pairing_explanation">Zwei Geräte zu koppeln ermöglicht diesen, auf das jeweils andere zuzugreifen. Koppeln Sie nur Ihre eigenen Geräte.</string>
<string name="settings">Einstellungen</string> <string name="settings">Einstellungen</string>
<string name="mpris_play">Wiedergabe</string> <string name="mpris_play">Wiedergabe</string>
<string name="mpris_pause">Anhalten</string> <string name="mpris_pause">Anhalten</string>
@@ -190,16 +186,13 @@
<string name="mpris_notifications_explanation">Benachrichtigungen müssen erlaubt sein, um entfernte Medien im Benachrichtigungsfenster zu zeigen.</string> <string name="mpris_notifications_explanation">Benachrichtigungen müssen erlaubt sein, um entfernte Medien im Benachrichtigungsfenster zu zeigen.</string>
<string name="mpris_notification_settings_title">Benachrichtigung zur Medienkontrolle anzeigen</string> <string name="mpris_notification_settings_title">Benachrichtigung zur Medienkontrolle anzeigen</string>
<string name="mpris_notification_settings_summary">Die Steuerung der Medienwiedergabe auch dann erlauben wenn KDE Connect nicht geöffnet ist</string> <string name="mpris_notification_settings_summary">Die Steuerung der Medienwiedergabe auch dann erlauben wenn KDE Connect nicht geöffnet ist</string>
<string name="share_to">Freigeben für …</string> <string name="share_to">Freigeben für ...</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">URLs, die mit einem nicht erreichbaren Gerät geteilt werden, werden zugestellt sobald es erreichbar wird.\n\n</string> <string name="unreachable_device_url_share_text">URLs, die mit einem nicht erreichbaren Gerät geteilt werden, werden zugestellt sobald es erreichbar wird.\n\n</string>
<string name="protocol_version">Protokollversion:</string>
<string name="protocol_version_newer">Dieses Gerät verwendet eine neuere Protokollversion</string> <string name="protocol_version_newer">Dieses Gerät verwendet eine neuere Protokollversion</string>
<string name="plugin_settings_with_name">%s-Einstellungen</string> <string name="plugin_settings_with_name">%s-Einstellungen</string>
<string name="invalid_device_name">Ungültiger Gerätename</string> <string name="invalid_device_name">Ungültiger Gerätename</string>
<string name="shareplugin_text_saved">Text empfangen und in die Zwischenablage kopiert</string> <string name="shareplugin_text_saved">Text empfangen und in die Zwischenablage kopiert</string>
<string name="custom_devices_settings">Benutzerdefinierte Geräteliste</string> <string name="custom_devices_settings">Benutzerdefinierte Geräteliste</string>
<string name="custom_devices_settings_summary">%d Geräte manuell hinzugefügt</string>
<string name="custom_device_list">Geräte nach IP-Adresse hinzufügen</string> <string name="custom_device_list">Geräte nach IP-Adresse hinzufügen</string>
<string name="custom_device_deleted">Benutzerdefinierte Geräte gelöscht</string> <string name="custom_device_deleted">Benutzerdefinierte Geräte gelöscht</string>
<string name="custom_device_list_help">Falls Ihr Gerät nicht automatisch erkannt wird, können Sie es über die IP-Adresse oder den Gerätenamen hinzufügen. Klicken Sie dafür auf den schwebenden Aktionsknopf</string> <string name="custom_device_list_help">Falls Ihr Gerät nicht automatisch erkannt wird, können Sie es über die IP-Adresse oder den Gerätenamen hinzufügen. Klicken Sie dafür auf den schwebenden Aktionsknopf</string>
@@ -382,7 +375,6 @@
<string name="kde_be_free">KDE - Freiheit genießen.</string> <string name="kde_be_free">KDE - Freiheit genießen.</string>
<string name="kde">KDE</string> <string name="kde">KDE</string>
<string name="konqi">Konqi</string> <string name="konqi">Konqi</string>
<string name="click_here_to_type">Hier tippen, um zu schreiben</string>
<string name="clear_compose">Leeren</string> <string name="clear_compose">Leeren</string>
<string name="send_compose">Senden</string> <string name="send_compose">Senden</string>
<string name="open_compose_send">Text schreiben</string> <string name="open_compose_send">Text schreiben</string>
@@ -399,14 +391,10 @@
<string name="everyone_else">Jeder, der über die Jahre noch zu KDE Connect beigetragen hat</string> <string name="everyone_else">Jeder, der über die Jahre noch zu KDE Connect beigetragen hat</string>
<string name="send_clipboard">Zwischenablage senden</string> <string name="send_clipboard">Zwischenablage senden</string>
<string name="tap_to_execute">Tippen um auszuführen</string> <string name="tap_to_execute">Tippen um auszuführen</string>
<string name="plugin_stats">Modul-Statistik</string>
<string name="enable_udp_broadcast">UDP-Geräteerkennung einschalten</string> <string name="enable_udp_broadcast">UDP-Geräteerkennung einschalten</string>
<string name="enable_bluetooth">Bluetooth aktivieren (Beta)</string>
<string name="findmyphone_notifications_explanation">Benachrichtigungen müssen erlaubt sein, damit das Telefon klingeln kann, wenn die App im Hintergrund ist</string> <string name="findmyphone_notifications_explanation">Benachrichtigungen müssen erlaubt sein, damit das Telefon klingeln kann, wenn die App im Hintergrund ist</string>
<string name="no_notifications">Benachrichtigungen sind abgeschaltet, Sie erhalten keine Benachrichtigungen für eingehende Verbindungen.</string> <string name="no_notifications">Benachrichtigungen sind abgeschaltet, Sie erhalten keine Benachrichtigungen für eingehende Verbindungen.</string>
<string name="mpris_keepwatching">Wiedergabe fortsetzen</string> <string name="mpris_keepwatching">Wiedergabe fortsetzen</string>
<string name="mpris_keepwatching_settings_title">Wiedergabe fortsetzen</string> <string name="mpris_keepwatching_settings_title">Wiedergabe fortsetzen</string>
<string name="notification_channel_keepwatching">Wiedergabe fortsetzen</string> <string name="notification_channel_keepwatching">Wiedergabe fortsetzen</string>
<string name="ping_result">Ping-Dauer: %1$d Millisekunden</string>
<string name="ping_in_progress">Ping läuft </string>
</resources> </resources>

View File

@@ -192,7 +192,7 @@
<string name="mpris_notifications_explanation">Urruneko euskarria jakinarazpen tiraderan erakusteko jakinarazpen-baimena behar da</string> <string name="mpris_notifications_explanation">Urruneko euskarria jakinarazpen tiraderan erakusteko jakinarazpen-baimena behar da</string>
<string name="mpris_notification_settings_title">Erakutsi euskarri kontrolaren jakinarazpena</string> <string name="mpris_notification_settings_title">Erakutsi euskarri kontrolaren jakinarazpena</string>
<string name="mpris_notification_settings_summary">Utzi zure euskarri-jotzaileak kontrolatzen KDE Connect ireki gabe</string> <string name="mpris_notification_settings_summary">Utzi zure euskarri-jotzaileak kontrolatzen KDE Connect ireki gabe</string>
<string name="share_to">Partekatu honekin</string> <string name="share_to">Partekatu honekin...</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string> <string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">Gailu eskuraezinekin partekatutako URLak, hartara bidaliko dira eskuragarri dagoenean.\n\n</string> <string name="unreachable_device_url_share_text">Gailu eskuraezinekin partekatutako URLak, hartara bidaliko dira eskuragarri dagoenean.\n\n</string>
<string name="protocol_version">Protokoloaren bertsioa:</string> <string name="protocol_version">Protokoloaren bertsioa:</string>
@@ -429,7 +429,7 @@
<string name="notification_channel_keepwatching">Jarraitu jotzen</string> <string name="notification_channel_keepwatching">Jarraitu jotzen</string>
<string name="ping_result">«Ping» %1$d milisegundotan egin da</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_failed">Ezin izan dio gailuari «ping» egin</string>
<string name="ping_in_progress">«Ping» egiten</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_invalid">Ostalaria baliogabea da. Erabili balio duen ostalari-izen bat, IPv4, edo IPv6</string>
<string name="device_host_duplicate">Ostalaria jada zerrendan dago</string> <string name="device_host_duplicate">Ostalaria jada zerrendan dago</string>
</resources> </resources>

View File

@@ -115,7 +115,6 @@
<string name="error_not_reachable">Dispositivo inacessível</string> <string name="error_not_reachable">Dispositivo inacessível</string>
<string name="error_already_paired">Dispositivo já emparelhado</string> <string name="error_already_paired">Dispositivo já emparelhado</string>
<string name="error_timed_out">Tempo limite expirou</string> <string name="error_timed_out">Tempo limite expirou</string>
<string name="error_clocks_not_match">Os relógios dos dispositivos estão dessincronizados</string>
<string name="error_canceled_by_user">Cancelado pelo usuário</string> <string name="error_canceled_by_user">Cancelado pelo usuário</string>
<string name="error_canceled_by_other_peer">Cancelado pelo outro dispositivo</string> <string name="error_canceled_by_other_peer">Cancelado pelo outro dispositivo</string>
<string name="encryption_info_title">Informação de criptografia</string> <string name="encryption_info_title">Informação de criptografia</string>
@@ -165,11 +164,9 @@
<string name="middle_click">Enviar um Botão do Meio</string> <string name="middle_click">Enviar um Botão do Meio</string>
<string name="show_keyboard">Mostrar teclado</string> <string name="show_keyboard">Mostrar teclado</string>
<string name="device_not_paired">Dispositivo não emparelhado</string> <string name="device_not_paired">Dispositivo não emparelhado</string>
<string name="pairing_duplicate_names">Cuidado: Há vários dispositivos com o mesmo nome.</string>
<string name="request_pairing">Solicitar emparelhamento</string> <string name="request_pairing">Solicitar emparelhamento</string>
<string name="pairing_accept">Aceitar</string> <string name="pairing_accept">Aceitar</string>
<string name="pairing_reject">Rejeitar</string> <string name="pairing_reject">Rejeitar</string>
<string name="pairing_explanation">Emparelhar dois dispositivos dará acesso um ao outro. Emparelhe apenas seus próprios dispositivos.</string>
<string name="settings">Configurações</string> <string name="settings">Configurações</string>
<string name="mpris_play">Reproduzir</string> <string name="mpris_play">Reproduzir</string>
<string name="mpris_pause">Pausar</string> <string name="mpris_pause">Pausar</string>
@@ -193,15 +190,12 @@
<string name="mpris_notification_settings_title">Mostrar a notificação do controle multimídia</string> <string name="mpris_notification_settings_title">Mostrar a notificação do controle multimídia</string>
<string name="mpris_notification_settings_summary">Permite controlar os seus reprodutores de mídias sem abrir o KDE Connect</string> <string name="mpris_notification_settings_summary">Permite controlar os seus reprodutores de mídias sem abrir o KDE Connect</string>
<string name="share_to">Compartilhar com...</string> <string name="share_to">Compartilhar com...</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">URLs compartilhadas com um dispositivo inalcançável serão enviadas para ele assim que ele voltar a ficar disponível.\n\n</string> <string name="unreachable_device_url_share_text">URLs compartilhadas com um dispositivo inalcançável serão enviadas para ele assim que ele voltar a ficar disponível.\n\n</string>
<string name="protocol_version">Versão do protocolo:</string>
<string name="protocol_version_newer">Este dispositivo usa uma versão mais recente do protocolo</string> <string name="protocol_version_newer">Este dispositivo usa uma versão mais recente do protocolo</string>
<string name="plugin_settings_with_name">Configurações de %s</string> <string name="plugin_settings_with_name">Configurações de %s</string>
<string name="invalid_device_name">Nome do dispositivo inválido</string> <string name="invalid_device_name">Nome do dispositivo inválido</string>
<string name="shareplugin_text_saved">Texto recebido e salvo na área de transferência</string> <string name="shareplugin_text_saved">Texto recebido e salvo na área de transferência</string>
<string name="custom_devices_settings">Lista de dispositivos personalizada</string> <string name="custom_devices_settings">Lista de dispositivos personalizada</string>
<string name="custom_devices_settings_summary">%d dispositivos adicionados manualmente</string>
<string name="custom_device_list">Adicionar dispositivos pelo IP</string> <string name="custom_device_list">Adicionar dispositivos pelo IP</string>
<string name="custom_device_deleted">Dispositivo personalizado excluído</string> <string name="custom_device_deleted">Dispositivo personalizado excluído</string>
<string name="custom_device_list_help">Se o seu dispositivo não for detectado automaticamente você pode adicionar o endereço IP ou nome de máquina dele clicando no botão de ação flutuante</string> <string name="custom_device_list_help">Se o seu dispositivo não for detectado automaticamente você pode adicionar o endereço IP ou nome de máquina dele clicando no botão de ação flutuante</string>
@@ -311,8 +305,6 @@
<string name="devices">Dispositivos</string> <string name="devices">Dispositivos</string>
<string name="settings_rename">Nome do dispositivo</string> <string name="settings_rename">Nome do dispositivo</string>
<string name="settings_dark_mode">Tema escuro</string> <string name="settings_dark_mode">Tema escuro</string>
<string name="settings_export_logs">Exportar registros do KDE Connect</string>
<string name="settings_export_logs_text">Gera um arquivo com informações de execução que podem ajudar a solucionar problemas.</string>
<string name="settings_more_settings_title">Mais opções</string> <string name="settings_more_settings_title">Mais opções</string>
<string name="settings_more_settings_text">As configurações por dispositivo podem ser encontradas nas \'Configurações do plugin\' dentro de um determinado dispositivo.</string> <string name="settings_more_settings_text">As configurações por dispositivo podem ser encontradas nas \'Configurações do plugin\' dentro de um determinado dispositivo.</string>
<string name="setting_persistent_notification">Mostrar a notificação persistente</string> <string name="setting_persistent_notification">Mostrar a notificação persistente</string>
@@ -333,7 +325,6 @@
<string name="empty_trusted_networks_list_text">Você ainda não adicionou nenhuma rede confiável</string> <string name="empty_trusted_networks_list_text">Você ainda não adicionou nenhuma rede confiável</string>
<string name="allow_all_networks_text">Permitir tudo</string> <string name="allow_all_networks_text">Permitir tudo</string>
<string name="location_permission_needed_title">É necessário ter permissão</string> <string name="location_permission_needed_title">É necessário ter permissão</string>
<string name="bluetooth_permission_needed_desc">O KDE Connect precisa de permissão para se conectar a dispositivos próximos para tornar os dispositivos pareados via Bluetooth disponíveis no KDE Connect.</string>
<string name="location_permission_needed_desc">O KDE Connect precisa da permissão de localização em segundo plano para conhecer a rede WiFi à qual você está conectado, mesmo quando o aplicativo está em segundo plano. Isso ocorre porque o nome da rede WiFi ao seu redor pode ser usado para encontrar sua localização, mesmo quando não é isso que o KDE Connect faz.</string> <string name="location_permission_needed_desc">O KDE Connect precisa da permissão de localização em segundo plano para conhecer a rede WiFi à qual você está conectado, mesmo quando o aplicativo está em segundo plano. Isso ocorre porque o nome da rede WiFi ao seu redor pode ser usado para encontrar sua localização, mesmo quando não é isso que o KDE Connect faz.</string>
<string name="clipboard_android_x_incompat">O Android 10 removeu o acesso à área de transferência para todos os aplicativos. Este plugin ficará desativado.</string> <string name="clipboard_android_x_incompat">O Android 10 removeu o acesso à área de transferência para todos os aplicativos. Este plugin ficará desativado.</string>
<string name="mpris_open_url">Continuar tocando aqui</string> <string name="mpris_open_url">Continuar tocando aqui</string>
@@ -419,7 +410,6 @@
<string name="tap_to_execute">Toque para executar</string> <string name="tap_to_execute">Toque para executar</string>
<string name="plugin_stats">Estatísticas do plugin</string> <string name="plugin_stats">Estatísticas do plugin</string>
<string name="enable_udp_broadcast">Habilitar a descoberta de dispositivo via UDP</string> <string name="enable_udp_broadcast">Habilitar a descoberta de dispositivo via UDP</string>
<string name="enable_bluetooth">Habilitar o bluetooth (beta)</string>
<string name="receive_notifications_permission_explanation">Notificações devem ser permitidas para receber notificações dos outros dispositivos</string> <string name="receive_notifications_permission_explanation">Notificações devem ser permitidas para receber notificações dos outros dispositivos</string>
<string name="findmyphone_notifications_explanation">A permissão de notificação é necessária para que o telefone possa tocar quando o app estiver em segudo plano</string> <string name="findmyphone_notifications_explanation">A permissão de notificação é necessária para que o telefone possa tocar quando o app estiver em segudo plano</string>
<string name="no_notifications">As notificações estão desabilitadas, você não receberá notificações de solicitação de pareamento.</string> <string name="no_notifications">As notificações estão desabilitadas, você não receberá notificações de solicitação de pareamento.</string>
@@ -427,9 +417,4 @@
<string name="mpris_keepwatching_settings_title">Continuar a execução</string> <string name="mpris_keepwatching_settings_title">Continuar a execução</string>
<string name="mpris_keepwatching_settings_summary">Exibe uma notificação silenciosa para continuar a execução neste dispositivo após o fechamento da mídia.</string> <string name="mpris_keepwatching_settings_summary">Exibe uma notificação silenciosa para continuar a execução neste dispositivo após o fechamento da mídia.</string>
<string name="notification_channel_keepwatching">Continuar a execução</string> <string name="notification_channel_keepwatching">Continuar a execução</string>
<string name="ping_result">Pingado em %1$d milissegundos</string>
<string name="ping_failed">Não foi possível pingar o dispositivo</string>
<string name="ping_in_progress">Pingando...</string>
<string name="device_host_invalid">O host é inválido. Use um nome de host válido, IPv4 ou IPv6.</string>
<string name="device_host_duplicate">O host já existe na lista</string>
</resources> </resources>

View File

@@ -30,8 +30,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="pref_plugin_clipboard_desc">Share the clipboard content</string> <string name="pref_plugin_clipboard_desc">Share the clipboard content</string>
<string name="pref_plugin_clipboard_sent">Clipboard Sent</string> <string name="pref_plugin_clipboard_sent">Clipboard Sent</string>
<string name="pref_plugin_mousepad">Remote input</string> <string name="pref_plugin_mousepad">Remote input</string>
<string name="pref_plugin_mousepad_desc_nontv">Use your phone or tablet as a touchpad and keyboard</string> <string name="pref_plugin_mousepad_desc">Use your phone or tablet as a touchpad and keyboard</string>
<string name="pref_plugin_mousepad_desc_tv">Use your phone or tablet as a TV remote</string>
<string name="pref_plugin_presenter">Presentation remote</string> <string name="pref_plugin_presenter">Presentation remote</string>
<string name="pref_plugin_presenter_desc">Use your device to change slides in a presentation</string> <string name="pref_plugin_presenter_desc">Use your device to change slides in a presentation</string>
<string name="pref_plugin_remotekeyboard">Receive remote keypresses</string> <string name="pref_plugin_remotekeyboard">Receive remote keypresses</string>
@@ -138,6 +137,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<item>stronger</item> <item>stronger</item>
</string-array> </string-array>
<string name="virtualmonitor_rdp_client_not_installed">No app can handle RDP. Please install aFreeRDP or another client.</string>
<string name="sendkeystrokes_send_to">Send keystrokes to</string> <string name="sendkeystrokes_send_to">Send keystrokes to</string>
<string name="sendkeystrokes_textbox_hint">Send keystrokes to host</string> <string name="sendkeystrokes_textbox_hint">Send keystrokes to host</string>
<string name="sendkeystrokes_disabled_toast">Sending keystrokes is disabled - enable it in the settings</string> <string name="sendkeystrokes_disabled_toast">Sending keystrokes is disabled - enable it in the settings</string>
@@ -227,7 +228,6 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="right_click">Send Right Click</string> <string name="right_click">Send Right Click</string>
<string name="middle_click">Send Middle Click</string> <string name="middle_click">Send Middle Click</string>
<string name="show_keyboard">Show Keyboard</string> <string name="show_keyboard">Show Keyboard</string>
<string name="show_mouse_and_keyboard">Show Mouse and Keyboard</string>
<string name="device_not_paired">Device not paired</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="pairing_duplicate_names">Caution: There are multiple devices with the same name.</string>
<string name="request_pairing">Request pairing</string> <string name="request_pairing">Request pairing</string>
@@ -395,6 +395,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="pref_plugin_findremotedevice">Find remote device</string> <string name="pref_plugin_findremotedevice">Find remote device</string>
<string name="pref_plugin_findremotedevice_desc">Ring your remote device</string> <string name="pref_plugin_findremotedevice_desc">Ring your remote device</string>
<string name="ring">Ring</string> <string name="ring">Ring</string>
<string name="pref_plugin_virtualmonitor">Virtual Monitor</string>
<string name="pref_plugin_virtualmonitor_desc">Extend your devices monitors</string>
<string name="pref_plugin_systemvolume">System volume</string> <string name="pref_plugin_systemvolume">System volume</string>
<string name="pref_plugin_systemvolume_desc">Control the system volume of the remote device</string> <string name="pref_plugin_systemvolume_desc">Control the system volume of the remote device</string>

View File

@@ -9,6 +9,7 @@ package org.kde.kdeconnect.Backends;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread; import androidx.annotation.WorkerThread;
import org.kde.kdeconnect.Device; import org.kde.kdeconnect.Device;
@@ -16,6 +17,8 @@ import org.kde.kdeconnect.DeviceInfo;
import org.kde.kdeconnect.NetworkPacket; import org.kde.kdeconnect.NetworkPacket;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.util.ArrayList; import java.util.ArrayList;
@@ -43,6 +46,8 @@ public abstract class BaseLink {
return getDeviceInfo().id; return getDeviceInfo().id;
} }
public abstract @Nullable InetAddress getDeviceIp();
public BaseLinkProvider getLinkProvider() { public BaseLinkProvider getLinkProvider() {
return linkProvider; return linkProvider;
} }

View File

@@ -21,6 +21,7 @@ import java.io.InputStream
import java.io.InputStreamReader import java.io.InputStreamReader
import java.io.OutputStream import java.io.OutputStream
import java.io.Reader import java.io.Reader
import java.net.InetAddress
import java.util.UUID import java.util.UUID
import kotlin.text.Charsets.UTF_8 import kotlin.text.Charsets.UTF_8
@@ -98,6 +99,10 @@ class BluetoothLink(
return theDeviceInfo return theDeviceInfo
} }
override fun getDeviceIp(): InetAddress? {
return null;
}
override fun disconnect() { override fun disconnect() {
if (connection == null) { if (connection == null) {
return return
@@ -159,4 +164,4 @@ class BluetoothLink(
false false
} }
} }
} }

View File

@@ -27,9 +27,11 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.nio.channels.NotYetConnectedException; import java.nio.channels.NotYetConnectedException;
@@ -256,4 +258,7 @@ public class LanLink extends BaseLink {
packetReceived(np); packetReceived(np);
} }
@Override
public InetAddress getDeviceIp() { return socket.getInetAddress(); }
} }

View File

@@ -13,12 +13,16 @@ import org.kde.kdeconnect.Device
import org.kde.kdeconnect.DeviceInfo import org.kde.kdeconnect.DeviceInfo
import org.kde.kdeconnect.Helpers.DeviceHelper.getDeviceInfo import org.kde.kdeconnect.Helpers.DeviceHelper.getDeviceInfo
import org.kde.kdeconnect.NetworkPacket import org.kde.kdeconnect.NetworkPacket
import java.net.InetAddress
class LoopbackLink : BaseLink { class LoopbackLink : BaseLink {
constructor(context: Context, linkProvider: BaseLinkProvider) : super(context, linkProvider) constructor(context: Context, linkProvider: BaseLinkProvider) : super(context, linkProvider)
override fun getName(): String = "LoopbackLink" override fun getName(): String = "LoopbackLink"
override fun getDeviceInfo(): DeviceInfo = getDeviceInfo(context) override fun getDeviceInfo(): DeviceInfo = getDeviceInfo(context)
override fun getDeviceIp(): InetAddress {
return InetAddress.getLoopbackAddress()
}
@WorkerThread @WorkerThread
override fun sendPacket(packet: NetworkPacket, callback: Device.SendPacketStatusCallback, sendPayloadFromSameThread: Boolean): Boolean { override fun sendPacket(packet: NetworkPacket, callback: Device.SendPacketStatusCallback, sendPayloadFromSameThread: Boolean): Boolean {

View File

@@ -46,6 +46,8 @@ import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentMap import java.util.concurrent.ConcurrentMap
import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CopyOnWriteArrayList
import androidx.core.content.edit import androidx.core.content.edit
import java.net.InetAddress
import java.net.SocketAddress
class Device : PacketReceiver { class Device : PacketReceiver {
@@ -647,6 +649,10 @@ class Device : PacketReceiver {
fun removePluginsChangedListener(listener: PluginsChangedListener) = pluginsChangedListeners.remove(listener) fun removePluginsChangedListener(listener: PluginsChangedListener) = pluginsChangedListeners.remove(listener)
fun ipAddress(): InetAddress? {
return links.firstNotNullOf { it.deviceIp }
}
fun disconnect() { fun disconnect() {
links.forEach(BaseLink::disconnect) links.forEach(BaseLink::disconnect)
} }

View File

@@ -43,7 +43,7 @@ class DeviceHost private constructor(private val host: String) {
companion object { companion object {
/** Ping timeout */ /** Ping timeout */
private const val PING_TIMEOUT = 3_000 private const val PING_TIMEOUT = 3_000
private val hostnameValidityPattern = Regex("^[0-9A-Za-z.:_-]+$") private val hostnameValidityPattern = Regex("^[0-9A-Za-z._-]+$")
@JvmStatic @JvmStatic
fun isValidDeviceHost(host: String): Boolean { fun isValidDeviceHost(host: String): Boolean {

View File

@@ -19,7 +19,7 @@ object NetworkHelper {
// //
// If we run across an interface that has this, we can safely // If we run across an interface that has this, we can safely
// ignore it. In fact, it's much safer to do. If we don't, we // ignore it. In fact, it's much safer to do. If we don't, we
// might get invalid IP adddresses out of it. // might get invalid IP addresses out of it.
@JvmStatic @JvmStatic
val localIpAddress: InetAddress? val localIpAddress: InetAddress?
get() { get() {
@@ -34,7 +34,7 @@ object NetworkHelper {
// //
// If we run across an interface that has this, we can safely // If we run across an interface that has this, we can safely
// ignore it. In fact, it's much safer to do. If we don't, we // ignore it. In fact, it's much safer to do. If we don't, we
// might get invalid IP adddresses out of it. // might get invalid IP addresses out of it.
if (intf.displayName.contains("rmnet")) { if (intf.displayName.contains("rmnet")) {
continue continue
} }

View File

@@ -3,9 +3,9 @@
* SPDX-FileCopyrightText: 2020 Sylvia van Os <sylvia@hackerchick.me> * SPDX-FileCopyrightText: 2020 Sylvia van Os <sylvia@hackerchick.me>
* *
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/ */
package org.kde.kdeconnect.Plugins.MousePadPlugin; package org.kde.kdeconnect.Plugins.BigscreenPlugin;
import android.Manifest; import android.Manifest;
import android.app.Activity; import android.app.Activity;
@@ -13,9 +13,6 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.speech.RecognizerIntent; import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer; import android.speech.SpeechRecognizer;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -36,9 +33,9 @@ import kotlin.LazyKt;
public class BigscreenActivity extends BaseActivity<ActivityBigscreenBinding> { public class BigscreenActivity extends BaseActivity<ActivityBigscreenBinding> {
private static final int REQUEST_SPEECH = 100; private static final int REQUEST_SPEECH = 100;
private final Lazy<ActivityBigscreenBinding> lazyBinding = LazyKt.lazy(() -> ActivityBigscreenBinding.inflate(getLayoutInflater())); private final Lazy<ActivityBigscreenBinding> lazyBinding = LazyKt.lazy(() -> ActivityBigscreenBinding.inflate(getLayoutInflater()));
@NonNull @NonNull
@Override @Override
protected ActivityBigscreenBinding getBinding() { protected ActivityBigscreenBinding getBinding() {
@@ -60,7 +57,7 @@ public class BigscreenActivity extends BaseActivity<ActivityBigscreenBinding> {
getBinding().micButton.setVisibility(View.INVISIBLE); getBinding().micButton.setVisibility(View.INVISIBLE);
} }
MousePadPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, MousePadPlugin.class); BigscreenPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, BigscreenPlugin.class);
if (plugin == null) { if (plugin == null) {
finish(); finish();
return; return;
@@ -93,27 +90,6 @@ public class BigscreenActivity extends BaseActivity<ActivityBigscreenBinding> {
startActivityForResult(intent, REQUEST_SPEECH); startActivityForResult(intent, REQUEST_SPEECH);
} }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_bigscreen, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_use_mouse_and_keyboard) {
Intent intent = new Intent(this, MousePadActivity.class);
intent.putExtra("deviceId", getIntent().getStringExtra("deviceId"));
startActivity(intent);
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
@@ -123,7 +99,7 @@ public class BigscreenActivity extends BaseActivity<ActivityBigscreenBinding> {
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
if (result.get(0) != null) { if (result.get(0) != null) {
final String deviceId = getIntent().getStringExtra("deviceId"); final String deviceId = getIntent().getStringExtra("deviceId");
MousePadPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, MousePadPlugin.class); BigscreenPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, BigscreenPlugin.class);
if (plugin == null) { if (plugin == null) {
finish(); finish();
return; return;

View File

@@ -0,0 +1,146 @@
/*
* SPDX-FileCopyrightText: 2014 Ahmed I. Khalil <ahmedibrahimkhali@gmail.com>
* SPDX-FileCopyrightText: 2020 Sylvia van Os <sylvia@hackerchick.me>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
package org.kde.kdeconnect.Plugins.BigscreenPlugin;
import static org.kde.kdeconnect.Plugins.MousePadPlugin.KeyListenerView.SpecialKeysMap;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.KeyEvent;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import org.kde.kdeconnect.DeviceType;
import org.kde.kdeconnect.NetworkPacket;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.Plugins.PluginFactory;
import org.kde.kdeconnect_tp.R;
@PluginFactory.LoadablePlugin
public class BigscreenPlugin extends Plugin {
private final static String PACKET_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request";
private final static String PACKET_TYPE_BIGSCREEN_STT = "kdeconnect.bigscreen.stt";
@Override
public boolean isCompatible() {
return getDevice().getDeviceType().equals(DeviceType.TV) && super.isCompatible();
}
@Override
protected int getOptionalPermissionExplanation() {
return R.string.bigscreen_optional_permission_explanation;
}
@Override
public @NonNull String getDisplayName() {
return context.getString(R.string.pref_plugin_bigscreen);
}
@Override
public @NonNull String getDescription() {
return context.getString(R.string.pref_plugin_bigscreen_desc);
}
@Override
public @DrawableRes int getIcon() {
return R.drawable.ic_presenter_24dp;
}
@Override
public boolean isEnabledByDefault() {
return true;
}
@Override
public boolean hasSettings() {
return false;
}
@Override
public boolean displayAsButton(Context context) {
return true;
}
@Override
public void startMainActivity(Activity parentActivity) {
Intent intent = new Intent(parentActivity, BigscreenActivity.class);
intent.putExtra("deviceId", getDevice().getDeviceId());
parentActivity.startActivity(intent);
}
@Override
public @NonNull String[] getSupportedPacketTypes() { return new String[]{PACKET_TYPE_BIGSCREEN_STT}; }
@Override
public @NonNull String[] getOutgoingPacketTypes() {
return new String[]{PACKET_TYPE_MOUSEPAD_REQUEST, PACKET_TYPE_BIGSCREEN_STT};
}
@Override
public @NonNull String getActionName() {
return context.getString(R.string.pref_plugin_bigscreen);
}
public @NonNull String[] getOptionalPermissions() {
return new String[]{Manifest.permission.RECORD_AUDIO};
}
public Boolean hasMicPermission() {
return isPermissionGranted(Manifest.permission.RECORD_AUDIO);
}
public void sendLeft() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_LEFT));
getDevice().sendPacket(np);
}
public void sendRight() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_RIGHT));
getDevice().sendPacket(np);
}
public void sendUp() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_UP));
getDevice().sendPacket(np);
}
public void sendDown() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_DOWN));
getDevice().sendPacket(np);
}
public void sendSelect() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_ENTER));
getDevice().sendPacket(np);
}
public void sendHome() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("alt", true);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_F4));
getDevice().sendPacket(np);
}
public void sendSTT(String content) {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_BIGSCREEN_STT);
np.set("type", "stt");
np.set("content", content);
getDevice().sendPacket(np);
}
}

View File

@@ -6,18 +6,13 @@
package org.kde.kdeconnect.Plugins.MousePadPlugin; package org.kde.kdeconnect.Plugins.MousePadPlugin;
import static org.kde.kdeconnect.Plugins.MousePadPlugin.KeyListenerView.SpecialKeysMap;
import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.view.KeyEvent;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.kde.kdeconnect.DeviceType;
import org.kde.kdeconnect.NetworkPacket; import org.kde.kdeconnect.NetworkPacket;
import org.kde.kdeconnect.Plugins.Plugin; import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.Plugins.PluginFactory; import org.kde.kdeconnect.Plugins.PluginFactory;
@@ -30,7 +25,6 @@ public class MousePadPlugin extends Plugin {
//public final static String PACKET_TYPE_MOUSEPAD = "kdeconnect.mousepad"; //public final static String PACKET_TYPE_MOUSEPAD = "kdeconnect.mousepad";
public final static String PACKET_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request"; public final static String PACKET_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request";
private final static String PACKET_TYPE_MOUSEPAD_KEYBOARDSTATE = "kdeconnect.mousepad.keyboardstate"; private final static String PACKET_TYPE_MOUSEPAD_KEYBOARDSTATE = "kdeconnect.mousepad.keyboardstate";
private final static String PACKET_TYPE_BIGSCREEN_STT = "kdeconnect.bigscreen.stt";
private boolean keyboardEnabled = true; private boolean keyboardEnabled = true;
@@ -49,7 +43,7 @@ public class MousePadPlugin extends Plugin {
@Override @Override
public @NonNull String getDescription() { public @NonNull String getDescription() {
return context.getString(R.string.pref_plugin_mousepad_desc_nontv); return context.getString(R.string.pref_plugin_mousepad_desc);
} }
@Override @Override
@@ -74,15 +68,9 @@ public class MousePadPlugin extends Plugin {
@Override @Override
public void startMainActivity(Activity parentActivity) { public void startMainActivity(Activity parentActivity) {
if (getDevice().getDeviceType() == DeviceType.TV) { Intent intent = new Intent(parentActivity, MousePadActivity.class);
Intent intent = new Intent(parentActivity, BigscreenActivity.class); intent.putExtra("deviceId", getDevice().getDeviceId());
intent.putExtra("deviceId", getDevice().getDeviceId()); parentActivity.startActivity(intent);
parentActivity.startActivity(intent);
} else {
Intent intent = new Intent(parentActivity, MousePadActivity.class);
intent.putExtra("deviceId", getDevice().getDeviceId());
parentActivity.startActivity(intent);
}
} }
@Override @Override
@@ -107,10 +95,6 @@ public class MousePadPlugin extends Plugin {
getDevice().sendPacket(np); getDevice().sendPacket(np);
} }
public Boolean hasMicPermission() {
return isPermissionGranted(Manifest.permission.RECORD_AUDIO);
}
public void sendLeftClick() { public void sendLeftClick() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST); NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("singleclick", true); np.set("singleclick", true);
@@ -155,50 +139,6 @@ public class MousePadPlugin extends Plugin {
getDevice().sendPacket(np); getDevice().sendPacket(np);
} }
public void sendLeft() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_LEFT));
getDevice().sendPacket(np);
}
public void sendRight() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_RIGHT));
getDevice().sendPacket(np);
}
public void sendUp() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_UP));
getDevice().sendPacket(np);
}
public void sendDown() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_DPAD_DOWN));
getDevice().sendPacket(np);
}
public void sendSelect() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_ENTER));
getDevice().sendPacket(np);
}
public void sendHome() {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("alt", true);
np.set("specialKey", SpecialKeysMap.get(KeyEvent.KEYCODE_F4));
getDevice().sendPacket(np);
}
public void sendSTT(String content) {
NetworkPacket np = new NetworkPacket(PACKET_TYPE_BIGSCREEN_STT);
np.set("type", "stt");
np.set("content", content);
getDevice().sendPacket(np);
}
public void sendKeyboardPacket(NetworkPacket np) { public void sendKeyboardPacket(NetworkPacket np) {
getDevice().sendPacket(np); getDevice().sendPacket(np);
} }

View File

@@ -36,7 +36,6 @@ import java.util.stream.Collectors;
import kotlin.Lazy; import kotlin.Lazy;
import kotlin.LazyKt; import kotlin.LazyKt;
import kotlin.Unit;
public class SendKeystrokesToHostActivity extends BaseActivity<ActivitySendkeystrokesBinding> { public class SendKeystrokesToHostActivity extends BaseActivity<ActivitySendkeystrokesBinding> {
@@ -167,16 +166,17 @@ public class SendKeystrokesToHostActivity extends BaseActivity<ActivitySendkeyst
for (Device d : devices) { for (Device d : devices) {
if (d.isReachable() && d.isPaired()) { if (d.isReachable() && d.isPaired()) {
devicesList.add(d); devicesList.add(d);
items.add(new DeviceItem(d, this::deviceClicked)); items.add(new DeviceItem(d));
section.isEmpty = false; section.isEmpty = false;
} }
} }
getBinding().devicesList.setAdapter(new ListAdapter(SendKeystrokesToHostActivity.this, items)); getBinding().devicesList.setAdapter(new ListAdapter(SendKeystrokesToHostActivity.this, items));
getBinding().devicesList.setOnItemClickListener((adapterView, view, i, l) -> {
// Configure focus order for Accessibility, for touchpads, and for TV remotes Device device = devicesList.get(i - 1); // NOTE: -1 because of the title!
// (allow focus of items in the device list) sendKeys(device);
getBinding().devicesList.setItemsCanFocus(true); this.finish(); // close the activity
});
// only one device is connected and we trust the text to send -> send it and close the activity. // only one device is connected and we trust the text to send -> send it and close the activity.
// Usually we already check it in `onStart` - but if the BackgroundService was not started/connected to the host // Usually we already check it in `onStart` - but if the BackgroundService was not started/connected to the host
@@ -185,15 +185,8 @@ public class SendKeystrokesToHostActivity extends BaseActivity<ActivitySendkeyst
if (devicesList.size() == 1 && contentIsOkay) { if (devicesList.size() == 1 && contentIsOkay) {
Device device = devicesList.get(0); Device device = devicesList.get(0);
sendKeys(device); sendKeys(device);
finish(); // close the activity this.finish(); // close the activity
} }
} }
private Unit deviceClicked(Device device) {
sendKeys(device);
finish(); // close the activity
return Unit.INSTANCE;
}
} }

View File

@@ -99,7 +99,7 @@ class MprisMediaSession : OnSharedPreferenceChangeListener, NotificationReceiver
* @param device The device id * @param device The device id
*/ */
fun onCreate(context: Context?, plugin: MprisPlugin, device: String) { fun onCreate(context: Context?, plugin: MprisPlugin, device: String) {
if (mprisDevices.isEmpty()) { if (mprisDevices.isEmpty) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context) val prefs = PreferenceManager.getDefaultSharedPreferences(context)
prefs.registerOnSharedPreferenceChangeListener(this) prefs.registerOnSharedPreferenceChangeListener(this)
} }
@@ -137,7 +137,7 @@ class MprisMediaSession : OnSharedPreferenceChangeListener, NotificationReceiver
plugin.removePlayerListUpdatedHandler("media_notification") plugin.removePlayerListUpdatedHandler("media_notification")
updateMediaNotification() updateMediaNotification()
if (mprisDevices.isEmpty()) { if (mprisDevices.isEmpty) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context) val prefs = PreferenceManager.getDefaultSharedPreferences(context)
prefs.unregisterOnSharedPreferenceChangeListener(this) prefs.unregisterOnSharedPreferenceChangeListener(this)
} }

View File

@@ -103,14 +103,14 @@ class MprisNowPlayingFragment : Fragment(), VolumeKeyListener {
performActionOnClick(mprisControlBinding.stopButton, MprisPlayer::sendStop) performActionOnClick(mprisControlBinding.stopButton, MprisPlayer::sendStop)
mprisControlBinding.volumeSeek.setOnSeekBarChangeListener(object : OnSeekBarChangeListener { mprisControlBinding.volumeSeek.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) { override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {}
val targetPlayer = targetPlayer ?: return
targetPlayer.sendSetVolume(seekBar.progress)
}
override fun onStartTrackingTouch(seekBar: SeekBar) {} override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {} override fun onStopTrackingTouch(seekBar: SeekBar) {
val targetPlayer = targetPlayer ?: return
targetPlayer.sendSetVolume(seekBar.progress)
}
}) })
positionSeekUpdateRunnable = Runnable { positionSeekUpdateRunnable = Runnable {

View File

@@ -11,14 +11,21 @@ import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.view.Window import android.view.Window
import android.widget.ArrayAdapter
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.edit import androidx.core.content.edit
import org.kde.kdeconnect.Device import org.kde.kdeconnect.Device
import org.kde.kdeconnect.KdeConnect import org.kde.kdeconnect.KdeConnect
import org.kde.kdeconnect.UserInterface.List.DeviceItem import org.kde.kdeconnect.UserInterface.List.DeviceItem
import org.kde.kdeconnect.UserInterface.List.ListAdapter import org.kde.kdeconnect.UserInterface.List.ListAdapter
import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.WidgetRemoteCommandPluginDialogBinding import org.kde.kdeconnect_tp.databinding.WidgetRemoteCommandPluginDialogBinding
import java.util.stream.Collectors
class RunCommandWidgetConfigActivity : AppCompatActivity() { class RunCommandWidgetConfigActivity : AppCompatActivity() {
@@ -40,25 +47,24 @@ class RunCommandWidgetConfigActivity : AppCompatActivity() {
val binding = WidgetRemoteCommandPluginDialogBinding.inflate(layoutInflater) val binding = WidgetRemoteCommandPluginDialogBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
val pairedDevices = KdeConnect.getInstance().devices.values.asSequence().filter(Device::isPaired).toList() val pairedDevices = KdeConnect.getInstance().devices.values.stream().filter(Device::isPaired).collect(Collectors.toList())
val list = ListAdapter(this, pairedDevices.map { DeviceItem(it, ::deviceClicked) }) val list = ListAdapter(this, pairedDevices.map { DeviceItem(it) })
binding.runCommandsDeviceList.adapter = list binding.runCommandsDeviceList.adapter = list
binding.runCommandsDeviceList.setOnItemClickListener { _, _, position, _ ->
val deviceId = pairedDevices[position].deviceId
saveWidgetDeviceIdPref(this, appWidgetId, deviceId)
val appWidgetManager = AppWidgetManager.getInstance(this)
updateAppWidget(this, appWidgetManager, appWidgetId)
val resultValue = Intent()
resultValue.putExtra(EXTRA_APPWIDGET_ID, appWidgetId)
setResult(RESULT_OK, resultValue)
finish()
}
binding.runCommandsDeviceList.emptyView = binding.noDevices binding.runCommandsDeviceList.emptyView = binding.noDevices
} }
fun deviceClicked(device: Device) {
val deviceId = device.deviceId
saveWidgetDeviceIdPref(this, appWidgetId, deviceId)
val appWidgetManager = AppWidgetManager.getInstance(this)
updateAppWidget(this, appWidgetManager, appWidgetId)
val resultValue = Intent()
resultValue.putExtra(EXTRA_APPWIDGET_ID, appWidgetId)
setResult(RESULT_OK, resultValue)
finish()
}
} }
private const val PREFS_NAME = "org.kde.kdeconnect_tp.WidgetProvider" private const val PREFS_NAME = "org.kde.kdeconnect_tp.WidgetProvider"

View File

@@ -39,7 +39,6 @@ import java.util.Set;
import kotlin.Lazy; import kotlin.Lazy;
import kotlin.LazyKt; import kotlin.LazyKt;
import kotlin.Unit;
public class ShareActivity extends BaseActivity<ActivityShareBinding> { public class ShareActivity extends BaseActivity<ActivityShareBinding> {
private static final String KEY_UNREACHABLE_URL_LIST = "key_unreachable_url_list"; private static final String KEY_UNREACHABLE_URL_LIST = "key_unreachable_url_list";
@@ -112,31 +111,26 @@ public class ShareActivity extends BaseActivity<ActivityShareBinding> {
if (d.isPaired() && (intentHasUrl || d.isReachable())) { if (d.isPaired() && (intentHasUrl || d.isReachable())) {
devicesList.add(d); devicesList.add(d);
if (!d.isReachable()) { if (!d.isReachable()) {
items.add(new UnreachableDeviceItem(d, device -> deviceClicked(device, intentHasUrl, intent))); items.add(new UnreachableDeviceItem(d));
} else { } else {
items.add(new DeviceItem(d, device -> deviceClicked(device, intentHasUrl, intent))); items.add(new DeviceItem(d));
} }
section.isEmpty = false; section.isEmpty = false;
} }
} }
getBinding().devicesListLayout.devicesList.setAdapter(new ListAdapter(ShareActivity.this, items)); getBinding().devicesListLayout.devicesList.setAdapter(new ListAdapter(ShareActivity.this, items));
getBinding().devicesListLayout.devicesList.setOnItemClickListener((adapterView, view, i, l) -> {
// Configure focus order for Accessibility, for touchpads, and for TV remotes Device device = devicesList.get(i - 1); //NOTE: -1 because of the title!
// (allow focus of items in the device list) SharePlugin plugin = KdeConnect.getInstance().getDevicePlugin(device.getDeviceId(), SharePlugin.class);
getBinding().devicesListLayout.devicesList.setItemsCanFocus(true); if (intentHasUrl && !device.isReachable()) {
} // Store the URL to be delivered once device becomes online
storeUrlForFutureDelivery(device, intent.getStringExtra(Intent.EXTRA_TEXT));
private Unit deviceClicked(Device device, boolean intentHasUrl, Intent intent) { } else if (plugin != null) {
SharePlugin plugin = KdeConnect.getInstance().getDevicePlugin(device.getDeviceId(), SharePlugin.class); plugin.share(intent);
if (intentHasUrl && !device.isReachable()) { }
// Store the URL to be delivered once device becomes online finish();
storeUrlForFutureDelivery(device, intent.getStringExtra(Intent.EXTRA_TEXT)); });
} else if (plugin != null) {
plugin.share(intent);
}
finish();
return Unit.INSTANCE;
} }
private boolean doesIntentContainUrl(Intent intent) { private boolean doesIntentContainUrl(Intent intent) {

View File

@@ -0,0 +1,104 @@
/*
* SPDX-FileCopyrightText: 2025 Aleix Pol i Gonzalez <aleixpol@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
package org.kde.kdeconnect.Plugins.VirtualMonitorPlugin
import android.content.Intent
import android.net.Uri
import android.util.Log
import android.widget.Toast
import androidx.core.net.toUri
import org.json.JSONArray
import org.json.JSONObject
import org.kde.kdeconnect.NetworkPacket
import org.kde.kdeconnect.Plugins.Plugin
import org.kde.kdeconnect.Plugins.PluginFactory.LoadablePlugin
import org.kde.kdeconnect_tp.R
const val PACKET_TYPE_VIRTUALMONITOR: String = "kdeconnect.virtualmonitor"
const val PACKET_TYPE_VIRTUALMONITOR_REQUEST: String = "kdeconnect.virtualmonitor.request"
@LoadablePlugin
class VirtualMonitorPlugin : Plugin() {
override val displayName: String
get() = context.resources.getString(R.string.pref_plugin_virtualmonitor)
override val description: String
get() = context.resources.getString(R.string.pref_plugin_virtualmonitor_desc)
private fun openUrlExternally(url: Uri): Boolean {
val intent = Intent(Intent.ACTION_VIEW, url)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
if (intent.resolveActivity(context.packageManager) != null) {
context.startActivity(intent)
return true
} else {
return false
}
}
override fun onPacketReceived(np: NetworkPacket): Boolean {
if (np.type == PACKET_TYPE_VIRTUALMONITOR_REQUEST) {
// At least a password is necessary, we have defaults for all other parameters
if (!np.has("password")) {
Log.e("KDE/VirtualMonitor", "Request invalid, missing password")
return false
}
val addr = device.ipAddress()?.hostAddress
if (addr == null) {
Log.e("KDE/VirtualMonitor", "Request invalid, no address")
return false
}
val protocol = np.getString("protocol")
val username = np.getString("username")
val password = np.getString("password")
val port = np.getInt("port", -1)
val url = "$protocol://$username:$password@$addr:$port".toUri()
Log.i("KDE/VirtualMonitor", "Received request, try connecting to $url")
if (!openUrlExternally(url)) {
Toast.makeText(context, R.string.virtualmonitor_rdp_client_not_installed, Toast.LENGTH_LONG).show()
openUrlExternally("https://f-droid.org/en/packages/com.freerdp.afreerdp/".toUri())
val failure = NetworkPacket(PACKET_TYPE_VIRTUALMONITOR).apply {
this["failed"] = 0
}
device.sendPacket(failure)
}
}
return true
}
override fun onCreate() : Boolean
{
if (device.ipAddress() == null) {
Log.e("KDE/VirtualMonitor", "No IP address for device, pass.")
return false
}
val metrics = context.resources.displayMetrics
val np = NetworkPacket(PACKET_TYPE_VIRTUALMONITOR).apply {
this["resolutions"] = JSONArray().apply {
put(JSONObject().apply {
put("resolution", "${metrics.widthPixels}x${metrics.heightPixels}")
put("scale", metrics.density)
})
}
this["supports_rdp"] = true
this["supports_virt_mon"] = false
}
device.sendPacket(np)
return true
}
override val supportedPacketTypes: Array<String>
get() = arrayOf(PACKET_TYPE_VIRTUALMONITOR, PACKET_TYPE_VIRTUALMONITOR_REQUEST)
override val outgoingPacketTypes: Array<String>
get() = arrayOf(PACKET_TYPE_VIRTUALMONITOR)
}

View File

@@ -12,9 +12,11 @@ import org.kde.kdeconnect_tp.databinding.ListItemDeviceEntryBinding
open class DeviceItem( open class DeviceItem(
val device: Device, val device: Device,
private val callback: ((d: Device) -> Unit) private val callback: ((d: Device) -> Unit)?
) : ListAdapter.Item ) : ListAdapter.Item
{ {
constructor(device: Device) : this(device, null)
protected lateinit var binding: ListItemDeviceEntryBinding protected lateinit var binding: ListItemDeviceEntryBinding
override fun inflateView(layoutInflater: LayoutInflater): View { override fun inflateView(layoutInflater: LayoutInflater): View {
@@ -23,9 +25,11 @@ open class DeviceItem(
binding.listItemEntryIcon.setImageDrawable(device.icon) binding.listItemEntryIcon.setImageDrawable(device.icon)
binding.listItemEntryTitle.text = device.name binding.listItemEntryTitle.text = device.name
binding.getRoot().setOnClickListener(View.OnClickListener { v1: View? -> if (callback != null) {
callback(device) binding.getRoot().setOnClickListener(View.OnClickListener { v1: View? ->
}) callback(device)
})
}
return binding.getRoot() return binding.getRoot()
} }

View File

@@ -12,7 +12,7 @@ import org.kde.kdeconnect_tp.R
class PairingDeviceItem( class PairingDeviceItem(
device: Device, device: Device,
callback: ((d: Device) -> Unit) callback: ((d: Device) -> Unit)?
) : DeviceItem(device, callback) { ) : DeviceItem(device, callback) {
override fun inflateView(layoutInflater: LayoutInflater): View { override fun inflateView(layoutInflater: LayoutInflater): View {
return super.inflateView(layoutInflater).also { return super.inflateView(layoutInflater).also {

View File

@@ -10,10 +10,7 @@ import android.view.View
import org.kde.kdeconnect.Device import org.kde.kdeconnect.Device
import org.kde.kdeconnect_tp.R import org.kde.kdeconnect_tp.R
class UnreachableDeviceItem( class UnreachableDeviceItem(device: Device) : DeviceItem(device) {
device: Device,
callback: ((d: Device) -> Unit),
) : DeviceItem(device, callback) {
override fun inflateView(layoutInflater: LayoutInflater): View { override fun inflateView(layoutInflater: LayoutInflater): View {
return super.inflateView(layoutInflater).also { return super.inflateView(layoutInflater).also {
binding.listItemEntrySummary.setText(R.string.runcommand_notreachable) binding.listItemEntrySummary.setText(R.string.runcommand_notreachable)