Skip to content

Commit d51f23a

Browse files
committed
feat: implement methods and network operation to edit a space public link (password not included)
1 parent 98e2db2 commit d51f23a

File tree

13 files changed

+222
-3
lines changed

13 files changed

+222
-3
lines changed

owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import com.owncloud.android.domain.files.usecases.SortFilesUseCase
8080
import com.owncloud.android.domain.files.usecases.SortFilesWithSyncInfoUseCase
8181
import com.owncloud.android.domain.files.usecases.UpdateAlreadyDownloadedFilesPathUseCase
8282
import com.owncloud.android.domain.links.usecases.AddLinkUseCase
83+
import com.owncloud.android.domain.links.usecases.EditLinkUseCase
8384
import com.owncloud.android.domain.links.usecases.RemoveLinkUseCase
8485
import com.owncloud.android.domain.members.usecases.AddMemberUseCase
8586
import com.owncloud.android.domain.members.usecases.EditMemberUseCase
@@ -321,5 +322,6 @@ val useCaseModule = module {
321322

322323
// Links
323324
factoryOf(::AddLinkUseCase)
325+
factoryOf(::EditLinkUseCase)
324326
factoryOf(::RemoveLinkUseCase)
325327
}

owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/links/AddPublicLinkFragment.kt

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,16 @@ class AddPublicLinkFragment: Fragment(), SetPasswordDialogFragment.SetPasswordLi
136136
}
137137
}
138138

139+
collectLatestLifecycleFlow(spaceLinksViewModel.editLinkResultFlow) { event ->
140+
event?.peekContent()?.let { uiResult ->
141+
when (uiResult) {
142+
is UIResult.Loading -> { }
143+
is UIResult.Success -> parentFragmentManager.popBackStack()
144+
is UIResult.Error -> showErrorInSnackbar(R.string.public_link_edit_failed, uiResult.error)
145+
}
146+
}
147+
}
148+
139149
if (editMode) { bindEditMode() }
140150

141151
binding.publicLinkPermissions.apply {
@@ -160,9 +170,12 @@ class AddPublicLinkFragment: Fragment(), SetPasswordDialogFragment.SetPasswordLi
160170
}
161171

162172
binding.createPublicLinkButton.setOnClickListener {
163-
spaceLinksViewModel.createPublicLink(
164-
binding.publicLinkNameEditText.text.toString().ifEmpty { getString(R.string.public_link_default_display_name) }
165-
)
173+
val displayName = binding.publicLinkNameEditText.text.toString().ifEmpty { getString(R.string.public_link_default_display_name) }
174+
if (editMode) {
175+
selectedPublicLink?.let { spaceLinksViewModel.editPublicLink(it.id, displayName) }
176+
} else {
177+
spaceLinksViewModel.createPublicLink(displayName)
178+
}
166179
}
167180
}
168181

owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/links/SpaceLinksViewModel.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.owncloud.android.domain.capabilities.model.OCCapability
2727
import com.owncloud.android.domain.capabilities.usecases.GetStoredCapabilitiesUseCase
2828
import com.owncloud.android.domain.links.model.OCLinkType
2929
import com.owncloud.android.domain.links.usecases.AddLinkUseCase
30+
import com.owncloud.android.domain.links.usecases.EditLinkUseCase
3031
import com.owncloud.android.domain.links.usecases.RemoveLinkUseCase
3132
import com.owncloud.android.domain.spaces.model.OCSpace
3233
import com.owncloud.android.domain.utils.Event
@@ -42,6 +43,7 @@ import kotlinx.coroutines.launch
4243

4344
class SpaceLinksViewModel(
4445
private val addLinkUseCase: AddLinkUseCase,
46+
private val editLinkUseCase: EditLinkUseCase,
4547
private val getStoredCapabilitiesUseCase: GetStoredCapabilitiesUseCase,
4648
private val removeLinkUseCase: RemoveLinkUseCase,
4749
private val accountName: String,
@@ -58,6 +60,9 @@ class SpaceLinksViewModel(
5860
private val _removeLinkResultFlow = MutableSharedFlow<UIResult<Unit>>()
5961
val removeLinkResultFlow: SharedFlow<UIResult<Unit>> = _removeLinkResultFlow
6062

63+
private val _editLinkResultFlow = MutableStateFlow<Event<UIResult<Unit>>?>(null)
64+
val editLinkResultFlow: StateFlow<Event<UIResult<Unit>>?> = _editLinkResultFlow
65+
6166
private var capabilities: OCCapability? = null
6267

6368
init {
@@ -110,6 +115,24 @@ class SpaceLinksViewModel(
110115
)
111116
}
112117

118+
fun editPublicLink(linkId: String, displayName: String) {
119+
_addPublicLinkUIState.value?.selectedPermission?.let {
120+
runUseCaseWithResult(
121+
coroutineDispatcher = coroutineDispatcherProvider.io,
122+
flow = _editLinkResultFlow,
123+
useCase = editLinkUseCase,
124+
useCaseParams = EditLinkUseCase.Params(
125+
accountName = accountName,
126+
spaceId = space.id,
127+
linkId = linkId,
128+
displayName = displayName,
129+
type = it,
130+
expirationDate = _addPublicLinkUIState.value?.selectedExpirationDate,
131+
)
132+
)
133+
}
134+
}
135+
113136
fun checkPasswordEnforced(selectedPermission: OCLinkType) =
114137
when(selectedPermission) {
115138
OCLinkType.CAN_VIEW -> capabilities?.filesSharingPublicPasswordEnforcedReadOnly == CapabilityBooleanType.TRUE
@@ -121,6 +144,7 @@ class SpaceLinksViewModel(
121144
fun resetViewModel() {
122145
_addLinkResultFlow.value = null
123146
_addPublicLinkUIState.value = AddPublicLinkUIState()
147+
_editLinkResultFlow.value = null
124148
}
125149

126150
data class AddPublicLinkUIState(

owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/members/SpaceMembersFragment.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ class SpaceMembersFragment : Fragment(), SpaceMembersAdapter.SpaceMembersAdapter
219219
observeEditMemberResult()
220220
observeAddLinkResult()
221221
observeRemoveLinkResult()
222+
observeEditLinkResult()
222223
}
223224

224225
private fun observeRoles() {
@@ -369,6 +370,21 @@ class SpaceMembersFragment : Fragment(), SpaceMembersAdapter.SpaceMembersAdapter
369370
}
370371
}
371372

373+
private fun observeEditLinkResult() {
374+
collectLatestLifecycleFlow(spaceLinksViewModel.editLinkResultFlow) { event ->
375+
event?.peekContent()?.let { uiResult ->
376+
when (uiResult) {
377+
is UIResult.Loading -> { }
378+
is UIResult.Success -> {
379+
showMessageInSnackbar(getString(R.string.public_link_edit_correctly))
380+
spaceLinksViewModel.resetViewModel()
381+
}
382+
is UIResult.Error -> { }
383+
}
384+
}
385+
}
386+
}
387+
372388
private fun checkPermissions(spacePermissions: List<String>) {
373389
val hasCreatePermission = DRIVES_CREATE_PERMISSION in spacePermissions
374390
canRemoveMembersAndLinks = DRIVES_DELETE_PERMISSION in spacePermissions

owncloudApp/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,8 @@
937937
<string name="public_link_remove_correctly">Public link removed correctly</string>
938938
<string name="public_link_remove_failed">Public link could not be removed</string>
939939
<string name="public_link_edit_title">Edit public link</string>
940+
<string name="public_link_edit_correctly">Public link edited correctly</string>
941+
<string name="public_link_edit_failed">Public link could not be edited</string>
940942

941943
<string name="feedback_dialog_get_in_contact_description"><![CDATA[ Ask for help in our <a href=\"%1$s\"><b>forum</b></a> or contribute in our <a href=\"%2$s\"><b>GitHub repo</b></a>]]></string>
942944

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* ownCloud Android client application
3+
*
4+
* @author Jorge Aguado Recio
5+
*
6+
* Copyright (C) 2026 ownCloud GmbH.
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License version 2,
10+
* as published by the Free Software Foundation.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.owncloud.android.lib.resources.links
22+
23+
import com.owncloud.android.lib.common.OwnCloudClient
24+
import com.owncloud.android.lib.common.http.HttpConstants
25+
import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_JSON
26+
import com.owncloud.android.lib.common.http.methods.nonwebdav.PatchMethod
27+
import com.owncloud.android.lib.common.operations.RemoteOperation
28+
import com.owncloud.android.lib.common.operations.RemoteOperationResult
29+
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode
30+
import okhttp3.MediaType.Companion.toMediaType
31+
import okhttp3.RequestBody.Companion.toRequestBody
32+
import org.json.JSONObject
33+
import timber.log.Timber
34+
import java.net.URL
35+
36+
class EditRemoteLinkOperation(
37+
private val spaceId: String,
38+
private val linkId: String,
39+
private val displayName: String,
40+
private val type: String,
41+
private val expirationDate: String?
42+
): RemoteOperation<Unit>() {
43+
override fun run(client: OwnCloudClient): RemoteOperationResult<Unit> {
44+
var result: RemoteOperationResult<Unit>
45+
try {
46+
val uriBuilder = client.baseUri.buildUpon().apply {
47+
appendEncodedPath(GRAPH_API_DRIVES_PATH)
48+
appendEncodedPath(spaceId)
49+
appendEncodedPath(GRAPH_API_ROOT_PERMISSIONS_PATH)
50+
appendEncodedPath(linkId)
51+
}
52+
53+
val requestBody = JSONObject().apply {
54+
put(EXPIRATION_DATE_BODY_PARAM, expirationDate ?: JSONObject.NULL)
55+
put(LINK_BODY_PARAM, JSONObject().apply {
56+
put(DISPLAY_NAME_BODY_PARAM, displayName)
57+
put(TYPE_BODY_PARAM, type)
58+
})
59+
}.toString().toRequestBody(CONTENT_TYPE_JSON.toMediaType())
60+
61+
val patchMethod = PatchMethod(URL(uriBuilder.build().toString()), requestBody)
62+
63+
val status = client.executeHttpMethod(patchMethod)
64+
65+
val response = patchMethod.getResponseBodyAsString()
66+
67+
if (status == HttpConstants.HTTP_OK) {
68+
Timber.d("Successful response: $response")
69+
result = RemoteOperationResult(ResultCode.OK)
70+
Timber.d("Edit public link operation completed and parsed to ${result.data}")
71+
} else {
72+
result = RemoteOperationResult(patchMethod)
73+
Timber.e("Failed response while editing a public link; status code: $status, response: $response")
74+
}
75+
} catch (e: Exception) {
76+
result = RemoteOperationResult(e)
77+
Timber.e(e, "Exception while editing a public link")
78+
}
79+
return result
80+
}
81+
82+
companion object {
83+
private const val GRAPH_API_DRIVES_PATH = "graph/v1beta1/drives/"
84+
private const val GRAPH_API_ROOT_PERMISSIONS_PATH = "root/permissions"
85+
private const val EXPIRATION_DATE_BODY_PARAM = "expirationDateTime"
86+
private const val LINK_BODY_PARAM = "link"
87+
private const val DISPLAY_NAME_BODY_PARAM = "@libre.graph.displayName"
88+
private const val TYPE_BODY_PARAM = "type"
89+
}
90+
}

owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/links/services/LinksService.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ import com.owncloud.android.lib.resources.Service
2525

2626
interface LinksService: Service {
2727
fun addLink(spaceId: String, displayName: String, type: String, expirationDate: String?, password: String?): RemoteOperationResult<Unit>
28+
fun editLink(spaceId: String, linkId: String, displayName: String, type: String, expirationDate: String?): RemoteOperationResult<Unit>
2829
fun removeLink(spaceId: String, linkId: String): RemoteOperationResult<Unit>
2930
}

owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/links/services/OCLinksService.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ package com.owncloud.android.lib.resources.links.services
2323
import com.owncloud.android.lib.common.OwnCloudClient
2424
import com.owncloud.android.lib.common.operations.RemoteOperationResult
2525
import com.owncloud.android.lib.resources.links.AddRemoteLinkOperation
26+
import com.owncloud.android.lib.resources.links.EditRemoteLinkOperation
2627
import com.owncloud.android.lib.resources.links.RemoveRemoteLinkOperation
2728

2829
class OCLinksService(override val client: OwnCloudClient) : LinksService {
@@ -42,6 +43,21 @@ class OCLinksService(override val client: OwnCloudClient) : LinksService {
4243
password = password
4344
).execute(client)
4445

46+
override fun editLink(
47+
spaceId: String,
48+
linkId: String,
49+
displayName: String,
50+
type: String,
51+
expirationDate: String?
52+
): RemoteOperationResult<Unit> =
53+
EditRemoteLinkOperation(
54+
spaceId = spaceId,
55+
linkId = linkId,
56+
displayName = displayName,
57+
type = type,
58+
expirationDate = expirationDate
59+
).execute(client)
60+
4561
override fun removeLink(spaceId: String, linkId: String): RemoteOperationResult<Unit> =
4662
RemoveRemoteLinkOperation(
4763
spaceId = spaceId,

owncloudData/src/main/java/com/owncloud/android/data/links/datasources/RemoteLinksDataSource.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ import com.owncloud.android.domain.links.model.OCLinkType
2424

2525
interface RemoteLinksDataSource {
2626
fun addLink(accountName: String, spaceId: String, displayName: String, type: OCLinkType, expirationDate: String?, password: String?)
27+
fun editLink(accountName: String, spaceId: String, linkId: String, displayName: String, type: OCLinkType, expirationDate: String?)
2728
fun removeLink(accountName: String, spaceId: String, linkId: String)
2829
}

owncloudData/src/main/java/com/owncloud/android/data/links/datasources/implementation/OCRemoteLinksDataSource.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ class OCRemoteLinksDataSource(
3535
}
3636
}
3737

38+
override fun editLink(accountName: String, spaceId: String, linkId: String, displayName: String, type: OCLinkType, expirationDate: String?) {
39+
executeRemoteOperation {
40+
clientManager.getLinksService(accountName).editLink(spaceId, linkId, displayName, OCLinkType.toString(type), expirationDate)
41+
}
42+
}
43+
3844
override fun removeLink(accountName: String, spaceId: String, linkId: String) {
3945
executeRemoteOperation {
4046
clientManager.getLinksService(accountName).removeLink(spaceId, linkId)

0 commit comments

Comments
 (0)