Skip to content

Commit

Permalink
Merge pull request #1263 from nextcloud/feature/live-photo-impl
Browse files Browse the repository at this point in the history
Feature Live Photo
  • Loading branch information
tobiasKaminsky authored Dec 4, 2023
2 parents e34a5df + b3f2a36 commit df8e9ec
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,51 @@ class ReadFileRemoteOperationIT : AbstractIT() {
assertEquals(remotePath, (result.data[0] as RemoteFile).remotePath)
}

@Test
fun testLivePhoto() {
testOnlyOnServer(NextcloudVersion.nextcloud_28)

val movieFile = createFile("sample")
val movieFilePath = "/sampleMovie.mov"
assertTrue(
UploadFileRemoteOperation(movieFile, movieFilePath, "video/mov", RANDOM_MTIME)
.execute(client).isSuccess
)

val livePhoto = createFile("sample")
val livePhotoPath = "/samplePic.jpg"
assertTrue(
UploadFileRemoteOperation(livePhoto, livePhotoPath, "image/jpeg", RANDOM_MTIME)
.execute(client).isSuccess
)

// link them
assertTrue(
LinkLivePhotoRemoteOperation(
livePhotoPath,
movieFilePath
).execute(client).isSuccess
)

assertTrue(
LinkLivePhotoRemoteOperation(
movieFilePath,
livePhotoPath
).execute(client).isSuccess
)

val movieFileResult = ReadFileRemoteOperation(movieFilePath).execute(client)
assertTrue(movieFileResult.isSuccess)
val movieRemoteFile = movieFileResult.data[0] as RemoteFile

val livePhotoResult = ReadFileRemoteOperation(livePhotoPath).execute(client)
assertTrue(livePhotoResult.isSuccess)
val livePhotoRemoteFile = livePhotoResult.data[0] as RemoteFile

assertEquals(livePhotoRemoteFile.livePhoto, movieRemoteFile.remotePath)
assertTrue(movieRemoteFile.hidden)
}

@Test
fun readRemoteFile() {
// create file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ class WebdavEntry constructor(ms: MultiStatusResponse, splitElement: String) {
var tags = arrayOfNulls<String>(0)
var imageDimension: ImageDimension? = null
var geoLocation: GeoLocation? = null
var hidden = false
private set
var livePhoto: String? = null
private set

private val gson = Gson()

Expand Down Expand Up @@ -461,6 +465,21 @@ class WebdavEntry constructor(ms: MultiStatusResponse, splitElement: String) {
GeoLocation(latitude, longitude)
}

// NC metadata live photo property: <nc:metadata-files-live-photo/>
prop = propSet[EXTENDED_PROPERTY_METADATA_LIVE_PHOTO, ncNamespace]
if (prop != null && prop.value != null) {
livePhoto = prop.value.toString()
}

// NC has hidden property <nc:hidden>
prop = propSet[EXTENDED_PROPERTY_HIDDEN, ncNamespace]
hidden =
if (prop != null) {
java.lang.Boolean.valueOf(prop.value.toString())
} else {
false
}

parseLockProperties(ncNamespace, propSet)
} else {
Log_OC.e("WebdavEntry", "General error, no status for webdav response")
Expand Down Expand Up @@ -619,6 +638,9 @@ class WebdavEntry constructor(ms: MultiStatusResponse, splitElement: String) {
const val EXTENDED_PROPERTY_METADATA_SIZE = "file-metadata-size"
const val EXTENDED_PROPERTY_METADATA_GPS = "file-metadata-gps"

const val EXTENDED_PROPERTY_HIDDEN = "hidden"
const val EXTENDED_PROPERTY_METADATA_LIVE_PHOTO = "metadata-files-live-photo"

const val EXTENDED_PROPERTY_METADATA_PHOTOS_SIZE = "metadata-photos-size"
const val EXTENDED_PROPERTY_METADATA_PHOTOS_GPS = "metadata-photos-gps"
const val TRASHBIN_FILENAME = "trashbin-filename"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ public static DavPropertyNameSet getAllPropSet() {
propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_GPS, ncNamespace);
propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_PHOTOS_SIZE, ncNamespace);
propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_PHOTOS_GPS, ncNamespace);
propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_LIVE_PHOTO, ncNamespace);
propSet.add(WebdavEntry.EXTENDED_PROPERTY_HIDDEN, ncNamespace);

return propSet;
}
Expand Down Expand Up @@ -173,6 +175,8 @@ public static DavPropertyNameSet getFilePropSet() {
propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_GPS, ncNamespace);
propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_PHOTOS_SIZE, ncNamespace);
propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_PHOTOS_GPS, ncNamespace);
propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_LIVE_PHOTO, ncNamespace);
propSet.add(WebdavEntry.EXTENDED_PROPERTY_HIDDEN, ncNamespace);

return propSet;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* Nextcloud Android Library is available under MIT license
*
* @author Tobias Kaminsky
* Copyright (C) 2018 Tobias Kaminsky
* Copyright (C) 2018 Nextcloud GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/

package com.owncloud.android.lib.resources.files

import com.owncloud.android.lib.common.OwnCloudClient
import com.owncloud.android.lib.common.network.WebdavEntry
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import org.apache.commons.httpclient.HttpStatus
import org.apache.jackrabbit.webdav.client.methods.PropPatchMethod
import org.apache.jackrabbit.webdav.property.DavPropertyNameSet
import org.apache.jackrabbit.webdav.property.DavPropertySet
import org.apache.jackrabbit.webdav.property.DefaultDavProperty
import org.apache.jackrabbit.webdav.xml.Namespace
import java.io.IOException

/**
* Links live photos
*/
class LinkLivePhotoRemoteOperation(
private val path: String,
private val linkedFileName: String
) : RemoteOperation<Void>() {
@Deprecated("Deprecated in Java")
override fun run(client: OwnCloudClient): RemoteOperationResult<Void> {
var result: RemoteOperationResult<Void>
lateinit var propPatchMethod: PropPatchMethod
val newProps = DavPropertySet()
val removeProperties = DavPropertyNameSet()
val readMarkerProperty =
DefaultDavProperty(
"nc:metadata-files-live-photo",
linkedFileName,
Namespace.getNamespace(WebdavEntry.NAMESPACE_NC)
)
newProps.add(readMarkerProperty)

val commentsPath = client.getFilesDavUri(path)
try {
propPatchMethod = PropPatchMethod(commentsPath, newProps, removeProperties)
val status = client.executeMethod(propPatchMethod)
val isSuccess =
status == HttpStatus.SC_NO_CONTENT || status == HttpStatus.SC_OK || status == HttpStatus.SC_MULTI_STATUS
result =
if (isSuccess) {
RemoteOperationResult<Void>(true, status, propPatchMethod.responseHeaders)
} else {
client.exhaustResponse(propPatchMethod.responseBodyAsStream)
RemoteOperationResult<Void>(false, status, propPatchMethod.responseHeaders)
}
} catch (e: IOException) {
result = RemoteOperationResult<Void>(e)
} finally {
propPatchMethod.releaseConnection()
}
return result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class RemoteFile : Parcelable, Serializable {
var tags: Array<String?>? = null
var imageDimension: ImageDimension? = null
var geoLocation: GeoLocation? = null
var hidden = false
var livePhoto: String? = null

constructor() {
resetData()
Expand All @@ -85,7 +87,7 @@ class RemoteFile : Parcelable, Serializable {
*/
constructor(path: String?) {
resetData()
require(!(path == null || path.isEmpty() || !path.startsWith(FileUtils.PATH_SEPARATOR))) {
require(!(path.isNullOrEmpty() || !path.startsWith(FileUtils.PATH_SEPARATOR))) {
"Trying to create a OCFile with a non valid remote path: $path"
}
remotePath = path
Expand Down Expand Up @@ -123,6 +125,8 @@ class RemoteFile : Parcelable, Serializable {
tags = we.tags
imageDimension = we.imageDimension
geoLocation = we.geoLocation
livePhoto = we.livePhoto
hidden = we.hidden
}

/**
Expand Down Expand Up @@ -153,6 +157,8 @@ class RemoteFile : Parcelable, Serializable {
lockTimeout = 0
lockToken = null
tags = null
hidden = false
livePhoto = null
}

/**
Expand Down Expand Up @@ -191,6 +197,8 @@ class RemoteFile : Parcelable, Serializable {
lockTimestamp = source.readLong()
lockTimeout = source.readLong()
lockToken = source.readString()
livePhoto = source.readString()
hidden = source.readInt() == 1
}

override fun describeContents(): Int {
Expand Down Expand Up @@ -227,6 +235,8 @@ class RemoteFile : Parcelable, Serializable {
dest.writeLong(lockTimestamp)
dest.writeLong(lockTimeout)
dest.writeString(lockToken)
dest.writeString(livePhoto)
dest.writeInt(if (hidden) 1 else 0)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class NextcloudVersion : OwnCloudVersion {

@JvmField
val nextcloud_27 = NextcloudVersion(0x1B000000) // 27.0

@JvmField
val nextcloud_28 = NextcloudVersion(0x1C000000) // 28.0
}

constructor(string: String) : super(string)
Expand Down

0 comments on commit df8e9ec

Please sign in to comment.