Merge pull request #4544 from nextcloud/style/noid/detekt-improvements

detekt improvements
This commit is contained in:
Andy Scherzinger 2024-12-13 18:52:32 +01:00 committed by GitHub
commit a73099da2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 486 additions and 491 deletions

View File

@ -82,9 +82,8 @@ class OutcomingTextMessageViewHolder(itemView: View) :
itemView itemView
) )
val messageParameters = message.messageParameters
if ( if (
(messageParameters == null || messageParameters.size <= 0) && (message.messageParameters == null || message.messageParameters!!.size <= 0) &&
TextMatchers.isMessageWithSingleEmoticonOnly(message.text) TextMatchers.isMessageWithSingleEmoticonOnly(message.text)
) { ) {
textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat() textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat()
@ -115,13 +114,29 @@ class OutcomingTextMessageViewHolder(itemView: View) :
binding.messageQuote.quotedChatMessageView.visibility = View.GONE binding.messageQuote.quotedChatMessageView.visibility = View.GONE
} }
val readStatusDrawableInt = when (message.readStatus) { setReadStatus(message.readStatus)
itemView.setTag(R.string.replyable_message_view_tag, message.replyable)
Reaction().showReactions(
message,
::clickOnReaction,
::longClickOnReaction,
binding.reactions,
context,
true,
viewThemeUtils
)
}
private fun setReadStatus(readStatus: Enum<ReadStatus>) {
val readStatusDrawableInt = when (readStatus) {
ReadStatus.READ -> R.drawable.ic_check_all ReadStatus.READ -> R.drawable.ic_check_all
ReadStatus.SENT -> R.drawable.ic_check ReadStatus.SENT -> R.drawable.ic_check
else -> null else -> null
} }
val readStatusContentDescriptionString = when (message.readStatus) { val readStatusContentDescriptionString = when (readStatus) {
ReadStatus.READ -> context.resources?.getString(R.string.nc_message_read) ReadStatus.READ -> context.resources?.getString(R.string.nc_message_read)
ReadStatus.SENT -> context.resources?.getString(R.string.nc_message_sent) ReadStatus.SENT -> context.resources?.getString(R.string.nc_message_sent)
else -> null else -> null
@ -135,18 +150,6 @@ class OutcomingTextMessageViewHolder(itemView: View) :
} }
binding.checkMark.contentDescription = readStatusContentDescriptionString binding.checkMark.contentDescription = readStatusContentDescriptionString
itemView.setTag(R.string.replyable_message_view_tag, message.replyable)
Reaction().showReactions(
message,
::clickOnReaction,
::longClickOnReaction,
binding.reactions,
context,
true,
viewThemeUtils
)
} }
private fun longClickOnReaction(chatMessage: ChatMessage) { private fun longClickOnReaction(chatMessage: ChatMessage) {

View File

@ -131,26 +131,7 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) :
} }
}) })
val readStatusDrawableInt = when (message.readStatus) { setReadStatus(message.readStatus)
ReadStatus.READ -> R.drawable.ic_check_all
ReadStatus.SENT -> R.drawable.ic_check
else -> null
}
val readStatusContentDescriptionString = when (message.readStatus) {
ReadStatus.READ -> context?.resources?.getString(R.string.nc_message_read)
ReadStatus.SENT -> context?.resources?.getString(R.string.nc_message_sent)
else -> null
}
readStatusDrawableInt?.let { drawableInt ->
AppCompatResources.getDrawable(context!!, drawableInt)?.let {
binding.checkMark.setImageDrawable(it)
viewThemeUtils.talk.themeMessageCheckMark(binding.checkMark)
}
}
binding.checkMark.contentDescription = readStatusContentDescriptionString
voiceMessageInterface.registerMessageToObservePlaybackSpeedPreferences(message.user.id) { speed -> voiceMessageInterface.registerMessageToObservePlaybackSpeedPreferences(message.user.id) { speed ->
binding.playbackSpeedControlBtn.setSpeed(speed) binding.playbackSpeedControlBtn.setSpeed(speed)
@ -168,6 +149,29 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) :
isBound = true isBound = true
} }
private fun setReadStatus(readStatus: Enum<ReadStatus>) {
val readStatusDrawableInt = when (readStatus) {
ReadStatus.READ -> R.drawable.ic_check_all
ReadStatus.SENT -> R.drawable.ic_check
else -> null
}
val readStatusContentDescriptionString = when (readStatus) {
ReadStatus.READ -> context?.resources?.getString(R.string.nc_message_read)
ReadStatus.SENT -> context?.resources?.getString(R.string.nc_message_sent)
else -> null
}
readStatusDrawableInt?.let { drawableInt ->
AppCompatResources.getDrawable(context!!, drawableInt)?.let {
binding.checkMark.setImageDrawable(it)
viewThemeUtils.talk.themeMessageCheckMark(binding.checkMark)
}
}
binding.checkMark.contentDescription = readStatusContentDescriptionString
}
private fun longClickOnReaction(chatMessage: ChatMessage) { private fun longClickOnReaction(chatMessage: ChatMessage) {
commonMessageInterface.onLongClickReactions(chatMessage) commonMessageInterface.onLongClickReactions(chatMessage)
} }

View File

@ -85,34 +85,7 @@ class SystemMessageViewHolder(itemView: View) : MessageHolders.IncomingTextMessa
binding.systemMessageLayout.visibility = View.VISIBLE binding.systemMessageLayout.visibility = View.VISIBLE
binding.similarMessagesHint.visibility = View.GONE binding.similarMessagesHint.visibility = View.GONE
if (message.expandableParent) { if (message.expandableParent) {
binding.expandCollapseIcon.visibility = View.VISIBLE processExpandableParent(message, messageString)
if (!message.isExpanded) {
val similarMessages = String.format(
sharedApplication!!.resources.getString(R.string.see_similar_system_messages),
message.expandableChildrenAmount
)
binding.messageText.text = messageString
binding.similarMessagesHint.visibility = View.VISIBLE
binding.similarMessagesHint.text = similarMessages
binding.expandCollapseIcon.setImageDrawable(
ContextCompat.getDrawable(context!!, R.drawable.baseline_unfold_more_24)
)
binding.systemMessageLayout.setOnClickListener { systemMessageInterface.expandSystemMessage(message) }
binding.messageText.setOnClickListener { systemMessageInterface.expandSystemMessage(message) }
} else {
binding.messageText.text = messageString
binding.similarMessagesHint.visibility = View.GONE
binding.similarMessagesHint.text = ""
binding.expandCollapseIcon.setImageDrawable(
ContextCompat.getDrawable(context!!, R.drawable.baseline_unfold_less_24)
)
binding.systemMessageLayout.setOnClickListener { systemMessageInterface.collapseSystemMessages() }
binding.messageText.setOnClickListener { systemMessageInterface.collapseSystemMessages() }
}
} else if (message.hiddenByCollapse) { } else if (message.hiddenByCollapse) {
binding.systemMessageLayout.visibility = View.GONE binding.systemMessageLayout.visibility = View.GONE
} else { } else {
@ -131,6 +104,38 @@ class SystemMessageViewHolder(itemView: View) : MessageHolders.IncomingTextMessa
itemView.setTag(R.string.replyable_message_view_tag, message.replyable) itemView.setTag(R.string.replyable_message_view_tag, message.replyable)
} }
@SuppressLint("SetTextI18n", "StringFormatInvalid")
private fun processExpandableParent(message: ChatMessage, messageString: Spannable) {
binding.expandCollapseIcon.visibility = View.VISIBLE
if (!message.isExpanded) {
val similarMessages = String.format(
sharedApplication!!.resources.getString(R.string.see_similar_system_messages),
message.expandableChildrenAmount
)
binding.messageText.text = messageString
binding.similarMessagesHint.visibility = View.VISIBLE
binding.similarMessagesHint.text = similarMessages
binding.expandCollapseIcon.setImageDrawable(
ContextCompat.getDrawable(context!!, R.drawable.baseline_unfold_more_24)
)
binding.systemMessageLayout.setOnClickListener { systemMessageInterface.expandSystemMessage(message) }
binding.messageText.setOnClickListener { systemMessageInterface.expandSystemMessage(message) }
} else {
binding.messageText.text = messageString
binding.similarMessagesHint.visibility = View.GONE
binding.similarMessagesHint.text = ""
binding.expandCollapseIcon.setImageDrawable(
ContextCompat.getDrawable(context!!, R.drawable.baseline_unfold_less_24)
)
binding.systemMessageLayout.setOnClickListener { systemMessageInterface.collapseSystemMessages() }
binding.messageText.setOnClickListener { systemMessageInterface.collapseSystemMessages() }
}
}
fun assignSystemMessageInterface(systemMessageInterface: SystemMessageInterface) { fun assignSystemMessageInterface(systemMessageInterface: SystemMessageInterface) {
this.systemMessageInterface = systemMessageInterface this.systemMessageInterface = systemMessageInterface
} }

View File

@ -3387,8 +3387,6 @@ class ChatActivity :
} }
fun shareToNotes(message: ChatMessage, roomToken: String) { fun shareToNotes(message: ChatMessage, roomToken: String) {
val apiVersion = ApiUtils.getChatApiVersion(spreedCapabilities, intArrayOf(1))
val type = message.getCalculateMessageType()
var shareUri: Uri? = null var shareUri: Uri? = null
val data: HashMap<String?, String?>? val data: HashMap<String?, String?>?
var metaData: String = "" var metaData: String = ""
@ -3418,6 +3416,17 @@ class ChatActivity :
"\"longitude\":\"$lon\",\"name\":\"$name\"}" "\"longitude\":\"$lon\",\"name\":\"$name\"}"
} }
shareToNotes(shareUri, roomToken, message, objectId, metaData)
}
private fun shareToNotes(
shareUri: Uri?,
roomToken: String,
message: ChatMessage,
objectId: String,
metaData: String
) {
val type = message.getCalculateMessageType()
when (type) { when (type) {
ChatMessage.MessageType.VOICE_MESSAGE -> { ChatMessage.MessageType.VOICE_MESSAGE -> {
uploadFile(shareUri.toString(), true, token = roomToken) uploadFile(shareUri.toString(), true, token = roomToken)
@ -3432,7 +3441,7 @@ class ChatActivity :
uploadFile(shareUri.toString(), false, caption!!, roomToken) uploadFile(shareUri.toString(), false, caption!!, roomToken)
Snackbar.make(binding.root, R.string.nc_message_sent, Snackbar.LENGTH_SHORT).show() Snackbar.make(binding.root, R.string.nc_message_sent, Snackbar.LENGTH_SHORT).show()
} catch (e: java.lang.Exception) { } catch (e: java.lang.Exception) {
Log.w(TAG, "File corresponding to the uri does not exist " + shareUri.toString()) Log.w(TAG, "File corresponding to the uri does not exist $shareUri")
downloadFileToCache(message, false) { downloadFileToCache(message, false) {
uploadFile(shareUri.toString(), false, caption!!, roomToken) uploadFile(shareUri.toString(), false, caption!!, roomToken)
Snackbar.make(binding.root, R.string.nc_message_sent, Snackbar.LENGTH_SHORT).show() Snackbar.make(binding.root, R.string.nc_message_sent, Snackbar.LENGTH_SHORT).show()
@ -3442,6 +3451,7 @@ class ChatActivity :
} }
ChatMessage.MessageType.SINGLE_NC_GEOLOCATION_MESSAGE -> { ChatMessage.MessageType.SINGLE_NC_GEOLOCATION_MESSAGE -> {
val apiVersion = ApiUtils.getChatApiVersion(spreedCapabilities, intArrayOf(1))
chatViewModel.shareLocationToNotes( chatViewModel.shareLocationToNotes(
credentials!!, credentials!!,
ApiUtils.getUrlToSendLocation(apiVersion, conversationUser!!.baseUrl!!, roomToken), ApiUtils.getUrlToSendLocation(apiVersion, conversationUser!!.baseUrl!!, roomToken),
@ -3453,6 +3463,7 @@ class ChatActivity :
} }
ChatMessage.MessageType.REGULAR_TEXT_MESSAGE -> { ChatMessage.MessageType.REGULAR_TEXT_MESSAGE -> {
val apiVersion = ApiUtils.getChatApiVersion(spreedCapabilities, intArrayOf(1))
chatViewModel.shareToNotes( chatViewModel.shareToNotes(
credentials!!, credentials!!,
ApiUtils.getUrlForChat(apiVersion, conversationUser!!.baseUrl!!, roomToken), ApiUtils.getUrlForChat(apiVersion, conversationUser!!.baseUrl!!, roomToken),

View File

@ -128,7 +128,7 @@ class MessageInputFragment : Fragment() {
private var mentionAutocomplete: Autocomplete<*>? = null private var mentionAutocomplete: Autocomplete<*>? = null
private var xcounter = 0f private var xcounter = 0f
private var ycounter = 0f private var ycounter = 0f
private var isCollapsed = false private var collapsed = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -219,11 +219,7 @@ class MessageInputFragment : Fragment() {
binding.fragmentCallStarted.callAuthorChipSecondary.text = message.actorDisplayName binding.fragmentCallStarted.callAuthorChipSecondary.text = message.actorDisplayName
val user = userManager.currentUser.blockingGet() val user = userManager.currentUser.blockingGet()
val url: String = if (message.actorType == "guests" || message.actorType == "guest") { val url: String = if (message.actorType == "guests" || message.actorType == "guest") {
ApiUtils.getUrlForGuestAvatar( ApiUtils.getUrlForGuestAvatar(user!!.baseUrl!!, message.actorDisplayName, true)
user!!.baseUrl!!,
message.actorDisplayName,
true
)
} else { } else {
ApiUtils.getUrlForAvatar(user!!.baseUrl!!, message.actorId, false) ApiUtils.getUrlForAvatar(user!!.baseUrl!!, message.actorId, false)
} }
@ -457,20 +453,12 @@ class MessageInputFragment : Fragment() {
} }
binding.fragmentCallStarted.callStartedCloseBtn.setOnClickListener { binding.fragmentCallStarted.callStartedCloseBtn.setOnClickListener {
isCollapsed = !isCollapsed collapsed = !collapsed
if (isCollapsed) { binding.fragmentCallStarted.callAuthorLayout.visibility = if (collapsed) View.GONE else View.VISIBLE
binding.fragmentCallStarted.callAuthorLayout.visibility = View.GONE binding.fragmentCallStarted.callBtnLayout.visibility = if (collapsed) View.GONE else View.VISIBLE
binding.fragmentCallStarted.callBtnLayout.visibility = View.GONE binding.fragmentCallStarted.callAuthorChipSecondary.visibility = if (collapsed) View.VISIBLE else View.GONE
binding.fragmentCallStarted.callAuthorChipSecondary.visibility = View.VISIBLE binding.fragmentCallStarted.callStartedSecondaryText.visibility = if (collapsed) View.VISIBLE else View.GONE
binding.fragmentCallStarted.callStartedSecondaryText.visibility = View.VISIBLE setDropDown(collapsed)
} else {
binding.fragmentCallStarted.callAuthorLayout.visibility = View.VISIBLE
binding.fragmentCallStarted.callBtnLayout.visibility = View.VISIBLE
binding.fragmentCallStarted.callAuthorChipSecondary.visibility = View.GONE
binding.fragmentCallStarted.callStartedSecondaryText.visibility = View.GONE
}
setDropDown(isCollapsed)
} }
} }

View File

@ -506,50 +506,12 @@ class OfflineFirstChatRepository @Inject constructor(
} }
if (result.second.isNotEmpty()) { if (result.second.isNotEmpty()) {
val chatMessagesJson = result.second chatMessagesFromSync = updateMessagesData(
result.second,
handleUpdateMessages(chatMessagesJson) blockContainingQueriedMessage,
lookIntoFuture,
chatMessagesFromSync = chatMessagesJson.map { hasHistory
it.asEntity(currentUser.id!!)
}
chatDao.upsertChatMessages(chatMessagesFromSync)
val oldestIdFromSync = chatMessagesFromSync.minByOrNull { it.id }!!.id
val newestIdFromSync = chatMessagesFromSync.maxByOrNull { it.id }!!.id
Log.d(TAG, "oldestIdFromSync: $oldestIdFromSync")
Log.d(TAG, "newestIdFromSync: $newestIdFromSync")
var oldestMessageIdForNewChatBlock = oldestIdFromSync
var newestMessageIdForNewChatBlock = newestIdFromSync
if (blockContainingQueriedMessage != null) {
if (lookIntoFuture) {
val oldestMessageIdFromBlockOfQueriedMessage = blockContainingQueriedMessage.oldestMessageId
Log.d(TAG, "oldestMessageIdFromBlockOfQueriedMessage: $oldestMessageIdFromBlockOfQueriedMessage")
oldestMessageIdForNewChatBlock = oldestMessageIdFromBlockOfQueriedMessage
} else {
val newestMessageIdFromBlockOfQueriedMessage = blockContainingQueriedMessage.newestMessageId
Log.d(TAG, "newestMessageIdFromBlockOfQueriedMessage: $newestMessageIdFromBlockOfQueriedMessage")
newestMessageIdForNewChatBlock = newestMessageIdFromBlockOfQueriedMessage
}
}
Log.d(TAG, "oldestMessageIdForNewChatBlock: $oldestMessageIdForNewChatBlock")
Log.d(TAG, "newestMessageIdForNewChatBlock: $newestMessageIdForNewChatBlock")
val newChatBlock = ChatBlockEntity(
internalConversationId = internalConversationId,
accountId = conversationModel.accountId,
token = conversationModel.token,
oldestMessageId = oldestMessageIdForNewChatBlock,
newestMessageId = newestMessageIdForNewChatBlock,
hasHistory = hasHistory
) )
chatBlocksDao.upsertChatBlock(newChatBlock)
updateBlocks(newChatBlock)
} else { } else {
Log.d(TAG, "no data is updated...") Log.d(TAG, "no data is updated...")
} }
@ -557,6 +519,57 @@ class OfflineFirstChatRepository @Inject constructor(
return chatMessagesFromSync return chatMessagesFromSync
} }
private suspend fun OfflineFirstChatRepository.updateMessagesData(
chatMessagesJson: List<ChatMessageJson>,
blockContainingQueriedMessage: ChatBlockEntity?,
lookIntoFuture: Boolean,
hasHistory: Boolean
): List<ChatMessageEntity> {
handleUpdateMessages(chatMessagesJson)
val chatMessagesFromSyncToProcess = chatMessagesJson.map {
it.asEntity(currentUser.id!!)
}
chatDao.upsertChatMessages(chatMessagesFromSyncToProcess)
val oldestIdFromSync = chatMessagesFromSyncToProcess.minByOrNull { it.id }!!.id
val newestIdFromSync = chatMessagesFromSyncToProcess.maxByOrNull { it.id }!!.id
Log.d(TAG, "oldestIdFromSync: $oldestIdFromSync")
Log.d(TAG, "newestIdFromSync: $newestIdFromSync")
var oldestMessageIdForNewChatBlock = oldestIdFromSync
var newestMessageIdForNewChatBlock = newestIdFromSync
if (blockContainingQueriedMessage != null) {
if (lookIntoFuture) {
val oldestMessageIdFromBlockOfQueriedMessage = blockContainingQueriedMessage.oldestMessageId
Log.d(TAG, "oldestMessageIdFromBlockOfQueriedMessage: $oldestMessageIdFromBlockOfQueriedMessage")
oldestMessageIdForNewChatBlock = oldestMessageIdFromBlockOfQueriedMessage
} else {
val newestMessageIdFromBlockOfQueriedMessage = blockContainingQueriedMessage.newestMessageId
Log.d(TAG, "newestMessageIdFromBlockOfQueriedMessage: $newestMessageIdFromBlockOfQueriedMessage")
newestMessageIdForNewChatBlock = newestMessageIdFromBlockOfQueriedMessage
}
}
Log.d(TAG, "oldestMessageIdForNewChatBlock: $oldestMessageIdForNewChatBlock")
Log.d(TAG, "newestMessageIdForNewChatBlock: $newestMessageIdForNewChatBlock")
val newChatBlock = ChatBlockEntity(
internalConversationId = internalConversationId,
accountId = conversationModel.accountId,
token = conversationModel.token,
oldestMessageId = oldestMessageIdForNewChatBlock,
newestMessageId = newestMessageIdForNewChatBlock,
hasHistory = hasHistory
)
chatBlocksDao.upsertChatBlock(newChatBlock)
updateBlocks(newChatBlock)
return chatMessagesFromSyncToProcess
}
private suspend fun handleUpdateMessages(messagesJson: List<ChatMessageJson>) { private suspend fun handleUpdateMessages(messagesJson: List<ChatMessageJson>) {
messagesJson.forEach { messageJson -> messagesJson.forEach { messageJson ->
when (messageJson.systemMessageType) { when (messageJson.systemMessageType) {

View File

@ -21,6 +21,7 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.View.GONE import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import androidx.annotation.DrawableRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
@ -204,33 +205,7 @@ class ConversationInfoActivity :
} }
private fun initObservers() { private fun initObservers() {
viewModel.viewState.observe(this) { state -> initViewStateObserver()
when (state) {
is ConversationInfoViewModel.GetRoomSuccessState -> {
conversation = state.conversationModel
viewModel.getCapabilities(conversationUser, conversationToken, conversation!!)
if (ConversationUtils.isNoteToSelfConversation(conversation)) {
binding.shareConversationButton.visibility = GONE
}
val canGeneratePrettyURL = CapabilitiesUtil.canGeneratePrettyURL(conversationUser)
binding.shareConversationButton.setOnClickListener {
ShareUtils.shareConversationLink(
this,
conversationUser.baseUrl,
conversation?.token,
conversation?.name,
canGeneratePrettyURL
)
}
}
is ConversationInfoViewModel.GetRoomErrorState -> {
Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
}
else -> {}
}
}
viewModel.getCapabilitiesViewState.observe(this) { state -> viewModel.getCapabilitiesViewState.observe(this) { state ->
when (state) { when (state) {
@ -289,6 +264,36 @@ class ConversationInfoActivity :
} }
} }
private fun initViewStateObserver() {
viewModel.viewState.observe(this) { state ->
when (state) {
is ConversationInfoViewModel.GetRoomSuccessState -> {
conversation = state.conversationModel
viewModel.getCapabilities(conversationUser, conversationToken, conversation!!)
if (ConversationUtils.isNoteToSelfConversation(conversation)) {
binding.shareConversationButton.visibility = GONE
}
val canGeneratePrettyURL = CapabilitiesUtil.canGeneratePrettyURL(conversationUser)
binding.shareConversationButton.setOnClickListener {
ShareUtils.shareConversationLink(
this,
conversationUser.baseUrl,
conversation?.token,
conversation?.name,
canGeneratePrettyURL
)
}
}
is ConversationInfoViewModel.GetRoomErrorState -> {
Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
}
else -> {}
}
}
}
private fun setupActionBar() { private fun setupActionBar() {
setSupportActionBar(binding.conversationInfoToolbar) setSupportActionBar(binding.conversationInfoToolbar)
binding.conversationInfoToolbar.setNavigationOnClickListener { binding.conversationInfoToolbar.setNavigationOnClickListener {
@ -1330,117 +1335,59 @@ class ConversationInfoActivity :
val userItem = adapter?.getItem(position) as ParticipantItem val userItem = adapter?.getItem(position) as ParticipantItem
val participant = userItem.model val participant = userItem.model
val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4, 1)) val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4, 1))
if (participant.calculatedActorType == USERS && participant.calculatedActorId == conversationUser.userId) { if (participant.calculatedActorType == USERS && participant.calculatedActorId == conversationUser.userId) {
if (participant.attendeePin?.isNotEmpty() == true) { if (participant.attendeePin?.isNotEmpty() == true) {
val items = mutableListOf( launchRemoveAttendeeFromConversationDialog(
BasicListItemWithImage( participant,
R.drawable.ic_lock_grey600_24px, apiVersion,
context.getString(R.string.nc_attendee_pin, participant.attendeePin) context.getString(R.string.nc_attendee_pin, participant.attendeePin),
) R.drawable.ic_lock_grey600_24px
) )
MaterialDialog(this, BottomSheet(WRAP_CONTENT)).show {
cornerRadius(res = R.dimen.corner_radius)
title(text = participant.displayName)
viewThemeUtils.material.colorBottomSheetBackground(this.view)
listItemsWithImage(items = items) { _, index, _ ->
if (index == 0) {
removeAttendeeFromConversation(apiVersion, participant)
}
}
}
} }
return true } else if (participant.type == Participant.ParticipantType.OWNER) {
}
if (participant.type == Participant.ParticipantType.OWNER) {
// Can not moderate owner // Can not moderate owner
return true } else if (participant.calculatedActorType == GROUPS) {
} launchRemoveAttendeeFromConversationDialog(
participant,
if (participant.calculatedActorType == GROUPS) { apiVersion,
val items = mutableListOf( context.getString(R.string.nc_remove_group_and_members)
BasicListItemWithImage(
R.drawable.ic_delete_grey600_24dp,
context.getString(R.string.nc_remove_group_and_members)
)
) )
MaterialDialog(this, BottomSheet(WRAP_CONTENT)).show { } else if (participant.calculatedActorType == CIRCLES) {
cornerRadius(res = R.dimen.corner_radius) launchRemoveAttendeeFromConversationDialog(
participant,
title(text = participant.displayName) apiVersion,
listItemsWithImage(items = items) { _, index, _ -> context.getString(R.string.nc_remove_team_and_members)
if (index == 0) {
removeAttendeeFromConversation(apiVersion, participant)
}
}
}
return true
}
if (participant.calculatedActorType == CIRCLES) {
val items = mutableListOf(
BasicListItemWithImage(
R.drawable.ic_delete_grey600_24dp,
context.getString(R.string.nc_remove_team_and_members)
)
) )
MaterialDialog(this, BottomSheet(WRAP_CONTENT)).show { } else {
cornerRadius(res = R.dimen.corner_radius) launchDefaultActions(participant, apiVersion)
title(text = participant.displayName)
listItemsWithImage(items = items) { _, index, _ ->
if (index == 0) {
removeAttendeeFromConversation(apiVersion, participant)
}
}
}
return true
} }
return true
}
val items = mutableListOf( @SuppressLint("CheckResult")
BasicListItemWithImage( private fun launchDefaultActions(participant: Participant, apiVersion: Int) {
R.drawable.ic_lock_grey600_24px, val items = getDefaultActionItems(participant)
context.getString(R.string.nc_attendee_pin, participant.attendeePin)
),
BasicListItemWithImage(
R.drawable.ic_pencil_grey600_24dp,
context.getString(R.string.nc_promote)
),
BasicListItemWithImage(
R.drawable.ic_pencil_grey600_24dp,
context.getString(R.string.nc_demote)
),
BasicListItemWithImage(
R.drawable.ic_delete_grey600_24dp,
context.getString(R.string.nc_remove_participant)
)
)
if (CapabilitiesUtil.isBanningAvailable(conversationUser.capabilities?.spreedCapability!!)) { if (CapabilitiesUtil.isBanningAvailable(conversationUser.capabilities?.spreedCapability!!)) {
items.add( items.add(BasicListItemWithImage(R.drawable.baseline_block_24, context.getString(R.string.ban_participant)))
BasicListItemWithImage(
R.drawable.baseline_block_24,
context.getString(R.string.ban_participant)
)
)
} }
if (participant.type == Participant.ParticipantType.MODERATOR || when (participant.type) {
participant.type == Participant.ParticipantType.GUEST_MODERATOR Participant.ParticipantType.MODERATOR, Participant.ParticipantType.GUEST_MODERATOR -> {
) { items.removeAt(1)
items.removeAt(1) }
} else if (participant.type == Participant.ParticipantType.USER ||
participant.type == Participant.ParticipantType.GUEST Participant.ParticipantType.USER, Participant.ParticipantType.GUEST -> {
) { items.removeAt(2)
items.removeAt(2) }
} else {
// Self joined users can not be promoted nor demoted else -> {
items.removeAt(2) // Self joined users can not be promoted nor demoted
items.removeAt(1) items.removeAt(2)
items.removeAt(1)
}
} }
if (participant.attendeePin == null || participant.attendeePin!!.isEmpty()) { if (participant.attendeePin == null || participant.attendeePin!!.isEmpty()) {
@ -1483,21 +1430,61 @@ class ConversationInfoActivity :
} }
} }
} }
return true }
@SuppressLint("StringFormatInvalid")
private fun getDefaultActionItems(participant: Participant): MutableList<BasicListItemWithImage> {
val items = mutableListOf(
BasicListItemWithImage(
R.drawable.ic_lock_grey600_24px,
context.getString(R.string.nc_attendee_pin, participant.attendeePin)
),
BasicListItemWithImage(
R.drawable.ic_pencil_grey600_24dp,
context.getString(R.string.nc_promote)
),
BasicListItemWithImage(
R.drawable.ic_pencil_grey600_24dp,
context.getString(R.string.nc_demote)
),
BasicListItemWithImage(
R.drawable.ic_delete_grey600_24dp,
context.getString(R.string.nc_remove_participant)
)
)
return items
}
@SuppressLint("CheckResult")
private fun launchRemoveAttendeeFromConversationDialog(
participant: Participant,
apiVersion: Int,
itemText: String,
@DrawableRes itemIcon: Int = R.drawable.ic_delete_grey600_24dp
) {
val items = mutableListOf(BasicListItemWithImage(itemIcon, itemText))
MaterialDialog(this, BottomSheet(WRAP_CONTENT)).show {
cornerRadius(res = R.dimen.corner_radius)
title(text = participant.displayName)
listItemsWithImage(items = items) { _, index, _ ->
if (index == 0) {
removeAttendeeFromConversation(apiVersion, participant)
}
}
}
} }
private fun MaterialDialog.handleBan(participant: Participant) { private fun MaterialDialog.handleBan(participant: Participant) {
val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4, 1)) val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4, 1))
val binding = DialogBanParticipantBinding.inflate(layoutInflater) val binding = DialogBanParticipantBinding.inflate(layoutInflater)
val actorTypeConverter = EnumActorTypeConverter() val actorTypeConverter = EnumActorTypeConverter()
val dialog = MaterialAlertDialogBuilder(context) val dialog = MaterialAlertDialogBuilder(context).setView(binding.root).create()
.setView(binding.root)
.create()
binding.avatarImage.loadUserAvatar( binding.avatarImage.loadUserAvatar(
conversationUser, conversationUser,
participant.actorId!!, participant.actorId!!,
true, requestBigSize = true,
false ignoreCache = false
) )
binding.displayNameText.text = participant.actorId binding.displayNameText.text = participant.actorId
binding.buttonBan.setOnClickListener { binding.buttonBan.setOnClickListener {

View File

@ -122,6 +122,45 @@ class ConversationInfoEditActivity : BaseActivity() {
} }
private fun initObservers() { private fun initObservers() {
initViewStateObserver()
conversationInfoEditViewModel.renameRoomUiState.observe(this) { uiState ->
when (uiState) {
is ConversationInfoEditViewModel.RenameRoomUiState.None -> {
}
is ConversationInfoEditViewModel.RenameRoomUiState.Success -> {
if (CapabilitiesUtil.isConversationDescriptionEndpointAvailable(spreedCapabilities)) {
saveConversationDescription()
} else {
finish()
}
}
is ConversationInfoEditViewModel.RenameRoomUiState.Error -> {
Snackbar
.make(binding.root, context.getString(R.string.default_error_msg), Snackbar.LENGTH_LONG)
.show()
Log.e(TAG, "Error while saving conversation name", uiState.exception)
}
}
}
conversationInfoEditViewModel.setConversationDescriptionUiState.observe(this) { uiState ->
when (uiState) {
is ConversationInfoEditViewModel.SetConversationDescriptionUiState.None -> {
}
is ConversationInfoEditViewModel.SetConversationDescriptionUiState.Success -> {
finish()
}
is ConversationInfoEditViewModel.SetConversationDescriptionUiState.Error -> {
Snackbar
.make(binding.root, context.getString(R.string.default_error_msg), Snackbar.LENGTH_LONG)
.show()
Log.e(TAG, "Error while saving conversation description", uiState.exception)
}
}
}
}
private fun initViewStateObserver() {
conversationInfoEditViewModel.viewState.observe(this) { state -> conversationInfoEditViewModel.viewState.observe(this) { state ->
when (state) { when (state) {
is ConversationInfoEditViewModel.GetRoomSuccessState -> { is ConversationInfoEditViewModel.GetRoomSuccessState -> {
@ -131,7 +170,7 @@ class ConversationInfoEditActivity : BaseActivity() {
binding.conversationName.setText(conversation!!.displayName) binding.conversationName.setText(conversation!!.displayName)
if (conversation!!.description != null && conversation!!.description!!.isNotEmpty()) { if (conversation!!.description.isNotEmpty()) {
binding.conversationDescription.setText(conversation!!.description) binding.conversationDescription.setText(conversation!!.description)
} }
@ -167,45 +206,6 @@ class ConversationInfoEditActivity : BaseActivity() {
else -> {} else -> {}
} }
} }
conversationInfoEditViewModel.renameRoomUiState.observe(this) { uiState ->
when (uiState) {
is ConversationInfoEditViewModel.RenameRoomUiState.None -> {
}
is ConversationInfoEditViewModel.RenameRoomUiState.Success -> {
if (CapabilitiesUtil.isConversationDescriptionEndpointAvailable(spreedCapabilities)) {
saveConversationDescription()
} else {
finish()
}
}
is ConversationInfoEditViewModel.RenameRoomUiState.Error -> {
Snackbar.make(
binding.root,
context.getString(R.string.default_error_msg),
Snackbar.LENGTH_LONG
).show()
Log.e(TAG, "Error while saving conversation name", uiState.exception)
}
}
}
conversationInfoEditViewModel.setConversationDescriptionUiState.observe(this) { uiState ->
when (uiState) {
is ConversationInfoEditViewModel.SetConversationDescriptionUiState.None -> {
}
is ConversationInfoEditViewModel.SetConversationDescriptionUiState.Success -> {
finish()
}
is ConversationInfoEditViewModel.SetConversationDescriptionUiState.Error -> {
Snackbar.make(
binding.root,
context.getString(R.string.default_error_msg),
Snackbar.LENGTH_LONG
).show()
Log.e(TAG, "Error while saving conversation description", uiState.exception)
}
}
}
} }
private fun setupAvatarOptions() { private fun setupAvatarOptions() {

View File

@ -325,18 +325,12 @@ class ConversationsListActivity :
conversationsListViewModel.getFederationInvitationsViewState.observe(this) { state -> conversationsListViewModel.getFederationInvitationsViewState.observe(this) { state ->
when (state) { when (state) {
is ConversationsListViewModel.GetFederationInvitationsStartState -> { is ConversationsListViewModel.GetFederationInvitationsStartState -> {
binding.conversationListHintInclude.conversationListHintLayout.visibility = binding.conversationListHintInclude.conversationListHintLayout.visibility = View.GONE
View.GONE
} }
is ConversationsListViewModel.GetFederationInvitationsSuccessState -> { is ConversationsListViewModel.GetFederationInvitationsSuccessState -> {
if (state.showInvitationsHint) { binding.conversationListHintInclude.conversationListHintLayout.visibility =
binding.conversationListHintInclude.conversationListHintLayout.visibility = if (state.showInvitationsHint) View.VISIBLE else View.GONE
View.VISIBLE
} else {
binding.conversationListHintInclude.conversationListHintLayout.visibility =
View.GONE
}
} }
is ConversationsListViewModel.GetFederationInvitationsErrorState -> { is ConversationsListViewModel.GetFederationInvitationsErrorState -> {
@ -387,31 +381,35 @@ class ConversationsListActivity :
lifecycleScope.launch { lifecycleScope.launch {
conversationsListViewModel.getRoomsFlow conversationsListViewModel.getRoomsFlow
.onEach { list -> .onEach { list ->
// Update Conversations setConversationList(list)
conversationItems.clear()
conversationItemsWithHeader.clear()
for (conversation in list) {
addToConversationItems(conversation)
}
sortConversations(conversationItems)
sortConversations(conversationItemsWithHeader)
// Filter Conversations
if (!hasFilterEnabled()) filterableConversationItems = conversationItems
filterConversation()
adapter!!.updateDataSet(filterableConversationItems, false)
Handler().postDelayed({ checkToShowUnreadBubble() }, UNREAD_BUBBLE_DELAY.toLong())
// Fetch Open Conversations
val apiVersion = ApiUtils.getConversationApiVersion(
currentUser!!,
intArrayOf(ApiUtils.API_V4, ApiUtils.API_V3, 1)
)
fetchOpenConversations(apiVersion)
}.collect() }.collect()
} }
} }
private fun setConversationList(list: List<ConversationModel>) {
// Update Conversations
conversationItems.clear()
conversationItemsWithHeader.clear()
for (conversation in list) {
addToConversationItems(conversation)
}
sortConversations(conversationItems)
sortConversations(conversationItemsWithHeader)
// Filter Conversations
if (!hasFilterEnabled()) filterableConversationItems = conversationItems
filterConversation()
adapter!!.updateDataSet(filterableConversationItems, false)
Handler().postDelayed({ checkToShowUnreadBubble() }, UNREAD_BUBBLE_DELAY.toLong())
// Fetch Open Conversations
val apiVersion = ApiUtils.getConversationApiVersion(
currentUser!!,
intArrayOf(ApiUtils.API_V4, ApiUtils.API_V3, 1)
)
fetchOpenConversations(apiVersion)
}
private fun hasFilterEnabled(): Boolean { private fun hasFilterEnabled(): Boolean {
for ((k, v) in filterState) { for ((k, v) in filterState) {
if (k != FilterConversationFragment.DEFAULT && v) return true if (k != FilterConversationFragment.DEFAULT && v) return true

View File

@ -282,7 +282,7 @@ class DiagnoseActivity : BaseActivity() {
if (appPreferences.pushToken.isNullOrEmpty()) { if (appPreferences.pushToken.isNullOrEmpty()) {
addValue(context.resources.getString(R.string.nc_diagnose_firebase_push_token_missing)) addValue(context.resources.getString(R.string.nc_diagnose_firebase_push_token_missing))
} else { } else {
addValue("${appPreferences.pushToken.substring(0, 5)}...") addValue("${appPreferences.pushToken.substring(0, PUSH_TOKEN_PREFIX_END)}...")
} }
addKey(context.resources.getString(R.string.nc_diagnose_firebase_push_token_latest_generated)) addKey(context.resources.getString(R.string.nc_diagnose_firebase_push_token_latest_generated))
@ -466,6 +466,7 @@ class DiagnoseActivity : BaseActivity() {
val TAG = DiagnoseActivity::class.java.simpleName val TAG = DiagnoseActivity::class.java.simpleName
private const val MARKDOWN_HEADLINE = "###" private const val MARKDOWN_HEADLINE = "###"
private const val MARKDOWN_BOLD = "**" private const val MARKDOWN_BOLD = "**"
private const val PUSH_TOKEN_PREFIX_END: Int = 5
private const val ORIGINAL_NEXTCLOUD_TALK_APPLICATION_ID = "com.nextcloud.talk2" private const val ORIGINAL_NEXTCLOUD_TALK_APPLICATION_ID = "com.nextcloud.talk2"
} }
} }

View File

@ -292,16 +292,74 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
return hasLinkedAccount return hasLinkedAccount
} }
fun createOps(
cloudId: String,
numbers: MutableList<String>,
displayName: String?
): ArrayList<ContentProviderOperation> {
val ops = ArrayList<ContentProviderOperation>()
val rawContactsUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().build()
val dataUri = ContactsContract.Data.CONTENT_URI.buildUpon().build()
ops.add(
ContentProviderOperation
.newInsert(rawContactsUri)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
.withValue(
ContactsContract.RawContacts.AGGREGATION_MODE,
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT
)
.withValue(ContactsContract.RawContacts.SYNC2, cloudId)
.build()
)
ops.add(
ContentProviderOperation
.newInsert(dataUri)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, numbers[0])
.build()
)
ops.add(
ContentProviderOperation
.newInsert(dataUri)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
.build()
)
ops.add(
ContentProviderOperation
.newInsert(dataUri)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
"vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat"
)
.withValue(ContactsContract.Data.DATA1, cloudId)
.withValue(
ContactsContract.Data.DATA2,
String.format(
context.resources.getString(R.string.nc_phone_book_integration_chat_via),
accountName
)
)
.build()
)
return ops
}
fun createLinkedAccount(lookupKey: String, cloudId: String) { fun createLinkedAccount(lookupKey: String, cloudId: String) {
val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey) val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
val lookupContactUri = ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri) val lookupContactUri = ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri)
val contactCursor = context.contentResolver.query( val contactCursor = context.contentResolver.query(lookupContactUri, null, null, null, null)
lookupContactUri,
null,
null,
null,
null
)
if (contactCursor != null) { if (contactCursor != null) {
if (contactCursor.count > 0) { if (contactCursor.count > 0) {
@ -319,71 +377,14 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
return return
} }
val ops = ArrayList<ContentProviderOperation>() val ops = createOps(cloudId, numbers, displayName)
val rawContactsUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().build()
val dataUri = ContactsContract.Data.CONTENT_URI.buildUpon().build()
ops.add(
ContentProviderOperation
.newInsert(rawContactsUri)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
.withValue(
ContactsContract.RawContacts.AGGREGATION_MODE,
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT
)
.withValue(ContactsContract.RawContacts.SYNC2, cloudId)
.build()
)
ops.add(
ContentProviderOperation
.newInsert(dataUri)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, numbers[0])
.build()
)
ops.add(
ContentProviderOperation
.newInsert(dataUri)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
.build()
)
ops.add(
ContentProviderOperation
.newInsert(dataUri)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
"vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat"
)
.withValue(ContactsContract.Data.DATA1, cloudId)
.withValue(
ContactsContract.Data.DATA2,
String.format(
context.resources.getString(
R.string.nc_phone_book_integration_chat_via
),
accountName
)
)
.build()
)
try { try {
context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops) context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)
} catch (e: OperationApplicationException) { } catch (e: OperationApplicationException) {
Log.e(javaClass.simpleName, "", e) Log.e(TAG, "", e)
} catch (e: RemoteException) { } catch (e: RemoteException) {
Log.e(javaClass.simpleName, "", e) Log.e(TAG, "", e)
} }
Log.d( Log.d(

View File

@ -217,8 +217,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
private fun handleCallPushMessage() { private fun handleCallPushMessage() {
val userBeingCalled = userManager.getUserWithId(signatureVerification.user!!.id!!).blockingGet() val userBeingCalled = userManager.getUserWithId(signatureVerification.user!!.id!!).blockingGet()
fun prepareCallNotificationScreen(conversation: ConversationModel) { fun createBundle(conversation: ConversationModel): Bundle {
val fullScreenIntent = Intent(context, CallNotificationActivity::class.java)
val bundle = Bundle() val bundle = Bundle()
bundle.putString(KEY_ROOM_TOKEN, pushMessage.id) bundle.putString(KEY_ROOM_TOKEN, pushMessage.id)
bundle.putInt(KEY_NOTIFICATION_TIMESTAMP, pushMessage.timestamp.toInt()) bundle.putInt(KEY_NOTIFICATION_TIMESTAMP, pushMessage.timestamp.toInt())
@ -248,6 +247,12 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
BundleKeys.KEY_IS_MODERATOR, BundleKeys.KEY_IS_MODERATOR,
ConversationUtils.isParticipantOwnerOrModerator(conversation) ConversationUtils.isParticipantOwnerOrModerator(conversation)
) )
return bundle
}
fun prepareCallNotificationScreen(conversation: ConversationModel) {
val fullScreenIntent = Intent(context, CallNotificationActivity::class.java)
val bundle = createBundle(conversation)
fullScreenIntent.putExtras(bundle) fullScreenIntent.putExtras(bundle)
fullScreenIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK fullScreenIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
@ -509,6 +514,42 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
val autoCancelOnClick = TYPE_RECORDING != pushMessage.type val autoCancelOnClick = TYPE_RECORDING != pushMessage.type
val notificationBuilder =
createNotificationBuilder(category, contentTitle, contentText, baseUrl, pendingIntent, autoCancelOnClick)
val activeStatusBarNotification = findNotificationForRoom(
context,
signatureVerification.user!!,
pushMessage.id!!
)
// NOTE - systemNotificationId is an internal ID used on the device only.
// It is NOT the same as the notification ID used in communication with the server.
val systemNotificationId: Int =
activeStatusBarNotification?.id ?: calculateCRC32(System.currentTimeMillis().toString()).toInt()
if ((TYPE_CHAT == pushMessage.type || TYPE_REMINDER == pushMessage.type) &&
pushMessage.notificationUser != null
) {
prepareChatNotification(notificationBuilder, activeStatusBarNotification, systemNotificationId)
addReplyAction(notificationBuilder, systemNotificationId)
addMarkAsReadAction(notificationBuilder, systemNotificationId)
}
if (TYPE_RECORDING == pushMessage.type && ncNotification != null) {
addDismissRecordingAvailableAction(notificationBuilder, systemNotificationId, ncNotification)
addShareRecordingToChatAction(notificationBuilder, systemNotificationId, ncNotification)
}
sendNotification(systemNotificationId, notificationBuilder.build())
}
private fun createNotificationBuilder(
category: String,
contentTitle: CharSequence?,
contentText: CharSequence?,
baseUrl: String?,
pendingIntent: PendingIntent?,
autoCancelOnClick: Boolean
): NotificationCompat.Builder {
val notificationBuilder = NotificationCompat.Builder(context!!, "1") val notificationBuilder = NotificationCompat.Builder(context!!, "1")
.setPriority(NotificationCompat.PRIORITY_HIGH) .setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(category) .setCategory(category)
@ -551,30 +592,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
notificationBuilder.setContentIntent(pendingIntent) notificationBuilder.setContentIntent(pendingIntent)
val groupName = signatureVerification.user!!.id.toString() + "@" + pushMessage.id val groupName = signatureVerification.user!!.id.toString() + "@" + pushMessage.id
notificationBuilder.setGroup(calculateCRC32(groupName).toString()) notificationBuilder.setGroup(calculateCRC32(groupName).toString())
val activeStatusBarNotification = findNotificationForRoom( return notificationBuilder
context,
signatureVerification.user!!,
pushMessage.id!!
)
// NOTE - systemNotificationId is an internal ID used on the device only.
// It is NOT the same as the notification ID used in communication with the server.
val systemNotificationId: Int =
activeStatusBarNotification?.id ?: calculateCRC32(System.currentTimeMillis().toString()).toInt()
if ((TYPE_CHAT == pushMessage.type || TYPE_REMINDER == pushMessage.type) &&
pushMessage.notificationUser != null
) {
prepareChatNotification(notificationBuilder, activeStatusBarNotification, systemNotificationId)
addReplyAction(notificationBuilder, systemNotificationId)
addMarkAsReadAction(notificationBuilder, systemNotificationId)
}
if (TYPE_RECORDING == pushMessage.type && ncNotification != null) {
addDismissRecordingAvailableAction(notificationBuilder, systemNotificationId, ncNotification)
addShareRecordingToChatAction(notificationBuilder, systemNotificationId, ncNotification)
}
sendNotification(systemNotificationId, notificationBuilder.build())
} }
private fun getLargeIcon(): Bitmap { private fun getLargeIcon(): Bitmap {

View File

@ -74,33 +74,21 @@ class SaveFileToStorageWorker(val context: Context, workerParameters: WorkerPara
MediaScannerConnection.scanFile(context, arrayOf(cacheFile.absolutePath), null, null) MediaScannerConnection.scanFile(context, arrayOf(cacheFile.absolutePath), null, null)
Handler(Looper.getMainLooper()).post { Handler(Looper.getMainLooper()).post {
Toast.makeText( Toast.makeText(context, R.string.nc_save_success, Toast.LENGTH_SHORT).show()
context,
context.resources.getString(R.string.nc_save_success),
Toast.LENGTH_SHORT
).show()
} }
return Result.success() return Result.success()
} catch (e: IOException) { } catch (e: IOException) {
Log.e(TAG, "Something went wrong when trying to save file to internal storage", e) Log.e(TAG, "Something went wrong when trying to save file to internal storage", e)
Handler(Looper.getMainLooper()).post { Handler(Looper.getMainLooper()).post {
Toast.makeText( Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_SHORT).show()
context,
context.resources.getString(R.string.nc_common_error_sorry),
Toast.LENGTH_SHORT
).show()
} }
return Result.failure() return Result.failure()
} catch (e: NullPointerException) { } catch (e: NullPointerException) {
Log.e(TAG, "Something went wrong when trying to save file to internal storage", e) Log.e(TAG, "Something went wrong when trying to save file to internal storage", e)
Handler(Looper.getMainLooper()).post { Handler(Looper.getMainLooper()).post {
Toast.makeText( Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_SHORT).show()
context,
context.resources.getString(R.string.nc_common_error_sorry),
Toast.LENGTH_SHORT
).show()
} }
return Result.failure() return Result.failure()

View File

@ -110,46 +110,10 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
fileName = FileUtils.getFileName(sourceFileUri, context) fileName = FileUtils.getFileName(sourceFileUri, context)
file = FileUtils.getFileFromUri(context, sourceFileUri) file = FileUtils.getFileFromUri(context, sourceFileUri)
val remotePath = getRemotePath(currentUser) val remotePath = getRemotePath(currentUser)
val uploadSuccess: Boolean
initNotificationSetup() initNotificationSetup()
file?.let { isChunkedUploading = it.length() > CHUNK_UPLOAD_THRESHOLD_SIZE } file?.let { isChunkedUploading = it.length() > CHUNK_UPLOAD_THRESHOLD_SIZE }
if (file == null) { val uploadSuccess: Boolean = uploadFile(sourceFileUri, metaData, remotePath)
uploadSuccess = false
} else if (isChunkedUploading) {
Log.d(TAG, "starting chunked upload because size is " + file!!.length())
initNotificationWithPercentage()
val mimeType = context.contentResolver.getType(sourceFileUri)?.toMediaTypeOrNull()
chunkedFileUploader = ChunkedFileUploader(
okHttpClient,
currentUser,
roomToken,
metaData,
this
)
uploadSuccess = chunkedFileUploader!!.upload(
file!!,
mimeType,
remotePath
)
} else {
Log.d(TAG, "starting normal upload (not chunked) of $fileName")
uploadSuccess = FileUploader(
context,
currentUser,
roomToken,
ncApi
).upload(
sourceFileUri,
fileName,
remotePath,
metaData
).blockingFirst()
}
if (uploadSuccess) { if (uploadSuccess) {
cancelNotification() cancelNotification()
@ -169,16 +133,31 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
} }
} }
private fun uploadFile(sourceFileUri: Uri, metaData: String?, remotePath: String): Boolean {
return if (file == null) {
false
} else if (isChunkedUploading) {
Log.d(TAG, "starting chunked upload because size is " + file!!.length())
initNotificationWithPercentage()
val mimeType = context.contentResolver.getType(sourceFileUri)?.toMediaTypeOrNull()
chunkedFileUploader = ChunkedFileUploader(okHttpClient, currentUser, roomToken, metaData, this)
chunkedFileUploader!!.upload(file!!, mimeType, remotePath)
} else {
Log.d(TAG, "starting normal upload (not chunked) of $fileName")
FileUploader(context, currentUser, roomToken, ncApi)
.upload(sourceFileUri, fileName, remotePath, metaData)
.blockingFirst()
}
}
private fun getRemotePath(currentUser: User): String { private fun getRemotePath(currentUser: User): String {
var remotePath = CapabilitiesUtil.getAttachmentFolder( val remotePath = CapabilitiesUtil.getAttachmentFolder(
currentUser.capabilities!!.spreedCapability!! currentUser.capabilities!!.spreedCapability!!
) + "/" + fileName ) + "/" + fileName
remotePath = RemoteFileUtils.getNewPathIfFileExists( return RemoteFileUtils.getNewPathIfFileExists(ncApi, currentUser, remotePath)
ncApi,
currentUser,
remotePath
)
return remotePath
} }
override fun onTransferProgress(percentage: Int) { override fun onTransferProgress(percentage: Int) {

View File

@ -117,15 +117,14 @@ class PushUtils {
private fun saveKeyToFile(key: Key, path: String): Int { private fun saveKeyToFile(key: Key, path: String): Int {
val encoded = key.encoded val encoded = key.encoded
try { try {
if (!File(path).exists()) { return if (!File(path).exists() && !File(path).createNewFile()) {
if (!File(path).createNewFile()) { -1
return -1 } else {
FileOutputStream(path).use { keyFileOutputStream ->
keyFileOutputStream.write(encoded)
0
} }
} }
FileOutputStream(path).use { keyFileOutputStream ->
keyFileOutputStream.write(encoded)
return 0
}
} catch (e: FileNotFoundException) { } catch (e: FileNotFoundException) {
Log.d(TAG, "Failed to save key to file") Log.d(TAG, "Failed to save key to file")
} catch (e: IOException) { } catch (e: IOException) {

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: 99 maxIssues: 82
weights: weights:
# complexity: 2 # complexity: 2
# LongParameterList: 1 # LongParameterList: 1

View File

@ -1,2 +1,2 @@
DO NOT TOUCH; GENERATED BY DRONE DO NOT TOUCH; GENERATED BY DRONE
<span class="mdl-layout-title">Lint Report: 72 errors and 158 warnings</span> <span class="mdl-layout-title">Lint Report: 71 errors and 158 warnings</span>