Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit df8e9ec9 authored by Tobias Kaminsky's avatar Tobias Kaminsky Committed by GitHub
Browse files

Merge pull request #1263 from nextcloud/feature/live-photo-impl

Feature Live Photo 
parents e34a5dfc b3f2a365
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -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
+22 −0
Original line number Diff line number Diff line
@@ -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()

@@ -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")
@@ -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"
+4 −0
Original line number Diff line number Diff line
@@ -130,6 +130,8 @@ public class WebdavUtils {
        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;
    }
@@ -173,6 +175,8 @@ public class WebdavUtils {
        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;
    }
+83 −0
Original line number Diff line number Diff line
/* 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
    }
}
+11 −1
Original line number Diff line number Diff line
@@ -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()
@@ -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
@@ -123,6 +125,8 @@ class RemoteFile : Parcelable, Serializable {
        tags = we.tags
        imageDimension = we.imageDimension
        geoLocation = we.geoLocation
        livePhoto = we.livePhoto
        hidden = we.hidden
    }

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

    /**
@@ -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 {
@@ -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 {
Loading