Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing Add to Notes in Message Actions #3586

Merged
merged 1 commit into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 81 additions & 2 deletions app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2682,8 +2682,9 @@ class ChatActivity :
}
}

private fun uploadFile(fileUri: String, isVoiceMessage: Boolean, caption: String = "") {
private fun uploadFile(fileUri: String, isVoiceMessage: Boolean, caption: String = "", token: String = "") {
var metaData = ""
var room = ""

if (!participantPermissions.hasChatPermission()) {
Log.w(TAG, "uploading file(s) is forbidden because of missing attendee permissions")
Expand All @@ -2698,11 +2699,13 @@ class ChatActivity :
metaData = "{\"caption\":\"$caption\"}"
}

if (token == "") room = roomToken else room = token

try {
require(fileUri.isNotEmpty())
UploadAndShareFilesWorker.upload(
fileUri,
roomToken,
room,
currentConversation?.displayName!!,
metaData
)
Expand Down Expand Up @@ -4171,6 +4174,82 @@ class ChatActivity :
}
}

fun shareToNotes(message: ChatMessage, roomToken: String) {
val apiVersion = ApiUtils.getChatApiVersion(conversationUser, intArrayOf(1))
val type = message.getCalculateMessageType()
var shareUri: Uri? = null
var data: HashMap<String?, String?>?
var metaData: String = ""
var objectId: String = ""
if (message.hasFileAttachment()) {
val filename = message.selectedIndividualHashMap!!["name"]
path = applicationContext.cacheDir.absolutePath + "/" + filename
shareUri = FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID,
File(path)
)

this.grantUriPermission(
applicationContext.packageName,
shareUri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
)
} else if (message.hasGeoLocation()) {
data = message.messageParameters?.get("object")
objectId = data?.get("id")!!
val name = data.get("name")!!
val lat = data.get("latitude")!!
val lon = data.get("longitude")!!
metaData =
"{\"type\":\"geo-location\",\"id\":\"geo:$lat,$lon\",\"latitude\":\"$lat\"," +
"\"longitude\":\"$lon\",\"name\":\"$name\"}"
}

when (type) {
ChatMessage.MessageType.VOICE_MESSAGE -> {
uploadFile(shareUri.toString(), true, token = roomToken)
Snackbar.make(binding.root, R.string.nc_message_sent, Snackbar.LENGTH_SHORT).show()
}
ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE -> {
val caption = if (message.message != "{file}") message.message else ""
if (null != shareUri) {
try {
context.contentResolver.openInputStream(shareUri)?.close()
uploadFile(shareUri.toString(), false, caption!!, roomToken)
Snackbar.make(binding.root, R.string.nc_message_sent, Snackbar.LENGTH_SHORT).show()
} catch (e: java.lang.Exception) {
Log.w(TAG, "File corresponding to the uri does not exist " + shareUri.toString())
downloadFileToCache(message, false) {
uploadFile(shareUri.toString(), false, caption!!, roomToken)
Snackbar.make(binding.root, R.string.nc_message_sent, Snackbar.LENGTH_SHORT).show()
}
}
}
}
ChatMessage.MessageType.SINGLE_NC_GEOLOCATION_MESSAGE -> {
chatViewModel.shareLocationToNotes(
credentials!!,
ApiUtils.getUrlToSendLocation(apiVersion, conversationUser!!.baseUrl, roomToken),
"geo-location",
objectId,
metaData
)
Snackbar.make(binding.root, R.string.nc_message_sent, Snackbar.LENGTH_SHORT).show()
}
ChatMessage.MessageType.REGULAR_TEXT_MESSAGE -> {
chatViewModel.shareToNotes(
credentials!!,
ApiUtils.getUrlForChat(apiVersion, conversationUser!!.baseUrl, roomToken),
message.message!!,
conversationUser!!.displayName!!
)
Snackbar.make(binding.root, R.string.nc_message_sent, Snackbar.LENGTH_SHORT).show()
}
else -> {}
}
}

fun openInFilesApp(message: ChatMessage) {
val keyID = message.selectedIndividualHashMap!![PreviewMessageViewHolder.KEY_ID]
val link = message.selectedIndividualHashMap!!["link"]
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/java/com/nextcloud/talk/chat/data/ChatRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package com.nextcloud.talk.chat.data

import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.models.json.conversations.RoomsOverall
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.reminder.Reminder
import io.reactivex.Observable
Expand All @@ -32,4 +33,18 @@ interface ChatRepository {
fun setReminder(user: User, roomToken: String, messageId: String, timeStamp: Int): Observable<Reminder>
fun getReminder(user: User, roomToken: String, messageId: String): Observable<Reminder>
fun deleteReminder(user: User, roomToken: String, messageId: String): Observable<GenericOverall>
fun shareToNotes(
credentials: String,
url: String,
message: String,
displayName: String
): Observable<GenericOverall> // last two fields are false
fun checkForNoteToSelf(credentials: String, url: String, includeStatus: Boolean): Observable<RoomsOverall>
fun shareLocationToNotes(
credentials: String,
url: String,
objectType: String,
objectId: String,
metadata: String
): Observable<GenericOverall>
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ package com.nextcloud.talk.chat.data
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.models.json.conversations.RoomsOverall
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.reminder.Reminder
import com.nextcloud.talk.utils.ApiUtils
Expand Down Expand Up @@ -83,4 +84,40 @@ class ChatRepositoryImpl(private val ncApi: NcApi) : ChatRepository {
it
}
}

override fun shareToNotes(
credentials: String,
url: String,
message: String,
displayName: String
): Observable<GenericOverall> {
return ncApi.sendChatMessage(
credentials,
url,
message,
displayName,
null,
false
).map {
it
}
}

override fun checkForNoteToSelf(
credentials: String,
url: String,
includeStatus: Boolean
): Observable<RoomsOverall> {
return ncApi.getRooms(credentials, url, includeStatus).map { it }
}

override fun shareLocationToNotes(
credentials: String,
url: String,
objectType: String,
objectId: String,
metadata: String
): Observable<GenericOverall> {
return ncApi.sendLocation(credentials, url, objectType, objectId, metadata).map { it }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import androidx.lifecycle.ViewModel
import com.nextcloud.talk.chat.data.ChatRepository
import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.models.json.conversations.RoomsOverall
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.reminder.Reminder
import com.nextcloud.talk.utils.ConversationUtils
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
Expand All @@ -49,6 +51,13 @@ class ChatViewModel @Inject constructor(private val repository: ChatRepository)
val getReminderExistState: LiveData<ViewState>
get() = _getReminderExistState

object NoteToSelfNotAvaliableState : ViewState
open class NoteToSelfAvaliableState(val roomToken: String) : ViewState

private val _getNoteToSelfAvaliability: MutableLiveData<ViewState> = MutableLiveData(NoteToSelfNotAvaliableState)
val getNoteToSelfAvaliability: LiveData<ViewState>
get() = _getNoteToSelfAvaliability

open class GetRoomSuccessState(val conversationModel: ConversationModel) : ViewState

private val _getRoomViewState: MutableLiveData<ViewState> = MutableLiveData(GetRoomStartState)
Expand Down Expand Up @@ -117,6 +126,58 @@ class ChatViewModel @Inject constructor(private val repository: ChatRepository)
})
}

fun shareToNotes(credentials: String, url: String, message: String, displayName: String) {
repository.shareToNotes(credentials, url, message, displayName)
.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<GenericOverall> {
override fun onSubscribe(d: Disposable) {
// unused atm
}

override fun onNext(genericOverall: GenericOverall) {
// unused atm
}

override fun onError(e: Throwable) {
Log.d(TAG, "Error when sharing to notes $e")
}

override fun onComplete() {
// unused atm
}
})
}

fun checkForNoteToSelf(credentials: String, baseUrl: String, includeStatus: Boolean) {
repository.checkForNoteToSelf(credentials, baseUrl, includeStatus).subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(CheckForNoteToSelfObserver())
}

fun shareLocationToNotes(credentials: String, url: String, objectType: String, objectId: String, metadata: String) {
repository.shareLocationToNotes(credentials, url, objectType, objectId, metadata)
.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<GenericOverall> {
override fun onSubscribe(d: Disposable) {
// unused atm
}

override fun onNext(genericOverall: GenericOverall) {
// unused atm
}

override fun onError(e: Throwable) {
Log.e(TAG, "Error when sharing location to notes $e")
}

override fun onComplete() {
// unused atm
}
})
}

inner class GetRoomObserver : Observer<ConversationModel> {
override fun onSubscribe(d: Disposable) {
// unused atm
Expand Down Expand Up @@ -192,6 +253,36 @@ class ChatViewModel @Inject constructor(private val repository: ChatRepository)
}
}

inner class CheckForNoteToSelfObserver : Observer<RoomsOverall> {
override fun onSubscribe(d: Disposable) {
// unused atm
}

override fun onNext(roomsOverall: RoomsOverall) {
val rooms = roomsOverall.ocs?.data
rooms?.let {
try {
val noteToSelf = rooms.first {
val model = ConversationModel.mapToConversationModel(it)
ConversationUtils.isNoteToSelfConversation(model)
}
_getNoteToSelfAvaliability.value = NoteToSelfAvaliableState(noteToSelf.token!!)
} catch (e: NoSuchElementException) {
_getNoteToSelfAvaliability.value = NoteToSelfNotAvaliableState
Log.e(TAG, "Note to self not found $e")
}
}
}

override fun onError(e: Throwable) {
Log.d(TAG, "Error when getting rooms for Note to Self Observer $e")
}

override fun onComplete() {
// unused atm
}
}

companion object {
private val TAG = ChatViewModel::class.simpleName
const val JOIN_ROOM_RETRY_COUNT: Long = 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
remotePath
)
} else {
Log.d(TAG, "starting normal upload (not chunked)")
Log.d(TAG, "starting normal upload (not chunked) of $fileName")

uploadSuccess = FileUploader(
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.chat.ChatActivity
import com.nextcloud.talk.chat.viewmodels.ChatViewModel
import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.DialogMessageActionsBinding
import com.nextcloud.talk.models.domain.ConversationModel
Expand All @@ -48,6 +49,8 @@ import com.nextcloud.talk.models.domain.ReactionDeletedModel
import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.repositories.reactions.ReactionsRepository
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ConversationUtils
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
import com.vanniktech.emoji.EmojiPopup
import com.vanniktech.emoji.EmojiTextView
Expand Down Expand Up @@ -96,6 +99,31 @@ class MessageActionsDialog(
viewThemeUtils.platform.themeDialog(dialogMessageActionsBinding.root)
initEmojiBar(hasChatPermission)
initMenuItemCopy(!message.isDeleted)
val apiVersion = ApiUtils.getConversationApiVersion(user, intArrayOf(ApiUtils.APIv4, ApiUtils.APIv3, 1))
chatActivity.chatViewModel.checkForNoteToSelf(
ApiUtils.getCredentials(user!!.username, user.token),
ApiUtils.getUrlForRooms(
apiVersion,
user.baseUrl
),
false
)
chatActivity.chatViewModel.getNoteToSelfAvaliability.observe(this) { state ->
when (state) {
is ChatViewModel.NoteToSelfAvaliableState -> {
initMenuAddToNote(
!message.isDeleted && !ConversationUtils.isNoteToSelfConversation(currentConversation),
state.roomToken
)
}
else -> {
initMenuAddToNote(
false
)
}
}
}

initMenuItemTranslate(
!message.isDeleted &&
ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getCalculateMessageType() &&
Expand Down Expand Up @@ -374,6 +402,16 @@ class MessageActionsDialog(
dialogMessageActionsBinding.menuSaveMessage.visibility = getVisibility(visible)
}

private fun initMenuAddToNote(visible: Boolean, roomToken: String = "") {
if (visible) {
dialogMessageActionsBinding.menuShareToNote.setOnClickListener {
chatActivity.shareToNotes(message, roomToken)
dismiss()
}
}
dialogMessageActionsBinding.menuShareToNote.visibility = getVisibility(visible)
}

private fun getVisibility(visible: Boolean): Int {
return if (visible) {
View.VISIBLE
Expand Down
Loading
Loading