Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5dae4b5
first attempt
diegolmello Mar 27, 2026
d324a86
fix(android): guard hasActiveCall Telecom check for READ_PHONE_STATE
diegolmello Mar 30, 2026
266922e
feat(android): add READ_PHONE_STATE runtime request helper for VoIP
diegolmello Mar 30, 2026
bd7158c
feat(voip): request READ_PHONE_STATE when starting a VoIP call
diegolmello Mar 30, 2026
309cbba
fix(android): treat ringing/dialing CallKeep connections as busy for …
diegolmello Mar 30, 2026
328b646
fix(ios): skip initial-events stash for busy VoIP push
diegolmello Mar 30, 2026
8fc00f5
feat(voip): implement videoconference blocking logic and related tests
diegolmello Mar 30, 2026
f30a57a
feat(ios): CallKit call-waiting — multi-call observer, disable hold
diegolmello Mar 30, 2026
12c6cac
feat: Enhance MediaSessionInstance tests for new call handling
diegolmello Mar 30, 2026
5ae590d
test(voip): add MediaCallEvents tests for cross-server accept pipeline
diegolmello Mar 30, 2026
beb9a7c
refactor(voip): keep MediaCallEvents native handlers private
diegolmello Mar 30, 2026
385991d
chore(voip): dedupe MediaCallEvents tests, clarify nativeAccept docs
diegolmello Mar 30, 2026
4a0e2f7
chore(voip): iOS CallKit call-waiting + drop JS callee busy-reject af…
diegolmello Mar 30, 2026
36ed84f
chore(voip): document iOS busy-call helpers; tighten videoconf guard …
diegolmello Mar 30, 2026
9e71e6c
i18n: add phone state permission strings for supported locales
diegolmello Mar 30, 2026
c7e4f74
fix: resolve ESLint errors in VoIP-related test files
diegolmello Mar 30, 2026
72ab82e
fix voipservice
diegolmello Mar 31, 2026
408cced
feat(voip): auto-hold RC call on OS hold (CallKeep didToggleHoldCallA…
diegolmello Apr 1, 2026
5828949
Fix for phone calls on iOS
diegolmello Apr 1, 2026
ab85a8f
support holding
diegolmello Apr 1, 2026
d7bffcd
fix(voip): localize phone-state OK button; gate FCM before busy check
diegolmello Apr 1, 2026
6bebf15
feat: per-call DDP registry for call waiting
diegolmello Apr 1, 2026
db0bb36
chore: format code and fix lint issues
diegolmello Apr 1, 2026
3bc1473
fix(voip): detect cellular calls in no-permission audio mode fallback
diegolmello Apr 1, 2026
126715d
fix(voip): guard toggleHold against already-resumed state on OS unhold
diegolmello Apr 1, 2026
f279495
fix(voip): thread-safe iOS accept callbacks and lightweight Android b…
diegolmello Apr 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package chat.rocket.reactnative.voip

import android.Manifest
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.RingtoneManager
import android.os.Build
import android.os.Bundle
Expand All @@ -17,6 +20,7 @@ import android.os.Looper
import android.provider.Settings
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import android.content.ComponentName
import android.net.Uri
Expand Down Expand Up @@ -477,6 +481,70 @@ class VoipNotification(private val context: Context) {
}
}

/**
* True when the user is already in a call: this app's Telecom connections (ringing, dialing,
* active, hold — same idea as iOS CXCallObserver "any non-ended"), any system in-call state
* (API 26+ when READ_PHONE_STATE is granted), or audio in communication mode (fallback on all
* API levels when Telecom is unavailable or denied).
*/
private fun hasActiveCall(context: Context): Boolean {
val ownBusy = VoiceConnectionService.currentConnections.values.any { connection ->
when (connection.state) {
android.telecom.Connection.STATE_RINGING,
android.telecom.Connection.STATE_DIALING,
android.telecom.Connection.STATE_ACTIVE,
android.telecom.Connection.STATE_HOLDING -> true
else -> false
}
}
if (ownBusy) {
return true
}
return hasSystemLevelActiveCallIndicators(context)
}

/**
* Telecom in-call check (API 26+) requires [READ_PHONE_STATE]; without it, [TelecomManager.isInCall]
* can throw [SecurityException]. Always falls back to [AudioManager.MODE_IN_COMMUNICATION] on all APIs.
*/
private fun hasSystemLevelActiveCallIndicators(context: Context): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val granted = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) ==
PackageManager.PERMISSION_GRANTED
if (granted) {
val telecom = context.getSystemService(Context.TELECOM_SERVICE) as? TelecomManager
try {
if (telecom?.isInCall == true) {
return true
}
} catch (e: SecurityException) {
Log.w(TAG, "TelecomManager.isInCall not allowed", e)
}
}
}
val audio = context.getSystemService(Context.AUDIO_SERVICE) as? AudioManager
if (audio?.mode == AudioManager.MODE_IN_COMMUNICATION) {
return true
}
return false
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

/**
* Rejects an incoming call because the user is already on another call.
* Sends a reject signal via DDP and cleans up without showing any UI.
*/
@JvmStatic
fun rejectBusyCall(context: Context, payload: VoipPayload) {
Log.d(TAG, "Rejected busy call ${payload.callId} — user already on a call")
cancelTimeout(payload.callId)
startListeningForCallEnd(context, payload)
if (isDdpLoggedIn) {
sendRejectSignal(context, payload)
} else {
queueRejectSignal(context, payload)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

// -- Native DDP Listener (Call End Detection) --

@JvmStatic
Expand Down Expand Up @@ -613,7 +681,13 @@ class VoipNotification(private val context: Context) {

fun onMessageReceived(voipPayload: VoipPayload) {
when {
voipPayload.isVoipIncomingCall() -> showIncomingCall(voipPayload)
voipPayload.isVoipIncomingCall() -> {
if (hasActiveCall(context)) {
rejectBusyCall(context, voipPayload)
} else {
showIncomingCall(voipPayload)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
else -> Log.w(TAG, "Ignoring unsupported VoIP payload type: ${voipPayload.type}")
}
}
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@
"Pause": "توقف مؤقت",
"Permalink_copied_to_clipboard": "تم نسخ الرابط الثابت إلى الحافظة!",
"Phone": "الهاتف",
"Phone_state_permission_message": "يتيح ذلك لـ Rocket.Chat معرفة ما إذا كنت في مكالمة هاتفية أو VoIP حاليًا كي تُعالج المكالمات الواردة بشكل صحيح.",
"Phone_state_permission_title": "السماح بالوصول إلى حالة الهاتف",
"Pin": "ثبت",
"Pinned": "مثبت",
"Play": "لعب",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/bn-IN.json
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,8 @@
"Permalink_copied_to_clipboard": "পারমালিঙ্ক ক্লিপবোর্ডে কপি করা হয়েছে!",
"Person_or_channel": "ব্যক্তি বা চ্যানেল",
"Phone": "ফোন",
"Phone_state_permission_message": "এটি Rocket.Chat-কে আপনি ইতিমধ্যে কোনও ফোন বা VoIP কলে আছেন কিনা তা শনাক্ত করতে দেয়, যাতে ইনকামিং কলগুলি সঠিকভাবে পরিচালনা করা যায়।",
"Phone_state_permission_title": "ফোনের অবস্থা অ্যাক্সেসের অনুমতি দিন",
"Pin": "পিন",
"Pinned": "পিনকরা",
"Pinned_a_message": "একটি বার্তা পিন করা হয়েছে:",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,8 @@
"Permalink_copied_to_clipboard": "Trvalý odkaz zkopírován do schránky!",
"Person_or_channel": "Osoba nebo kanál",
"Phone": "Telefon",
"Phone_state_permission_message": "Rocket.Chat tak může zjistit, zda již probíhá telefonní nebo hlasový (VoIP) hovor, a správně zpracovat příchozí hovory.",
"Phone_state_permission_title": "Povolit přístup ke stavu telefonu",
"Pin": "Kolík",
"Pinned": "Připnuto",
"Pinned_a_message": "Připnuta zpráva:",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,8 @@
"Pause": "Pause",
"Permalink_copied_to_clipboard": "Permalink in die Zwischenablage kopiert!",
"Phone": "Telefon",
"Phone_state_permission_message": "Damit kann Rocket.Chat erkennen, ob Sie bereits in einem Telefon- oder VoIP-Gespräch sind, damit eingehende Anrufe korrekt behandelt werden können.",
"Phone_state_permission_title": "Zugriff auf den Telefonstatus erlauben",
"Pin": "Anheften",
"Pinned": "Angeheftet",
"Place_chat_on_hold": "Chat in die Warteschleife stellen",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,8 @@
"Permalink_copied_to_clipboard": "Permalink copied to clipboard!",
"Person_or_channel": "Person or channel",
"Phone": "Phone",
"Phone_state_permission_message": "This lets Rocket.Chat detect when you are already on a phone or VoIP call so incoming calls can be handled correctly.",
"Phone_state_permission_title": "Allow phone state access",
"Pin": "Pin",
"Pinned": "Pinned",
"Pinned_a_message": "Pinned a message:",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@
"Passwords_do_not_match": "Las contraseñas no coinciden.",
"Pause": "Pausa",
"Permalink_copied_to_clipboard": "¡Enlace permanente copiado al portapapeles!",
"Phone_state_permission_message": "Permite que Rocket.Chat detecte si ya está en una llamada telefónica o VoIP para gestionar correctamente las llamadas entrantes.",
"Phone_state_permission_title": "Permitir acceso al estado del teléfono",
"Pin": "Fijar",
"Pinned": "Fijado",
"Play": "Jugar",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,8 @@
"Pause": "Tauko",
"Permalink_copied_to_clipboard": "Pysyvä linkki kopioitu leikepöydälle!",
"Phone": "Puhelin",
"Phone_state_permission_message": "Tämän avulla Rocket.Chat voi havaita, oletko jo puhelimessa tai VoIP-puhelussa, jotta saapuvat puhelut voidaan käsitellä oikein.",
"Phone_state_permission_title": "Salli puhelimen tilan käyttö",
"Pin": "Kiinnitä",
"Pinned": "Kiinnitetty",
"Place_chat_on_hold": "Aseta keskustelu pitoon",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,8 @@
"Pause": "Pause",
"Permalink_copied_to_clipboard": "Lien permanent copié dans le presse-papiers !",
"Phone": "Téléphone",
"Phone_state_permission_message": "Cela permet à Rocket.Chat de détecter si vous êtes déjà en appel téléphonique ou VoIP afin de traiter correctement les appels entrants.",
"Phone_state_permission_title": "Autoriser l’accès à l’état du téléphone",
"Pin": "Épingler",
"Pinned": "Épinglé",
"Place_chat_on_hold": "Mettre le chat en attente",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/hi-IN.json
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,8 @@
"Permalink_copied_to_clipboard": "पर्मालिंक क्लिपबोर्ड पर कॉपी किया गया!",
"Person_or_channel": "व्यक्ति या चैनल",
"Phone": "फ़ोन",
"Phone_state_permission_message": "इससे Rocket.Chat यह पता लगा सकता है कि क्या आप पहले से किसी फ़ोन या VoIP कॉल पर हैं, ताकि आने वाली कॉल को सही ढंग से संभाला जा सके।",
"Phone_state_permission_title": "फ़ोन स्थिति तक पहुँच की अनुमति दें",
"Pin": "पिन",
"Pinned": "पिन किया गया",
"Pinned_a_message": "एक संदेश को पिन किया गया है:",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/hu.json
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,8 @@
"Permalink_copied_to_clipboard": "Permalink a vágólapra másolva!",
"Person_or_channel": "Személy vagy csatorna",
"Phone": "Telefon",
"Phone_state_permission_message": "Így a Rocket.Chat észlelheti, ha már telefonos vagy VoIP-hívásban van, hogy a bejövő hívások helyesen kezelhetők legyenek.",
"Phone_state_permission_title": "Telefonállapot elérésének engedélyezése",
"Pin": "Pin",
"Pinned": "Kitűzve",
"Pinned_a_message": "Kitűzött üzenet:",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@
"Pause": "Pausa",
"Permalink_copied_to_clipboard": "Permalink copiato negli appunti!",
"Phone": "Telefono",
"Phone_state_permission_message": "Consente a Rocket.Chat di rilevare se sei già in una chiamata telefonica o VoIP, così da gestire correttamente le chiamate in arrivo.",
"Phone_state_permission_title": "Consenti l’accesso allo stato del telefono",
"Pin": "Appunta",
"Pinned": "Appuntati",
"Play": "Giocare",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@
"Passwords_do_not_match": "パスワードが一致しません。",
"Pause": "一時停止",
"Permalink_copied_to_clipboard": "リンクをクリップボードにコピーしました!",
"Phone_state_permission_message": "電話またはVoIP通話中かどうかをRocket.Chatが検知し、着信を適切に処理できるようにします。",
"Phone_state_permission_title": "電話状態へのアクセスを許可",
"Pin": "ピン留め",
"Pinned": "ピン留めされました",
"Play": "遊ぶ",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,8 @@
"Pause": "Pauze",
"Permalink_copied_to_clipboard": "Permalink gekopiëerd naar klembord!",
"Phone": "Telefoon",
"Phone_state_permission_message": "Hiermee kan Rocket.Chat detecteren of u al in een telefoon- of VoIP-gesprek bent, zodat inkomende oproepen correct worden afgehandeld.",
"Phone_state_permission_title": "Toegang tot telefoonstatus toestaan",
"Pin": "Vastzetten",
"Pinned": "Vastgezet",
"Place_chat_on_hold": "Chat in de wacht zetten",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/nn.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@
"Passwords_do_not_match": "Passorda stemmer ikkje overeins",
"Pause": "Pause",
"Phone": "Telefon",
"Phone_state_permission_message": "Dette lèt Rocket.Chat oppdage om du allereie er i ein telefon- eller VoIP-samtale, slik at innkomande samtalar kan handsamast korrekt.",
"Phone_state_permission_title": "Tillat tilgang til telefonstatus",
"Pin": "Pin",
"Pinned_a_message": "Pinned en melding:",
"Please_add_a_comment": "Vennligst legg til en kommentar",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/no.json
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,8 @@
"Permalink_copied_to_clipboard": "Permalenke kopiert til utklippstavlen!",
"Person_or_channel": "Person eller kanal",
"Phone": "Telefon",
"Phone_state_permission_message": "Dette lar Rocket.Chat oppdage om du allerede er i en telefon- eller VoIP-samtale, slik at innkommende anrop kan håndteres riktig.",
"Phone_state_permission_title": "Tillat tilgang til telefonstatus",
"Pin": "Pin",
"Pinned": "Festet",
"Pinned_a_message": "Festet en melding:",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,8 @@
"Permalink_copied_to_clipboard": "Link-permanente copiado para a área de transferência!",
"Person_or_channel": "Pessoa ou canal",
"Phone": "Telefone",
"Phone_state_permission_message": "Isso permite que o Rocket.Chat detecte quando você já está em uma chamada telefônica ou VoIP para que as chamadas recebidas sejam tratadas corretamente.",
"Phone_state_permission_title": "Permitir acesso ao estado do telefone",
"Pin": "Fixar",
"Pinned": "Mensagens Fixadas",
"Pinned_a_message": "Fixou uma mensagem:",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/pt-PT.json
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@
"Pause": "Pausa",
"Permalink_copied_to_clipboard": "Link permanente copiado para a área de transferência!",
"Phone": "Telefone",
"Phone_state_permission_message": "Isto permite ao Rocket.Chat detetar se já está numa chamada telefónica ou VoIP, para que as chamadas recebidas sejam tratadas corretamente.",
"Phone_state_permission_title": "Permitir acesso ao estado do telefone",
"Pin": "Afixar",
"Pinned": "Afixada",
"Pinned_a_message": "Fixou uma mensagem:",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,8 @@
"Pause": "Пауза",
"Permalink_copied_to_clipboard": "Постоянная ссылка скопирована в буфер обмена!",
"Phone": "Телефон",
"Phone_state_permission_message": "Это позволяет Rocket.Chat определять, идёт ли у вас уже телефонный или VoIP-звонок, чтобы правильно обрабатывать входящие вызовы.",
"Phone_state_permission_title": "Разрешить доступ к состоянию телефона",
"Pin": "Прикрепить сообщение",
"Pinned": "Прикреплено",
"Place_chat_on_hold": "Поставить чат на удержание",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/sl-SI.json
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,8 @@
"Pause": "Premor",
"Permalink_copied_to_clipboard": "Permalink, kopirano v odložišče!",
"Phone": "Telefon",
"Phone_state_permission_message": "To omogoča Rocket.Chatu, da zazna, ali ste že v telefonskem ali VoIP klicu, da se dohodni klici pravilno obdelajo.",
"Phone_state_permission_title": "Dovoli dostop do stanja telefona",
"Pin": "Zatič",
"Pinned": "Pripet",
"Place_chat_on_hold": "Postavite klepet na \"pridržan\"",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/sv.json
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,8 @@
"Pause": "Paus",
"Permalink_copied_to_clipboard": "Permalänken har kopierats till urklipp.",
"Phone": "Telefonnummer",
"Phone_state_permission_message": "Detta låter Rocket.Chat upptäcka om du redan är i ett telefon- eller VoIP-samtal så att inkommande samtal kan hanteras korrekt.",
"Phone_state_permission_title": "Tillåt åtkomst till telefonstatus",
"Pin": "Fäst",
"Pinned": "Fästa",
"Place_chat_on_hold": "Parkera chatten",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/ta-IN.json
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,8 @@
"Permalink_copied_to_clipboard": "நிரல்களுக்கு பதில் நகல் எடுக்கப்பட்டுவிட்டது!",
"Person_or_channel": "நபர் அல்லது சேனல்",
"Phone": "கைபேசி",
"Phone_state_permission_message": "நீங்கள் ஏற்கனவே தொலைபேசி அல்லது VoIP அழைப்பில் இருக்கிறீர்களா என்பதை Rocket.Chat கண்டறிய இது உதவுகிறது; வரும் அழைப்புகள் சரியாக கையாளப்படும்.",
"Phone_state_permission_title": "தொலைபேசி நிலை அணுகலை அனுமதி",
"Pin": "சிறுமைக்கான பிணி",
"Pinned": "பிண்டு",
"Pinned_a_message": "ஒரு செய்தியை கொண்டுவந்தன்:",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/te-IN.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,8 @@
"Permalink_copied_to_clipboard": "పర్మాలింక్ కోపీ అయ్యింది!",
"Person_or_channel": "వ్యక్తి లేదా చానల్",
"Phone": "ఫోన్",
"Phone_state_permission_message": "మీరు ఇప్పటికే ఫోన్ లేదా VoIP కాల్‌లో ఉన్నారో లేదో Rocket.Chat గుర్తించడానికి ఇది సహాయపడుతుంది, తద్వారా ఇన్‌కమింగ్ కాల్‌లు సరిగ్గా నిర్వహించబడతాయి.",
"Phone_state_permission_title": "ఫోన్ స్థితి యాక్సెస్‌ను అనుమతించండి",
"Pin": "పిన్",
"Pinned": "పిన్ చేసినది",
"Pinned_a_message": "ఒక సందేశాన్ని పించింది:",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,8 @@
"Pause": "Duraklat",
"Permalink_copied_to_clipboard": "Kalıcı bağlantı panoya kopyalandı!",
"Phone": "Telefon",
"Phone_state_permission_message": "Bununla Rocket.Chat, zaten bir telefon veya VoIP görüşmesinde olup olmadığınızı algılayabilir; böylece gelen aramalar doğru şekilde yönetilir.",
"Phone_state_permission_title": "Telefon durumuna erişime izin ver",
"Pin": "Sabitle",
"Pinned": "Sabitlendi",
"Play": "Oyna",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@
"Pause": "暂停",
"Permalink_copied_to_clipboard": "永久链接已复制到剪贴板!",
"Phone": "电话",
"Phone_state_permission_message": "这样 Rocket.Chat 可以检测您是否已在通话或 VoIP 通话中,从而正确处理来电。",
"Phone_state_permission_title": "允许访问电话状态",
"Pin": "钉选",
"Pinned": "被钉选",
"Play": "玩",
Expand Down
2 changes: 2 additions & 0 deletions app/i18n/locales/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,8 @@
"Pause": "暫停",
"Permalink_copied_to_clipboard": "永久連結已複製到剪貼簿!",
"Phone": "電話",
"Phone_state_permission_message": "讓 Rocket.Chat 偵測您是否已在一般電話或 VoIP 通話中,以正確處理來電。",
"Phone_state_permission_title": "允許存取電話狀態",
"Pin": "釘選",
"Pinned": "被釘選",
"Play": "遊戲",
Expand Down
Loading
Loading