diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index c45ce9ecfe8..ef4763fae72 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -33,7 +33,7 @@ jobs: echo "pr=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" echo "repo=${{ github.event.pull_request.head.repo.full_name }}" >> "$GITHUB_OUTPUT" fi - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 with: repository: ${{ steps.get-vars.outputs.repo }} ref: ${{ steps.get-vars.outputs.branch }} diff --git a/.github/workflows/assembleFlavors.yml b/.github/workflows/assembleFlavors.yml index e8820ed8321..0623b59e371 100644 --- a/.github/workflows/assembleFlavors.yml +++ b/.github/workflows/assembleFlavors.yml @@ -19,7 +19,7 @@ jobs: matrix: flavor: [ Generic, Gplay ] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - name: set up JDK 17 uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3.12.0 with: diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index a4f88765f49..6684edf73aa 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -19,7 +19,7 @@ jobs: matrix: task: [ detekt, ktlintCheck ] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - name: Set up JDK 17 uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3.12.0 with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3acb9857357..16ee4b00571 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -26,7 +26,7 @@ jobs: language: [ 'java' ] steps: - name: Checkout repository - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - name: Set Swap Space uses: pierotofy/set-swap-space@49819abfb41bd9b44fb781159c033dba90353a7c # v1.0 with: diff --git a/.github/workflows/command-rebase.yml b/.github/workflows/command-rebase.yml index 2e73d9935df..44c1c583edc 100644 --- a/.github/workflows/command-rebase.yml +++ b/.github/workflows/command-rebase.yml @@ -31,7 +31,7 @@ jobs: reaction-type: "+1" - name: Checkout the latest code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 with: fetch-depth: 0 token: ${{ secrets.COMMAND_BOT_PAT }} diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index b3c59d7508d..fec622d7069 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -18,5 +18,5 @@ jobs: name: "Validation" runs-on: ubuntu-latest steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 # v1.1.0 diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 55da4398f29..c5b076a49e6 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -19,7 +19,7 @@ jobs: - name: Check if secrets are available run: echo "::set-output name=ok::${{ secrets.KS_PASS != '' }}" id: check-secrets - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 if: ${{ steps.check-secrets.outputs.ok == 'true' }} - name: set up JDK 17 uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3.12.0 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index ed0861e453d..b8b36b1241c 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -24,7 +24,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 with: persist-credentials: false diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt index 7b1ef8fc8e7..2bca2977053 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt @@ -138,6 +138,7 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) : message.selectedIndividualHashMap!![KEY_NAME]!!, message.selectedIndividualHashMap!![KEY_ID]!!, message.selectedIndividualHashMap!![KEY_MIMETYPE], + message.openWhenDownloaded, ProgressUi(progressBar, messageText, image) ) } else if (message.getCalculateMessageType() === ChatMessage.MessageType.SINGLE_LINK_GIPHY_MESSAGE) { diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt index 7a695204391..159a99b4168 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -191,7 +191,7 @@ import com.nextcloud.talk.ui.dialog.ShowReactionsDialog import com.nextcloud.talk.ui.recyclerview.MessageSwipeActions import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback import com.nextcloud.talk.utils.ApiUtils -import com.nextcloud.talk.utils.AudioUtils +import com.nextcloud.talk.utils.AudioUtils.audioFileToFloatArray import com.nextcloud.talk.utils.ContactUtils import com.nextcloud.talk.utils.ConversationUtils import com.nextcloud.talk.utils.DateConstants @@ -201,6 +201,7 @@ import com.nextcloud.talk.utils.FileUtils import com.nextcloud.talk.utils.FileViewerUtils import com.nextcloud.talk.utils.ImageEmojiEditText import com.nextcloud.talk.utils.MagicCharPolicy +import com.nextcloud.talk.utils.Mimetype import com.nextcloud.talk.utils.NotificationUtils import com.nextcloud.talk.utils.ParticipantPermissions import com.nextcloud.talk.utils.VibrationUtils @@ -316,6 +317,7 @@ class ChatActivity : var voiceOnly: Boolean = true var isFirstMessagesProcessing = true private var emojiPopup: EmojiPopup? = null + private lateinit var path: String var myFirstMessage: CharSequence? = null var checkingLobbyStatus: Boolean = false @@ -887,7 +889,9 @@ class ChatActivity : } } else { Log.d(TAG, "Downloaded to cache") - downloadFileToCache(message) + downloadFileToCache(message, true) { + setUpWaveform(message) + } } } } @@ -899,7 +903,7 @@ class ChatActivity : message.isDownloadingVoiceMessage = true adapter?.update(message) CoroutineScope(Dispatchers.Default).launch { - val r = AudioUtils.audioFileToFloatArray(file) + val r = audioFileToFloatArray(file) message.voiceMessageFloatArray = r withContext(Dispatchers.Main) { startPlayback(message) @@ -1933,8 +1937,13 @@ class ChatActivity : } @SuppressLint("LongLogTag") - private fun downloadFileToCache(message: ChatMessage) { + private fun downloadFileToCache( + message: ChatMessage, + openWhenDownloaded: Boolean, + funToCallWhenDownloadSuccessful: (() -> Unit) + ) { message.isDownloadingVoiceMessage = true + message.openWhenDownloaded = openWhenDownloaded adapter?.update(message) val baseUrl = message.activeUser!!.baseUrl @@ -1985,8 +1994,7 @@ class ChatActivity : WorkManager.getInstance(context).getWorkInfoByIdLiveData(downloadWorker.id) .observeForever { workInfo: WorkInfo -> if (workInfo.state == WorkInfo.State.SUCCEEDED) { - setUpWaveform(message) - // startPlayback(message) + funToCallWhenDownloadSuccessful() } } } @@ -3997,6 +4005,37 @@ class ChatActivity : startActivity(intent) } + fun share(message: ChatMessage) { + val filename = message.selectedIndividualHashMap!!["name"] + path = applicationContext.cacheDir.absolutePath + "/" + filename + val shareUri = FileProvider.getUriForFile( + this, + BuildConfig.APPLICATION_ID, + File(path) + ) + + val shareIntent: Intent = Intent().apply { + action = Intent.ACTION_SEND + putExtra(Intent.EXTRA_STREAM, shareUri) + type = Mimetype.IMAGE_PREFIX_GENERIC + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + } + startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to))) + } + + fun checkIfSharable(message: ChatMessage) { + val filename = message.selectedIndividualHashMap!!["name"] + path = applicationContext.cacheDir.absolutePath + "/" + filename + val file = File(context.cacheDir, filename!!) + if (file.exists()) { + share(message) + } else { + downloadFileToCache(message, false) { + share(message) + } + } + } + fun openInFilesApp(message: ChatMessage) { val keyID = message.selectedIndividualHashMap!![PreviewMessageViewHolder.KEY_ID] val link = message.selectedIndividualHashMap!!["link"] diff --git a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.kt b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.kt index 0db7ea97bf7..e05fea28b01 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.kt +++ b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.kt @@ -145,7 +145,9 @@ data class ChatMessage( var expandableChildrenAmount: Int = 0, - var hiddenByCollapse: Boolean = false + var hiddenByCollapse: Boolean = false, + + var openWhenDownloaded: Boolean = true ) : Parcelable, MessageContentType, MessageContentType.Image { diff --git a/app/src/main/java/com/nextcloud/talk/shareditems/adapters/SharedItemsViewHolder.kt b/app/src/main/java/com/nextcloud/talk/shareditems/adapters/SharedItemsViewHolder.kt index b011006a427..fb4d97947d6 100644 --- a/app/src/main/java/com/nextcloud/talk/shareditems/adapters/SharedItemsViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/shareditems/adapters/SharedItemsViewHolder.kt @@ -83,7 +83,8 @@ abstract class SharedItemsViewHolder( progressBar, null, image - ) + ), + true ) } @@ -91,7 +92,8 @@ abstract class SharedItemsViewHolder( item.name, item.id, item.mimeType, - FileViewerUtils.ProgressUi(progressBar, null, image) + true, + FileViewerUtils.ProgressUi(progressBar, null, image), ) } diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt index dc95b210a52..9fd90fbcaae 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt @@ -114,6 +114,7 @@ class MessageActionsDialog( message.previousMessageId > NO_PREVIOUS_MESSAGE_ID && ChatMessage.MessageType.SYSTEM_MESSAGE != message.getCalculateMessageType() ) + initMenuShare(ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE == message.getCalculateMessageType()) initMenuItemOpenNcApp( ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE == message.getCalculateMessageType() ) @@ -330,6 +331,15 @@ class MessageActionsDialog( dialogMessageActionsBinding.menuTranslateMessage.visibility = getVisibility(visible) } + private fun initMenuShare(visible: Boolean) { + if (visible) { + dialogMessageActionsBinding.menuShare.setOnClickListener { + chatActivity.checkIfSharable(message) + dismiss() + } + } + dialogMessageActionsBinding.menuShare.visibility = getVisibility(visible) + } private fun initMenuItemOpenNcApp(visible: Boolean) { if (visible) { diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileViewerUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/FileViewerUtils.kt index 611f6d65910..29712b59a73 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/FileViewerUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/FileViewerUtils.kt @@ -95,7 +95,8 @@ class FileViewerUtils(private val context: Context, private val user: User) { path, link, mimetype, - progressUi + progressUi, + message.openWhenDownloaded ) } @@ -104,14 +105,16 @@ class FileViewerUtils(private val context: Context, private val user: User) { path: String, link: String?, mimetype: String?, - progressUi: ProgressUi + progressUi: ProgressUi, + openWhenDownloaded: Boolean ) { if (isSupportedForInternalViewer(mimetype) || canBeHandledByExternalApp(mimetype, fileInfo.fileName)) { openOrDownloadFile( fileInfo, path, mimetype, - progressUi + progressUi, + openWhenDownloaded ) } else if (!link.isNullOrEmpty()) { openFileInFilesApp(link, fileInfo.fileId) @@ -138,7 +141,8 @@ class FileViewerUtils(private val context: Context, private val user: User) { fileInfo: FileInfo, path: String, mimetype: String?, - progressUi: ProgressUi + progressUi: ProgressUi, + openWhenDownloaded: Boolean ) { val file = File(context.cacheDir, fileInfo.fileName) if (file.exists()) { @@ -148,7 +152,8 @@ class FileViewerUtils(private val context: Context, private val user: User) { fileInfo, path, mimetype, - progressUi + progressUi, + openWhenDownloaded ) } } @@ -276,7 +281,8 @@ class FileViewerUtils(private val context: Context, private val user: User) { fileInfo: FileInfo, path: String, mimetype: String?, - progressUi: ProgressUi + progressUi: ProgressUi, + openWhenDownloaded: Boolean ) { // check if download worker is already running val workers = WorkManager.getInstance(context).getWorkInfosByTag(fileInfo.fileId!!) @@ -324,7 +330,8 @@ class FileViewerUtils(private val context: Context, private val user: User) { fileInfo.fileName, mimetype, workInfo!!, - progressUi + progressUi, + openWhenDownloaded ) } } @@ -333,7 +340,8 @@ class FileViewerUtils(private val context: Context, private val user: User) { fileName: String, mimetype: String?, workInfo: WorkInfo, - progressUi: ProgressUi + progressUi: ProgressUi, + openWhenDownloaded: Boolean ) { when (workInfo.state) { WorkInfo.State.RUNNING -> { @@ -347,13 +355,12 @@ class FileViewerUtils(private val context: Context, private val user: User) { } } WorkInfo.State.SUCCEEDED -> { - if (progressUi.previewImage.isShown) { + if (progressUi.previewImage.isShown && openWhenDownloaded) { openFileByMimetype(fileName, mimetype) } else { - Log.d( - TAG, - "file " + fileName + - " was downloaded but it's not opened because view is not shown on screen" + Log.d(TAG, "file " + fileName + + " was downloaded but it's not opened because view is not shown on screen or " + + "openWhenDownloaded is false" ) } progressUi.messageText?.text = fileName @@ -372,6 +379,7 @@ class FileViewerUtils(private val context: Context, private val user: User) { fileName: String, fileId: String, mimeType: String?, + openWhenDownloaded: Boolean, progressUi: ProgressUi ) { val workers = WorkManager.getInstance(context).getWorkInfosByTag(fileId) @@ -390,7 +398,8 @@ class FileViewerUtils(private val context: Context, private val user: User) { fileName, mimeType, info!!, - progressUi + progressUi, + openWhenDownloaded ) } } diff --git a/app/src/main/res/drawable/baseline_unfold_less_24.xml b/app/src/main/res/drawable/baseline_unfold_less_24.xml index 3956a5c3015..550896334c4 100644 --- a/app/src/main/res/drawable/baseline_unfold_less_24.xml +++ b/app/src/main/res/drawable/baseline_unfold_less_24.xml @@ -1,9 +1,8 @@ - + diff --git a/app/src/main/res/drawable/baseline_unfold_more_24.xml b/app/src/main/res/drawable/baseline_unfold_more_24.xml index 3b01290afdf..b8bcbb7ea81 100644 --- a/app/src/main/res/drawable/baseline_unfold_more_24.xml +++ b/app/src/main/res/drawable/baseline_unfold_more_24.xml @@ -1,9 +1,8 @@ - + diff --git a/app/src/main/res/layout/dialog_message_actions.xml b/app/src/main/res/layout/dialog_message_actions.xml index b1f2042bdff..2bb7db056c1 100644 --- a/app/src/main/res/layout/dialog_message_actions.xml +++ b/app/src/main/res/layout/dialog_message_actions.xml @@ -353,6 +353,39 @@ + + + + + + + +