Skip to content

Commit f4feed3

Browse files
Merge pull request #1836 from nextcloud/declarative-ui
Declarative UI
2 parents 498d2b9 + 8a9afa1 commit f4feed3

File tree

21 files changed

+544
-1
lines changed

21 files changed

+544
-1
lines changed

.idea/codeStyles/Project.xml

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

library/src/androidTest/java/com/owncloud/android/GetCapabilitiesRemoteOperationIT.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.owncloud.android.lib.resources.status.NextcloudVersion;
2424
import com.owncloud.android.lib.resources.status.OCCapability;
2525
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
26+
import com.owncloud.android.lib.resources.status.Type;
2627

2728
import org.junit.Test;
2829

@@ -161,4 +162,17 @@ private void checkCapability(OCCapability capability, String userId) {
161162
assertTrue(capability.isWCFEnabled().isFalse());
162163
}
163164
}
165+
166+
@Test
167+
public void testClientIntegration() {
168+
// get capabilities
169+
RemoteOperationResult<OCCapability> result = new GetCapabilitiesRemoteOperation().execute(nextcloudClient);
170+
assertTrue(result.isSuccess());
171+
assertNotNull(result.getResultData());
172+
173+
OCCapability capability = result.getResultData();
174+
175+
assertEquals(1, capability.getClientIntegrationEndpoints(Type.CONTEXT_MENU, "application/pdf").size());
176+
assertEquals(0, capability.getClientIntegrationEndpoints(Type.CREATE_NEW, "").size());
177+
}
164178
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Nextcloud Android Library
3+
*
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-FileCopyrightText: 2025 Tobias Kaminsky <[email protected]>
6+
* SPDX-License-Identifier: MIT
7+
*/
8+
9+
package com.nextcloud.android.lib.resources.clientintegration
10+
11+
import com.google.gson.annotations.SerializedName
12+
13+
data class App(
14+
val version: Double,
15+
@SerializedName("context-menu")
16+
val contextMenu: List<Endpoint>,
17+
@SerializedName("create-new")
18+
val createNew: List<Endpoint>
19+
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Nextcloud Android Library
3+
*
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-FileCopyrightText: 2025 Tobias Kaminsky <[email protected]>
6+
* SPDX-License-Identifier: MIT
7+
*/
8+
9+
package com.nextcloud.android.lib.resources.clientintegration
10+
11+
import android.os.Parcelable
12+
import kotlinx.parcelize.Parcelize
13+
14+
@Parcelize
15+
data class ClientIntegrationUI(
16+
val version: Double,
17+
val root: Layout?
18+
) : Parcelable
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Nextcloud Android Library
3+
*
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-FileCopyrightText: 2025 Tobias Kaminsky <[email protected]>
6+
* SPDX-License-Identifier: MIT
7+
*/
8+
9+
package com.nextcloud.android.lib.resources.clientintegration
10+
11+
import android.os.Parcelable
12+
13+
interface Element : Parcelable
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Nextcloud Android Library
3+
*
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-FileCopyrightText: 2025 Tobias Kaminsky <[email protected]>
6+
* SPDX-License-Identifier: MIT
7+
*/
8+
9+
package com.nextcloud.android.lib.resources.clientintegration
10+
11+
import com.google.gson.Gson
12+
import com.google.gson.JsonDeserializationContext
13+
import com.google.gson.JsonDeserializer
14+
import com.google.gson.JsonElement
15+
import com.google.gson.JsonParseException
16+
import com.google.gson.JsonSerializationContext
17+
import com.google.gson.JsonSerializer
18+
import java.lang.reflect.Type
19+
20+
class ElementTypeAdapter :
21+
JsonSerializer<Element>,
22+
JsonDeserializer<Element> {
23+
override fun serialize(
24+
src: Element,
25+
type: Type,
26+
context: JsonSerializationContext
27+
): JsonElement {
28+
// needs to be a new Gson instance, otherwise we end up in a loop
29+
val element = Gson().toJsonTree(src)
30+
element.asJsonObject.addProperty("element", src.javaClass.name)
31+
32+
return element
33+
}
34+
35+
@Throws(JsonParseException::class, ClassNotFoundException::class, Throwable::class)
36+
override fun deserialize(
37+
json: JsonElement,
38+
type: Type,
39+
context: JsonDeserializationContext
40+
): Element? {
41+
val jsonObject = json.asJsonObject
42+
val typeName = jsonObject.get("element").asString
43+
44+
try {
45+
val prefix = "com.nextcloud.android.lib.resources.clientintegration"
46+
val cls: Class<out Element> =
47+
when (typeName) {
48+
"Button" ->
49+
Class.forName("$prefix.LayoutButton") as Class<out Element>
50+
51+
"Text" ->
52+
Class.forName("$prefix.LayoutText") as Class<out Element>
53+
54+
"Image" ->
55+
Class.forName("$prefix.LayoutImage") as Class<out Element>
56+
57+
"URL" ->
58+
Class.forName("$prefix.LayoutURL") as Class<out Element>
59+
60+
else -> return null
61+
}
62+
63+
return Gson().fromJson(json, cls)
64+
} catch (e: ClassNotFoundException) {
65+
throw JsonParseException(e)
66+
}
67+
}
68+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Nextcloud Android Library
3+
*
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-FileCopyrightText: 2025 Tobias Kaminsky <[email protected]>
6+
* SPDX-License-Identifier: MIT
7+
*/
8+
9+
package com.nextcloud.android.lib.resources.clientintegration
10+
11+
import android.os.Parcelable
12+
import com.google.gson.annotations.SerializedName
13+
import com.owncloud.android.lib.resources.status.Method
14+
import kotlinx.parcelize.Parcelize
15+
16+
@Parcelize
17+
data class Endpoint(
18+
val name: String,
19+
val url: String,
20+
var method: Method?,
21+
@SerializedName("mimetype_filters")
22+
val mimetypeFilter: String?,
23+
val params: Map<String, String>?,
24+
val icon: String?
25+
) : Parcelable
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Nextcloud Android Library
3+
*
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-FileCopyrightText: 2025 Tobias Kaminsky <[email protected]>
6+
* SPDX-License-Identifier: MIT
7+
*/
8+
9+
package com.nextcloud.android.lib.resources.clientintegration
10+
11+
import android.os.Parcelable
12+
import com.google.gson.annotations.SerializedName
13+
import kotlinx.parcelize.Parcelize
14+
15+
@Parcelize
16+
data class Layout(
17+
@SerializedName("orientation")
18+
var orientation: LayoutOrientation,
19+
var rows: List<LayoutRow>
20+
) : Parcelable
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Nextcloud Android Library
3+
*
4+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-FileCopyrightText: 2025 Tobias Kaminsky <[email protected]>
6+
* SPDX-License-Identifier: MIT
7+
*/
8+
9+
package com.nextcloud.android.lib.resources.clientintegration
10+
11+
import android.os.Parcelable
12+
import kotlinx.parcelize.Parcelize
13+
14+
@Parcelize
15+
data class LayoutButton(
16+
val label: String,
17+
val type: String
18+
) : Element,
19+
Parcelable
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Nextcloud Android Library
3+
*
4+
* SPDX-FileCopyrightText: 2025 Alper Ozturk <[email protected]>
5+
* SPDX-License-Identifier: MIT
6+
*/
7+
8+
package com.nextcloud.android.lib.resources.clientintegration
9+
10+
import android.os.Parcelable
11+
import kotlinx.parcelize.Parcelize
12+
13+
@Parcelize
14+
data class LayoutImage(
15+
val url: String
16+
) : Element,
17+
Parcelable

0 commit comments

Comments
 (0)