mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 19:49:33 +01:00
add silent call feature
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
6669c9fecc
commit
a23d4ef692
@ -231,6 +231,7 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
private boolean microphoneOn = false;
|
private boolean microphoneOn = false;
|
||||||
|
|
||||||
private boolean isVoiceOnlyCall;
|
private boolean isVoiceOnlyCall;
|
||||||
|
private boolean isCallWithoutNotification;
|
||||||
private boolean isIncomingCallFromNotification;
|
private boolean isIncomingCallFromNotification;
|
||||||
private Handler callControlHandler = new Handler();
|
private Handler callControlHandler = new Handler();
|
||||||
private Handler callInfosHandler = new Handler();
|
private Handler callInfosHandler = new Handler();
|
||||||
@ -287,6 +288,7 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
conversationPassword = extras.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), "");
|
conversationPassword = extras.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), "");
|
||||||
conversationName = extras.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), "");
|
conversationName = extras.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), "");
|
||||||
isVoiceOnlyCall = extras.getBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
|
isVoiceOnlyCall = extras.getBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
|
||||||
|
isCallWithoutNotification = extras.getBoolean(BundleKeys.INSTANCE.getKEY_CALL_WITHOUT_NOTIFICATION(), false);
|
||||||
|
|
||||||
if (extras.containsKey(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL())) {
|
if (extras.containsKey(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL())) {
|
||||||
isIncomingCallFromNotification = extras.getBoolean(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL());
|
isIncomingCallFromNotification = extras.getBoolean(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL());
|
||||||
@ -1356,7 +1358,11 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
|
|
||||||
int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
|
int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
|
||||||
|
|
||||||
ncApi.joinCall(credentials, ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken), inCallFlag)
|
ncApi.joinCall(
|
||||||
|
credentials,
|
||||||
|
ApiUtils.getUrlForCall(apiVersion, baseUrl, roomToken),
|
||||||
|
inCallFlag,
|
||||||
|
isCallWithoutNotification)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.retry(3)
|
.retry(3)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -1825,11 +1831,11 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
|
int apiVersion = ApiUtils.getCallApiVersion(conversationUser, new int[]{ApiUtils.APIv4, 1});
|
||||||
|
|
||||||
ncApi.getPeersForCall(
|
ncApi.getPeersForCall(
|
||||||
credentials,
|
credentials,
|
||||||
ApiUtils.getUrlForCall(
|
ApiUtils.getUrlForCall(
|
||||||
apiVersion,
|
apiVersion,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
roomToken))
|
roomToken))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe(new Observer<ParticipantsOverall>() {
|
.subscribe(new Observer<ParticipantsOverall>() {
|
||||||
@Override
|
@Override
|
||||||
@ -2468,7 +2474,7 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
mediaPlayer.setDataSource(this, ringtoneUri);
|
mediaPlayer.setDataSource(this, ringtoneUri);
|
||||||
mediaPlayer.setLooping(true);
|
mediaPlayer.setLooping(true);
|
||||||
AudioAttributes audioAttributes = new AudioAttributes.Builder().setContentType(
|
AudioAttributes audioAttributes = new AudioAttributes.Builder().setContentType(
|
||||||
AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||||
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
|
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
|
||||||
.build();
|
.build();
|
||||||
mediaPlayer.setAudioAttributes(audioAttributes);
|
mediaPlayer.setAudioAttributes(audioAttributes);
|
||||||
|
@ -211,7 +211,8 @@ public interface NcApi {
|
|||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST
|
@POST
|
||||||
Observable<GenericOverall> joinCall(@Nullable @Header("Authorization") String authorization, @Url String url,
|
Observable<GenericOverall> joinCall(@Nullable @Header("Authorization") String authorization, @Url String url,
|
||||||
@Field("flags") Integer inCall);
|
@Field("flags") Integer inCall,
|
||||||
|
@Field("silent") Boolean callWithoutNotification);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
|
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
|
||||||
@ -239,8 +240,8 @@ public interface NcApi {
|
|||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
Observable<SignalingOverall> pullSignalingMessages(@Nullable @Header("Authorization") String authorization, @Url
|
Observable<SignalingOverall> pullSignalingMessages(@Nullable @Header("Authorization") String authorization, @Url
|
||||||
String
|
String
|
||||||
url);
|
url);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
QueryMap items are as follows:
|
QueryMap items are as follows:
|
||||||
@ -259,7 +260,7 @@ public interface NcApi {
|
|||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@PUT
|
@PUT
|
||||||
Observable<GenericOverall> setUserData(@Header("Authorization") String authorization, @Url String url,
|
Observable<GenericOverall> setUserData(@Header("Authorization") String authorization, @Url String url,
|
||||||
@Field("key") String key, @Field("value") String value);
|
@Field("key") String key, @Field("value") String value);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -281,14 +282,14 @@ public interface NcApi {
|
|||||||
|
|
||||||
@POST
|
@POST
|
||||||
Observable<PushRegistrationOverall> registerDeviceForNotificationsWithNextcloud(@Header("Authorization")
|
Observable<PushRegistrationOverall> registerDeviceForNotificationsWithNextcloud(@Header("Authorization")
|
||||||
String authorization,
|
String authorization,
|
||||||
@Url String url,
|
@Url String url,
|
||||||
@QueryMap Map<String,
|
@QueryMap Map<String,
|
||||||
String> options);
|
String> options);
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
Observable<GenericOverall> unregisterDeviceForNotificationsWithNextcloud(@Header("Authorization")
|
Observable<GenericOverall> unregisterDeviceForNotificationsWithNextcloud(@Header("Authorization")
|
||||||
String authorization,
|
String authorization,
|
||||||
@Url String url);
|
@Url String url);
|
||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@ -438,10 +439,10 @@ public interface NcApi {
|
|||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST
|
@POST
|
||||||
Observable<GenericOverall> sendLocation(@Header("Authorization") String authorization,
|
Observable<GenericOverall> sendLocation(@Header("Authorization") String authorization,
|
||||||
@Url String url,
|
@Url String url,
|
||||||
@Field("objectType") String objectType,
|
@Field("objectType") String objectType,
|
||||||
@Field("objectId") String objectId,
|
@Field("objectId") String objectId,
|
||||||
@Field("metaData") String metaData);
|
@Field("metaData") String metaData);
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
Observable<GenericOverall> clearChatHistory(@Header("Authorization") String authorization, @Url String url);
|
Observable<GenericOverall> clearChatHistory(@Header("Authorization") String authorization, @Url String url);
|
||||||
@ -484,23 +485,23 @@ public interface NcApi {
|
|||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@PUT
|
@PUT
|
||||||
Observable<GenericOverall> setPredefinedStatusMessage(@Header("Authorization") String authorization,
|
Observable<GenericOverall> setPredefinedStatusMessage(@Header("Authorization") String authorization,
|
||||||
@Url String url,
|
@Url String url,
|
||||||
@Field("messageId") String selectedPredefinedMessageId,
|
@Field("messageId") String selectedPredefinedMessageId,
|
||||||
@Field("clearAt") Long clearAt);
|
@Field("clearAt") Long clearAt);
|
||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@PUT
|
@PUT
|
||||||
Observable<GenericOverall> setCustomStatusMessage(@Header("Authorization") String authorization,
|
Observable<GenericOverall> setCustomStatusMessage(@Header("Authorization") String authorization,
|
||||||
@Url String url,
|
@Url String url,
|
||||||
@Field("statusIcon") String statusIcon,
|
@Field("statusIcon") String statusIcon,
|
||||||
@Field("message") String message,
|
@Field("message") String message,
|
||||||
@Field("clearAt") Long clearAt);
|
@Field("clearAt") Long clearAt);
|
||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@PUT
|
@PUT
|
||||||
Observable<GenericOverall> setStatusType(@Header("Authorization") String authorization,
|
Observable<GenericOverall> setStatusType(@Header("Authorization") String authorization,
|
||||||
@Url String url,
|
@Url String url,
|
||||||
@Field("statusType") String statusType);
|
@Field("statusType") String statusType);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
Observable<StatusesOverall> getUserStatuses(@Header("Authorization") String authorization, @Url String url);
|
Observable<StatusesOverall> getUserStatuses(@Header("Authorization") String authorization, @Url String url);
|
||||||
@ -508,7 +509,7 @@ public interface NcApi {
|
|||||||
|
|
||||||
@POST
|
@POST
|
||||||
Observable<GenericOverall> sendReaction(@Header("Authorization") String authorization, @Url String url,
|
Observable<GenericOverall> sendReaction(@Header("Authorization") String authorization, @Url String url,
|
||||||
@Query("reaction") String reaction);
|
@Query("reaction") String reaction);
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
Observable<GenericOverall> deleteReaction(@Header("Authorization") String authorization, @Url String url,
|
Observable<GenericOverall> deleteReaction(@Header("Authorization") String authorization, @Url String url,
|
||||||
|
@ -103,7 +103,6 @@ import com.nextcloud.talk.BuildConfig
|
|||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.activities.CallActivity
|
import com.nextcloud.talk.activities.CallActivity
|
||||||
import com.nextcloud.talk.activities.MainActivity
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
|
|
||||||
import com.nextcloud.talk.activities.TakePhotoActivity
|
import com.nextcloud.talk.activities.TakePhotoActivity
|
||||||
import com.nextcloud.talk.adapters.messages.IncomingLocationMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.IncomingLocationMessageViewHolder
|
||||||
import com.nextcloud.talk.adapters.messages.IncomingPreviewMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.IncomingPreviewMessageViewHolder
|
||||||
@ -143,6 +142,7 @@ import com.nextcloud.talk.models.json.conversations.RoomsOverall
|
|||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
import com.nextcloud.talk.models.json.mention.Mention
|
import com.nextcloud.talk.models.json.mention.Mention
|
||||||
import com.nextcloud.talk.presenters.MentionAutocompletePresenter
|
import com.nextcloud.talk.presenters.MentionAutocompletePresenter
|
||||||
|
import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
|
||||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
|
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
|
||||||
import com.nextcloud.talk.ui.dialog.AttachmentDialog
|
import com.nextcloud.talk.ui.dialog.AttachmentDialog
|
||||||
import com.nextcloud.talk.ui.dialog.MessageActionsDialog
|
import com.nextcloud.talk.ui.dialog.MessageActionsDialog
|
||||||
@ -886,6 +886,35 @@ class ChatController(args: Bundle) :
|
|||||||
popupMenu.show()
|
popupMenu.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showCallButtonMenu(isVoiceOnlyCall: Boolean) {
|
||||||
|
val anchor: View? = if (isVoiceOnlyCall) {
|
||||||
|
activity?.findViewById(R.id.conversation_voice_call)
|
||||||
|
} else {
|
||||||
|
activity?.findViewById(R.id.conversation_video_call)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anchor != null) {
|
||||||
|
val popupMenu = PopupMenu(
|
||||||
|
ContextThemeWrapper(view?.context, R.style.CallButtonMenu),
|
||||||
|
anchor,
|
||||||
|
Gravity.END
|
||||||
|
)
|
||||||
|
popupMenu.inflate(R.menu.chat_call_menu)
|
||||||
|
|
||||||
|
popupMenu.setOnMenuItemClickListener { item: MenuItem ->
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.call_without_notification -> startACall(isVoiceOnlyCall, true)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
popupMenu.setForceShowIcon(true)
|
||||||
|
}
|
||||||
|
popupMenu.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun startPlayback(message: ChatMessage) {
|
private fun startPlayback(message: ChatMessage) {
|
||||||
|
|
||||||
if (!this.isAttached) {
|
if (!this.isAttached) {
|
||||||
@ -1827,7 +1856,7 @@ class ChatController(args: Bundle) :
|
|||||||
}
|
}
|
||||||
if (startCallFromNotification != null && startCallFromNotification ?: false) {
|
if (startCallFromNotification != null && startCallFromNotification ?: false) {
|
||||||
startCallFromNotification = false
|
startCallFromNotification = false
|
||||||
startACall(voiceOnly)
|
startACall(voiceOnly, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2403,6 +2432,22 @@ class ChatController(args: Bundle) :
|
|||||||
if (CapabilitiesUtil.isAbleToCall(conversationUser)) {
|
if (CapabilitiesUtil.isAbleToCall(conversationUser)) {
|
||||||
conversationVoiceCallMenuItem = menu.findItem(R.id.conversation_voice_call)
|
conversationVoiceCallMenuItem = menu.findItem(R.id.conversation_voice_call)
|
||||||
conversationVideoMenuItem = menu.findItem(R.id.conversation_video_call)
|
conversationVideoMenuItem = menu.findItem(R.id.conversation_video_call)
|
||||||
|
|
||||||
|
if (CapabilitiesUtil.hasSpreedFeatureCapability(conversationUser, "silent-call")) {
|
||||||
|
Handler().post {
|
||||||
|
activity?.findViewById<View?>(R.id.conversation_voice_call)?.setOnLongClickListener {
|
||||||
|
showCallButtonMenu(true)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Handler().post {
|
||||||
|
activity?.findViewById<View?>(R.id.conversation_video_call)?.setOnLongClickListener {
|
||||||
|
showCallButtonMenu(false)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
menu.removeItem(R.id.conversation_video_call)
|
menu.removeItem(R.id.conversation_video_call)
|
||||||
menu.removeItem(R.id.conversation_voice_call)
|
menu.removeItem(R.id.conversation_voice_call)
|
||||||
@ -2425,11 +2470,11 @@ class ChatController(args: Bundle) :
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.conversation_video_call -> {
|
R.id.conversation_video_call -> {
|
||||||
startACall(false)
|
startACall(false, false)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.conversation_voice_call -> {
|
R.id.conversation_voice_call -> {
|
||||||
startACall(true)
|
startACall(true, false)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.conversation_info -> {
|
R.id.conversation_info -> {
|
||||||
@ -2493,19 +2538,19 @@ class ChatController(args: Bundle) :
|
|||||||
currentMessage.value.systemMessageType == ChatMessage.SystemMessageType.REACTION_REVOKED
|
currentMessage.value.systemMessageType == ChatMessage.SystemMessageType.REACTION_REVOKED
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startACall(isVoiceOnlyCall: Boolean) {
|
private fun startACall(isVoiceOnlyCall: Boolean, callWithoutNotification: Boolean) {
|
||||||
if (currentConversation?.canStartCall == false && currentConversation?.hasCall == false) {
|
if (currentConversation?.canStartCall == false && currentConversation?.hasCall == false) {
|
||||||
Toast.makeText(context, R.string.startCallForbidden, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, R.string.startCallForbidden, Toast.LENGTH_LONG).show()
|
||||||
} else {
|
} else {
|
||||||
ApplicationWideCurrentRoomHolder.getInstance().isDialing = true
|
ApplicationWideCurrentRoomHolder.getInstance().isDialing = true
|
||||||
val callIntent = getIntentForCall(isVoiceOnlyCall)
|
val callIntent = getIntentForCall(isVoiceOnlyCall, callWithoutNotification)
|
||||||
if (callIntent != null) {
|
if (callIntent != null) {
|
||||||
startActivity(callIntent)
|
startActivity(callIntent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getIntentForCall(isVoiceOnlyCall: Boolean): Intent? {
|
private fun getIntentForCall(isVoiceOnlyCall: Boolean, callWithoutNotification: Boolean): Intent? {
|
||||||
currentConversation?.let {
|
currentConversation?.let {
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString(KEY_ROOM_TOKEN, roomToken)
|
bundle.putString(KEY_ROOM_TOKEN, roomToken)
|
||||||
@ -2518,6 +2563,9 @@ class ChatController(args: Bundle) :
|
|||||||
if (isVoiceOnlyCall) {
|
if (isVoiceOnlyCall) {
|
||||||
bundle.putBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, true)
|
bundle.putBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, true)
|
||||||
}
|
}
|
||||||
|
if (callWithoutNotification) {
|
||||||
|
bundle.putBoolean(BundleKeys.KEY_CALL_WITHOUT_NOTIFICATION, true)
|
||||||
|
}
|
||||||
|
|
||||||
return if (activity != null) {
|
return if (activity != null) {
|
||||||
val callIntent = Intent(activity, CallActivity::class.java)
|
val callIntent = Intent(activity, CallActivity::class.java)
|
||||||
|
@ -55,6 +55,7 @@ object BundleKeys {
|
|||||||
val KEY_INVITED_EMAIL = "KEY_INVITED_EMAIL"
|
val KEY_INVITED_EMAIL = "KEY_INVITED_EMAIL"
|
||||||
val KEY_CONVERSATION_NAME = "KEY_CONVERSATION_NAME"
|
val KEY_CONVERSATION_NAME = "KEY_CONVERSATION_NAME"
|
||||||
val KEY_CALL_VOICE_ONLY = "KEY_CALL_VOICE_ONLY"
|
val KEY_CALL_VOICE_ONLY = "KEY_CALL_VOICE_ONLY"
|
||||||
|
val KEY_CALL_WITHOUT_NOTIFICATION = "KEY_CALL_WITHOUT_NOTIFICATION"
|
||||||
val KEY_ACTIVE_CONVERSATION = "KEY_ACTIVE_CONVERSATION"
|
val KEY_ACTIVE_CONVERSATION = "KEY_ACTIVE_CONVERSATION"
|
||||||
val KEY_SERVER_CAPABILITIES = "KEY_SERVER_CAPABILITIES"
|
val KEY_SERVER_CAPABILITIES = "KEY_SERVER_CAPABILITIES"
|
||||||
val KEY_FROM_NOTIFICATION_START_CALL = "KEY_FROM_NOTIFICATION_START_CALL"
|
val KEY_FROM_NOTIFICATION_START_CALL = "KEY_FROM_NOTIFICATION_START_CALL"
|
||||||
|
26
app/src/main/res/menu/chat_call_menu.xml
Normal file
26
app/src/main/res/menu/chat_call_menu.xml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Nextcloud Talk application
|
||||||
|
~
|
||||||
|
~ @author Marcel Hibbe
|
||||||
|
~ Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/call_without_notification"
|
||||||
|
android:icon="@drawable/ic_baseline_notifications_off_24"
|
||||||
|
android:title="@string/call_without_notification" />
|
||||||
|
</menu>
|
@ -522,5 +522,6 @@
|
|||||||
|
|
||||||
<string name="reactions_tab_all">All</string>
|
<string name="reactions_tab_all">All</string>
|
||||||
<string name="send_without_notification">Send without notification</string>
|
<string name="send_without_notification">Send without notification</string>
|
||||||
|
<string name="call_without_notification">Call without notification</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -63,6 +63,8 @@
|
|||||||
<item name="iconTint">@color/fontAppbar</item>
|
<item name="iconTint">@color/fontAppbar</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="CallButtonMenu" parent="@style/ChatSendButtonMenu"></style>
|
||||||
|
|
||||||
<style name="BottomNavigationView" parent="@style/Widget.MaterialComponents.BottomNavigationView">
|
<style name="BottomNavigationView" parent="@style/Widget.MaterialComponents.BottomNavigationView">
|
||||||
<item name="elevation">1dp</item>
|
<item name="elevation">1dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user