Merge pull request #4527 from nextcloud/style/noid/lowerDetektScore

Lower detekt score
This commit is contained in:
Marcel Hibbe 2024-12-10 09:13:25 +01:00 committed by GitHub
commit 54d1512fff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 704 additions and 674 deletions

View file

@ -239,41 +239,13 @@ class ServerSelectionActivity : BaseActivity() {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ status: Status -> .subscribe({ status: Status ->
val productName = resources!!.getString(R.string.nc_server_product_name)
val versionString: String = status.version!!.substring(0, status.version!!.indexOf(".")) val versionString: String = status.version!!.substring(0, status.version!!.indexOf("."))
val version: Int = versionString.toInt() val version: Int = versionString.toInt()
if (isServerStatusQueryable(status) && version >= MIN_SERVER_MAJOR_VERSION) { if (isServerStatusQueryable(status) && version >= MIN_SERVER_MAJOR_VERSION) {
findServerTalkApp(url) findServerTalkApp(url)
} else if (!status.installed) { } else {
setErrorText( showErrorTextForStatus(status)
String.format(
resources!!.getString(R.string.nc_server_not_installed),
productName
)
)
} else if (status.needsUpgrade) {
setErrorText(
String.format(
resources!!.getString(R.string.nc_server_db_upgrade_needed),
productName
)
)
} else if (status.maintenance) {
setErrorText(
String.format(
resources!!.getString(R.string.nc_server_maintenance),
productName
)
)
} else if (!status.version!!.startsWith("13.")) {
setErrorText(
String.format(
resources!!.getString(R.string.nc_server_version),
resources!!.getString(R.string.nc_app_product_name),
productName
)
)
} }
}, { throwable: Throwable -> }, { throwable: Throwable ->
if (checkForcedHttps) { if (checkForcedHttps) {
@ -303,6 +275,39 @@ class ServerSelectionActivity : BaseActivity() {
} }
} }
private fun showErrorTextForStatus(status: Status) {
if (!status.installed) {
setErrorText(
String.format(
resources!!.getString(R.string.nc_server_not_installed),
resources!!.getString(R.string.nc_server_product_name)
)
)
} else if (status.needsUpgrade) {
setErrorText(
String.format(
resources!!.getString(R.string.nc_server_db_upgrade_needed),
resources!!.getString(R.string.nc_server_product_name)
)
)
} else if (status.maintenance) {
setErrorText(
String.format(
resources!!.getString(R.string.nc_server_maintenance),
resources!!.getString(R.string.nc_server_product_name)
)
)
} else if (!status.version!!.startsWith("13.")) {
setErrorText(
String.format(
resources!!.getString(R.string.nc_server_version),
resources!!.getString(R.string.nc_app_product_name),
resources!!.getString(R.string.nc_server_product_name)
)
)
}
}
private fun findServerTalkApp(queryUrl: String) { private fun findServerTalkApp(queryUrl: String) {
ncApi.getCapabilities(ApiUtils.getUrlForCapabilities(queryUrl)) ncApi.getCapabilities(ApiUtils.getUrlForCapabilities(queryUrl))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -364,7 +369,7 @@ class ServerSelectionActivity : BaseActivity() {
return status.installed && !status.maintenance && !status.needsUpgrade return status.installed && !status.maintenance && !status.needsUpgrade
} }
private fun setErrorText(text: String) { private fun setErrorText(text: String?) {
binding.errorWrapper.visibility = View.VISIBLE binding.errorWrapper.visibility = View.VISIBLE
binding.errorText.text = text binding.errorText.text = text
hideserverEntryProgressBar() hideserverEntryProgressBar()

View file

@ -220,11 +220,11 @@ class WebViewLoginActivity : BaseActivity() {
} }
override fun onReceivedClientCertRequest(view: WebView, request: ClientCertRequest) { override fun onReceivedClientCertRequest(view: WebView, request: ClientCertRequest) {
val user = userManager.currentUser.blockingGet()
var alias: String? = null var alias: String? = null
if (!reauthorizeAccount) { if (!reauthorizeAccount) {
alias = appPreferences.temporaryClientCertAlias alias = appPreferences.temporaryClientCertAlias
} }
val user = userManager.currentUser.blockingGet()
if (TextUtils.isEmpty(alias) && user != null) { if (TextUtils.isEmpty(alias) && user != null) {
alias = user.clientCertificate alias = user.clientCertificate
} }

View file

@ -371,27 +371,11 @@ class CallActivity : CallBaseActivity() {
binding = CallActivityBinding.inflate(layoutInflater) binding = CallActivityBinding.inflate(layoutInflater)
setContentView(binding!!.root) setContentView(binding!!.root)
hideNavigationIfNoPipAvailable() hideNavigationIfNoPipAvailable()
conversationUser = currentUserProvider.currentUser.blockingGet() processExtras(intent.extras!!)
val extras = intent.extras
roomId = extras!!.getString(KEY_ROOM_ID, "") conversationUser = currentUserProvider.currentUser.blockingGet()
roomToken = extras.getString(KEY_ROOM_TOKEN, "")
conversationPassword = extras.getString(KEY_CONVERSATION_PASSWORD, "")
conversationName = extras.getString(KEY_CONVERSATION_NAME, "")
isVoiceOnlyCall = extras.getBoolean(KEY_CALL_VOICE_ONLY, false)
isCallWithoutNotification = extras.getBoolean(KEY_CALL_WITHOUT_NOTIFICATION, false)
canPublishAudioStream = extras.getBoolean(KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_AUDIO)
canPublishVideoStream = extras.getBoolean(KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_VIDEO)
isModerator = extras.getBoolean(KEY_IS_MODERATOR, false)
isOneToOneConversation = extras.getBoolean(KEY_ROOM_ONE_TO_ONE, false)
if (extras.containsKey(KEY_FROM_NOTIFICATION_START_CALL)) {
isIncomingCallFromNotification = extras.getBoolean(KEY_FROM_NOTIFICATION_START_CALL)
}
if (extras.containsKey(KEY_IS_BREAKOUT_ROOM)) {
isBreakoutRoom = extras.getBoolean(KEY_IS_BREAKOUT_ROOM)
}
credentials = ApiUtils.getCredentials(conversationUser!!.username, conversationUser!!.token) credentials = ApiUtils.getCredentials(conversationUser!!.username, conversationUser!!.token)
baseUrl = extras.getString(KEY_MODIFIED_BASE_URL, "")
if (TextUtils.isEmpty(baseUrl)) { if (TextUtils.isEmpty(baseUrl)) {
baseUrl = conversationUser!!.baseUrl baseUrl = conversationUser!!.baseUrl
} }
@ -399,28 +383,30 @@ class CallActivity : CallBaseActivity() {
setCallState(CallStatus.CONNECTING) setCallState(CallStatus.CONNECTING)
raiseHandViewModel = ViewModelProvider(this, viewModelFactory).get(RaiseHandViewModel::class.java) initRaiseHandViewModel()
raiseHandViewModel!!.setData(roomToken!!, isBreakoutRoom) initCallRecordingViewModel(intent.extras!!.getInt(KEY_RECORDING_STATE))
raiseHandViewModel!!.viewState.observe(this) { viewState: RaiseHandViewModel.ViewState? -> initClickListeners(isModerator, isOneToOneConversation)
var raised = false binding!!.microphoneButton.setOnTouchListener(MicrophoneButtonTouchListener())
if (viewState is RaisedHandState) { pulseAnimation = PulseAnimation.create().with(binding!!.microphoneButton)
binding!!.lowerHandButton.visibility = View.VISIBLE .setDuration(PULSE_ANIMATION_DURATION)
raised = true .setRepeatCount(PulseAnimation.INFINITE)
} else if (viewState is LoweredHandState) { .setRepeatMode(PulseAnimation.REVERSE)
binding!!.lowerHandButton.visibility = View.GONE basicInitialization()
raised = false callParticipants = HashMap()
} participantDisplayItems = HashMap()
if (isConnectionEstablished) { initViews()
for (peerConnectionWrapper in peerConnectionWrapperList) { updateSelfVideoViewPosition()
peerConnectionWrapper.raiseHand(raised) reactionAnimator = ReactionAnimator(context, binding!!.reactionAnimationWrapper, viewThemeUtils)
}
} checkRecordingConsentAndInitiateCall()
} }
private fun initCallRecordingViewModel(recordingState: Int) {
callRecordingViewModel = ViewModelProvider(this, viewModelFactory).get( callRecordingViewModel = ViewModelProvider(this, viewModelFactory).get(
CallRecordingViewModel::class.java CallRecordingViewModel::class.java
) )
callRecordingViewModel!!.setData(roomToken!!) callRecordingViewModel!!.setData(roomToken!!)
callRecordingViewModel!!.setRecordingState(extras.getInt(KEY_RECORDING_STATE)) callRecordingViewModel!!.setRecordingState(recordingState)
callRecordingViewModel!!.viewState.observe(this) { viewState: CallRecordingViewModel.ViewState? -> callRecordingViewModel!!.viewState.observe(this) { viewState: CallRecordingViewModel.ViewState? ->
if (viewState is RecordingStartedState) { if (viewState is RecordingStartedState) {
binding!!.callRecordingIndicator.setImageResource(R.drawable.record_stop) binding!!.callRecordingIndicator.setImageResource(R.drawable.record_stop)
@ -473,20 +459,48 @@ class CallActivity : CallBaseActivity() {
binding!!.callRecordingIndicator.visibility = View.GONE binding!!.callRecordingIndicator.visibility = View.GONE
} }
} }
initClickListeners(isModerator, isOneToOneConversation) }
binding!!.microphoneButton.setOnTouchListener(MicrophoneButtonTouchListener())
pulseAnimation = PulseAnimation.create().with(binding!!.microphoneButton)
.setDuration(PULSE_ANIMATION_DURATION)
.setRepeatCount(PulseAnimation.INFINITE)
.setRepeatMode(PulseAnimation.REVERSE)
basicInitialization()
callParticipants = HashMap()
participantDisplayItems = HashMap()
initViews()
updateSelfVideoViewPosition()
reactionAnimator = ReactionAnimator(context, binding!!.reactionAnimationWrapper, viewThemeUtils)
checkRecordingConsentAndInitiateCall() private fun initRaiseHandViewModel() {
raiseHandViewModel = ViewModelProvider(this, viewModelFactory).get(RaiseHandViewModel::class.java)
raiseHandViewModel!!.setData(roomToken!!, isBreakoutRoom)
raiseHandViewModel!!.viewState.observe(this) { viewState: RaiseHandViewModel.ViewState? ->
var raised = false
if (viewState is RaisedHandState) {
binding!!.lowerHandButton.visibility = View.VISIBLE
raised = true
} else if (viewState is LoweredHandState) {
binding!!.lowerHandButton.visibility = View.GONE
raised = false
}
if (isConnectionEstablished) {
for (peerConnectionWrapper in peerConnectionWrapperList) {
peerConnectionWrapper.raiseHand(raised)
}
}
}
}
private fun processExtras(extras: Bundle) {
roomId = extras.getString(KEY_ROOM_ID, "")
roomToken = extras.getString(KEY_ROOM_TOKEN, "")
conversationPassword = extras.getString(KEY_CONVERSATION_PASSWORD, "")
conversationName = extras.getString(KEY_CONVERSATION_NAME, "")
isVoiceOnlyCall = extras.getBoolean(KEY_CALL_VOICE_ONLY, false)
isCallWithoutNotification = extras.getBoolean(KEY_CALL_WITHOUT_NOTIFICATION, false)
canPublishAudioStream = extras.getBoolean(KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_AUDIO)
canPublishVideoStream = extras.getBoolean(KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_VIDEO)
isModerator = extras.getBoolean(KEY_IS_MODERATOR, false)
isOneToOneConversation = extras.getBoolean(KEY_ROOM_ONE_TO_ONE, false)
if (extras.containsKey(KEY_FROM_NOTIFICATION_START_CALL)) {
isIncomingCallFromNotification = extras.getBoolean(KEY_FROM_NOTIFICATION_START_CALL)
}
if (extras.containsKey(KEY_IS_BREAKOUT_ROOM)) {
isBreakoutRoom = extras.getBoolean(KEY_IS_BREAKOUT_ROOM)
}
baseUrl = extras.getString(KEY_MODIFIED_BASE_URL, "")
} }
private fun checkRecordingConsentAndInitiateCall() { private fun checkRecordingConsentAndInitiateCall() {
@ -618,17 +632,7 @@ class CallActivity : CallBaseActivity() {
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
private fun initClickListeners(isModerator: Boolean, isOneToOneConversation: Boolean) { private fun initClickListeners(isModerator: Boolean, isOneToOneConversation: Boolean) {
binding!!.pictureInPictureButton.setOnClickListener { enterPipMode() } initCallActionClickListeners(isModerator, isOneToOneConversation)
binding!!.audioOutputButton.setOnClickListener {
audioOutputDialog = AudioOutputDialog(this)
audioOutputDialog!!.show()
}
binding!!.moreCallActions.setOnClickListener {
moreCallActionsDialog = MoreCallActionsDialog(this)
moreCallActionsDialog!!.show()
}
if (canPublishAudioStream) { if (canPublishAudioStream) {
binding!!.microphoneButton.setOnClickListener { onMicrophoneClick() } binding!!.microphoneButton.setOnClickListener { onMicrophoneClick() }
@ -648,11 +652,7 @@ class CallActivity : CallBaseActivity() {
} }
} else { } else {
binding!!.microphoneButton.setOnClickListener { binding!!.microphoneButton.setOnClickListener {
Snackbar.make( Snackbar.make(binding!!.root, R.string.nc_not_allowed_to_activate_audio, Snackbar.LENGTH_SHORT).show()
binding!!.root,
R.string.nc_not_allowed_to_activate_audio,
Snackbar.LENGTH_SHORT
).show()
} }
} }
@ -660,58 +660,14 @@ class CallActivity : CallBaseActivity() {
binding!!.cameraButton.setOnClickListener { onCameraClick() } binding!!.cameraButton.setOnClickListener { onCameraClick() }
} else { } else {
binding!!.cameraButton.setOnClickListener { binding!!.cameraButton.setOnClickListener {
Snackbar.make( Snackbar.make(binding!!.root, R.string.nc_not_allowed_to_activate_video, Snackbar.LENGTH_SHORT).show()
binding!!.root,
R.string.nc_not_allowed_to_activate_video,
Snackbar.LENGTH_SHORT
).show()
} }
} }
if (isOneToOneConversation) {
binding!!.hangupButton.setOnLongClickListener {
showLeaveCallPopupMenu()
true
}
binding!!.hangupButton.setOnClickListener {
hangup(true, true)
}
} else {
if (isModerator) {
binding!!.hangupButton.setOnLongClickListener {
showEndCallForAllPopupMenu()
true
}
}
binding!!.hangupButton.setOnClickListener {
hangup(true, false)
}
}
if (!isOneToOneConversation) {
binding!!.endCallPopupMenu.setOnClickListener {
hangup(true, true)
binding!!.endCallPopupMenu.visibility = View.GONE
}
} else {
binding!!.endCallPopupMenu.setOnClickListener {
hangup(true, false)
binding!!.endCallPopupMenu.visibility = View.GONE
}
}
binding!!.switchSelfVideoButton.setOnClickListener { switchCamera() }
binding!!.gridview.onItemClickListener =
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, _: Int, _: Long ->
animateCallControls(
true,
0
)
}
binding!!.callStates.callStateRelativeLayout.setOnClickListener { binding!!.callStates.callStateRelativeLayout.setOnClickListener {
if (currentCallStatus === CallStatus.CALLING_TIMEOUT) { if (currentCallStatus === CallStatus.CALLING_TIMEOUT) {
setCallState(CallStatus.RECONNECTING) setCallState(CallStatus.RECONNECTING)
hangupNetworkCalls(false, false) hangupNetworkCalls(shutDownView = false, endCallForAll = false)
} }
} }
binding!!.callRecordingIndicator.setOnClickListener { binding!!.callRecordingIndicator.setOnClickListener {
@ -732,7 +688,54 @@ class CallActivity : CallBaseActivity() {
).show() ).show()
} }
} }
}
private fun initCallActionClickListeners(isModerator: Boolean, isOneToOneConversation: Boolean) {
binding!!.audioOutputButton.setOnClickListener {
audioOutputDialog = AudioOutputDialog(this)
audioOutputDialog!!.show()
}
binding!!.moreCallActions.setOnClickListener {
moreCallActionsDialog = MoreCallActionsDialog(this)
moreCallActionsDialog!!.show()
}
if (isOneToOneConversation) {
binding!!.hangupButton.setOnLongClickListener {
showLeaveCallPopupMenu()
true
}
binding!!.hangupButton.setOnClickListener {
hangup(shutDownView = true, endCallForAll = true)
}
binding!!.endCallPopupMenu.setOnClickListener {
hangup(shutDownView = true, endCallForAll = true)
binding!!.endCallPopupMenu.visibility = View.GONE
}
} else {
if (isModerator) {
binding!!.hangupButton.setOnLongClickListener {
showEndCallForAllPopupMenu()
true
}
}
binding!!.hangupButton.setOnClickListener {
hangup(shutDownView = true, endCallForAll = false)
}
binding!!.endCallPopupMenu.setOnClickListener {
hangup(shutDownView = true, endCallForAll = false)
binding!!.endCallPopupMenu.visibility = View.GONE
}
}
binding!!.switchSelfVideoButton.setOnClickListener { switchCamera() }
binding!!.gridview.onItemClickListener =
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, _: Int, _: Long ->
animateCallControls(true, 0)
}
binding!!.lowerHandButton.setOnClickListener { l: View? -> raiseHandViewModel!!.lowerHand() } binding!!.lowerHandButton.setOnClickListener { l: View? -> raiseHandViewModel!!.lowerHand() }
binding!!.pictureInPictureButton.setOnClickListener { enterPipMode() }
} }
private fun showEndCallForAllPopupMenu() { private fun showEndCallForAllPopupMenu() {
@ -2013,64 +2016,63 @@ class CallActivity : CallBaseActivity() {
dispose(null) dispose(null)
if (shutDownView) { if (shutDownView) {
if (videoCapturer != null) { terminateAudioVideo()
try {
videoCapturer!!.stopCapture()
} catch (e: InterruptedException) {
Log.e(TAG, "Failed to stop capturing while hanging up")
}
videoCapturer!!.dispose()
videoCapturer = null
}
binding!!.selfVideoRenderer.release()
if (audioSource != null) {
audioSource!!.dispose()
audioSource = null
}
runOnUiThread {
if (audioManager != null) {
audioManager!!.stop()
audioManager = null
}
}
if (videoSource != null) {
videoSource = null
}
if (peerConnectionFactory != null) {
peerConnectionFactory = null
}
localAudioTrack = null
localVideoTrack = null
if (TextUtils.isEmpty(credentials) && hasExternalSignalingServer) {
WebSocketConnectionHelper.deleteExternalSignalingInstanceForUserEntity(-1)
}
} }
val peerConnectionIdsToEnd: MutableList<String> = ArrayList(peerConnectionWrapperList.size) val peerConnectionIdsToEnd: MutableList<String> = ArrayList(peerConnectionWrapperList.size)
for (wrapper in peerConnectionWrapperList) { for (wrapper in peerConnectionWrapperList) {
peerConnectionIdsToEnd.add(wrapper.sessionId) peerConnectionIdsToEnd.add(wrapper.sessionId)
} }
for (sessionId in peerConnectionIdsToEnd) { for (sessionId in peerConnectionIdsToEnd) {
endPeerConnection(sessionId, "video") endPeerConnection(sessionId, "video")
endPeerConnection(sessionId, "screen") endPeerConnection(sessionId, "screen")
} }
val callParticipantIdsToEnd: MutableList<String> = ArrayList(peerConnectionWrapperList.size) val callParticipantIdsToEnd: MutableList<String> = ArrayList(peerConnectionWrapperList.size)
for (callParticipant in callParticipants.values) { for (callParticipant in callParticipants.values) {
callParticipantIdsToEnd.add(callParticipant!!.callParticipantModel.sessionId) callParticipantIdsToEnd.add(callParticipant!!.callParticipantModel.sessionId)
} }
for (sessionId in callParticipantIdsToEnd) { for (sessionId in callParticipantIdsToEnd) {
removeCallParticipant(sessionId) removeCallParticipant(sessionId)
} }
ApplicationWideCurrentRoomHolder.getInstance().isInCall = false ApplicationWideCurrentRoomHolder.getInstance().isInCall = false
ApplicationWideCurrentRoomHolder.getInstance().isDialing = false ApplicationWideCurrentRoomHolder.getInstance().isDialing = false
hangupNetworkCalls(shutDownView, endCallForAll) hangupNetworkCalls(shutDownView, endCallForAll)
} }
private fun terminateAudioVideo() {
if (videoCapturer != null) {
try {
videoCapturer!!.stopCapture()
} catch (e: InterruptedException) {
Log.e(TAG, "Failed to stop capturing while hanging up")
}
videoCapturer!!.dispose()
videoCapturer = null
}
binding!!.selfVideoRenderer.release()
if (audioSource != null) {
audioSource!!.dispose()
audioSource = null
}
runOnUiThread {
if (audioManager != null) {
audioManager!!.stop()
audioManager = null
}
}
if (videoSource != null) {
videoSource = null
}
if (peerConnectionFactory != null) {
peerConnectionFactory = null
}
localAudioTrack = null
localVideoTrack = null
if (TextUtils.isEmpty(credentials) && hasExternalSignalingServer) {
WebSocketConnectionHelper.deleteExternalSignalingInstanceForUserEntity(-1)
}
}
private fun hangupNetworkCalls(shutDownView: Boolean, endCallForAll: Boolean) { private fun hangupNetworkCalls(shutDownView: Boolean, endCallForAll: Boolean) {
Log.d(TAG, "hangupNetworkCalls. shutDownView=$shutDownView") Log.d(TAG, "hangupNetworkCalls. shutDownView=$shutDownView")
val apiVersion = ApiUtils.getCallApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4, 1)) val apiVersion = ApiUtils.getCallApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4, 1))
@ -2170,22 +2172,16 @@ class CallActivity : CallBaseActivity() {
} }
if (!isSelfInCall && if (!isSelfInCall &&
currentCallStatus !== CallStatus.LEAVING && currentCallStatus !== CallStatus.LEAVING && ApplicationWideCurrentRoomHolder.getInstance().isInCall
ApplicationWideCurrentRoomHolder.getInstance().isInCall
) { ) {
Log.d(TAG, "Most probably a moderator ended the call for all.") Log.d(TAG, "Most probably a moderator ended the call for all.")
hangup(true, false) hangup(shutDownView = true, endCallForAll = false)
return return
} }
if (!isSelfInCall) { if (!isSelfInCall) {
Log.d(TAG, "Self not in call, disconnecting from all other sessions") Log.d(TAG, "Self not in call, disconnecting from all other sessions")
for ((_, _, _, _, _, _, _, _, _, _, sessionId) in participantsInCall) { removeSessions(participantsInCall)
Log.d(TAG, " session that will be removed is: $sessionId")
endPeerConnection(sessionId, "video")
endPeerConnection(sessionId, "screen")
removeCallParticipant(sessionId)
}
return return
} }
if (currentCallStatus === CallStatus.LEAVING) { if (currentCallStatus === CallStatus.LEAVING) {
@ -2199,6 +2195,28 @@ class CallActivity : CallBaseActivity() {
true true
) )
} }
handleJoinedCallParticipantsChanged(selfParticipant, joined, currentSessionId)
if (othersInCall && currentCallStatus !== CallStatus.IN_CONVERSATION) {
setCallState(CallStatus.IN_CONVERSATION)
}
removeSessions(left)
}
private fun removeSessions(sessions: Collection<Participant>) {
for ((_, _, _, _, _, _, _, _, _, _, session) in sessions) {
Log.d(TAG, " session that will be removed is: $session")
endPeerConnection(session, "video")
endPeerConnection(session, "screen")
removeCallParticipant(session)
}
}
private fun handleJoinedCallParticipantsChanged(
selfParticipant: Participant?,
joined: Collection<Participant>,
currentSessionId: String?
) {
var selfJoined = false var selfJoined = false
val selfParticipantHasAudioOrVideo = participantInCallFlagsHaveAudioOrVideo(selfParticipant) val selfParticipantHasAudioOrVideo = participantInCallFlagsHaveAudioOrVideo(selfParticipant)
for (participant in joined) { for (participant in joined) {
@ -2240,11 +2258,13 @@ class CallActivity : CallBaseActivity() {
// remote session ID. However, if the other participant does not have audio nor video that participant // remote session ID. However, if the other participant does not have audio nor video that participant
// will not send an offer, so no connection is actually established when the remote participant has a // will not send an offer, so no connection is actually established when the remote participant has a
// higher session ID but is not publishing media. // higher session ID but is not publishing media.
if (hasMCU && if (hasMCUAndAudioVideo(participantHasAudioOrVideo) ||
participantHasAudioOrVideo || hasNoMCUAndAudioVideo(
!hasMCU && participantHasAudioOrVideo,
selfParticipantHasAudioOrVideo && selfParticipantHasAudioOrVideo,
(!participantHasAudioOrVideo || sessionId < currentSessionId!!) sessionId,
currentSessionId!!
)
) { ) {
getOrCreatePeerConnectionWrapperForSessionIdAndType(sessionId, VIDEO_STREAM_TYPE_VIDEO, false) getOrCreatePeerConnectionWrapperForSessionIdAndType(sessionId, VIDEO_STREAM_TYPE_VIDEO, false)
} }
@ -2254,18 +2274,18 @@ class CallActivity : CallBaseActivity() {
} else { } else {
joined.isNotEmpty() joined.isNotEmpty()
} }
if (othersInCall && currentCallStatus !== CallStatus.IN_CONVERSATION) {
setCallState(CallStatus.IN_CONVERSATION)
}
for ((_, _, _, _, _, _, _, _, _, _, sessionId) in left) {
Log.d(TAG, " oldSession that will be removed is: $sessionId")
endPeerConnection(sessionId, "video")
endPeerConnection(sessionId, "screen")
removeCallParticipant(sessionId)
}
} }
private fun hasMCUAndAudioVideo(participantHasAudioOrVideo: Boolean): Boolean = hasMCU && participantHasAudioOrVideo
private fun hasNoMCUAndAudioVideo(
participantHasAudioOrVideo: Boolean,
selfParticipantHasAudioOrVideo: Boolean,
sessionId: String,
currentSessionId: String
): Boolean =
!hasMCU && selfParticipantHasAudioOrVideo && (!participantHasAudioOrVideo || sessionId < currentSessionId)
private fun participantInCallFlagsHaveAudioOrVideo(participant: Participant?): Boolean = private fun participantInCallFlagsHaveAudioOrVideo(participant: Participant?): Boolean =
if (participant == null) { if (participant == null) {
false false
@ -2289,8 +2309,7 @@ class CallActivity : CallBaseActivity() {
type: String, type: String,
publisher: Boolean publisher: Boolean
): PeerConnectionWrapper? { ): PeerConnectionWrapper? {
var peerConnectionWrapper: PeerConnectionWrapper? var peerConnectionWrapper = getPeerConnectionWrapperForSessionIdAndType(sessionId, type)
peerConnectionWrapper = getPeerConnectionWrapperForSessionIdAndType(sessionId, type)
return if (peerConnectionWrapper != null) { return if (peerConnectionWrapper != null) {
peerConnectionWrapper peerConnectionWrapper
@ -2302,68 +2321,10 @@ class CallActivity : CallBaseActivity() {
context.resources.getString(R.string.nc_common_error_sorry), context.resources.getString(R.string.nc_common_error_sorry),
Snackbar.LENGTH_LONG Snackbar.LENGTH_LONG
).show() ).show()
hangup(true, false) hangup(shutDownView = true, endCallForAll = false)
return null return null
} }
peerConnectionWrapper = if (hasMCU && publisher) { peerConnectionWrapper = createPeerConnectionWrapperForSessionIdAndType(publisher, sessionId, type)
PeerConnectionWrapper(
peerConnectionFactory,
iceServers,
sdpConstraintsForMCU,
sessionId,
callSession,
localStream,
true,
true,
type,
signalingMessageReceiver,
signalingMessageSender
)
} else if (hasMCU) {
PeerConnectionWrapper(
peerConnectionFactory,
iceServers,
sdpConstraints,
sessionId,
callSession,
null,
false,
true,
type,
signalingMessageReceiver,
signalingMessageSender
)
} else {
if ("screen" != type) {
PeerConnectionWrapper(
peerConnectionFactory,
iceServers,
sdpConstraints,
sessionId,
callSession,
localStream,
false,
false,
type,
signalingMessageReceiver,
signalingMessageSender
)
} else {
PeerConnectionWrapper(
peerConnectionFactory,
iceServers,
sdpConstraints,
sessionId,
callSession,
null,
false,
false,
type,
signalingMessageReceiver,
signalingMessageSender
)
}
}
peerConnectionWrapperList.add(peerConnectionWrapper) peerConnectionWrapperList.add(peerConnectionWrapper)
if (!publisher) { if (!publisher) {
var callParticipant = callParticipants[sessionId] var callParticipant = callParticipants[sessionId]
@ -2384,6 +2345,47 @@ class CallActivity : CallBaseActivity() {
} }
} }
private fun createPeerConnectionWrapperForSessionIdAndType(
publisher: Boolean,
sessionId: String?,
type: String
): PeerConnectionWrapper {
val tempIsMCUPublisher: Boolean
val tempHasMCU: Boolean
val tempLocalStream: MediaStream?
if (hasMCU && publisher) {
tempIsMCUPublisher = true
tempHasMCU = true
tempLocalStream = localStream
} else if (hasMCU) {
tempIsMCUPublisher = false
tempHasMCU = true
tempLocalStream = null
} else {
tempIsMCUPublisher = false
tempHasMCU = false
tempLocalStream = if ("screen" != type) {
localStream
} else {
null
}
}
return PeerConnectionWrapper(
peerConnectionFactory,
iceServers,
sdpConstraintsForMCU,
sessionId,
callSession,
tempLocalStream,
tempIsMCUPublisher,
tempHasMCU,
type,
signalingMessageReceiver,
signalingMessageSender
)
}
private fun addCallParticipant(sessionId: String?): CallParticipant { private fun addCallParticipant(sessionId: String?): CallParticipant {
val callParticipant = CallParticipant(sessionId, signalingMessageReceiver) val callParticipant = CallParticipant(sessionId, signalingMessageReceiver)
callParticipants[sessionId] = callParticipant callParticipants[sessionId] = callParticipant
@ -2530,7 +2532,7 @@ class CallActivity : CallBaseActivity() {
ProximitySensorEvent.ProximitySensorEventType.SENSOR_FAR && ProximitySensorEvent.ProximitySensorEventType.SENSOR_FAR &&
videoOn videoOn
if (permissionUtil!!.isCameraPermissionGranted() && if (permissionUtil!!.isCameraPermissionGranted() &&
(currentCallStatus === CallStatus.CONNECTING || isConnectionEstablished) && isConnectingOrEstablished() &&
videoOn && videoOn &&
enableVideo != localVideoTrack!!.enabled() enableVideo != localVideoTrack!!.enabled()
) { ) {
@ -2539,6 +2541,9 @@ class CallActivity : CallBaseActivity() {
} }
} }
private fun isConnectingOrEstablished(): Boolean =
currentCallStatus === CallStatus.CONNECTING || isConnectionEstablished
private fun startSendingNick() { private fun startSendingNick() {
val dataChannelMessage = DataChannelMessage() val dataChannelMessage = DataChannelMessage()
dataChannelMessage.type = "nickChanged" dataChannelMessage.type = "nickChanged"
@ -2602,164 +2607,173 @@ class CallActivity : CallBaseActivity() {
handler!!.removeCallbacksAndMessages(null) handler!!.removeCallbacksAndMessages(null)
} }
when (callState) { when (callState) {
CallStatus.CONNECTING -> handler!!.post { CallStatus.CONNECTING -> handler!!.post { handleCallStateConnected() }
playCallingSound() CallStatus.CALLING_TIMEOUT -> handler!!.post { handleCallStateCallingTimeout() }
if (isIncomingCallFromNotification) { CallStatus.PUBLISHER_FAILED -> handler!!.post { handleCallStatePublisherFailed() }
binding!!.callStates.callStateTextView.setText(R.string.nc_call_incoming) CallStatus.RECONNECTING -> handler!!.post { handleCallStateReconnecting() }
} else {
binding!!.callStates.callStateTextView.setText(R.string.nc_call_ringing)
}
binding!!.callConversationNameTextView.text = conversationName
binding!!.callModeTextView.text = descriptionForCallType
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.VISIBLE) {
binding!!.callStates.callStateProgressBar.visibility = View.VISIBLE
}
if (binding!!.callStates.errorImageView.visibility != View.GONE) {
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
CallStatus.CALLING_TIMEOUT -> handler!!.post {
hangup(false, false)
binding!!.callStates.callStateTextView.setText(R.string.nc_call_timeout)
binding!!.callModeTextView.text = descriptionForCallType
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.GONE) {
binding!!.callStates.callStateProgressBar.visibility = View.GONE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
binding!!.callStates.errorImageView.setImageResource(R.drawable.ic_av_timer_timer_24dp)
if (binding!!.callStates.errorImageView.visibility != View.VISIBLE) {
binding!!.callStates.errorImageView.visibility = View.VISIBLE
}
}
CallStatus.PUBLISHER_FAILED -> handler!!.post {
// No calling sound when the publisher failed
binding!!.callStates.callStateTextView.setText(R.string.nc_call_reconnecting)
binding!!.callModeTextView.text = descriptionForCallType
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.VISIBLE) {
binding!!.callStates.callStateProgressBar.visibility = View.VISIBLE
}
if (binding!!.callStates.errorImageView.visibility != View.GONE) {
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
CallStatus.RECONNECTING -> handler!!.post {
playCallingSound()
binding!!.callStates.callStateTextView.setText(R.string.nc_call_reconnecting)
binding!!.callModeTextView.text = descriptionForCallType
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.VISIBLE) {
binding!!.callStates.callStateProgressBar.visibility = View.VISIBLE
}
if (binding!!.callStates.errorImageView.visibility != View.GONE) {
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
CallStatus.JOINED -> { CallStatus.JOINED -> {
handler!!.postDelayed({ setCallState(CallStatus.CALLING_TIMEOUT) }, CALLING_TIMEOUT) handler!!.postDelayed({ setCallState(CallStatus.CALLING_TIMEOUT) }, CALLING_TIMEOUT)
handler!!.post { handler!!.post { handleCallStateJoined() }
binding!!.callModeTextView.text = descriptionForCallType
if (isIncomingCallFromNotification) {
binding!!.callStates.callStateTextView.setText(R.string.nc_call_incoming)
} else {
binding!!.callStates.callStateTextView.setText(R.string.nc_call_ringing)
}
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.VISIBLE) {
binding!!.callStates.callStateProgressBar.visibility = View.VISIBLE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
if (binding!!.callStates.errorImageView.visibility != View.GONE) {
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
}
CallStatus.IN_CONVERSATION -> handler!!.post {
stopCallingSound()
binding!!.callModeTextView.text = descriptionForCallType
if (!isVoiceOnlyCall) {
binding!!.callInfosLinearLayout.visibility = View.GONE
}
if (!isPushToTalkActive) {
animateCallControls(false, FIVE_SECONDS)
}
if (binding!!.callStates.callStateRelativeLayout.visibility != View.INVISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.INVISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.GONE) {
binding!!.callStates.callStateProgressBar.visibility = View.GONE
}
if (binding!!.gridview.visibility != View.VISIBLE) {
binding!!.gridview.visibility = View.VISIBLE
}
if (binding!!.callStates.errorImageView.visibility != View.GONE) {
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
CallStatus.OFFLINE -> handler!!.post {
stopCallingSound()
binding!!.callStates.callStateTextView.setText(R.string.nc_offline)
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.GONE) {
binding!!.callStates.callStateProgressBar.visibility = View.GONE
}
binding!!.callStates.errorImageView.setImageResource(R.drawable.ic_signal_wifi_off_white_24dp)
if (binding!!.callStates.errorImageView.visibility != View.VISIBLE) {
binding!!.callStates.errorImageView.visibility = View.VISIBLE
}
}
CallStatus.LEAVING -> handler!!.post {
if (!isDestroyed) {
stopCallingSound()
binding!!.callModeTextView.text = descriptionForCallType
binding!!.callStates.callStateTextView.setText(R.string.nc_leaving_call)
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
binding!!.gridview.visibility = View.INVISIBLE
binding!!.callStates.callStateProgressBar.visibility = View.VISIBLE
binding!!.callStates.errorImageView.visibility = View.GONE
}
} }
CallStatus.IN_CONVERSATION -> handler!!.post { handleCallStateInConversation() }
CallStatus.OFFLINE -> handler!!.post { handleCallStateOffline() }
CallStatus.LEAVING -> handler!!.post { handleCallStateLeaving() }
} }
} }
} }
private fun handleCallStateLeaving() {
if (!isDestroyed) {
stopCallingSound()
binding!!.callModeTextView.text = descriptionForCallType
binding!!.callStates.callStateTextView.setText(R.string.nc_leaving_call)
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
binding!!.gridview.visibility = View.INVISIBLE
binding!!.callStates.callStateProgressBar.visibility = View.VISIBLE
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
private fun handleCallStateOffline() {
stopCallingSound()
binding!!.callStates.callStateTextView.setText(R.string.nc_offline)
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.GONE) {
binding!!.callStates.callStateProgressBar.visibility = View.GONE
}
binding!!.callStates.errorImageView.setImageResource(R.drawable.ic_signal_wifi_off_white_24dp)
if (binding!!.callStates.errorImageView.visibility != View.VISIBLE) {
binding!!.callStates.errorImageView.visibility = View.VISIBLE
}
}
private fun handleCallStateInConversation() {
stopCallingSound()
binding!!.callModeTextView.text = descriptionForCallType
if (!isVoiceOnlyCall) {
binding!!.callInfosLinearLayout.visibility = View.GONE
}
if (!isPushToTalkActive) {
animateCallControls(false, FIVE_SECONDS)
}
if (binding!!.callStates.callStateRelativeLayout.visibility != View.INVISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.INVISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.GONE) {
binding!!.callStates.callStateProgressBar.visibility = View.GONE
}
if (binding!!.gridview.visibility != View.VISIBLE) {
binding!!.gridview.visibility = View.VISIBLE
}
if (binding!!.callStates.errorImageView.visibility != View.GONE) {
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
private fun handleCallStateJoined() {
binding!!.callModeTextView.text = descriptionForCallType
if (isIncomingCallFromNotification) {
binding!!.callStates.callStateTextView.setText(R.string.nc_call_incoming)
} else {
binding!!.callStates.callStateTextView.setText(R.string.nc_call_ringing)
}
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.VISIBLE) {
binding!!.callStates.callStateProgressBar.visibility = View.VISIBLE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
if (binding!!.callStates.errorImageView.visibility != View.GONE) {
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
private fun handleCallStateReconnecting() {
playCallingSound()
binding!!.callStates.callStateTextView.setText(R.string.nc_call_reconnecting)
binding!!.callModeTextView.text = descriptionForCallType
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.VISIBLE) {
binding!!.callStates.callStateProgressBar.visibility = View.VISIBLE
}
if (binding!!.callStates.errorImageView.visibility != View.GONE) {
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
private fun handleCallStatePublisherFailed() {
// No calling sound when the publisher failed
binding!!.callStates.callStateTextView.setText(R.string.nc_call_reconnecting)
binding!!.callModeTextView.text = descriptionForCallType
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.VISIBLE) {
binding!!.callStates.callStateProgressBar.visibility = View.VISIBLE
}
if (binding!!.callStates.errorImageView.visibility != View.GONE) {
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
private fun handleCallStateCallingTimeout() {
hangup(shutDownView = false, endCallForAll = false)
binding!!.callStates.callStateTextView.setText(R.string.nc_call_timeout)
binding!!.callModeTextView.text = descriptionForCallType
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.GONE) {
binding!!.callStates.callStateProgressBar.visibility = View.GONE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
binding!!.callStates.errorImageView.setImageResource(R.drawable.ic_av_timer_timer_24dp)
if (binding!!.callStates.errorImageView.visibility != View.VISIBLE) {
binding!!.callStates.errorImageView.visibility = View.VISIBLE
}
}
private fun handleCallStateConnected() {
playCallingSound()
if (isIncomingCallFromNotification) {
binding!!.callStates.callStateTextView.setText(R.string.nc_call_incoming)
} else {
binding!!.callStates.callStateTextView.setText(R.string.nc_call_ringing)
}
binding!!.callConversationNameTextView.text = conversationName
binding!!.callModeTextView.text = descriptionForCallType
if (binding!!.callStates.callStateRelativeLayout.visibility != View.VISIBLE) {
binding!!.callStates.callStateRelativeLayout.visibility = View.VISIBLE
}
if (binding!!.gridview.visibility != View.INVISIBLE) {
binding!!.gridview.visibility = View.INVISIBLE
}
if (binding!!.callStates.callStateProgressBar.visibility != View.VISIBLE) {
binding!!.callStates.callStateProgressBar.visibility = View.VISIBLE
}
if (binding!!.callStates.errorImageView.visibility != View.GONE) {
binding!!.callStates.errorImageView.visibility = View.GONE
}
}
private val descriptionForCallType: String private val descriptionForCallType: String
get() { get() {
val appName = resources.getString(R.string.nc_app_product_name) val appName = resources.getString(R.string.nc_app_product_name)

View file

@ -132,6 +132,10 @@ class ContactItem(
holder?.binding?.nameText?.text = sharedApplication!!.getString(R.string.nc_guest) holder?.binding?.nameText?.text = sharedApplication!!.getString(R.string.nc_guest)
} }
setAvatar(holder)
}
private fun setAvatar(holder: ContactItemViewHolder?) {
if (model.calculatedActorType == Participant.ActorType.GROUPS || if (model.calculatedActorType == Participant.ActorType.GROUPS ||
model.calculatedActorType == Participant.ActorType.CIRCLES model.calculatedActorType == Participant.ActorType.CIRCLES
) { ) {

View file

@ -120,7 +120,11 @@ class MentionAutocompleteItem(
} else { } else {
holder.binding.nameText.text = displayName holder.binding.nameText.text = displayName
} }
var avatarId = objectId setAvatar(holder, objectId)
drawStatus(holder)
}
private fun setAvatar(holder: ParticipantItemViewHolder, objectId: String?) {
when (source) { when (source) {
SOURCE_CALLS -> { SOURCE_CALLS -> {
run {} run {}
@ -136,10 +140,7 @@ class MentionAutocompleteItem(
SOURCE_GROUPS -> { SOURCE_GROUPS -> {
holder.binding.avatarView.loadUserAvatar( holder.binding.avatarView.loadUserAvatar(
viewThemeUtils.talk.themePlaceholderAvatar( viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.avatarView, R.drawable.ic_avatar_group)
holder.binding.avatarView,
R.drawable.ic_avatar_group
)
) )
} }
@ -149,27 +150,30 @@ class MentionAutocompleteItem(
currentUser, currentUser,
currentUser.baseUrl!!, currentUser.baseUrl!!,
roomToken, roomToken,
avatarId!!, objectId!!,
darkTheme, darkTheme,
true, requestBigSize = true,
false ignoreCache = false
) )
} }
SOURCE_GUESTS, SOURCE_EMAILS -> { SOURCE_GUESTS, SOURCE_EMAILS -> {
avatarId = displayName
if (displayName.equals(context.resources.getString(R.string.nc_guest))) { if (displayName.equals(context.resources.getString(R.string.nc_guest))) {
holder.binding.avatarView.loadDefaultAvatar(viewThemeUtils) holder.binding.avatarView.loadDefaultAvatar(viewThemeUtils)
} else { } else {
holder.binding.avatarView.loadGuestAvatar(currentUser, avatarId!!, false) holder.binding.avatarView.loadGuestAvatar(currentUser, displayName!!, false)
} }
} }
else -> { else -> {
holder.binding.avatarView.loadUserAvatar(currentUser, avatarId!!, true, false) holder.binding.avatarView.loadUserAvatar(
currentUser,
objectId!!,
requestBigSize = true,
ignoreCache = false
)
} }
} }
drawStatus(holder)
} }
private fun drawStatus(holder: ParticipantItemViewHolder) { private fun drawStatus(holder: ParticipantItemViewHolder) {

View file

@ -224,14 +224,11 @@ class IncomingDeckCardViewHolder(incomingView: View, payload: Any) : MessageHold
binding.messageQuote.quotedMessageAuthor binding.messageQuote.quotedMessageAuthor
.setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast)) .setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast))
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { viewThemeUtils.talk.themeParentMessage(
viewThemeUtils.platform.colorViewBackground( parentChatMessage,
binding.messageQuote.quoteColoredView, message,
ColorRole.PRIMARY binding.messageQuote.quoteColoredView
) )
} else {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
}
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -14,7 +14,6 @@ import android.view.View
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import autodagger.AutoInjector import autodagger.AutoInjector
import coil.load import coil.load
import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
@ -202,14 +201,11 @@ class IncomingLinkPreviewMessageViewHolder(incomingView: View, payload: Any) :
binding.messageQuote.quotedMessageAuthor binding.messageQuote.quotedMessageAuthor
.setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast)) .setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast))
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { viewThemeUtils.talk.themeParentMessage(
viewThemeUtils.platform.colorViewBackground( parentChatMessage,
binding.messageQuote.quoteColoredView, message,
ColorRole.PRIMARY binding.messageQuote.quoteColoredView
) )
} else {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
}
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -22,7 +22,6 @@ import android.webkit.WebViewClient
import autodagger.AutoInjector import autodagger.AutoInjector
import coil.load import coil.load
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
@ -187,14 +186,11 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) :
binding.messageQuote.quotedMessageAuthor binding.messageQuote.quotedMessageAuthor
.setTextColor(context.resources.getColor(R.color.textColorMaxContrast, null)) .setTextColor(context.resources.getColor(R.color.textColorMaxContrast, null))
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { viewThemeUtils.talk.themeParentMessage(
viewThemeUtils.platform.colorViewBackground( parentChatMessage,
binding.messageQuote.quoteColoredView, message,
ColorRole.PRIMARY binding.messageQuote.quoteColoredView
) )
} else {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
}
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -13,7 +13,6 @@ import android.view.View
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import autodagger.AutoInjector import autodagger.AutoInjector
import coil.load import coil.load
import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
@ -209,14 +208,11 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) :
binding.messageQuote.quotedMessageAuthor binding.messageQuote.quotedMessageAuthor
.setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast)) .setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast))
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { viewThemeUtils.talk.themeParentMessage(
viewThemeUtils.platform.colorViewBackground( parentChatMessage,
binding.messageQuote.quoteColoredView, message,
ColorRole.PRIMARY binding.messageQuote.quoteColoredView
) )
} else {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
}
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
} catch (e: Exception) { } catch (e: Exception) {
Log.d(TAG, "Error when processing parent message in view holder", e) Log.d(TAG, "Error when processing parent message in view holder", e)

View file

@ -13,10 +13,8 @@ import android.content.Context
import android.util.Log import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import android.view.View import android.view.View
import androidx.core.content.ContextCompat
import autodagger.AutoInjector import autodagger.AutoInjector
import coil.load import coil.load
import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
@ -212,19 +210,12 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
viewThemeUtils viewThemeUtils
) )
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { viewThemeUtils.talk.themeParentMessage(
viewThemeUtils.platform.colorViewBackground( parentChatMessage,
binding.messageQuote.quoteColoredView, message,
ColorRole.PRIMARY binding.messageQuote.quoteColoredView,
) R.color.high_emphasis_text
} else { )
binding.messageQuote.quoteColoredView.setBackgroundColor(
ContextCompat.getColor(
binding.messageQuote.quoteColoredView.context,
R.color.high_emphasis_text
)
)
}
binding.messageQuote.quotedChatMessageView.setOnClickListener { binding.messageQuote.quotedChatMessageView.setOnClickListener {
val chatActivity = commonMessageInterface as ChatActivity val chatActivity = commonMessageInterface as ChatActivity

View file

@ -119,15 +119,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) :
} }
if (message.resetVoiceMessage) { if (message.resetVoiceMessage) {
binding.playPauseBtn.visibility = View.VISIBLE resetVoiceMessage(message)
binding.playPauseBtn.icon = ContextCompat.getDrawable(
context!!,
R.drawable.ic_baseline_play_arrow_voice_message_24
)
binding.seekbar.progress = SEEKBAR_START
message.resetVoiceMessage = false
message.voiceMessagePlayedSeconds = 0
binding.voiceMessageDuration.visibility = View.INVISIBLE
} }
binding.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { binding.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
@ -163,6 +155,18 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) :
isBound = true isBound = true
} }
private fun resetVoiceMessage(chatMessage: ChatMessage) {
binding.playPauseBtn.visibility = View.VISIBLE
binding.playPauseBtn.icon = ContextCompat.getDrawable(
context!!,
R.drawable.ic_baseline_play_arrow_voice_message_24
)
binding.seekbar.progress = SEEKBAR_START
chatMessage.resetVoiceMessage = false
chatMessage.voiceMessagePlayedSeconds = 0
binding.voiceMessageDuration.visibility = View.INVISIBLE
}
private fun longClickOnReaction(chatMessage: ChatMessage) { private fun longClickOnReaction(chatMessage: ChatMessage) {
commonMessageInterface.onLongClickReactions(chatMessage) commonMessageInterface.onLongClickReactions(chatMessage)
} }
@ -322,14 +326,11 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) :
binding.messageQuote.quotedMessageAuthor binding.messageQuote.quotedMessageAuthor
.setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast)) .setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast))
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { viewThemeUtils.talk.themeParentMessage(
viewThemeUtils.platform.colorViewBackground( parentChatMessage,
binding.messageQuote.quoteColoredView, message,
ColorRole.PRIMARY binding.messageQuote.quoteColoredView
) )
} else {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
}
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -215,14 +215,11 @@ class OutcomingDeckCardViewHolder(
binding.messageQuote.quotedMessageAuthor binding.messageQuote.quotedMessageAuthor
.setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast)) .setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast))
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { viewThemeUtils.talk.themeParentMessage(
viewThemeUtils.platform.colorViewBackground( parentChatMessage,
binding.messageQuote.quoteColoredView, message,
ColorRole.PRIMARY binding.messageQuote.quoteColoredView
) )
} else {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
}
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -127,6 +127,7 @@ object Migrations {
db.execSQL("ALTER TABLE ArbitraryStorage_dualPK RENAME TO ArbitraryStorage") db.execSQL("ALTER TABLE ArbitraryStorage_dualPK RENAME TO ArbitraryStorage")
} }
@Suppress("Detekt.LongMethod")
fun migrateToOfflineSupport(db: SupportSQLiteDatabase) { fun migrateToOfflineSupport(db: SupportSQLiteDatabase) {
db.execSQL( db.execSQL(
"CREATE TABLE IF NOT EXISTS Conversations (" + "CREATE TABLE IF NOT EXISTS Conversations (" +

View file

@ -238,69 +238,73 @@ class DiagnoseActivity : BaseActivity() {
addValue(BuildConfig.FLAVOR) addValue(BuildConfig.FLAVOR)
if (isGooglePlayServicesAvailable) { if (isGooglePlayServicesAvailable) {
addKey(context.resources.getString(R.string.nc_diagnose_battery_optimization_title)) setupAppValuesForGooglePlayServices()
if (PowerManagerUtils().isIgnoringBatteryOptimizations()) {
addValue(context.resources.getString(R.string.nc_diagnose_battery_optimization_ignored))
} else {
addValue(context.resources.getString(R.string.nc_diagnose_battery_optimization_not_ignored))
}
// handle notification permission on API level >= 33
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
addKey(context.resources.getString(R.string.nc_diagnose_notification_permission))
if (platformPermissionUtil.isPostNotificationsPermissionGranted()) {
addValue(context.resources.getString(R.string.nc_settings_notifications_granted))
} else {
addValue(context.resources.getString(R.string.nc_settings_notifications_declined))
}
}
addKey(context.resources.getString(R.string.nc_diagnose_notification_calls_channel_permission))
addValue(
translateBoolean(
NotificationUtils.isCallsNotificationChannelEnabled(this)
)
)
addKey(context.resources.getString(R.string.nc_diagnose_notification_messages_channel_permission))
addValue(
translateBoolean(
NotificationUtils.isMessagesNotificationChannelEnabled(this)
)
)
addKey(context.resources.getString(R.string.nc_diagnose_firebase_push_token_title))
if (appPreferences.pushToken.isNullOrEmpty()) {
addValue(context.resources.getString(R.string.nc_diagnose_firebase_push_token_missing))
} else {
addValue("${appPreferences.pushToken.substring(0, 5)}...")
}
addKey(context.resources.getString(R.string.nc_diagnose_firebase_push_token_latest_generated))
if (appPreferences.pushTokenLatestGeneration != null && appPreferences.pushTokenLatestGeneration != 0L) {
addValue(
DisplayUtils.unixTimeToHumanReadable(
appPreferences
.pushTokenLatestGeneration
)
)
} else {
addValue(context.resources.getString(R.string.nc_common_unknown))
}
addKey(context.resources.getString(R.string.nc_diagnose_firebase_push_token_latest_fetch))
if (appPreferences.pushTokenLatestFetch != null && appPreferences.pushTokenLatestFetch != 0L) {
addValue(DisplayUtils.unixTimeToHumanReadable(appPreferences.pushTokenLatestFetch))
} else {
addValue(context.resources.getString(R.string.nc_common_unknown))
}
} }
addKey(context.resources.getString(R.string.nc_diagnose_app_users_amount)) addKey(context.resources.getString(R.string.nc_diagnose_app_users_amount))
addValue(userManager.users.blockingGet().size.toString()) addValue(userManager.users.blockingGet().size.toString())
} }
private fun setupAppValuesForGooglePlayServices() {
addKey(context.resources.getString(R.string.nc_diagnose_battery_optimization_title))
if (PowerManagerUtils().isIgnoringBatteryOptimizations()) {
addValue(context.resources.getString(R.string.nc_diagnose_battery_optimization_ignored))
} else {
addValue(context.resources.getString(R.string.nc_diagnose_battery_optimization_not_ignored))
}
// handle notification permission on API level >= 33
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
addKey(context.resources.getString(R.string.nc_diagnose_notification_permission))
if (platformPermissionUtil.isPostNotificationsPermissionGranted()) {
addValue(context.resources.getString(R.string.nc_settings_notifications_granted))
} else {
addValue(context.resources.getString(R.string.nc_settings_notifications_declined))
}
}
addKey(context.resources.getString(R.string.nc_diagnose_notification_calls_channel_permission))
addValue(
translateBoolean(
NotificationUtils.isCallsNotificationChannelEnabled(this)
)
)
addKey(context.resources.getString(R.string.nc_diagnose_notification_messages_channel_permission))
addValue(
translateBoolean(
NotificationUtils.isMessagesNotificationChannelEnabled(this)
)
)
addKey(context.resources.getString(R.string.nc_diagnose_firebase_push_token_title))
if (appPreferences.pushToken.isNullOrEmpty()) {
addValue(context.resources.getString(R.string.nc_diagnose_firebase_push_token_missing))
} else {
addValue("${appPreferences.pushToken.substring(0, 5)}...")
}
addKey(context.resources.getString(R.string.nc_diagnose_firebase_push_token_latest_generated))
if (appPreferences.pushTokenLatestGeneration != null && appPreferences.pushTokenLatestGeneration != 0L) {
addValue(
DisplayUtils.unixTimeToHumanReadable(
appPreferences
.pushTokenLatestGeneration
)
)
} else {
addValue(context.resources.getString(R.string.nc_common_unknown))
}
addKey(context.resources.getString(R.string.nc_diagnose_firebase_push_token_latest_fetch))
if (appPreferences.pushTokenLatestFetch != null && appPreferences.pushTokenLatestFetch != 0L) {
addValue(DisplayUtils.unixTimeToHumanReadable(appPreferences.pushTokenLatestFetch))
} else {
addValue(context.resources.getString(R.string.nc_common_unknown))
}
}
private fun setupAccountValues() { private fun setupAccountValues() {
addHeadline(context.resources.getString(R.string.nc_diagnose_account_category_title)) addHeadline(context.resources.getString(R.string.nc_diagnose_account_category_title))

View file

@ -39,16 +39,13 @@ class SaveFileToStorageWorker(val context: Context, workerParameters: WorkerPara
@Suppress("Detekt.TooGenericExceptionCaught") @Suppress("Detekt.TooGenericExceptionCaught")
override fun doWork(): Result { override fun doWork(): Result {
try { try {
val sourceFilePath = inputData.getString(KEY_SOURCE_FILE_PATH) val cacheFile = File(inputData.getString(KEY_SOURCE_FILE_PATH)!!)
val cacheFile = File(sourceFilePath!!)
val contentResolver = context.contentResolver val contentResolver = context.contentResolver
val mimeType = URLConnection.guessContentTypeFromName(cacheFile.name) val mimeType = URLConnection.guessContentTypeFromName(cacheFile.name)
val appName = applicationContext.resources!!.getString(R.string.nc_app_product_name)
val values = ContentValues().apply { val values = ContentValues().apply {
if (mimeType.startsWith(IMAGE_PREFIX) || mimeType.startsWith(VIDEO_PREFIX)) { if (mimeType.startsWith(IMAGE_PREFIX) || mimeType.startsWith(VIDEO_PREFIX)) {
val appName = applicationContext.resources!!.getString(R.string.nc_app_product_name)
put(FileColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM + "/" + appName) put(FileColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM + "/" + appName)
} }
put(FileColumns.DISPLAY_NAME, cacheFile.name) put(FileColumns.DISPLAY_NAME, cacheFile.name)
@ -58,11 +55,7 @@ class SaveFileToStorageWorker(val context: Context, workerParameters: WorkerPara
} }
} }
val collectionUri = getUriByType(mimeType) contentResolver.insert(getUriByType(mimeType), values)?.let { fileUri ->
val uri = contentResolver.insert(collectionUri, values)
uri?.let { fileUri ->
try { try {
val outputStream: OutputStream? = contentResolver.openOutputStream(fileUri) val outputStream: OutputStream? = contentResolver.openOutputStream(fileUri)
outputStream.use { output -> outputStream.use { output ->

View file

@ -241,7 +241,7 @@ class LocationPickerActivity :
return true return true
} }
@Suppress("Detekt.TooGenericExceptionCaught", "Detekt.ComplexMethod") @Suppress("Detekt.TooGenericExceptionCaught", "Detekt.ComplexMethod", "Detekt.LongMethod")
private fun initMap() { private fun initMap() {
binding.map.setTileSource(TileSourceFactory.MAPNIK) binding.map.setTileSource(TileSourceFactory.MAPNIK)
binding.map.onResume() binding.map.onResume()

View file

@ -77,6 +77,7 @@ import com.nextcloud.talk.chat.data.model.ChatMessage.SystemMessageType.USER_REM
* *
*/ */
class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.SystemMessageType>() { class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.SystemMessageType>() {
@Suppress("Detekt.LongMethod")
override fun getFromString(string: String): ChatMessage.SystemMessageType { override fun getFromString(string: String): ChatMessage.SystemMessageType {
return when (string) { return when (string) {
"conversation_created" -> CONVERSATION_CREATED "conversation_created" -> CONVERSATION_CREATED
@ -144,7 +145,7 @@ class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.Syst
} }
} }
@Suppress("Detekt.ComplexMethod") @Suppress("Detekt.ComplexMethod", "Detekt.LongMethod")
override fun convertToString(`object`: ChatMessage.SystemMessageType?): String { override fun convertToString(`object`: ChatMessage.SystemMessageType?): String {
return when (`object`) { return when (`object`) {
null -> "" null -> ""

View file

@ -943,10 +943,6 @@ class SettingsActivity :
binding.settingsShowNotificationWarning.visibility = View.GONE binding.settingsShowNotificationWarning.visibility = View.GONE
} }
binding.settingsScreenSecuritySwitch.isChecked = appPreferences.isScreenSecured
binding.settingsIncognitoKeyboardSwitch.isChecked = appPreferences.isKeyboardIncognito
if (CapabilitiesUtil.isReadStatusAvailable(currentUser!!.capabilities!!.spreedCapability!!)) { if (CapabilitiesUtil.isReadStatusAvailable(currentUser!!.capabilities!!.spreedCapability!!)) {
binding.settingsReadPrivacySwitch.isChecked = !CapabilitiesUtil.isReadStatusPrivate(currentUser!!) binding.settingsReadPrivacySwitch.isChecked = !CapabilitiesUtil.isReadStatusPrivate(currentUser!!)
} else { } else {
@ -954,15 +950,7 @@ class SettingsActivity :
} }
setupTypingStatusSetting() setupTypingStatusSetting()
setupProxyUseSetting()
binding.settingsPhoneBookIntegrationSwitch.isChecked = appPreferences.isPhoneBookIntegrationEnabled
binding.settingsProxyUseCredentialsSwitch.isChecked = appPreferences.proxyCredentials
binding.settingsProxyUseCredentials.setOnClickListener {
val isChecked = binding.settingsProxyUseCredentialsSwitch.isChecked
binding.settingsProxyUseCredentialsSwitch.isChecked = !isChecked
appPreferences.setProxyNeedsCredentials(!isChecked)
}
binding.settingsScreenLockSwitch.isChecked = appPreferences.isScreenLocked binding.settingsScreenLockSwitch.isChecked = appPreferences.isScreenLocked
binding.settingsScreenLock.setOnClickListener { binding.settingsScreenLock.setOnClickListener {
@ -977,12 +965,31 @@ class SettingsActivity :
appPreferences.setReadPrivacy(!isChecked) appPreferences.setReadPrivacy(!isChecked)
} }
binding.settingsIncognitoKeyboardSwitch.isChecked = appPreferences.isKeyboardIncognito
binding.settingsIncognitoKeyboard.setOnClickListener { binding.settingsIncognitoKeyboard.setOnClickListener {
val isChecked = binding.settingsIncognitoKeyboardSwitch.isChecked val isChecked = binding.settingsIncognitoKeyboardSwitch.isChecked
binding.settingsIncognitoKeyboardSwitch.isChecked = !isChecked binding.settingsIncognitoKeyboardSwitch.isChecked = !isChecked
appPreferences.setIncognitoKeyboard(!isChecked) appPreferences.setIncognitoKeyboard(!isChecked)
} }
setupPhoneBookIntegrationSetting()
binding.settingsScreenSecuritySwitch.isChecked = appPreferences.isScreenSecured
binding.settingsScreenSecurity.setOnClickListener {
val isChecked = binding.settingsScreenSecuritySwitch.isChecked
binding.settingsScreenSecuritySwitch.isChecked = !isChecked
appPreferences.setScreenSecurity(!isChecked)
}
binding.settingsTypingStatus.setOnClickListener {
val isChecked = binding.settingsTypingStatusSwitch.isChecked
binding.settingsTypingStatusSwitch.isChecked = !isChecked
appPreferences.setTypingStatus(!isChecked)
}
}
private fun setupPhoneBookIntegrationSetting() {
binding.settingsPhoneBookIntegrationSwitch.isChecked = appPreferences.isPhoneBookIntegrationEnabled
binding.settingsPhoneBookIntegration.setOnClickListener { binding.settingsPhoneBookIntegration.setOnClickListener {
val isChecked = binding.settingsPhoneBookIntegrationSwitch.isChecked val isChecked = binding.settingsPhoneBookIntegrationSwitch.isChecked
binding.settingsPhoneBookIntegrationSwitch.isChecked = !isChecked binding.settingsPhoneBookIntegrationSwitch.isChecked = !isChecked
@ -995,17 +1002,14 @@ class SettingsActivity :
deleteAll() deleteAll()
} }
} }
}
binding.settingsScreenSecurity.setOnClickListener { private fun setupProxyUseSetting() {
val isChecked = binding.settingsScreenSecuritySwitch.isChecked binding.settingsProxyUseCredentialsSwitch.isChecked = appPreferences.proxyCredentials
binding.settingsScreenSecuritySwitch.isChecked = !isChecked binding.settingsProxyUseCredentials.setOnClickListener {
appPreferences.setScreenSecurity(!isChecked) val isChecked = binding.settingsProxyUseCredentialsSwitch.isChecked
} binding.settingsProxyUseCredentialsSwitch.isChecked = !isChecked
appPreferences.setProxyNeedsCredentials(!isChecked)
binding.settingsTypingStatus.setOnClickListener {
val isChecked = binding.settingsTypingStatusSwitch.isChecked
binding.settingsTypingStatusSwitch.isChecked = !isChecked
appPreferences.setTypingStatus(!isChecked)
} }
} }

View file

@ -147,6 +147,10 @@ class MessageActionsDialog(
} }
} }
initMenuItems()
}
private fun initMenuItems() {
this.lifecycleScope.launch { this.lifecycleScope.launch {
initMenuItemTranslate( initMenuItemTranslate(
!message.isDeleted && !message.isDeleted &&

View file

@ -24,6 +24,7 @@ import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.RelativeLayout import android.widget.RelativeLayout
import android.widget.TextView import android.widget.TextView
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
@ -42,6 +43,7 @@ import com.nextcloud.android.common.ui.theme.ViewThemeUtilsBase
import com.nextcloud.android.common.ui.theme.utils.AndroidXViewThemeUtils import com.nextcloud.android.common.ui.theme.utils.AndroidXViewThemeUtils
import com.nextcloud.android.common.ui.util.buildColorStateList import com.nextcloud.android.common.ui.util.buildColorStateList
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.chat.data.model.ChatMessage
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding
import com.nextcloud.talk.ui.MicInputCloud import com.nextcloud.talk.ui.MicInputCloud
import com.nextcloud.talk.ui.StatusDrawable import com.nextcloud.talk.ui.StatusDrawable
@ -368,6 +370,21 @@ class TalkSpecificViewThemeUtils @Inject constructor(
} }
} }
fun themeParentMessage(
parentChatMessage: ChatMessage,
message: ChatMessage,
quoteColoredView: View,
@ColorRes quoteColorNonSelf: Int = R.color.textColorMaxContrast
) {
withScheme(quoteColoredView) { scheme ->
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
quoteColoredView.setBackgroundColor(dynamicColor.primary().getArgb(scheme))
} else {
quoteColoredView.setBackgroundResource(quoteColorNonSelf)
}
}
}
fun getTextColor(isOutgoingMessage: Boolean, isSelfReaction: Boolean, binding: ReactionsInsideMessageBinding): Int { fun getTextColor(isOutgoingMessage: Boolean, isSelfReaction: Boolean, binding: ReactionsInsideMessageBinding): Int {
return withScheme(binding.root) { scheme -> return withScheme(binding.root) { scheme ->
return@withScheme if (!isOutgoingMessage || isSelfReaction) { return@withScheme if (!isOutgoingMessage || isSelfReaction) {

View file

@ -102,11 +102,7 @@ class DatabaseStorageModule(conversationUser: User, conversationToken: String) {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
ncApiCoroutines!!.setMessageExpiration( ncApiCoroutines!!.setMessageExpiration(
getCredentials(conversationUser.username, conversationUser.token)!!, getCredentials(conversationUser.username, conversationUser.token)!!,
getUrlForMessageExpiration( getUrlForMessageExpiration(apiVersion, conversationUser.baseUrl, conversationToken),
apiVersion,
conversationUser.baseUrl,
conversationToken
),
valueInt valueInt
) )
messageExpiration = valueInt messageExpiration = valueInt
@ -132,10 +128,7 @@ class DatabaseStorageModule(conversationUser: User, conversationToken: String) {
val apiVersion = getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4, 1)) val apiVersion = getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4, 1))
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
ncApiCoroutines!!.setNotificationLevel( ncApiCoroutines!!.setNotificationLevel(
getCredentials( getCredentials(conversationUser.username, conversationUser.token)!!,
conversationUser.username,
conversationUser.token
)!!,
getUrlForRoomNotificationLevel( getUrlForRoomNotificationLevel(
apiVersion, apiVersion,
conversationUser.baseUrl, conversationUser.baseUrl,

View file

@ -69,58 +69,11 @@ class ConversationConversionTest(
// check if default values are set for the fields when API_V1 is used // check if default values are set for the fields when API_V1 is used
if (apiVersion == 1) { if (apiVersion == 1) {
// default values for API_V2 fields checkConversationEntityV1(conversationEntity)
assertEquals(false, conversationEntity.canDeleteConversation)
assertEquals(true, conversationEntity.canLeaveConversation)
// default values for API_V3 fields
assertEquals("", conversationEntity.description)
assertEquals("", conversationEntity.actorType)
assertEquals("", conversationEntity.actorId)
assertEquals(0, conversationEntity.callFlag)
assertEquals(0, conversationEntity.lastCommonReadMessage)
// default values for API_V4 fields
assertEquals("", conversationEntity.avatarVersion)
assertEquals(0, conversationEntity.callStartTime)
assertEquals(0, conversationEntity.callRecording)
assertEquals(false, conversationEntity.unreadMentionDirect)
assertEquals("", conversationEntity.status)
assertEquals("", conversationEntity.statusIcon)
assertEquals("", conversationEntity.statusMessage)
assertEquals(null, conversationEntity.statusClearAt)
assertEquals("", conversationEntity.avatarVersion)
assertEquals(0, conversationEntity.callStartTime)
assertEquals(0, conversationEntity.callRecording)
} }
if (apiVersion >= 1) { if (apiVersion >= 1) {
assertEquals("juwd77g6", conversationEntity.token) checkConversationEntityLargerThanV1(conversationEntity)
assertEquals(ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL, conversationEntity.type)
assertEquals("marcel", conversationEntity.name)
assertEquals("Marcel", conversationEntity.displayName)
assertEquals(Participant.ParticipantType.OWNER, conversationEntity.participantType)
assertEquals(
ConversationEnums.ConversationReadOnlyState.CONVERSATION_READ_WRITE,
conversationEntity.conversationReadOnlyState
)
assertEquals(1727185155, conversationEntity.lastPing)
assertEquals("0", conversationEntity.sessionId)
assertEquals(false, conversationEntity.hasPassword)
assertEquals(false, conversationEntity.hasCall)
assertEquals(true, conversationEntity.canStartCall)
assertEquals(1727098966, conversationEntity.lastActivity)
assertEquals(false, conversationEntity.favorite)
assertEquals(ConversationEnums.NotificationLevel.ALWAYS, conversationEntity.notificationLevel)
assertEquals(ConversationEnums.LobbyState.LOBBY_STATE_ALL_PARTICIPANTS, conversationEntity.lobbyState)
assertEquals(0, conversationEntity.lobbyTimer)
assertEquals(0, conversationEntity.unreadMessages)
assertEquals(false, conversationEntity.unreadMention)
assertEquals(92320, conversationEntity.lastReadMessage)
assertNotNull(conversationEntity.lastMessage)
assertTrue(conversationEntity.lastMessage is String)
assertTrue(conversationEntity.lastMessage!!.contains("token"))
assertEquals(ConversationEnums.ObjectType.DEFAULT, conversationEntity.objectType)
} }
if (apiVersion >= 2) { if (apiVersion >= 2) {
@ -143,23 +96,82 @@ class ConversationConversionTest(
} }
if (apiVersion >= 4) { if (apiVersion >= 4) {
assertEquals("143a9df3", conversationEntity.avatarVersion) checkConversationEntityV4(conversationEntity)
assertEquals(0, conversationEntity.callStartTime)
assertEquals(0, conversationEntity.callRecording)
assertEquals(false, conversationEntity.unreadMentionDirect)
// assertEquals(, conversationEntity.breakoutRoomMode) // Not implemented
// assertEquals(, conversationEntity.breakoutRoomStatus) // Not implemented
assertEquals("away", conversationEntity.status)
assertEquals("👻", conversationEntity.statusIcon)
assertEquals("buuuuh", conversationEntity.statusMessage)
assertEquals(null, conversationEntity.statusClearAt)
assertEquals("143a9df3", conversationEntity.avatarVersion)
// assertEquals("", conversationEntity.isCustomAvatar) // Not implemented
assertEquals(0, conversationEntity.callStartTime)
assertEquals(0, conversationEntity.callRecording)
// assertEquals("", conversationEntity.recordingConsent) // Not implemented
// assertEquals("", conversationEntity.mentionPermissions) // Not implemented
// assertEquals("", conversationEntity.isArchived) // Not implemented
} }
} }
private fun checkConversationEntityLargerThanV1(conversationEntity: ConversationEntity) {
assertEquals("juwd77g6", conversationEntity.token)
assertEquals(ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL, conversationEntity.type)
assertEquals("marcel", conversationEntity.name)
assertEquals("Marcel", conversationEntity.displayName)
assertEquals(Participant.ParticipantType.OWNER, conversationEntity.participantType)
assertEquals(
ConversationEnums.ConversationReadOnlyState.CONVERSATION_READ_WRITE,
conversationEntity.conversationReadOnlyState
)
assertEquals(1727185155, conversationEntity.lastPing)
assertEquals("0", conversationEntity.sessionId)
assertEquals(false, conversationEntity.hasPassword)
assertEquals(false, conversationEntity.hasCall)
assertEquals(true, conversationEntity.canStartCall)
assertEquals(1727098966, conversationEntity.lastActivity)
assertEquals(false, conversationEntity.favorite)
assertEquals(ConversationEnums.NotificationLevel.ALWAYS, conversationEntity.notificationLevel)
assertEquals(ConversationEnums.LobbyState.LOBBY_STATE_ALL_PARTICIPANTS, conversationEntity.lobbyState)
assertEquals(0, conversationEntity.lobbyTimer)
assertEquals(0, conversationEntity.unreadMessages)
assertEquals(false, conversationEntity.unreadMention)
assertEquals(92320, conversationEntity.lastReadMessage)
assertNotNull(conversationEntity.lastMessage)
assertTrue(conversationEntity.lastMessage is String)
assertTrue(conversationEntity.lastMessage!!.contains("token"))
assertEquals(ConversationEnums.ObjectType.DEFAULT, conversationEntity.objectType)
}
private fun checkConversationEntityV4(conversationEntity: ConversationEntity) {
assertEquals("143a9df3", conversationEntity.avatarVersion)
assertEquals(0, conversationEntity.callStartTime)
assertEquals(0, conversationEntity.callRecording)
assertEquals(false, conversationEntity.unreadMentionDirect)
// assertEquals(, conversationEntity.breakoutRoomMode) // Not implemented
// assertEquals(, conversationEntity.breakoutRoomStatus) // Not implemented
assertEquals("away", conversationEntity.status)
assertEquals("👻", conversationEntity.statusIcon)
assertEquals("buuuuh", conversationEntity.statusMessage)
assertEquals(null, conversationEntity.statusClearAt)
assertEquals("143a9df3", conversationEntity.avatarVersion)
// assertEquals("", conversationEntity.isCustomAvatar) // Not implemented
assertEquals(0, conversationEntity.callStartTime)
assertEquals(0, conversationEntity.callRecording)
// assertEquals("", conversationEntity.recordingConsent) // Not implemented
// assertEquals("", conversationEntity.mentionPermissions) // Not implemented
// assertEquals("", conversationEntity.isArchived) // Not implemented
}
private fun checkConversationEntityV1(conversationEntity: ConversationEntity) {
// default values for API_V2 fields
assertEquals(false, conversationEntity.canDeleteConversation)
assertEquals(true, conversationEntity.canLeaveConversation)
// default values for API_V3 fields
assertEquals("", conversationEntity.description)
assertEquals("", conversationEntity.actorType)
assertEquals("", conversationEntity.actorId)
assertEquals(0, conversationEntity.callFlag)
assertEquals(0, conversationEntity.lastCommonReadMessage)
// default values for API_V4 fields
assertEquals("", conversationEntity.avatarVersion)
assertEquals(0, conversationEntity.callStartTime)
assertEquals(0, conversationEntity.callRecording)
assertEquals(false, conversationEntity.unreadMentionDirect)
assertEquals("", conversationEntity.status)
assertEquals("", conversationEntity.statusIcon)
assertEquals("", conversationEntity.statusMessage)
assertEquals(null, conversationEntity.statusClearAt)
assertEquals("", conversationEntity.avatarVersion)
assertEquals(0, conversationEntity.callStartTime)
assertEquals(0, conversationEntity.callRecording)
}
} }

View file

@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors # SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
build: build:
maxIssues: 122 maxIssues: 99
weights: weights:
# complexity: 2 # complexity: 2
# LongParameterList: 1 # LongParameterList: 1
@ -48,7 +48,7 @@ complexity:
active: true active: true
ComplexCondition: ComplexCondition:
active: true active: true
threshold: 4 threshold: 5
ComplexInterface: ComplexInterface:
active: false active: false
threshold: 10 threshold: 10