diff --git a/res/menu/file_actions_menu.xml b/res/menu/file_actions_menu.xml index dcd451c40a..1e78a367fc 100644 --- a/res/menu/file_actions_menu.xml +++ b/res/menu/file_actions_menu.xml @@ -20,7 +20,8 @@ - + + diff --git a/res/values/strings.xml b/res/values/strings.xml index b86d608580..f6871a6a63 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -250,5 +250,6 @@ Sorry, sharing is not enabled on your server. Please contact your administrator. Unable to share this file or folder. Please, make sure it exists An error occurred while trying to share this file or folder + Unable to unshare this file or folder. It does not exist. An error occurred while trying to unshare this file or folder diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index 5604f05be6..a65833cdff 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -1115,8 +1115,22 @@ public class FileDataStorageManager { } } - - + + public void removeShare(OCShare share){ + Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE; + String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?"; + String [] whereArgs = new String[]{mAccount.name, share.getPath()}; + if (getContentProviderClient() != null) { + try { + getContentProviderClient().delete(share_uri, where, whereArgs); + } catch (RemoteException e) { + e.printStackTrace(); + } + } else { + getContentResolver().delete(share_uri, where, whereArgs); + } + } + public void saveSharesDB(ArrayList shares) { saveShares(shares); diff --git a/src/com/owncloud/android/files/FileOperationsHelper.java b/src/com/owncloud/android/files/FileOperationsHelper.java index f02dcde29d..1ddbd4ab39 100644 --- a/src/com/owncloud/android/files/FileOperationsHelper.java +++ b/src/com/owncloud/android/files/FileOperationsHelper.java @@ -30,8 +30,7 @@ import com.owncloud.android.R; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.accounts.AccountUtils.Constants; import com.owncloud.android.lib.common.network.WebdavUtils; -import com.owncloud.android.lib.resources.shares.ShareType; -import com.owncloud.android.operations.CreateShareOperation; +import com.owncloud.android.services.OperationsService; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.dialog.ActivityChooserDialog; import com.owncloud.android.utils.Log_OC; @@ -108,12 +107,13 @@ public class FileOperationsHelper { if (file != null) { callerActivity.showLoadingDialog(); - CreateShareOperation createShare = new CreateShareOperation(file.getRemotePath(), ShareType.PUBLIC_LINK, "", false, "", 1, sendIntent); - createShare.execute(callerActivity.getStorageManager(), - callerActivity, - callerActivity.getRemoteOperationListener(), - callerActivity.getHandler(), - callerActivity); + + Intent service = new Intent(callerActivity, OperationsService.class); + service.setAction(OperationsService.ACTION_CREATE_SHARE); + service.putExtra(OperationsService.EXTRA_ACCOUNT, callerActivity.getAccount()); + service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); + service.putExtra(OperationsService.EXTRA_SEND_INTENT, sendIntent); + callerActivity.startService(service); } else { Log_OC.wtf(TAG, "Trying to open a NULL OCFile"); @@ -140,4 +140,24 @@ public class FileOperationsHelper { return false; } + + public void unshareFileWithLink(OCFile file, FileActivity callerActivity) { + + if (isSharedSupported(callerActivity)) { + // Unshare the file + Intent service = new Intent(callerActivity, OperationsService.class); + service.setAction(OperationsService.ACTION_UNSHARE); + service.putExtra(OperationsService.EXTRA_ACCOUNT, callerActivity.getAccount()); + service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); + callerActivity.startService(service); + + callerActivity.showLoadingDialog(); + + } else { + // Show a Message + Toast t = Toast.makeText(callerActivity, callerActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG); + t.show(); + + } + } } diff --git a/src/com/owncloud/android/files/services/FileDownloader.java b/src/com/owncloud/android/files/services/FileDownloader.java index cc66b095c9..e59e37d9a7 100644 --- a/src/com/owncloud/android/files/services/FileDownloader.java +++ b/src/com/owncloud/android/files/services/FileDownloader.java @@ -382,7 +382,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis * Updates the OC File after a successful download. */ private void saveDownloadedFile() { - OCFile file = mCurrentDownload.getFile(); + OCFile file = mStorageManager.getFileById(mCurrentDownload.getFile().getFileId()); long syncDate = System.currentTimeMillis(); file.setLastSyncDateForProperties(syncDate); file.setLastSyncDateForData(syncDate); diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java index c8a26121a2..6fc332775c 100644 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@ -597,6 +597,9 @@ public class FileUploader extends Service implements OnDatatransferProgressListe */ private void saveUploadedFile() { OCFile file = mCurrentUpload.getFile(); + if (file.fileExists()) { + file = mStorageManager.getFileById(file.getFileId()); + } long syncDate = System.currentTimeMillis(); file.setLastSyncDateForData(syncDate); diff --git a/src/com/owncloud/android/operations/CreateShareOperation.java b/src/com/owncloud/android/operations/CreateShareOperation.java index 1a89f1c5bb..7277b3a761 100644 --- a/src/com/owncloud/android/operations/CreateShareOperation.java +++ b/src/com/owncloud/android/operations/CreateShareOperation.java @@ -92,12 +92,10 @@ public class CreateShareOperation extends SyncOperation { OCShare share = (OCShare) result.getData().get(0); // Update DB with the response + share.setPath(mPath); if (mPath.endsWith(FileUtils.PATH_SEPARATOR)) { - share.setPath(mPath.substring(0, mPath.length()-1)); share.setIsFolder(true); - } else { - share.setPath(mPath); share.setIsFolder(false); } share.setPermissions(mPermissions); diff --git a/src/com/owncloud/android/operations/GetSharesOperation.java b/src/com/owncloud/android/operations/GetSharesOperation.java index 126dcdee52..c9cce406a0 100644 --- a/src/com/owncloud/android/operations/GetSharesOperation.java +++ b/src/com/owncloud/android/operations/GetSharesOperation.java @@ -1,5 +1,5 @@ /* ownCloud Android client application - * Copyright (C) 2012-2013 ownCloud Inc. + * Copyright (C) 2012-2014 ownCloud Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, diff --git a/src/com/owncloud/android/operations/UnshareLinkOperation.java b/src/com/owncloud/android/operations/UnshareLinkOperation.java new file mode 100644 index 0000000000..2bacc4b0c5 --- /dev/null +++ b/src/com/owncloud/android/operations/UnshareLinkOperation.java @@ -0,0 +1,93 @@ +/* ownCloud Android client application + * Copyright (C) 2014 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.owncloud.android.operations; + +import android.content.Context; + +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; +import com.owncloud.android.lib.resources.shares.OCShare; +import com.owncloud.android.lib.operations.remote.RemoveRemoteShareOperation; +import com.owncloud.android.operations.common.SyncOperation; +import com.owncloud.android.utils.Log_OC; + +/** + * Unshare file/folder + * Save the data in Database + * + * @author masensio + */ +public class UnshareLinkOperation extends SyncOperation { + + private static final String TAG = UnshareLinkOperation.class.getSimpleName(); + + private String mRemotePath; + private Context mContext; + + + public UnshareLinkOperation(String remotePath, Context context) { + mRemotePath = remotePath; + mContext = context; + } + + @Override + protected RemoteOperationResult run(OwnCloudClient client) { + RemoteOperationResult result = null; + + // Get Share for a file + OCShare share = getStorageManager().getShareByPath(mRemotePath); + + if (share != null) { + RemoveRemoteShareOperation operation = new RemoveRemoteShareOperation((int) share.getIdRemoteShared()); + result = operation.execute(client); + + if (result.isSuccess() || result.getCode() == ResultCode.SHARE_NOT_FOUND) { + Log_OC.d(TAG, "Share id = " + share.getIdRemoteShared() + " deleted"); + + OCFile file = getStorageManager().getFileByPath(mRemotePath); + file.setShareByLink(false); + file.setPublicLink(""); + getStorageManager().saveFile(file); + getStorageManager().removeShare(share); + + if (result.getCode() == ResultCode.SHARE_NOT_FOUND) { + if (existsFile(client, file.getRemotePath())) { + result = new RemoteOperationResult(ResultCode.OK); + } else { + getStorageManager().removeFile(file, true, true); + } + } + } + + } else { + result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); + } + + return result; + } + + private boolean existsFile(OwnCloudClient client, String remotePath){ + ExistenceCheckRemoteOperation existsOperation = new ExistenceCheckRemoteOperation(remotePath, mContext, false); + RemoteOperationResult result = existsOperation.execute(client); + return result.isSuccess(); + } + +} diff --git a/src/com/owncloud/android/services/OperationsService.java b/src/com/owncloud/android/services/OperationsService.java index 258f0aa446..80caea71a3 100644 --- a/src/com/owncloud/android/services/OperationsService.java +++ b/src/com/owncloud/android/services/OperationsService.java @@ -18,16 +18,21 @@ package com.owncloud.android.services; import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; import com.owncloud.android.datamodel.FileDataStorageManager; - import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.OwnCloudClient; -import com.owncloud.android.operations.GetSharesOperation; -import com.owncloud.android.operations.common.SyncOperation; +import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.operations.common.SyncOperation; +import com.owncloud.android.operations.CreateShareOperation; +import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.utils.Log_OC; import android.accounts.Account; @@ -51,7 +56,12 @@ public class OperationsService extends Service { public static final String EXTRA_ACCOUNT = "ACCOUNT"; public static final String EXTRA_SERVER_URL = "SERVER_URL"; - public static final String EXTRA_RESULT = "RESULT"; + public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH"; + public static final String EXTRA_SEND_INTENT = "SEND_INTENT"; + public static final String EXTRA_RESULT = "RESULT"; + + public static final String ACTION_CREATE_SHARE = "CREATE_SHARE"; + public static final String ACTION_UNSHARE = "UNSHARE"; public static final String ACTION_OPERATION_ADDED = OperationsService.class.getName() + ".OPERATION_ADDED"; public static final String ACTION_OPERATION_FINISHED = OperationsService.class.getName() + ".OPERATION_FINISHED"; @@ -69,7 +79,7 @@ public class OperationsService extends Service { private Looper mServiceLooper; private ServiceHandler mServiceHandler; - private IBinder mBinder; + private OperationsServiceBinder mBinder; private OwnCloudClient mOwnCloudClient = null; private Target mLastTarget = null; private FileDataStorageManager mStorageManager; @@ -107,10 +117,30 @@ public class OperationsService extends Service { try { Account account = intent.getParcelableExtra(EXTRA_ACCOUNT); String serverUrl = intent.getStringExtra(EXTRA_SERVER_URL); + Target target = new Target(account, (serverUrl == null) ? null : Uri.parse(serverUrl)); - GetSharesOperation operation = new GetSharesOperation(); + RemoteOperation operation = null; + + String action = intent.getAction(); + if (action.equals(ACTION_CREATE_SHARE)) { // Create Share + String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH); + Intent sendIntent = intent.getParcelableExtra(EXTRA_SEND_INTENT); + if (remotePath.length() > 0) { + operation = new CreateShareOperation(remotePath, ShareType.PUBLIC_LINK, + "", false, "", 1, sendIntent); + } + } else if (action.equals(ACTION_UNSHARE)) { // Unshare file + String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH); + if (remotePath.length() > 0) { + operation = new UnshareLinkOperation(remotePath, this.getApplicationContext()); + } + } else { + // nothing we are going to handle + return START_NOT_STICKY; + } + mPendingOperations.add(new Pair(target, operation)); - sendBroadcastNewOperation(target, operation); + //sendBroadcastNewOperation(target, operation); Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; @@ -150,8 +180,59 @@ public class OperationsService extends Service { * * It provides by itself the available operations. */ - public class OperationsServiceBinder extends Binder { - // TODO + public class OperationsServiceBinder extends Binder /* implements OnRemoteOperationListener */ { + + /** + * Map of listeners that will be reported about the end of operations from a {@link OperationsServiceBinder} instance + */ + private Map mBoundListeners = new HashMap(); + + /** + * Cancels an operation + * + * TODO + */ + public void cancel() { + // TODO + } + + + public void clearListeners() { + + mBoundListeners.clear(); + } + + + /** + * Adds a listener interested in being reported about the end of operations. + * + * @param listener Object to notify about the end of operations. + * @param callbackHandler {@link Handler} to access the listener without breaking Android threading protection. + */ + public void addOperationListener (OnRemoteOperationListener listener, Handler callbackHandler) { + mBoundListeners.put(listener, callbackHandler); + } + + + /** + * Removes a listener from the list of objects interested in the being reported about the end of operations. + * + * @param listener Object to notify about progress of transfer. + */ + public void removeOperationListener (OnRemoteOperationListener listener) { + mBoundListeners.remove(listener); + } + + + /** + * TODO - IMPORTANT: update implementation when more operations are moved into the service + * + * @return 'True' when an operation that enforces the user to wait for completion is in process. + */ + public boolean isPerformingBlockingOperation() { + return (!mPendingOperations.isEmpty()); + } + } @@ -242,15 +323,16 @@ public class OperationsService extends Service { } } - sendBroadcastOperationFinished(mLastTarget, mCurrentOperation, result); + //sendBroadcastOperationFinished(mLastTarget, mCurrentOperation, result); + callbackOperationListeners(mLastTarget, mCurrentOperation, result); } } /** - * Sends a LOCAL broadcast when a new operation is added to the queue. + * Sends a broadcast when a new operation is added to the queue. * - * Local broadcasts are only delivered to activities in the same process. + * Local broadcasts are only delivered to activities in the same process, but can't be done sticky :\ * * @param target Account or URL pointing to an OC server. * @param operation Added operation. @@ -291,6 +373,31 @@ public class OperationsService extends Service { //lbm.sendBroadcast(intent); sendStickyBroadcast(intent); } + + /** + * Notifies the currently subscribed listeners about the end of an operation. + * + * @param target Account or URL pointing to an OC server. + * @param operation Finished operation. + * @param result Result of the operation. + */ + private void callbackOperationListeners(Target target, final RemoteOperation operation, final RemoteOperationResult result) { + Iterator listeners = mBinder.mBoundListeners.keySet().iterator(); + while (listeners.hasNext()) { + final OnRemoteOperationListener listener = listeners.next(); + final Handler handler = mBinder.mBoundListeners.get(listener); + if (handler != null) { + handler.post(new Runnable() { + @Override + public void run() { + listener.onRemoteOperationFinish(operation, result); + } + }); + } + } + + } + } diff --git a/src/com/owncloud/android/ui/activity/FileActivity.java b/src/com/owncloud/android/ui/activity/FileActivity.java index ddf7ca7ea4..42b90aec17 100644 --- a/src/com/owncloud/android/ui/activity/FileActivity.java +++ b/src/com/owncloud/android/ui/activity/FileActivity.java @@ -23,9 +23,13 @@ import android.accounts.AccountManager; import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerFuture; import android.accounts.OperationCanceledException; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; @@ -43,7 +47,10 @@ import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.operations.CreateShareOperation; +import com.owncloud.android.operations.UnshareLinkOperation; +import com.owncloud.android.services.OperationsService; +import com.owncloud.android.services.OperationsService.OperationsServiceBinder; import com.owncloud.android.ui.dialog.LoadingDialog; import com.owncloud.android.utils.Log_OC; @@ -90,6 +97,10 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp private FileDataStorageManager mStorageManager = null; private FileOperationsHelper mFileOperationsHelper; + + private ServiceConnection mOperationsServiceConnection = null; + + private OperationsServiceBinder mOperationsServiceBinder = null; /** @@ -116,7 +127,9 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp } setAccount(account, savedInstanceState != null); - + + mOperationsServiceConnection = new OperationsServiceConnection(); + bindService(new Intent(this, OperationsService.class), mOperationsServiceConnection, Context.BIND_AUTO_CREATE); } @@ -132,7 +145,6 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp if (!validAccount) { swapToDefaultAccount(); } - } @@ -142,6 +154,28 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp if (mAccountWasSet) { onAccountSet(mAccountWasRestored); } + if (mOperationsServiceBinder != null) { + mOperationsServiceBinder.addOperationListener(FileActivity.this, mHandler); + } + } + + + @Override + protected void onStop() { + super.onStop(); + if (mOperationsServiceBinder != null) { + mOperationsServiceBinder.removeOperationListener(this); + } + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mOperationsServiceConnection != null) { + unbindService(mOperationsServiceConnection); + mOperationsServiceBinder = null; + } } @@ -353,16 +387,22 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp Log_OC.d(TAG, "Received result of operation in FileActivity - common behaviour for all the FileActivities "); if (operation instanceof CreateShareOperation) { onCreateShareOperationFinish((CreateShareOperation) operation, result); - } + + } else if (operation instanceof UnshareLinkOperation) { + onUnshareLinkOperationFinish((UnshareLinkOperation)operation, result); + + } } private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) { dismissLoadingDialog(); if (result.isSuccess()) { + updateFileFromDB(); + Intent sendIntent = operation.getSendIntent(); startActivity(sendIntent); - } else if (result.getCode() == ResultCode.FILE_NOT_FOUND) { // Error --> SHARE_NOT_FOUND + } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND) { // Error --> SHARE_NOT_FOUND Toast t = Toast.makeText(this, getString(R.string.share_link_file_no_exist), Toast.LENGTH_LONG); t.show(); } else { // Generic error @@ -373,6 +413,31 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp } + private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) { + dismissLoadingDialog(); + + if (result.isSuccess()){ + updateFileFromDB(); + + } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND) { // Error --> SHARE_NOT_FOUND + Toast t = Toast.makeText(this, getString(R.string.unshare_link_file_no_exist), Toast.LENGTH_LONG); + t.show(); + } else { // Generic error + // Show a Message, operation finished without success + Toast t = Toast.makeText(this, getString(R.string.unshare_link_file_error), Toast.LENGTH_LONG); + t.show(); + } + + } + + + private void updateFileFromDB(){ + OCFile file = getStorageManager().getFileByPath(getFile().getRemotePath()); + if (file != null) { + setFile(file); + } + } + /** * Show loading dialog */ @@ -396,5 +461,37 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp loading.dismiss(); } } + + + /** + * Implements callback methods for service binding. Passed as a parameter to { + */ + private class OperationsServiceConnection implements ServiceConnection { + + @Override + public void onServiceConnected(ComponentName component, IBinder service) { + if (component.equals(new ComponentName(FileActivity.this, OperationsService.class))) { + Log_OC.d(TAG, "Operations service connected"); + mOperationsServiceBinder = (OperationsServiceBinder) service; + mOperationsServiceBinder.addOperationListener(FileActivity.this, mHandler); + if (!mOperationsServiceBinder.isPerformingBlockingOperation()) { + dismissLoadingDialog(); + } + + } else { + return; + } + } + + + @Override + public void onServiceDisconnected(ComponentName component) { + if (component.equals(new ComponentName(FileActivity.this, OperationsService.class))) { + Log_OC.d(TAG, "Operations service disconnected"); + mOperationsServiceBinder = null; + // TODO whatever could be waiting for the service is unbound + } + } + }; } diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index 9c4fb06b49..d5429dac9b 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -75,6 +75,7 @@ import com.owncloud.android.operations.RemoveFileOperation; import com.owncloud.android.operations.RenameFileOperation; import com.owncloud.android.operations.SynchronizeFileOperation; import com.owncloud.android.operations.SynchronizeFolderOperation; +import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.services.OperationsService; import com.owncloud.android.syncadapter.FileSyncAdapter; import com.owncloud.android.ui.dialog.EditNameDialog; @@ -85,6 +86,7 @@ import com.owncloud.android.ui.fragment.FileDetailFragment; import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.ui.fragment.OCFileListFragment; import com.owncloud.android.ui.preview.PreviewImageActivity; +import com.owncloud.android.ui.preview.PreviewImageFragment; import com.owncloud.android.ui.preview.PreviewMediaFragment; import com.owncloud.android.ui.preview.PreviewVideoActivity; import com.owncloud.android.utils.DisplayUtils; @@ -186,6 +188,11 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa mRightFragmentContainer = findViewById(R.id.right_fragment_container); if (savedInstanceState == null) { createMinFragments(); + } else { + Log_OC.d(TAG, "Init the secondFragment again"); + if (mDualPane) { + initFragmentsWithFile(); + } } // Action bar setup @@ -200,6 +207,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa protected void onStart() { super.onStart(); getSupportActionBar().setIcon(DisplayUtils.getSeasonalIconId()); + refeshListOfFilesFragment(); } @Override @@ -278,7 +286,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa transaction.add(R.id.left_fragment_container, listOfFiles, TAG_LIST_OF_FILES); transaction.commit(); } - + private void initFragmentsWithFile() { if (getAccount() != null && getFile() != null) { /// First fragment @@ -1327,21 +1335,53 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa } else if (operation instanceof CreateFolderOperation) { onCreateFolderOperationFinish((CreateFolderOperation)operation, result); - + } else if (operation instanceof CreateShareOperation) { onCreateShareOperationFinish((CreateShareOperation) operation, result); - } + + } else if (operation instanceof UnshareLinkOperation) { + onUnshareLinkOperationFinish((UnshareLinkOperation)operation, result); + + } } - + private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) { if (result.isSuccess()) { + refreshShowDetails(); refeshListOfFilesFragment(); } } + private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) { + if (result.isSuccess()) { + refreshShowDetails(); + refeshListOfFilesFragment(); + } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND) { + cleanSecondFragment(); + refeshListOfFilesFragment(); + } + } + + private void refreshShowDetails() { + FileFragment details = getSecondFragment(); + if (details != null) { + OCFile file = details.getFile(); + if (file != null) { + file = getStorageManager().getFileByPath(file.getRemotePath()); + if (details instanceof PreviewMediaFragment) { + // Refresh OCFile of the fragment + ((PreviewMediaFragment) details).updateFile(file); + } else { + showDetails(file); + } + } + invalidateOptionsMenu(); + } + } + /** * Updates the view associated to the activity after the finish of an operation trying to remove a * file. diff --git a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java index 888261a413..af29cffb0a 100644 --- a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java +++ b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java @@ -186,6 +186,10 @@ public class FileDetailFragment extends FileFragment implements super.onActivityCreated(savedInstanceState); if (mAccount != null) { mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver()); + OCFile file = mStorageManager.getFileByPath(getFile().getRemotePath()); + if (file != null) { + setFile(file); + } } } @@ -310,7 +314,14 @@ public class FileDetailFragment extends FileFragment implements toHide.add(R.id.action_remove_file); } - + + // Options shareLink + if (!file.isShareByLink()) { + toHide.add(R.id.action_unshare_file); + } else { + toShow.add(R.id.action_unshare_file); + } + MenuItem item = null; for (int i : toHide) { item = menu.findItem(i); @@ -340,6 +351,11 @@ public class FileDetailFragment extends FileFragment implements activity.getFileOperationsHelper().shareFileWithLink(getFile(), activity); return true; } + case R.id.action_unshare_file: { + FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); + activity.getFileOperationsHelper().unshareFileWithLink(getFile(), activity); + return true; + } case R.id.action_open_file_with: { FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); activity.getFileOperationsHelper().openFile(getFile(), activity); diff --git a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java index b43275fa13..9a49b2c264 100644 --- a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -257,6 +257,11 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName toHide.add(R.id.action_cancel_upload); } } + + // Options shareLink + if (!targetFile.isShareByLink()) { + toHide.add(R.id.action_unshare_file); + } for (int i : toHide) { item = menu.findItem(i); @@ -282,12 +287,17 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName public boolean onContextItemSelected (MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); mTargetFile = (OCFile) mAdapter.getItem(info.position); - switch (item.getItemId()) { + switch (item.getItemId()) { case R.id.action_share_file: { FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); activity.getFileOperationsHelper().shareFileWithLink(mTargetFile, activity); return true; } + case R.id.action_unshare_file: { + FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); + activity.getFileOperationsHelper().unshareFileWithLink(mTargetFile, activity); + return true; + } case R.id.action_rename_file: { String fileName = mTargetFile.getFileName(); int extensionStart = mTargetFile.isFolder() ? -1 : fileName.lastIndexOf("."); @@ -353,7 +363,7 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName return super.onContextItemSelected(item); } } - + /** * Use this to query the {@link OCFile} that is currently @@ -422,7 +432,7 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName * @param file */ public void onBrowsedDownTo(OCFile folder); - + public void startDownloadForPreview(OCFile file); public void startMediaPreview(OCFile file, int i, boolean b); diff --git a/src/com/owncloud/android/ui/preview/PreviewImageActivity.java b/src/com/owncloud/android/ui/preview/PreviewImageActivity.java index 374a53b744..ece3991c8f 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImageActivity.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageActivity.java @@ -45,6 +45,12 @@ import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; +import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; +import com.owncloud.android.lib.common.operations.RemoteOperation; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.operations.CreateShareOperation; +import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; import com.owncloud.android.ui.activity.PinCodeActivity; @@ -59,7 +65,7 @@ import com.owncloud.android.utils.Log_OC; * * @author David A. Velasco */ -public class PreviewImageActivity extends FileActivity implements FileFragment.ContainerActivity, ViewPager.OnPageChangeListener, OnTouchListener { +public class PreviewImageActivity extends FileActivity implements FileFragment.ContainerActivity, ViewPager.OnPageChangeListener, OnTouchListener , OnRemoteOperationListener{ public static final int DIALOG_SHORT_WAIT = 0; @@ -147,7 +153,43 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C outState.putBoolean(KEY_WAITING_FOR_BINDER, mRequestWaitingForBinder); } - + @Override + public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { + super.onRemoteOperationFinish(operation, result); + + if (operation instanceof CreateShareOperation) { + onCreateShareOperationFinish((CreateShareOperation) operation, result); + + } else if (operation instanceof UnshareLinkOperation) { + onUnshareLinkOperationFinish((UnshareLinkOperation) operation, result); + + } + } + + + private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) { + if (result.isSuccess()) { + OCFile file = getStorageManager().getFileByPath(getFile().getRemotePath()); + if (file != null) { + setFile(file); + } + invalidateOptionsMenu(); + } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND) { + backToDisplayActivity(); + } + + } + + private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) { + if (result.isSuccess()) { + OCFile file = getStorageManager().getFileByPath(getFile().getRemotePath()); + if (file != null) { + setFile(file); + } + invalidateOptionsMenu(); + } + } + /** Defines callbacks for service binding, passed to bindService() */ private class PreviewImageServiceConnection implements ServiceConnection { diff --git a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java index 1676a8ebee..b323e5f141 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java @@ -176,8 +176,22 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver()); if (savedInstanceState != null) { if (!mIgnoreFirstSavedState) { - setFile((OCFile)savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_FILE)); + OCFile file = (OCFile)savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_FILE); mAccount = savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_ACCOUNT); + + // Update the file + if (mAccount!= null) { + mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver()); + OCFile updatedFile = mStorageManager.getFileByPath(file.getRemotePath()); + if (updatedFile != null) { + setFile(updatedFile); + } else { + setFile(file); + } + } else { + setFile(file); + } + } else { mIgnoreFirstSavedState = false; } @@ -230,6 +244,11 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper toHide.add(R.id.action_cancel_upload); toHide.add(R.id.action_download_file); toHide.add(R.id.action_rename_file); // by now + + // Options shareLink + if (!getFile().isShareByLink()) { + toHide.add(R.id.action_unshare_file); + } for (int i : toHide) { item = menu.findItem(i); @@ -241,6 +260,27 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper } + /** + * {@inheritDoc} + */ + @Override + public void onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + + MenuItem item = menu.findItem(R.id.action_unshare_file); + // Options shareLink + OCFile file = ((FileActivity) getSherlockActivity()).getFile(); + if (!file.isShareByLink()) { + item.setVisible(false); + item.setEnabled(false); + } else { + item.setVisible(true); + item.setEnabled(true); + } + + } + + /** * {@inheritDoc} @@ -253,6 +293,11 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper act.getFileOperationsHelper().shareFileWithLink(getFile(), act); return true; } + case R.id.action_unshare_file: { + FileActivity act = (FileActivity)getSherlockActivity(); + act.getFileOperationsHelper().unshareFileWithLink(getFile(), act); + return true; + } case R.id.action_open_file_with: { openFile(); return true; @@ -272,6 +317,7 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper } + private void seeDetails() { ((FileFragment.ContainerActivity)getActivity()).showDetails(getFile()); } diff --git a/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java b/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java index 3f6f6a76b4..83f937a3d3 100644 --- a/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java @@ -289,7 +289,12 @@ public class PreviewMediaFragment extends FileFragment implements toHide.add(R.id.action_download_file); toHide.add(R.id.action_sync_file); toHide.add(R.id.action_rename_file); // by now - + + // Options shareLink + if (!getFile().isShareByLink()) { + toHide.add(R.id.action_unshare_file); + } + for (int i : toHide) { item = menu.findItem(i); if (item != null) { @@ -300,6 +305,25 @@ public class PreviewMediaFragment extends FileFragment implements } + + /** + * {@inheritDoc} + */ + @Override + public void onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + + MenuItem item = menu.findItem(R.id.action_unshare_file); + // Options shareLink + if (!getFile().isShareByLink()) { + item.setVisible(false); + item.setEnabled(false); + } else { + item.setVisible(true); + item.setEnabled(true); + } + } + /** * {@inheritDoc} @@ -311,6 +335,10 @@ public class PreviewMediaFragment extends FileFragment implements shareFileWithLink(); return true; } + case R.id.action_unshare_file: { + unshareFileWithLink(); + return true; + } case R.id.action_open_file_with: { openFile(); return true; @@ -328,7 +356,22 @@ public class PreviewMediaFragment extends FileFragment implements return false; } } + + + /** + * Update the file of the fragment with file value + * @param file + */ + public void updateFile(OCFile file){ + setFile(file); + } + + private void unshareFileWithLink() { + stopPreview(false); + FileActivity activity = (FileActivity)((FileFragment.ContainerActivity)getActivity()); + activity.getFileOperationsHelper().unshareFileWithLink(getFile(), activity); + } private void shareFileWithLink() { stopPreview(false); @@ -545,17 +588,19 @@ public class PreviewMediaFragment extends FileFragment implements @Override public void onServiceConnected(ComponentName component, IBinder service) { - if (component.equals(new ComponentName(getActivity(), MediaService.class))) { - Log_OC.d(TAG, "Media service connected"); - mMediaServiceBinder = (MediaServiceBinder) service; - if (mMediaServiceBinder != null) { - prepareMediaController(); - playAudio(); // do not wait for the touch of nobody to play audio - - Log_OC.d(TAG, "Successfully bound to MediaService, MediaController ready"); - - } else { - Log_OC.e(TAG, "Unexpected response from MediaService while binding"); + if (getActivity() != null) { + if (component.equals(new ComponentName(getActivity(), MediaService.class))) { + Log_OC.d(TAG, "Media service connected"); + mMediaServiceBinder = (MediaServiceBinder) service; + if (mMediaServiceBinder != null) { + prepareMediaController(); + playAudio(); // do not wait for the touch of nobody to play audio + + Log_OC.d(TAG, "Successfully bound to MediaService, MediaController ready"); + + } else { + Log_OC.e(TAG, "Unexpected response from MediaService while binding"); + } } } }