@@ -10,19 +10,23 @@ package com.nextcloud.ui.fileactions
1010import android.content.Context
1111import android.content.Intent
1212import android.content.res.ColorStateList
13- import android.graphics.Color
14- import android.graphics.PorterDuff
13+ import android.graphics.Canvas
1514import android.graphics.Typeface
1615import android.graphics.drawable.Drawable
1716import android.graphics.drawable.PictureDrawable
17+ import android.os.Build
1818import android.os.Bundle
1919import android.text.style.StyleSpan
2020import android.view.LayoutInflater
2121import android.view.View
2222import android.view.ViewGroup
2323import android.widget.Toast
2424import androidx.annotation.IdRes
25+ import androidx.annotation.RequiresApi
2526import androidx.appcompat.content.res.AppCompatResources
27+ import androidx.core.graphics.createBitmap
28+ import androidx.core.graphics.drawable.toDrawable
29+ import androidx.core.net.toUri
2630import androidx.core.os.bundleOf
2731import androidx.core.view.isEmpty
2832import androidx.core.view.isVisible
@@ -36,6 +40,9 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
3640import com.google.android.material.bottomsheet.BottomSheetDialogFragment
3741import com.google.gson.Gson
3842import com.google.gson.GsonBuilder
43+ import com.google.gson.JsonElement
44+ import com.google.gson.JsonParser
45+ import com.google.gson.reflect.TypeToken
3946import com.nextcloud.android.common.ui.theme.utils.ColorRole
4047import com.nextcloud.android.lib.resources.clientintegration.ClientIntegrationUI
4148import com.nextcloud.android.lib.resources.clientintegration.Element
@@ -62,6 +69,7 @@ import com.owncloud.android.datamodel.OCFile
6269import com.owncloud.android.datamodel.SyncedFolderProvider
6370import com.owncloud.android.datamodel.ThumbnailsCacheManager
6471import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
72+ import com.owncloud.android.lib.ocs.ServerResponse
6573import com.owncloud.android.lib.resources.files.model.FileLockType
6674import com.owncloud.android.lib.resources.status.Method
6775import com.owncloud.android.ui.activity.ComponentsGetter
@@ -341,6 +349,7 @@ class FileActionsBottomSheet :
341349 return itemBinding.root
342350 }
343351
352+ @RequiresApi(Build .VERSION_CODES .Q )
344353 private fun inflateClientIntegrationActionView (endpoint : Endpoint ): View {
345354 val itemBinding = FileActionsBottomSheetItemBinding .inflate(layoutInflater, binding.fileActionsList, false )
346355 .apply {
@@ -366,16 +375,26 @@ class FileActionsBottomSheet :
366375 val drawable =
367376 GlideHelper .getDrawable(requireContext(), client, client.baseUri.toString() + endpoint.icon)
368377 ?.mutate()
378+
379+ val px = DisplayUtils .convertDpToPixel(
380+ requireContext().resources.getDimension(R .dimen.iconized_single_line_item_icon_size),
381+ requireContext()
382+ )
383+ val returnedBitmap =
384+ createBitmap(drawable?.intrinsicWidth ? : px, drawable?.intrinsicHeight ? : px)
385+
386+ val canvas = Canvas (returnedBitmap)
387+ canvas.drawPicture((drawable as PictureDrawable ).picture)
388+
389+ val d = returnedBitmap.toDrawable(requireContext().resources);
390+
369391 val tintedDrawable = viewThemeUtils.platform.tintDrawable(
370392 requireContext(),
371- drawable ? : AppCompatResources .getDrawable(requireContext(), R .drawable.ic_activity) !!
393+ d
372394 )
373395
374396 withContext(Dispatchers .Main ) {
375- val pd = (tintedDrawable as PictureDrawable )
376- pd.setColorFilter(Color .RED , PorterDuff .Mode .SRC_IN )
377- icon.setImageDrawable(pd)
378- icon.setColorFilter(Color .RED , PorterDuff .Mode .DST_OVER )
397+ icon.setImageDrawable(tintedDrawable)
379398 }
380399 }
381400 } else {
@@ -396,19 +415,17 @@ class FileActionsBottomSheet :
396415 .getNextcloudClientFor(currentUserProvider.user.toOwnCloudAccount(), context)
397416
398417 // construct url
399- var url = client.baseUri.toString() + endpoint.url
400-
418+ var url = (client.baseUri.toString() + endpoint.url).toUri()
419+ .buildUpon()
420+ .appendQueryParameter(" format" , " json" )
421+ .build()
422+ .toString()
423+
424+ // Always replace known placeholder in url
425+ url = url.replace(" {filePath}" , filePath, false )
426+ url = url.replace(" {fileId}" , fileId, false )
427+
401428 val method = when (endpoint.method) {
402- Method .GET -> {
403- endpoint.params!! .forEach {
404- when (it.value) {
405- " {fileId}" -> url = url.replace(it.key, fileId, false )
406- " {filePath}" -> url = url.replace(it.key, filePath, false )
407- }
408- }
409- GetMethod (url, true )
410- }
411-
412429 Method .POST -> {
413430 val requestBody = if (endpoint.params?.isNotEmpty() == true ) {
414431 val jsonRequestBody = JSONRequestBody ()
@@ -433,25 +450,28 @@ class FileActionsBottomSheet :
433450 val result = try {
434451 client.execute(method)
435452 } catch (exception: Exception ) {
436- val e = exception
437- TODO (" Add error handling here" )
453+ activity?.showToast(getString(R .string.failed_to_start_action))
438454 }
439455 val response = method.getResponseBodyAsString()
440456
441- var output: ClientIntegrationUI ? = null
457+ var output: ClientIntegrationUI ?
442458 try {
443459 output = parseClientIntegrationResult(response)
444- startClientIntegration(endpoint, output)
445- } catch (e : Exception ) {
446- try {
460+ if ( output.root != null ) {
461+ startClientIntegration(endpoint, output)
462+ } else {
447463 val tooltipResponse = parseTooltipResult(response)
448464
449465 activity?.showToast(tooltipResponse.tooltip)
450- } catch (e: Exception ) {
451- activity?.showToast(" Failed to start action!" )
452466 }
453- dismiss()
467+ } catch (e: Exception ) {
468+ if (result == 200 ) {
469+ activity?.showToast(getString(R .string.action_triggered))
470+ } else {
471+ activity?.showToast(getString(R .string.failed_to_start_action))
472+ }
454473 }
474+ dismiss()
455475 }
456476 }
457477
@@ -473,11 +493,20 @@ class FileActionsBottomSheet :
473493 .registerTypeHierarchyAdapter(Element ::class .java, ElementTypeAdapter ())
474494 .create()
475495
476- return gson.fromJson(response, ClientIntegrationUI ::class .java)
496+ val element: JsonElement = JsonParser .parseString(response)
497+ return gson
498+ .fromJson(element, object : TypeToken <ServerResponse <ClientIntegrationUI >>() {})
499+ .ocs
500+ .data
477501 }
478502
479- private fun parseTooltipResult (response : String? ): TooltipResponse =
480- Gson ().fromJson(response, TooltipResponse ::class .java)
503+ private fun parseTooltipResult (response : String? ): TooltipResponse {
504+ val element: JsonElement = JsonParser .parseString(response)
505+ return Gson ()
506+ .fromJson(element, object : TypeToken <ServerResponse <TooltipResponse >>() {})
507+ .ocs
508+ .data
509+ }
481510
482511 private fun dispatchActionClick (id : Int? ) {
483512 if (id != null ) {
@@ -491,6 +520,7 @@ class FileActionsBottomSheet :
491520 private const val REQUEST_KEY = " REQUEST_KEY_ACTION"
492521 private const val RESULT_KEY_ACTION_ID = " RESULT_KEY_ACTION_ID"
493522 private const val FILENAME_MAX_WIDTH_PERCENTAGE = 0.6
523+ private const val JSON_FORMAT = " ?format=json"
494524
495525 @JvmStatic
496526 @JvmOverloads
0 commit comments