Skip to content
Draft
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
35 changes: 35 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ public static File extractAsset(String fileName, Context context) throws IOExcep

@After
public void after() {
removeOnClient(client);
removeOnClient(client2);
// removeOnClient(client);
// removeOnClient(client2);
}

private void removeOnClient(OwnCloudClient client) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,24 @@
*/
package com.owncloud.android;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.resources.status.CapabilityBooleanType;
import com.owncloud.android.lib.resources.status.E2EVersion;
import com.owncloud.android.lib.resources.status.GetCapabilitiesRemoteOperation;
import com.owncloud.android.lib.resources.status.NextcloudVersion;
import com.owncloud.android.lib.resources.status.OCCapability;
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import com.owncloud.android.lib.resources.status.Type;

import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

/**
* Class to test GetRemoteCapabilitiesOperation
*/
Expand Down Expand Up @@ -165,4 +166,17 @@ private void checkCapability(OCCapability capability, String userId) {
assertTrue(capability.getUserStatusSupportsBusy().isTrue());
}
}

@Test
public void testClientIntegration() {
// get capabilities
RemoteOperationResult result = new GetCapabilitiesRemoteOperation().execute(nextcloudClient);
assertTrue(result.isSuccess());
assertNotNull(result.getSingleData());

OCCapability capability = (OCCapability) result.getSingleData();

assertEquals(5, capability.getClientIntegrationEndpoints(Type.CONTEXT_MENU, "").size());
assertEquals(2, capability.getClientIntegrationEndpoints(Type.CREATE_NEW, "").size());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Nextcloud Android Library
*
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2025 Tobias Kaminsky <[email protected]>
* SPDX-License-Identifier: MIT
*/

package com.nextcloud.android.lib.resources.clientintegration

import com.google.gson.annotations.SerializedName

data class App(
val version: Double,
@SerializedName("context-menu")
val contextMenu: List<Endpoint>,
@SerializedName("create-new")
val createNew: List<Endpoint>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.android.lib.resources.clientintegration

data class Button(
val label: String,
val type: String
) : Element
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.android.lib.resources.clientintegration

data class ClientIntegrationUI(
val version: Double,
val root: Layout
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Nextcloud Android Library
*
* SPDX-FileCopyrightText: 2025 Your Name <[email protected]>
* SPDX-License-Identifier: MIT
*/

package com.nextcloud.android.lib.resources.clientintegration

interface Element
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.android.lib.resources.clientintegration

import com.google.gson.Gson
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonParseException
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import java.lang.reflect.Type

class ElementTypeAdapter :
JsonSerializer<Element>,
JsonDeserializer<Element> {
override fun serialize(
src: Element,
type: Type,
context: JsonSerializationContext
): JsonElement {
// needs to be a new Gson instance, otherwise we end up in a loop
val element = Gson().toJsonTree(src)
element.asJsonObject.addProperty("element", src.javaClass.name)

return element
}

@Throws(JsonParseException::class, ClassNotFoundException::class, Throwable::class)
override fun deserialize(
json: JsonElement,
type: Type,
context: JsonDeserializationContext
): Element? {
val jsonObject = json.asJsonObject
val typeName = jsonObject.get("element").asString

try {
val cls: Class<out Element> =
when (typeName) {
"Button" ->
Class.forName("com.nextcloud.android.lib.resources.clientintegration.Button")
as Class<out Element>

"Text" ->
Class.forName("com.nextcloud.android.lib.resources.clientintegration.Text")
as Class<out Element>

"Image" ->
Class.forName("com.nextcloud.android.lib.resources.clientintegration.Image")
as Class<out Element>

"URL" ->
Class.forName("com.nextcloud.android.lib.resources.clientintegration.URL")
as Class<out Element>

else -> return null
}

return Gson().fromJson(json, cls)
} catch (e: ClassNotFoundException) {
throw JsonParseException(e)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Nextcloud Android Library
*
* SPDX-FileCopyrightText: 2025 Your Name <[email protected]>
* SPDX-License-Identifier: MIT
*/

package com.nextcloud.android.lib.resources.clientintegration

import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import com.owncloud.android.lib.resources.status.Method
import kotlinx.parcelize.Parcelize

@Parcelize
data class Endpoint(
val name: String,
val url: String,
var method: Method?,
@SerializedName("mimetype_filters")
val mimetypeFilter: String?,
val params: Map<String, String>?,
val icon: String?,
val filter: String?
) : Parcelable
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Nextcloud Android Library
*
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2025 Tobias Kaminsky <[email protected]>
* SPDX-License-Identifier: MIT
*/
package com.nextcloud.android.lib.resources.clientintegration

import com.google.gson.GsonBuilder
import com.google.gson.JsonArray
import com.google.gson.reflect.TypeToken
import com.nextcloud.common.NextcloudClient
import com.nextcloud.operations.GetMethod
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.ocs.ServerResponse
import com.owncloud.android.lib.resources.OCSRemoteOperation
import org.apache.commons.httpclient.HttpStatus

/**
* Get client integration
*/
class GetClientIntegrationJsonOperation(
val url: String
) : OCSRemoteOperation<JsonArray>() {
@Suppress("TooGenericExceptionCaught")
override fun run(client: NextcloudClient): RemoteOperationResult<JsonArray> {
var result: RemoteOperationResult<JsonArray>
var getMethod: GetMethod? = null
try {
getMethod =
GetMethod(
client.baseUri.toString() + url + JSON_FORMAT,
true
)
val status = client.execute(getMethod)
if (status == HttpStatus.SC_OK) {
val terms =
getServerResponse(
getMethod,
object : TypeToken<ServerResponse<JsonArray>>() {}
)?.ocs?.data

val json = parseResult(getMethod.getResponseBodyAsString())

if (terms != null) {
result = RemoteOperationResult(true, getMethod)
result.resultData = terms
} else {
result = RemoteOperationResult(false, getMethod)
}
} else {
result = RemoteOperationResult(false, getMethod)
}
} catch (e: Exception) {
result = RemoteOperationResult(e)
Log_OC.e(
TAG,
"Get client integration failed: " + result.logMessage,
result.exception
)
} finally {
getMethod?.releaseConnection()
}
return result
}

fun parseResult(response: String): ClientIntegrationUI {
val gson =
GsonBuilder()
.registerTypeHierarchyAdapter(Element::class.java, ElementTypeAdapter())
.create()

return gson.fromJson(response, ClientIntegrationUI::class.java)
}

companion object {
private val TAG = GetClientIntegrationJsonOperation::class.java.simpleName
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.android.lib.resources.clientintegration

data class Image(
val url: String
) : Element
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Nextcloud Android Library
*
* SPDX-FileCopyrightText: 2025 Your Name <[email protected]>
* SPDX-License-Identifier: MIT
*/

package com.nextcloud.android.lib.resources.clientintegration

import com.google.gson.annotations.SerializedName

data class Layout(
@SerializedName("orientation")
var orientation: Orientation,
var rows: List<Row>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Your Name <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.android.lib.resources.clientintegration

import com.google.gson.annotations.SerializedName

enum class Orientation {
@SerializedName("horizontal")
HORIZONTAL,

@SerializedName("vertical")
VERTICAL
}
Loading