From: masensio Date: Mon, 19 May 2014 06:29:28 +0000 (+0200) Subject: Merge branch 'develop' into refactor_update_filelist_from_database X-Git-Tag: oc-android-1.7.0_signed~309^2~14 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/c39e851f5eada08c93d3a57d41054ea112b4bfcf?hp=1c5f3331046f975444cff556d0af51fce8c936e9 Merge branch 'develop' into refactor_update_filelist_from_database --- diff --git a/owncloud-android-library b/owncloud-android-library index 796189a0..16d237e4 160000 --- a/owncloud-android-library +++ b/owncloud-android-library @@ -1 +1 @@ -Subproject commit 796189a04d5af05448993054a988658080128b20 +Subproject commit 16d237e42ad8338aea13365f6a50459f3b6c1fd8 diff --git a/res/menu/file_actions_menu.xml b/res/menu/file_actions_menu.xml index 986ce3ed..b1acc846 100644 --- a/res/menu/file_actions_menu.xml +++ b/res/menu/file_actions_menu.xml @@ -28,7 +28,7 @@ - + diff --git a/res/values/strings.xml b/res/values/strings.xml index b970fbb4..0bd9cef3 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -193,6 +193,7 @@ File contents already synchronized Folder could not be created Forbidden characters: / \\ < > : " | ? * + File name cannot be empty Wait a moment "Unexpected problem ; please select the file from a different app" No file was selected diff --git a/src/com/owncloud/android/authentication/AuthenticatorActivity.java b/src/com/owncloud/android/authentication/AuthenticatorActivity.java index 1247f3f5..32bbcdcc 100644 --- a/src/com/owncloud/android/authentication/AuthenticatorActivity.java +++ b/src/com/owncloud/android/authentication/AuthenticatorActivity.java @@ -114,7 +114,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener { private static final String KEY_AUTH_STATUS_TEXT = "AUTH_STATUS_TEXT"; private static final String KEY_AUTH_STATUS_ICON = "AUTH_STATUS_ICON"; private static final String KEY_SERVER_AUTH_METHOD = "SERVER_AUTH_METHOD"; - private static final String KEY_WAITING_FOR_OP_ID = "DETECT_AUTH_OP_ID"; + private static final String KEY_WAITING_FOR_OP_ID = "WAITING_FOR_OP_ID"; private static final String KEY_AUTH_TOKEN = "AUTH_TOKEN"; private static final String AUTH_ON = "on"; diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index f132d967..ec0a7efc 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -422,10 +422,11 @@ public class FileDataStorageManager { // } - public void removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) { + public boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) { + boolean success = true; if (file != null) { if (file.isFolder()) { - removeFolder(file, removeDBData, removeLocalCopy); + success = removeFolder(file, removeDBData, removeLocalCopy); } else { if (removeDBData) { @@ -433,19 +434,20 @@ public class FileDataStorageManager { Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()); String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?"; String [] whereArgs = new String[]{mAccount.name, file.getRemotePath()}; + int deleted = 0; if (getContentProviderClient() != null) { try { - getContentProviderClient().delete(file_uri, where, whereArgs); + deleted = getContentProviderClient().delete(file_uri, where, whereArgs); } catch (RemoteException e) { e.printStackTrace(); } } else { - getContentResolver().delete(file_uri, where, whereArgs); + deleted = getContentResolver().delete(file_uri, where, whereArgs); } - //updateFolderSize(file.getParentId()); + success &= (deleted > 0); } - if (removeLocalCopy && file.isDown() && file.getStoragePath() != null) { - boolean success = new File(file.getStoragePath()).delete(); + if (removeLocalCopy && file.isDown() && file.getStoragePath() != null && success) { + success = new File(file.getStoragePath()).delete(); if (!removeDBData && success) { // maybe unnecessary, but should be checked TODO remove if unnecessary file.setStoragePath(null); @@ -454,51 +456,64 @@ public class FileDataStorageManager { } } } + return success; } - public void removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) { + public boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) { + boolean success = true; if (folder != null && folder.isFolder()) { if (removeDBData && folder.getFileId() != -1) { - removeFolderInDb(folder); + success = removeFolderInDb(folder); } - if (removeLocalContent) { - File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder)); - removeLocalFolder(localFolder); + if (removeLocalContent && success) { + success = removeLocalFolder(folder); } } + return success; } - private void removeFolderInDb(OCFile folder) { + private boolean removeFolderInDb(OCFile folder) { Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, ""+ folder.getFileId()); // URI for recursive deletion String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?"; String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()}; + int deleted = 0; if (getContentProviderClient() != null) { try { - getContentProviderClient().delete(folder_uri, where, whereArgs); + deleted = getContentProviderClient().delete(folder_uri, where, whereArgs); } catch (RemoteException e) { e.printStackTrace(); } } else { - getContentResolver().delete(folder_uri, where, whereArgs); + deleted = getContentResolver().delete(folder_uri, where, whereArgs); } - //updateFolderSize(folder.getParentId()); + return deleted > 0; } - private void removeLocalFolder(File folder) { - if (folder.exists()) { - File[] files = folder.listFiles(); + private boolean removeLocalFolder(OCFile folder) { + boolean success = true; + File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder)); + if (localFolder.exists()) { + Vector files = getFolderContent(folder.getFileId()); if (files != null) { - for (File file : files) { - if (file.isDirectory()) { - removeLocalFolder(file); + for (OCFile file : files) { + if (file.isFolder()) { + success &= removeLocalFolder(file); } else { - file.delete(); + if (file.isDown()) { + File localFile = new File(file.getStoragePath()); + success &= localFile.delete(); + if (success) { + file.setStoragePath(null); + saveFile(file); + } + } } } } - folder.delete(); + success &= localFolder.delete(); } + return success; } /** @@ -838,25 +853,25 @@ public class FileDataStorageManager { return overriden; } - private OCShare getShareById(long id) { - Cursor c = getShareCursorForValue(ProviderTableMeta._ID, String.valueOf(id)); - OCShare share = null; - if (c.moveToFirst()) { - share = createShareInstance(c); - } - c.close(); - return share; - } - - private OCShare getShareByRemoteId(long remoteId) { - Cursor c = getShareCursorForValue(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, String.valueOf(remoteId)); - OCShare share = null; - if (c.moveToFirst()) { - share = createShareInstance(c); - } - c.close(); - return share; - } +// private OCShare getShareById(long id) { +// Cursor c = getShareCursorForValue(ProviderTableMeta._ID, String.valueOf(id)); +// OCShare share = null; +// if (c.moveToFirst()) { +// share = createShareInstance(c); +// } +// c.close(); +// return share; +// } +// +// private OCShare getShareByRemoteId(long remoteId) { +// Cursor c = getShareCursorForValue(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, String.valueOf(remoteId)); +// OCShare share = null; +// if (c.moveToFirst()) { +// share = createShareInstance(c); +// } +// c.close(); +// return share; +// } public OCShare getFirstShareByPathAndType(String path, ShareType type) { Cursor c = null; diff --git a/src/com/owncloud/android/files/FileMenuFilter.java b/src/com/owncloud/android/files/FileMenuFilter.java new file mode 100644 index 00000000..5b1933b3 --- /dev/null +++ b/src/com/owncloud/android/files/FileMenuFilter.java @@ -0,0 +1,239 @@ +/* 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.files; + +import java.util.ArrayList; +import java.util.List; + +import android.accounts.Account; +import android.content.Context; +import android.view.Menu; +import android.view.MenuItem; + +import com.owncloud.android.R; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.files.services.FileDownloader; +import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; +import com.owncloud.android.files.services.FileUploader; +import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; +import com.owncloud.android.ui.activity.ComponentsGetter; + +/** + * Filters out the file actions available in a given {@link Menu} for a given {@link OCFile} + * according to the current state of the latest. + * + * @author David A. Velasco + */ +public class FileMenuFilter { + + private OCFile mFile; + private ComponentsGetter mComponentsGetter; + private Account mAccount; + private Context mContext; + + /** + * Constructor + * + * @param targetFile {@link OCFile} target of the action to filter in the {@link Menu}. + * @param account ownCloud {@link Account} holding targetFile. + * @param cg Accessor to app components, needed to get access the + * {@link FileUploader} and {@link FileDownloader} services. + * @param context Android {@link Context}, needed to access build setup resources. + */ + public FileMenuFilter(OCFile targetFile, Account account, ComponentsGetter cg, Context context) { + mFile = targetFile; + mAccount = account; + mComponentsGetter = cg; + mContext = context; + } + + + /** + * Filters out the file actions available in the passed {@link Menu} taken into account + * the state of the {@link OCFile} held by the filter. + * + * @param menu Options or context menu to filter. + */ + public void filter(Menu menu) { + List toShow = new ArrayList(); + List toHide = new ArrayList(); + + filter(toShow, toHide); + + MenuItem item = null; + for (int i : toShow) { + item = menu.findItem(i); + if (item != null) { + item.setVisible(true); + item.setEnabled(true); + } + } + + for (int i : toHide) { + item = menu.findItem(i); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + } + } + + /** + * Filters out the file actions available in the passed {@link Menu} taken into account + * the state of the {@link OCFile} held by the filter. + * + * Second method needed thanks to ActionBarSherlock. + * + * TODO Get rid of it when ActionBarSherlock is replaced for newer Android Support Library. + * + * @param menu Options or context menu to filter. + */ + public void filter(com.actionbarsherlock.view.Menu menu) { + + List toShow = new ArrayList(); + List toHide = new ArrayList(); + + filter(toShow, toHide); + + com.actionbarsherlock.view.MenuItem item = null; + for (int i : toShow) { + item = menu.findItem(i); + if (item != null) { + item.setVisible(true); + item.setEnabled(true); + } + } + for (int i : toHide) { + item = menu.findItem(i); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + } + } + + /** + * Performs the real filtering, to be applied in the {@link Menu} by the caller methods. + * + * Decides what actions must be shown and hidden. + * + * @param toShow List to save the options that must be shown in the menu. + * @param toHide List to save the options that must be shown in the menu. + */ + private void filter(List toShow, List toHide) { + boolean downloading = false; + boolean uploading = false; + if (mComponentsGetter != null && mFile != null && mAccount != null) { + FileDownloaderBinder downloaderBinder = mComponentsGetter.getFileDownloaderBinder(); + downloading = downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile); + FileUploaderBinder uploaderBinder = mComponentsGetter.getFileUploaderBinder(); + uploading = uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile); + } + + /// decision is taken for each possible action on a file in the menu + + // DOWNLOAD + if (mFile == null || mFile.isFolder() || mFile.isDown() || downloading || uploading) { + toHide.add(R.id.action_download_file); + + } else { + toShow.add(R.id.action_download_file); + } + + // RENAME + if (mFile == null || downloading || uploading) { + toHide.add(R.id.action_rename_file); + + } else { + toShow.add(R.id.action_rename_file); + } + + // REMOVE + if (mFile == null || downloading || uploading) { + toHide.add(R.id.action_remove_file); + + } else { + toShow.add(R.id.action_remove_file); + } + + // OPEN WITH (different to preview!) + if (mFile == null || mFile.isFolder() || !mFile.isDown() || downloading || uploading) { + toHide.add(R.id.action_open_file_with); + + } else { + toShow.add(R.id.action_open_file_with); + } + + + // CANCEL DOWNLOAD + if (mFile == null || !downloading || mFile.isFolder()) { + toHide.add(R.id.action_cancel_download); + } else { + toShow.add(R.id.action_cancel_download); + } + + // CANCEL UPLOAD + if (mFile == null || !uploading || mFile.isFolder()) { + toHide.add(R.id.action_cancel_upload); + } else { + toShow.add(R.id.action_cancel_upload); + } + + // SYNC FILE CONTENTS + if (mFile == null || mFile.isFolder() || !mFile.isDown() || downloading || uploading) { + toHide.add(R.id.action_sync_file); + } else { + toShow.add(R.id.action_sync_file); + } + + // SHARE FILE + // TODO add check on SHARE available on server side? + if (mFile == null) { + toHide.add(R.id.action_share_file); + } else { + toShow.add(R.id.action_share_file); + } + + // UNSHARE FILE + // TODO add check on SHARE available on server side? + if (mFile == null || !mFile.isShareByLink()) { + toHide.add(R.id.action_unshare_file); + } else { + toShow.add(R.id.action_unshare_file); + } + + + // SEE DETAILS + if (mFile == null || mFile.isFolder()) { + toHide.add(R.id.action_see_details); + } else { + toShow.add(R.id.action_see_details); + } + + // SEND + boolean sendAllowed = (mContext != null && + mContext.getString(R.string.send_files_to_other_apps).equalsIgnoreCase("on")); + if (mFile == null || !sendAllowed || mFile.isFolder() || uploading || downloading) { + toHide.add(R.id.action_send_file); + } else { + toShow.add(R.id.action_send_file); + } + + } + +} diff --git a/src/com/owncloud/android/files/FileOperationsHelper.java b/src/com/owncloud/android/files/FileOperationsHelper.java index ff571e5d..73d598cf 100644 --- a/src/com/owncloud/android/files/FileOperationsHelper.java +++ b/src/com/owncloud/android/files/FileOperationsHelper.java @@ -48,8 +48,17 @@ public class FileOperationsHelper { private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG"; + protected FileActivity mFileActivity = null; + + /// Identifier of operation in progress which result shouldn't be lost + private long mWaitingForOpId = Long.MAX_VALUE; - public void openFile(OCFile file, FileActivity callerActivity) { + public FileOperationsHelper(FileActivity fileActivity) { + mFileActivity = fileActivity; + } + + + public void openFile(OCFile file) { if (file != null) { String storagePath = file.getStoragePath(); String encodedStoragePath = WebdavUtils.encodePath(storagePath); @@ -70,28 +79,28 @@ public class FileOperationsHelper { Intent chooserIntent = null; if (intentForGuessedMimeType != null) { - chooserIntent = Intent.createChooser(intentForGuessedMimeType, callerActivity.getString(R.string.actionbar_open_with)); + chooserIntent = Intent.createChooser(intentForGuessedMimeType, mFileActivity.getString(R.string.actionbar_open_with)); } else { - chooserIntent = Intent.createChooser(intentForSavedMimeType, callerActivity.getString(R.string.actionbar_open_with)); + chooserIntent = Intent.createChooser(intentForSavedMimeType, mFileActivity.getString(R.string.actionbar_open_with)); } - callerActivity.startActivity(chooserIntent); + mFileActivity.startActivity(chooserIntent); } else { Log_OC.wtf(TAG, "Trying to open a NULL OCFile"); } } - - public void shareFileWithLink(OCFile file, FileActivity callerActivity) { + + public void shareFileWithLink(OCFile file) { - if (isSharedSupported(callerActivity)) { + if (isSharedSupported()) { if (file != null) { String link = "https://fake.url"; Intent intent = createShareWithLinkIntent(link); - String[] packagesToExclude = new String[] { callerActivity.getPackageName() }; + String[] packagesToExclude = new String[] { mFileActivity.getPackageName() }; DialogFragment chooserDialog = ShareLinkToDialog.newInstance(intent, packagesToExclude, file); - chooserDialog.show(callerActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG); + chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG); } else { Log_OC.wtf(TAG, "Trying to share a NULL OCFile"); @@ -99,23 +108,23 @@ public class FileOperationsHelper { } else { // Show a Message - Toast t = Toast.makeText(callerActivity, callerActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG); + Toast t = Toast.makeText(mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG); t.show(); } } - public void shareFileWithLinkToApp(OCFile file, Intent sendIntent, FileActivity callerActivity) { + public void shareFileWithLinkToApp(OCFile file, Intent sendIntent) { if (file != null) { - callerActivity.showLoadingDialog(); + mFileActivity.showLoadingDialog(); - Intent service = new Intent(callerActivity, OperationsService.class); + Intent service = new Intent(mFileActivity, OperationsService.class); service.setAction(OperationsService.ACTION_CREATE_SHARE); - service.putExtra(OperationsService.EXTRA_ACCOUNT, callerActivity.getAccount()); + service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); service.putExtra(OperationsService.EXTRA_SEND_INTENT, sendIntent); - callerActivity.getOperationsServiceBinder().newOperation(service); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); } else { Log_OC.wtf(TAG, "Trying to open a NULL OCFile"); @@ -134,39 +143,38 @@ public class FileOperationsHelper { /** * @return 'True' if the server supports the Share API */ - public boolean isSharedSupported(FileActivity callerActivity) { - if (callerActivity.getAccount() != null) { - AccountManager accountManager = AccountManager.get(callerActivity); + public boolean isSharedSupported() { + if (mFileActivity.getAccount() != null) { + AccountManager accountManager = AccountManager.get(mFileActivity); - String version = accountManager.getUserData(callerActivity.getAccount(), Constants.KEY_OC_VERSION); + String version = accountManager.getUserData(mFileActivity.getAccount(), Constants.KEY_OC_VERSION); return (new OwnCloudVersion(version)).isSharedSupported(); - //return Boolean.parseBoolean(accountManager.getUserData(callerActivity.getAccount(), OwnCloudAccount.Constants.KEY_SUPPORTS_SHARE_API)); } return false; } - public void unshareFileWithLink(OCFile file, FileActivity callerActivity) { + public void unshareFileWithLink(OCFile file) { - if (isSharedSupported(callerActivity)) { + if (isSharedSupported()) { // Unshare the file - Intent service = new Intent(callerActivity, OperationsService.class); + Intent service = new Intent(mFileActivity, OperationsService.class); service.setAction(OperationsService.ACTION_UNSHARE); - service.putExtra(OperationsService.EXTRA_ACCOUNT, callerActivity.getAccount()); + service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); - callerActivity.getOperationsServiceBinder().newOperation(service); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); - callerActivity.showLoadingDialog(); + mFileActivity.showLoadingDialog(); } else { // Show a Message - Toast t = Toast.makeText(callerActivity, callerActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG); + Toast t = Toast.makeText(mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG); t.show(); } } - public void sendDownloadedFile(OCFile file, FileActivity callerActivity) { + public void sendDownloadedFile(OCFile file) { if (file != null) { Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND); // set MimeType @@ -175,13 +183,74 @@ public class FileOperationsHelper { sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action // Show dialog, without the own app - String[] packagesToExclude = new String[] { callerActivity.getPackageName() }; + String[] packagesToExclude = new String[] { mFileActivity.getPackageName() }; DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file); - chooserDialog.show(callerActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG); + chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG); } else { Log_OC.wtf(TAG, "Trying to send a NULL OCFile"); } } + + + public void syncFile(OCFile file) { + // Sync file + Intent service = new Intent(mFileActivity, OperationsService.class); + service.setAction(OperationsService.ACTION_SYNC_FILE); + service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); + service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); + service.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); + + mFileActivity.showLoadingDialog(); + } + + + public void renameFile(OCFile file, String newFilename) { + // RenameFile + Intent service = new Intent(mFileActivity, OperationsService.class); + service.setAction(OperationsService.ACTION_RENAME); + service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); + service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); + service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); + + mFileActivity.showLoadingDialog(); + } + + public void removeFile(OCFile file, boolean onlyLocalCopy) { + // RemoveFile + Intent service = new Intent(mFileActivity, OperationsService.class); + service.setAction(OperationsService.ACTION_REMOVE); + service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); + service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); + service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); + + mFileActivity.showLoadingDialog(); + } + + + public void createFolder(String remotePath, boolean createFullPath) { + // Create Folder + Intent service = new Intent(mFileActivity, OperationsService.class); + service.setAction(OperationsService.ACTION_CREATE_FOLDER); + service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); + service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath); + service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service); + + mFileActivity.showLoadingDialog(); + } + + + public long getOpIdWaitingFor() { + return mWaitingForOpId; + } + + + public void setOpIdWaitingFor(long waitingForOpId) { + mWaitingForOpId = waitingForOpId; + } } diff --git a/src/com/owncloud/android/files/OwnCloudFileObserver.java b/src/com/owncloud/android/files/OwnCloudFileObserver.java index d5a42b5e..551bc25f 100644 --- a/src/com/owncloud/android/files/OwnCloudFileObserver.java +++ b/src/com/owncloud/android/files/OwnCloudFileObserver.java @@ -1,6 +1,6 @@ /* ownCloud Android client application * Copyright (C) 2012 Bartek Przybylski - * 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, @@ -91,11 +91,10 @@ public class OwnCloudFileObserver extends FileObserver { // again, assuming that local files are linked to a remote file AT MOST, SOMETHING TO BE DONE; SynchronizeFileOperation sfo = new SynchronizeFileOperation(file, null, - storageManager, mOCAccount, true, mContext); - RemoteOperationResult result = sfo.execute(mOCAccount, mContext); + RemoteOperationResult result = sfo.execute(storageManager, mContext); if (result.getCode() == ResultCode.SYNC_CONFLICT) { // ISSUE 5: if the user is not running the app (this is a service!), this can be very intrusive; a notification should be preferred Intent i = new Intent(mContext, ConflictsResolveActivity.class); diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java index d302e267..08f9d3d4 100644 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@ -38,6 +38,7 @@ import com.owncloud.android.lib.resources.files.RemoteFile; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.operations.UploadFileOperation; +import com.owncloud.android.operations.common.SyncOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation; @@ -549,10 +550,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe RemoteOperation operation = new ExistenceCheckRemoteOperation(pathToGrant, this, false); RemoteOperationResult result = operation.execute(mUploadClient); if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND && mCurrentUpload.isRemoteFolderToBeCreated()) { - operation = new CreateFolderOperation( pathToGrant, - true, - mStorageManager ); - result = operation.execute(mUploadClient); + SyncOperation syncOp = new CreateFolderOperation( pathToGrant, true); + result = syncOp.execute(mUploadClient, mStorageManager); } if (result.isSuccess()) { OCFile parentDir = mStorageManager.getFileByPath(pathToGrant); diff --git a/src/com/owncloud/android/operations/CreateFolderOperation.java b/src/com/owncloud/android/operations/CreateFolderOperation.java index 19e9ddc4..1058a235 100644 --- a/src/com/owncloud/android/operations/CreateFolderOperation.java +++ b/src/com/owncloud/android/operations/CreateFolderOperation.java @@ -1,5 +1,5 @@ /* ownCloud Android client application - * Copyright (C) 2012 ownCloud Inc. + * 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, @@ -17,13 +17,13 @@ package com.owncloud.android.operations; -import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.resources.files.CreateRemoteFolderOperation; 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.operations.common.SyncOperation; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.Log_OC; @@ -35,24 +35,21 @@ import com.owncloud.android.utils.Log_OC; * @author David A. Velasco * @author masensio */ -public class CreateFolderOperation extends RemoteOperation implements OnRemoteOperationListener{ +public class CreateFolderOperation extends SyncOperation implements OnRemoteOperationListener{ private static final String TAG = CreateFolderOperation.class.getSimpleName(); protected String mRemotePath; protected boolean mCreateFullPath; - protected FileDataStorageManager mStorageManager; /** * Constructor * * @param createFullPath 'True' means that all the ancestor folders should be created if don't exist yet. - * @param storageManager Reference to the local database corresponding to the account where the file is contained. */ - public CreateFolderOperation(String remotePath, boolean createFullPath, FileDataStorageManager storageManager) { + public CreateFolderOperation(String remotePath, boolean createFullPath) { mRemotePath = remotePath; mCreateFullPath = createFullPath; - mStorageManager = storageManager; } @@ -94,10 +91,10 @@ public class CreateFolderOperation extends RemoteOperation implements OnRemoteOp public void saveFolderInDB() { OCFile newDir = new OCFile(mRemotePath); newDir.setMimetype("DIR"); - long parentId = mStorageManager.getFileByPath(FileStorageUtils.getParentPath(mRemotePath)).getFileId(); + long parentId = getStorageManager().getFileByPath(FileStorageUtils.getParentPath(mRemotePath)).getFileId(); newDir.setParentId(parentId); newDir.setModificationTimestamp(System.currentTimeMillis()); - mStorageManager.saveFile(newDir); + getStorageManager().saveFile(newDir); Log_OC.d(TAG, "Create directory " + mRemotePath + " in Database"); diff --git a/src/com/owncloud/android/operations/DownloadFileOperation.java b/src/com/owncloud/android/operations/DownloadFileOperation.java index c672d572..52425a5b 100644 --- a/src/com/owncloud/android/operations/DownloadFileOperation.java +++ b/src/com/owncloud/android/operations/DownloadFileOperation.java @@ -21,10 +21,12 @@ import java.io.File; import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.operations.OperationCancelledException; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation; @@ -48,6 +50,7 @@ public class DownloadFileOperation extends RemoteOperation { private OCFile mFile; private Set mDataTransferListeners = new HashSet(); private long mModificationTimestamp = 0; + private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); private DownloadRemoteFileOperation mDownloadOperation; @@ -129,6 +132,12 @@ public class DownloadFileOperation extends RemoteOperation { String tmpFolder = getTmpFolder(); /// perform the download + synchronized(mCancellationRequested) { + if (mCancellationRequested.get()) { + return new RemoteOperationResult(new OperationCancelledException()); + } + } + mDownloadOperation = new DownloadRemoteFileOperation(mFile.getRemotePath(), tmpFolder); Iterator listener = mDataTransferListeners.iterator(); while (listener.hasNext()) { @@ -152,7 +161,10 @@ public class DownloadFileOperation extends RemoteOperation { } public void cancel() { - mDownloadOperation.cancel(); + mCancellationRequested.set(true); // atomic set; there is no need of synchronizing it + if (mDownloadOperation != null) { + mDownloadOperation.cancel(); + } } diff --git a/src/com/owncloud/android/operations/RemoveFileOperation.java b/src/com/owncloud/android/operations/RemoveFileOperation.java index ff673cad..6bd4e8a0 100644 --- a/src/com/owncloud/android/operations/RemoveFileOperation.java +++ b/src/com/owncloud/android/operations/RemoveFileOperation.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, @@ -17,40 +17,40 @@ package com.owncloud.android.operations; -import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; -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.lib.resources.files.RemoveRemoteFileOperation; +import com.owncloud.android.operations.common.SyncOperation; /** * Remote operation performing the removal of a remote file or folder in the ownCloud server. * * @author David A. Velasco + * @author masensio */ -public class RemoveFileOperation extends RemoteOperation { +public class RemoveFileOperation extends SyncOperation { // private static final String TAG = RemoveFileOperation.class.getSimpleName(); OCFile mFileToRemove; - boolean mDeleteLocalCopy; - FileDataStorageManager mDataStorageManager; + String mRemotePath; + boolean mOnlyLocalCopy; /** * Constructor * - * @param fileToRemove OCFile instance describing the remote file or folder to remove from the server - * @param deleteLocalCopy When 'true', and a local copy of the file exists, it is also removed. - * @param storageManager Reference to the local database corresponding to the account where the file is contained. + * @param remotePath RemotePath of the OCFile instance describing the remote file or + * folder to remove from the server + * @param onlyLocalCopy When 'true', and a local copy of the file exists, only this is + * removed. */ - public RemoveFileOperation(OCFile fileToRemove, boolean deleteLocalCopy, FileDataStorageManager storageManager) { - mFileToRemove = fileToRemove; - mDeleteLocalCopy = deleteLocalCopy; - mDataStorageManager = storageManager; + public RemoveFileOperation(String remotePath, boolean onlyLocalCopy) { + mRemotePath = remotePath; + mOnlyLocalCopy = onlyLocalCopy; } @@ -72,11 +72,25 @@ public class RemoveFileOperation extends RemoteOperation { protected RemoteOperationResult run(OwnCloudClient client) { RemoteOperationResult result = null; - RemoveRemoteFileOperation operation = new RemoveRemoteFileOperation(mFileToRemove.getRemotePath()); - result = operation.execute(client); + mFileToRemove = getStorageManager().getFileByPath(mRemotePath); + + boolean localRemovalFailed = false; + if (!mOnlyLocalCopy) { + RemoveRemoteFileOperation operation = new RemoveRemoteFileOperation(mRemotePath); + result = operation.execute(client); + if (result.isSuccess() || result.getCode() == ResultCode.FILE_NOT_FOUND) { + localRemovalFailed = !(getStorageManager().removeFile(mFileToRemove, true, true)); + } + + } else { + localRemovalFailed = !(getStorageManager().removeFile(mFileToRemove, false, true)); + if (!localRemovalFailed) { + result = new RemoteOperationResult(ResultCode.OK); + } + } - if (result.isSuccess() || result.getCode() == ResultCode.FILE_NOT_FOUND) { - mDataStorageManager.removeFile(mFileToRemove, true, mDeleteLocalCopy); + if (localRemovalFailed) { + result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_REMOVED); } return result; diff --git a/src/com/owncloud/android/operations/RenameFileOperation.java b/src/com/owncloud/android/operations/RenameFileOperation.java index a007af2b..b251d383 100644 --- a/src/com/owncloud/android/operations/RenameFileOperation.java +++ b/src/com/owncloud/android/operations/RenameFileOperation.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, @@ -20,13 +20,12 @@ package com.owncloud.android.operations; import java.io.File; import java.io.IOException; -import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; -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.lib.resources.files.RenameRemoteFileOperation; +import com.owncloud.android.operations.common.SyncOperation; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.Log_OC; @@ -37,33 +36,32 @@ import android.accounts.Account; * Remote operation performing the rename of a remote file (or folder?) in the ownCloud server. * * @author David A. Velasco + * @author masensio */ -public class RenameFileOperation extends RemoteOperation { +public class RenameFileOperation extends SyncOperation { private static final String TAG = RenameFileOperation.class.getSimpleName(); - private OCFile mFile; + private String mRemotePath; private Account mAccount; private String mNewName; private String mNewRemotePath; - private FileDataStorageManager mStorageManager; + /** * Constructor * - * @param file OCFile instance describing the remote file or folder to rename + * @param remotePath RemotePath of the OCFile instance describing the remote file or folder to rename * @param account OwnCloud account containing the remote file * @param newName New name to set as the name of file. - * @param storageManager Reference to the local database corresponding to the account where the file is contained. */ - public RenameFileOperation(OCFile file, Account account, String newName, FileDataStorageManager storageManager) { - mFile = file; + public RenameFileOperation(String remotePath, Account account, String newName) { + mRemotePath = remotePath; mAccount = account; mNewName = newName; mNewRemotePath = null; - mStorageManager = storageManager; } public OCFile getFile() { @@ -80,6 +78,8 @@ public class RenameFileOperation extends RemoteOperation { protected RemoteOperationResult run(OwnCloudClient client) { RemoteOperationResult result = null; + mFile = getStorageManager().getFileByPath(mRemotePath); + // check if the new name is valid in the local file system try { if (!isValidNewName()) { @@ -92,8 +92,8 @@ public class RenameFileOperation extends RemoteOperation { mNewRemotePath += OCFile.PATH_SEPARATOR; } - // ckeck local overwrite - if (mStorageManager.getFileByPath(mNewRemotePath) != null) { + // check local overwrite + if (getStorageManager().getFileByPath(mNewRemotePath) != null) { return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE); } @@ -120,7 +120,7 @@ public class RenameFileOperation extends RemoteOperation { private void saveLocalDirectory() { - mStorageManager.moveFolder(mFile, mNewRemotePath); + getStorageManager().moveFolder(mFile, mNewRemotePath); String localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile); File localDir = new File(localPath); if (localDir.exists()) { @@ -145,7 +145,7 @@ public class RenameFileOperation extends RemoteOperation { // TODO - study conditions when this could be a problem } - mStorageManager.saveFile(mFile); + getStorageManager().saveFile(mFile); } /** diff --git a/src/com/owncloud/android/operations/SynchronizeFileOperation.java b/src/com/owncloud/android/operations/SynchronizeFileOperation.java index 7189167d..1614ba1c 100644 --- a/src/com/owncloud/android/operations/SynchronizeFileOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFileOperation.java @@ -1,6 +1,6 @@ /* ownCloud Android client application * Copyright (C) 2012 Bartek Przybylski - * 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, @@ -18,16 +18,15 @@ package com.owncloud.android.operations; -import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.resources.files.RemoteFile; -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.lib.resources.files.ReadRemoteFileOperation; +import com.owncloud.android.operations.common.SyncOperation; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.Log_OC; @@ -42,13 +41,13 @@ import android.content.Intent; * @author masensio */ -public class SynchronizeFileOperation extends RemoteOperation { +public class SynchronizeFileOperation extends SyncOperation { private String TAG = SynchronizeFileOperation.class.getSimpleName(); private OCFile mLocalFile; + private String mRemotePath; private OCFile mServerFile; - private FileDataStorageManager mStorageManager; private Account mAccount; private boolean mSyncFileContents; private Context mContext; @@ -58,25 +57,39 @@ public class SynchronizeFileOperation extends RemoteOperation { public SynchronizeFileOperation( OCFile localFile, OCFile serverFile, // make this null to let the operation checks the server; added to reuse info from SynchronizeFolderOperation - FileDataStorageManager storageManager, Account account, boolean syncFileContents, Context context) { mLocalFile = localFile; mServerFile = serverFile; - mStorageManager = storageManager; mAccount = account; mSyncFileContents = syncFileContents; mContext = context; } + public SynchronizeFileOperation( + String remotePath, + Account account, + boolean syncFileContents, + Context context) { + + mRemotePath = remotePath; + mServerFile = null; + mAccount = account; + mSyncFileContents = syncFileContents; + mContext = context; + } @Override protected RemoteOperationResult run(OwnCloudClient client) { RemoteOperationResult result = null; mTransferWasRequested = false; + + // Get local file from the DB + mLocalFile = getStorageManager().getFileByPath(mRemotePath); + if (!mLocalFile.isDown()) { /// easy decision requestForDownload(mLocalFile); @@ -135,7 +148,7 @@ public class SynchronizeFileOperation extends RemoteOperation { mServerFile.setLastSyncDateForData(mLocalFile.getLastSyncDateForData()); mServerFile.setStoragePath(mLocalFile.getStoragePath()); mServerFile.setParentId(mLocalFile.getParentId()); - mStorageManager.saveFile(mServerFile); + getStorageManager().saveFile(mServerFile); } result = new RemoteOperationResult(ResultCode.OK); diff --git a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java index 68e78578..a8e230d5 100644 --- a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFolderOperation.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, @@ -350,11 +350,11 @@ public class SynchronizeFolderOperation extends RemoteOperation { if (remoteFile.keepInSync()) { SynchronizeFileOperation operation = new SynchronizeFileOperation( localFile, remoteFile, - mStorageManager, - mAccount, + mAccount, true, mContext ); + filesToSyncContents.add(operation); } @@ -382,7 +382,7 @@ public class SynchronizeFolderOperation extends RemoteOperation { private void startContentSynchronizations(List filesToSyncContents, OwnCloudClient client) { RemoteOperationResult contentsResult = null; for (SynchronizeFileOperation op: filesToSyncContents) { - contentsResult = op.execute(client); // returns without waiting for upload or download finishes + contentsResult = op.execute(mStorageManager, mContext); // returns without waiting for upload or download finishes if (!contentsResult.isSuccess()) { if (contentsResult.getCode() == ResultCode.SYNC_CONFLICT) { mConflictsFound++; diff --git a/src/com/owncloud/android/providers/FileContentProvider.java b/src/com/owncloud/android/providers/FileContentProvider.java index 54e67a24..c84d66b0 100644 --- a/src/com/owncloud/android/providers/FileContentProvider.java +++ b/src/com/owncloud/android/providers/FileContentProvider.java @@ -99,6 +99,8 @@ public class FileContentProvider extends ContentProvider { private static final int DIRECTORY = 2; private static final int ROOT_DIRECTORY = 3; private static final int SHARES = 4; + + private static final String TAG = FileContentProvider.class.getSimpleName(); // Projection for ocshares table private static HashMap mOCSharesProjectionMap; @@ -414,6 +416,7 @@ public class FileContentProvider extends ContentProvider { // DB case_sensitive db.execSQL("PRAGMA case_sensitive_like = true"); Cursor c = sqlQuery.query(db, projection, selection, selectionArgs, null, null, order); + Log_OC.d(TAG, "setting notification URI: " + uri); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } diff --git a/src/com/owncloud/android/services/OperationsService.java b/src/com/owncloud/android/services/OperationsService.java index 75363051..1c841f51 100644 --- a/src/com/owncloud/android/services/OperationsService.java +++ b/src/com/owncloud/android/services/OperationsService.java @@ -34,9 +34,13 @@ import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.resources.users.GetRemoteUserNameOperation; import com.owncloud.android.operations.common.SyncOperation; +import com.owncloud.android.operations.CreateFolderOperation; import com.owncloud.android.operations.CreateShareOperation; import com.owncloud.android.operations.GetServerInfoOperation; import com.owncloud.android.operations.OAuth2GetAccessToken; +import com.owncloud.android.operations.RemoveFileOperation; +import com.owncloud.android.operations.RenameFileOperation; +import com.owncloud.android.operations.SynchronizeFileOperation; import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.utils.Log_OC; @@ -64,6 +68,10 @@ public class OperationsService extends Service { public static final String EXTRA_OAUTH2_QUERY_PARAMETERS = "OAUTH2_QUERY_PARAMETERS"; public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH"; public static final String EXTRA_SEND_INTENT = "SEND_INTENT"; + public static final String EXTRA_NEWNAME = "NEWNAME"; + public static final String EXTRA_REMOVE_ONLY_LOCAL = "REMOVE_LOCAL_COPY"; + public static final String EXTRA_CREATE_FULL_PATH = "CREATE_FULL_PATH"; + public static final String EXTRA_SYNC_FILE_CONTENTS = "SYNC_FILE_CONTENTS"; public static final String EXTRA_RESULT = "RESULT"; // TODO review if ALL OF THEM are necessary @@ -81,17 +89,16 @@ public class OperationsService extends Service { public static final String ACTION_OAUTH2_GET_ACCESS_TOKEN = "OAUTH2_GET_ACCESS_TOKEN"; public static final String ACTION_EXISTENCE_CHECK = "EXISTENCE_CHECK"; public static final String ACTION_GET_USER_NAME = "GET_USER_NAME"; + public static final String ACTION_RENAME = "RENAME"; + public static final String ACTION_REMOVE = "REMOVE"; + public static final String ACTION_CREATE_FOLDER = "CREATE_FOLDER"; + public static final String ACTION_SYNC_FILE = "SYNC_FILE"; public static final String ACTION_OPERATION_ADDED = OperationsService.class.getName() + ".OPERATION_ADDED"; public static final String ACTION_OPERATION_FINISHED = OperationsService.class.getName() + ".OPERATION_FINISHED"; private ConcurrentLinkedQueue> mPendingOperations = new ConcurrentLinkedQueue>(); - - /* - private ConcurrentMap mOperationResults = - new ConcurrentHashMap(); - */ private ConcurrentMap> mUndispatchedFinishedOperations = @@ -335,7 +342,32 @@ public class OperationsService extends Service { } else if (action.equals(ACTION_GET_USER_NAME)) { // Get User Name operation = new GetRemoteUserNameOperation(); + + } else if (action.equals(ACTION_RENAME)) { + // Rename file or folder + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + String newName = operationIntent.getStringExtra(EXTRA_NEWNAME); + operation = new RenameFileOperation(remotePath, account, newName); + + } else if (action.equals(ACTION_REMOVE)) { + // Remove file or folder + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + boolean onlyLocalCopy = operationIntent.getBooleanExtra(EXTRA_REMOVE_ONLY_LOCAL, false); + operation = new RemoveFileOperation(remotePath, onlyLocalCopy); + + } else if (action.equals(ACTION_CREATE_FOLDER)) { + // Create Folder + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + boolean createFullPath = operationIntent.getBooleanExtra(EXTRA_CREATE_FULL_PATH, true); + operation = new CreateFolderOperation(remotePath, createFullPath); + + } else if (action.equals(ACTION_SYNC_FILE)) { + // Sync file + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + boolean syncFileContents = operationIntent.getBooleanExtra(EXTRA_SYNC_FILE_CONTENTS, true); + operation = new SynchronizeFileOperation(remotePath, account, syncFileContents, getApplicationContext()); } + } } catch (IllegalArgumentException e) { @@ -440,20 +472,20 @@ public class OperationsService extends Service { } else { result = mCurrentOperation.execute(mOwnCloudClient); } - + } catch (AccountsException e) { if (mLastTarget.mAccount == null) { - Log_OC.e(TAG, "Error while trying to get autorization for a NULL account", e); + Log_OC.e(TAG, "Error while trying to get authorization for a NULL account", e); } else { - Log_OC.e(TAG, "Error while trying to get autorization for " + mLastTarget.mAccount.name, e); + Log_OC.e(TAG, "Error while trying to get authorization for " + mLastTarget.mAccount.name, e); } result = new RemoteOperationResult(e); } catch (IOException e) { if (mLastTarget.mAccount == null) { - Log_OC.e(TAG, "Error while trying to get autorization for a NULL account", e); + Log_OC.e(TAG, "Error while trying to get authorization for a NULL account", e); } else { - Log_OC.e(TAG, "Error while trying to get autorization for " + mLastTarget.mAccount.name, e); + Log_OC.e(TAG, "Error while trying to get authorization for " + mLastTarget.mAccount.name, e); } result = new RemoteOperationResult(e); } catch (Exception e) { diff --git a/src/com/owncloud/android/ui/activity/ComponentsGetter.java b/src/com/owncloud/android/ui/activity/ComponentsGetter.java new file mode 100644 index 00000000..076a6cba --- /dev/null +++ b/src/com/owncloud/android/ui/activity/ComponentsGetter.java @@ -0,0 +1,49 @@ +/* ownCloud Android client application + * Copyright (C) 2012 Bartek Przybylski + * Copyright (C) 2012-2013 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.ui.activity; + +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.files.FileOperationsHelper; +import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; +import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; + +public interface ComponentsGetter { + + /** + * Callback method invoked when the parent activity is fully created to get a reference to the FileDownloader service API. + * + * @return Directory to list firstly. Can be NULL. + */ + public FileDownloaderBinder getFileDownloaderBinder(); + + + /** + * Callback method invoked when the parent activity is fully created to get a reference to the FileUploader service API. + * + * @return Directory to list firstly. Can be NULL. + */ + public FileUploaderBinder getFileUploaderBinder(); + + + + public FileDataStorageManager getStorageManager(); + + public FileOperationsHelper getFileOperationsHelper(); + +} diff --git a/src/com/owncloud/android/ui/activity/FileActivity.java b/src/com/owncloud/android/ui/activity/FileActivity.java index be437db8..eda47843 100644 --- a/src/com/owncloud/android/ui/activity/FileActivity.java +++ b/src/com/owncloud/android/ui/activity/FileActivity.java @@ -1,6 +1,6 @@ /* ownCloud Android client application * Copyright (C) 2011 Bartek Przybylski - * 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, @@ -18,11 +18,15 @@ package com.owncloud.android.ui.activity; +import org.apache.commons.httpclient.Credentials; + import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerFuture; +import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -39,9 +43,15 @@ import com.actionbarsherlock.app.SherlockFragmentActivity; import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.authentication.AccountUtils; +import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.FileOperationsHelper; +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.network.BearerCredentials; import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -60,7 +70,8 @@ import com.owncloud.android.utils.Log_OC; * * @author David A. Velasco */ -public class FileActivity extends SherlockFragmentActivity implements OnRemoteOperationListener { +public class FileActivity extends SherlockFragmentActivity +implements OnRemoteOperationListener, ComponentsGetter { public static final String EXTRA_FILE = "com.owncloud.android.ui.activity.FILE"; public static final String EXTRA_ACCOUNT = "com.owncloud.android.ui.activity.ACCOUNT"; @@ -70,6 +81,7 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp public static final String TAG = FileActivity.class.getSimpleName(); private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT"; + private static final String KEY_WAITING_FOR_OP_ID = "WAITING_FOR_OP_ID";; /** OwnCloud {@link Account} where the main {@link OCFile} handled by the activity is located. */ @@ -101,7 +113,11 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp private ServiceConnection mOperationsServiceConnection = null; private OperationsServiceBinder mOperationsServiceBinder = null; - + + protected FileDownloaderBinder mDownloaderBinder = null; + protected FileUploaderBinder mUploaderBinder = null; + private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null; + /** * Loads the ownCloud {@link Account} and main {@link OCFile} to be handled by the instance of @@ -114,12 +130,15 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mHandler = new Handler(); - mFileOperationsHelper = new FileOperationsHelper(); + mFileOperationsHelper = new FileOperationsHelper(this); Account account; if(savedInstanceState != null) { account = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT); mFile = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE); mFromNotification = savedInstanceState.getBoolean(FileActivity.EXTRA_FROM_NOTIFICATION); + mFileOperationsHelper.setOpIdWaitingFor( + savedInstanceState.getLong(KEY_WAITING_FOR_OP_ID, Long.MAX_VALUE) + ); } else { account = getIntent().getParcelableExtra(FileActivity.EXTRA_ACCOUNT); mFile = getIntent().getParcelableExtra(FileActivity.EXTRA_FILE); @@ -130,6 +149,16 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp mOperationsServiceConnection = new OperationsServiceConnection(); bindService(new Intent(this, OperationsService.class), mOperationsServiceConnection, Context.BIND_AUTO_CREATE); + + mDownloadServiceConnection = newTransferenceServiceConnection(); + if (mDownloadServiceConnection != null) { + bindService(new Intent(this, FileDownloader.class), mDownloadServiceConnection, Context.BIND_AUTO_CREATE); + } + mUploadServiceConnection = newTransferenceServiceConnection(); + if (mUploadServiceConnection != null) { + bindService(new Intent(this, FileUploader.class), mUploadServiceConnection, Context.BIND_AUTO_CREATE); + } + } @@ -160,6 +189,24 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp } } + @Override + protected void onResume() { + super.onResume(); + + if (mOperationsServiceBinder != null) { + doOnResumeAndBound(); + } + + } + + @Override + protected void onPause() { + if (mOperationsServiceBinder != null) { + mOperationsServiceBinder.removeOperationListener(this); + } + + super.onPause(); + } @Override protected void onStop() { @@ -179,6 +226,14 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp unbindService(mOperationsServiceConnection); mOperationsServiceBinder = null; } + if (mDownloadServiceConnection != null) { + unbindService(mDownloadServiceConnection); + mDownloadServiceConnection = null; + } + if (mUploadServiceConnection != null) { + unbindService(mUploadServiceConnection); + mUploadServiceConnection = null; + } } @@ -258,6 +313,7 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp outState.putParcelable(FileActivity.EXTRA_FILE, mFile); outState.putParcelable(FileActivity.EXTRA_ACCOUNT, mAccount); outState.putBoolean(FileActivity.EXTRA_FROM_NOTIFICATION, mFromNotification); + outState.putLong(KEY_WAITING_FOR_OP_ID, mFileOperationsHelper.getOpIdWaitingFor()); } @@ -308,7 +364,11 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp public OperationsServiceBinder getOperationsServiceBinder() { return mOperationsServiceBinder; } - + + protected ServiceConnection newTransferenceServiceConnection() { + return null; + } + /** * Helper class handling a callback from the {@link AccountManager} after the creation of @@ -393,7 +453,18 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp @Override public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { Log_OC.d(TAG, "Received result of operation in FileActivity - common behaviour for all the FileActivities "); - if (operation instanceof CreateShareOperation) { + + mFileOperationsHelper.setOpIdWaitingFor(Long.MAX_VALUE); + + if (!result.isSuccess() && ( + result.getCode() == ResultCode.UNAUTHORIZED || + result.isIdPRedirection() || + (result.isException() && result.getException() instanceof AuthenticatorException) + )) { + + requestCredentialsUpdate(); + + } else if (operation instanceof CreateShareOperation) { onCreateShareOperationFinish((CreateShareOperation) operation, result); } else if (operation instanceof UnshareLinkOperation) { @@ -402,6 +473,17 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp } } + private void requestCredentialsUpdate() { + Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class); + updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, getAccount()); + updateAccountCredentials.putExtra( + AuthenticatorActivity.EXTRA_ACTION, + AuthenticatorActivity.ACTION_UPDATE_EXPIRED_TOKEN); + updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + startActivity(updateAccountCredentials); + } + + private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) { dismissLoadingDialog(); if (result.isSuccess()) { @@ -471,6 +553,15 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp } + private void doOnResumeAndBound() { + mOperationsServiceBinder.addOperationListener(FileActivity.this, mHandler); + long waitingForOpId = mFileOperationsHelper.getOpIdWaitingFor(); + if (waitingForOpId <= Integer.MAX_VALUE) { + mOperationsServiceBinder.dispatchResultIfFinished((int)waitingForOpId, this); + } + } + + /** * Implements callback methods for service binding. Passed as a parameter to { */ @@ -481,10 +572,10 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp 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()) { + /*if (!mOperationsServiceBinder.isPerformingBlockingOperation()) { dismissLoadingDialog(); - } + }*/ + doOnResumeAndBound(); } else { return; @@ -500,6 +591,19 @@ public class FileActivity extends SherlockFragmentActivity implements OnRemoteOp // TODO whatever could be waiting for the service is unbound } } + } + + + @Override + public FileDownloaderBinder getFileDownloaderBinder() { + return mDownloaderBinder; + } + + + @Override + public FileUploaderBinder getFileUploaderBinder() { + return mUploaderBinder; }; + } diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index f6136ed3..6cfa56c5 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -78,16 +78,15 @@ 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; +import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog; -import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener; 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; @@ -102,17 +101,13 @@ import com.owncloud.android.utils.Log_OC; */ public class FileDisplayActivity extends HookActivity implements -OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener, EditNameDialogListener { +FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener { private ArrayAdapter mDirectories; private SyncBroadcastReceiver mSyncBroadcastReceiver; private UploadFinishReceiver mUploadFinishReceiver; private DownloadFinishReceiver mDownloadFinishReceiver; - //private OperationsServiceReceiver mOperationsServiceReceiver; - private FileDownloaderBinder mDownloaderBinder = null; - private FileUploaderBinder mUploaderBinder = null; - private ServiceConnection mDownloadConnection = null, mUploadConnection = null; private RemoteOperationResult mLastSslUntrustedServerResult = null; private boolean mDualPane; @@ -121,12 +116,10 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa private static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW"; private static final String KEY_SYNC_IN_PROGRESS = "SYNC_IN_PROGRESS"; - //private static final String KEY_REFRESH_SHARES_IN_PROGRESS = "SHARES_IN_PROGRESS"; private static final String KEY_WAITING_TO_SEND = "WAITING_TO_SEND"; public static final int DIALOG_SHORT_WAIT = 0; private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 1; - //private static final int DIALOG_SSL_VALIDATOR = 2; private static final int DIALOG_CERT_NOT_SAVED = 2; public static final String ACTION_DETAILS = "com.owncloud.android.ui.activity.action.DETAILS"; @@ -142,7 +135,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa private OCFile mWaitingToPreview; private boolean mSyncInProgress = false; - //private boolean mRefreshSharesInProgress = false; private String DIALOG_UNTRUSTED_CERT; @@ -155,12 +147,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa super.onCreate(savedInstanceState); // this calls onAccountChanged() when ownCloud Account is valid - /// bindings to transference services - mUploadConnection = new ListServiceConnection(); - mDownloadConnection = new ListServiceConnection(); - bindService(new Intent(this, FileUploader.class), mUploadConnection, Context.BIND_AUTO_CREATE); - bindService(new Intent(this, FileDownloader.class), mDownloadConnection, Context.BIND_AUTO_CREATE); - // PIN CODE request ; best location is to decide, let's try this first if (getIntent().getAction() != null && getIntent().getAction().equals(Intent.ACTION_MAIN) && savedInstanceState == null) { requestPinCode(); @@ -177,13 +163,11 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa if(savedInstanceState != null) { mWaitingToPreview = (OCFile) savedInstanceState.getParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW); mSyncInProgress = savedInstanceState.getBoolean(KEY_SYNC_IN_PROGRESS); - //mRefreshSharesInProgress = savedInstanceState.getBoolean(KEY_REFRESH_SHARES_IN_PROGRESS); mWaitingToSend = (OCFile) savedInstanceState.getParcelable(FileDisplayActivity.KEY_WAITING_TO_SEND); } else { mWaitingToPreview = null; mSyncInProgress = false; - //mRefreshSharesInProgress = false; mWaitingToSend = null; } @@ -215,16 +199,11 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa protected void onStart() { super.onStart(); getSupportActionBar().setIcon(DisplayUtils.getSeasonalIconId()); - refeshListOfFilesFragment(); } @Override protected void onDestroy() { super.onDestroy(); - if (mDownloadConnection != null) - unbindService(mDownloadConnection); - if (mUploadConnection != null) - unbindService(mUploadConnection); } /** @@ -397,7 +376,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa return null; } - protected FileFragment getSecondFragment() { + public FileFragment getSecondFragment() { Fragment second = getSupportFragmentManager().findFragmentByTag(FileDisplayActivity.TAG_SECOND_FRAGMENT); if (second != null) { return (FileFragment)second; @@ -405,7 +384,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa return null; } - public void cleanSecondFragment() { + protected void cleanSecondFragment() { Fragment second = getSecondFragment(); if (second != null) { FragmentTransaction tr = getSupportFragmentManager().beginTransaction(); @@ -416,7 +395,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa updateNavigationElementsInActionBar(null); } - protected void refeshListOfFilesFragment() { + protected void refreshListOfFilesFragment() { OCFileListFragment fileListFragment = getListOfFilesFragment(); if (fileListFragment != null) { fileListFragment.listDirectory(); @@ -448,7 +427,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa startMediaPreview(mWaitingToPreview, 0, true); detailsFragmentChanged = true; } else { - getFileOperationsHelper().openFile(mWaitingToPreview, this); + getFileOperationsHelper().openFile(mWaitingToPreview); } } mWaitingToPreview = null; @@ -472,7 +451,8 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa boolean retval = true; switch (item.getItemId()) { case R.id.action_create_dir: { - EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.uploader_info_dirname), "", -1, -1, this); + CreateFolderDialogFragment dialog = + CreateFolderDialogFragment.newInstance(getCurrentDir()); dialog.show(getSupportFragmentManager(), "createdirdialog"); break; } @@ -689,7 +669,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa // Listen for sync messages IntentFilter syncIntentFilter = new IntentFilter(FileSyncAdapter.EVENT_FULL_SYNC_START); syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_END); - //syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED); syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED); syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED); syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED); @@ -708,14 +687,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa mDownloadFinishReceiver = new DownloadFinishReceiver(); registerReceiver(mDownloadFinishReceiver, downloadIntentFilter); - // Listen for messages from the OperationsService - /* - IntentFilter operationsIntentFilter = new IntentFilter(OperationsService.ACTION_OPERATION_ADDED); - operationsIntentFilter.addAction(OperationsService.ACTION_OPERATION_FINISHED); - mOperationsServiceReceiver = new OperationsServiceReceiver(); - LocalBroadcastManager.getInstance(this).registerReceiver(mOperationsServiceReceiver, operationsIntentFilter); - */ - Log_OC.d(TAG, "onResume() end"); } @@ -737,12 +708,9 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa unregisterReceiver(mDownloadFinishReceiver); mDownloadFinishReceiver = null; } - /* - if (mOperationsServiceReceiver != null) { - LocalBroadcastManager.getInstance(this).unregisterReceiver(mOperationsServiceReceiver); - mOperationsServiceReceiver = null; - } - */ + + dismissLoadingDialog(); + Log_OC.d(TAG, "onPause() end"); } @@ -940,7 +908,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa cleanSecondFragment(); currentFile = currentDir; } - + if (synchFolderRemotePath != null && currentDir.getRemotePath().equals(synchFolderRemotePath)) { OCFileListFragment fileListFragment = getListOfFilesFragment(); if (fileListFragment != null) { @@ -952,19 +920,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event)); - /* - if (synchResult != null && - synchResult.isSuccess() && - (SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SYNCED.equals(event) || - FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED.equals(event) - ) && - !mRefreshSharesInProgress && - getFileOperationsHelper().isSharedSupported(FileDisplayActivity.this) - ) { - startGetShares(); - } - */ - } removeStickyBroadcast(intent); Log_OC.d(TAG, "Setting progress visibility to " + mSyncInProgress); @@ -985,6 +940,9 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa } + /** + * Once the file upload has finished -> update view + */ private class UploadFinishReceiver extends BroadcastReceiver { /** * Once the file upload has finished -> update view @@ -997,12 +955,52 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME); boolean sameAccount = getAccount() != null && accountName.equals(getAccount().name); OCFile currentDir = getCurrentDir(); - boolean isDescendant = (currentDir != null) && (uploadedRemotePath != null) && (uploadedRemotePath.startsWith(currentDir.getRemotePath())); + boolean isDescendant = (currentDir != null) && (uploadedRemotePath != null) && + (uploadedRemotePath.startsWith(currentDir.getRemotePath())); + if (sameAccount && isDescendant) { - refeshListOfFilesFragment(); + refreshListOfFilesFragment(); } + + boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false); + boolean renamedInUpload = getFile().getRemotePath(). + equals(intent.getStringExtra(FileUploader.EXTRA_OLD_REMOTE_PATH)); + boolean sameFile = getFile().getRemotePath().equals(uploadedRemotePath) || + renamedInUpload; + FileFragment details = getSecondFragment(); + boolean detailFragmentIsShown = (details != null && + details instanceof FileDetailFragment); + + if (sameAccount && sameFile && detailFragmentIsShown) { + if (uploadWasFine) { + setFile(getStorageManager().getFileByPath(uploadedRemotePath)); + } + if (renamedInUpload) { + String newName = (new File(uploadedRemotePath)).getName(); + Toast msg = Toast.makeText( + context, + String.format( + getString(R.string.filedetails_renamed_in_upload_msg), + newName), + Toast.LENGTH_LONG); + msg.show(); + } + if (uploadWasFine || getFile().fileExists()) { + ((FileDetailFragment)details).updateFileDetails(false, true); + } else { + cleanSecondFragment(); + } + + // Force the preview if the file is an image + if (uploadWasFine && PreviewImageFragment.canBePreviewed(getFile())) { + startImagePreview(getFile()); + } // TODO what about other kind of previews? + } + + removeStickyBroadcast(intent); + } - + } @@ -1020,7 +1018,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa boolean isDescendant = isDescendant(downloadedRemotePath); if (sameAccount && isDescendant) { - refeshListOfFilesFragment(); + refreshListOfFilesFragment(); refreshSecondFragment(intent.getAction(), downloadedRemotePath, intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false)); } @@ -1046,44 +1044,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa } - /** - * Class waiting for broadcast events from the {@link OperationsService}. - * - * Updates the list of files when a get for shares is finished; at this moment the refresh of shares is the only - * operation performed in {@link OperationsService}. - * - * In the future will handle the progress or finalization of all the operations performed in {@link OperationsService}, - * probably all the operations associated to the app model. - */ - private class OperationsServiceReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - if (OperationsService.ACTION_OPERATION_ADDED.equals(intent.getAction())) { - - } else if (OperationsService.ACTION_OPERATION_FINISHED.equals(intent.getAction())) { - //mRefreshSharesInProgress = false; - - Account account = intent.getParcelableExtra(OperationsService.EXTRA_ACCOUNT); - RemoteOperationResult getSharesResult = (RemoteOperationResult)intent.getSerializableExtra(OperationsService.EXTRA_RESULT); - if (getAccount() != null && account.name.equals(getAccount().name) - && getStorageManager() != null - ) { - refeshListOfFilesFragment(); - } - if ((getSharesResult != null) && - RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED.equals(getSharesResult.getCode())) { - mLastSslUntrustedServerResult = getSharesResult; - showUntrustedCertDialog(mLastSslUntrustedServerResult); - } - - //setSupportProgressBarIndeterminateVisibility(mRefreshSharesInProgress || mSyncInProgress); - } - - } - - } - public void browseToRoot() { OCFileListFragment listOfFiles = getListOfFilesFragment(); if (listOfFiles != null) { // should never be null, indeed @@ -1132,54 +1092,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa } /** - * Opens the image gallery showing the image {@link OCFile} received as parameter. - * - * @param file Image {@link OCFile} to show. - */ - @Override - public void startImagePreview(OCFile file) { - Intent showDetailsIntent = new Intent(this, PreviewImageActivity.class); - showDetailsIntent.putExtra(EXTRA_FILE, file); - showDetailsIntent.putExtra(EXTRA_ACCOUNT, getAccount()); - startActivity(showDetailsIntent); - } - - /** - * Stars the preview of an already down media {@link OCFile}. - * - * @param file Media {@link OCFile} to preview. - * @param startPlaybackPosition Media position where the playback will be started, in milliseconds. - * @param autoplay When 'true', the playback will start without user interactions. - */ - @Override - public void startMediaPreview(OCFile file, int startPlaybackPosition, boolean autoplay) { - Fragment mediaFragment = new PreviewMediaFragment(file, getAccount(), startPlaybackPosition, autoplay); - setSecondFragment(mediaFragment); - updateFragmentsVisibility(true); - updateNavigationElementsInActionBar(file); - setFile(file); - } - - /** - * Requests the download of the received {@link OCFile} , updates the UI - * to monitor the download progress and prepares the activity to preview - * or open the file when the download finishes. - * - * @param file {@link OCFile} to download and preview. - */ - @Override - public void startDownloadForPreview(OCFile file) { - Fragment detailFragment = new FileDetailFragment(file, getAccount()); - setSecondFragment(detailFragment); - mWaitingToPreview = file; - requestForDownload(); - updateFragmentsVisibility(true); - updateNavigationElementsInActionBar(file); - setFile(file); - } - - - /** * Shows the information of the {@link OCFile} received as a * parameter in the second fragment. * @@ -1221,34 +1133,11 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa } - /** - * {@inheritDoc} - */ - @Override - public void onFileStateChanged() { - refeshListOfFilesFragment(); - updateNavigationElementsInActionBar(getSecondFragment().getFile()); - } - - - /** - * {@inheritDoc} - */ - @Override - public FileDownloaderBinder getFileDownloaderBinder() { - return mDownloaderBinder; - } - - - /** - * {@inheritDoc} - */ @Override - public FileUploaderBinder getFileUploaderBinder() { - return mUploaderBinder; + protected ServiceConnection newTransferenceServiceConnection() { + return new ListServiceConnection(); } - /** Defines callbacks for service binding, passed to bindService() */ private class ListServiceConnection implements ServiceConnection { @@ -1257,8 +1146,12 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) { Log_OC.d(TAG, "Download service connected"); mDownloaderBinder = (FileDownloaderBinder) service; - if (mWaitingToPreview != null) { - requestForDownload(); + if (mWaitingToPreview != null) + if (getStorageManager() != null) { + mWaitingToPreview = getStorageManager().getFileById(mWaitingToPreview.getFileId()); // update the file + if (!mWaitingToPreview.isDown()) { + requestForDownload(); + } } } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) { @@ -1362,7 +1255,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) { if (result.isSuccess()) { refreshShowDetails(); - refeshListOfFilesFragment(); + refreshListOfFilesFragment(); } } @@ -1370,10 +1263,11 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) { if (result.isSuccess()) { refreshShowDetails(); - refeshListOfFilesFragment(); + refreshListOfFilesFragment(); + } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND) { cleanSecondFragment(); - refeshListOfFilesFragment(); + refreshListOfFilesFragment(); } } @@ -1407,15 +1301,18 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa Toast msg = Toast.makeText(this, R.string.remove_success_msg, Toast.LENGTH_LONG); msg.show(); OCFile removedFile = operation.getFile(); - getSecondFragment(); FileFragment second = getSecondFragment(); if (second != null && removedFile.equals(second.getFile())) { + if (second instanceof PreviewMediaFragment) { + ((PreviewMediaFragment)second).stopPreview(true); + } + setFile(getStorageManager().getFileById(removedFile.getParentId())); cleanSecondFragment(); } if (getStorageManager().getFileById(removedFile.getParentId()).equals(getCurrentDir())) { - refeshListOfFilesFragment(); + refreshListOfFilesFragment(); } - + invalidateOptionsMenu(); } else { Toast msg = Toast.makeText(this, R.string.remove_fail_msg, Toast.LENGTH_LONG); msg.show(); @@ -1425,7 +1322,8 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa } } } - + + /** * Updates the view associated to the activity after the finish of an operation trying create a new folder * @@ -1435,8 +1333,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa private void onCreateFolderOperationFinish(CreateFolderOperation operation, RemoteOperationResult result) { if (result.isSuccess()) { dismissLoadingDialog(); - refeshListOfFilesFragment(); - + refreshListOfFilesFragment(); } else { dismissLoadingDialog(); if (result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME) { @@ -1465,14 +1362,24 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa dismissLoadingDialog(); OCFile renamedFile = operation.getFile(); if (result.isSuccess()) { - if (mDualPane) { - FileFragment details = getSecondFragment(); - if (details != null && details instanceof FileDetailFragment && renamedFile.equals(details.getFile()) ) { + FileFragment details = getSecondFragment(); + if (details != null) + if (details instanceof FileDetailFragment && renamedFile.equals(details.getFile()) ) { ((FileDetailFragment) details).updateFileDetails(renamedFile, getAccount()); + showDetails(renamedFile); + + } else if (details instanceof PreviewMediaFragment && renamedFile.equals(details.getFile())) { + ((PreviewMediaFragment) details).updateFile(renamedFile); + if (PreviewMediaFragment.canBePreviewed(renamedFile)) { + int position = ((PreviewMediaFragment)details).getPosition(); + startMediaPreview(renamedFile, position, true); + } else { + getFileOperationsHelper().openFile(renamedFile); } } + if (getStorageManager().getFileById(renamedFile.getParentId()).equals(getCurrentDir())) { - refeshListOfFilesFragment(); + refreshListOfFilesFragment(); } } else { @@ -1494,7 +1401,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa } } - private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, RemoteOperationResult result) { dismissLoadingDialog(); OCFile syncedFile = operation.getLocalFile(); @@ -1506,12 +1412,11 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa startActivity(i); } - + } else { if (operation.transferWasRequested()) { - refeshListOfFilesFragment(); onTransferStateChanged(syncedFile, true, true); - + } else { Toast msg = Toast.makeText(this, R.string.sync_file_nothing_to_do_msg, Toast.LENGTH_LONG); msg.show(); @@ -1519,42 +1424,18 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa } } - + /** * {@inheritDoc} */ @Override public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading) { - if (mDualPane) { - FileFragment details = getSecondFragment(); - if (details != null && details instanceof FileDetailFragment && file.equals(details.getFile()) ) { - if (downloading || uploading) { - ((FileDetailFragment)details).updateFileDetails(file, getAccount()); - } else { - ((FileDetailFragment)details).updateFileDetails(false, true); - } - } - } - } - - - public void onDismiss(EditNameDialog dialog) { - if (dialog.getResult()) { - String newDirectoryName = dialog.getNewFilename().trim(); - Log_OC.d(TAG, "'create directory' dialog dismissed with new name " + newDirectoryName); - if (newDirectoryName.length() > 0) { - String path = getCurrentDir().getRemotePath(); - - // Create directory - path += newDirectoryName + OCFile.PATH_SEPARATOR; - RemoteOperation operation = new CreateFolderOperation(path, false, getStorageManager()); - operation.execute( getAccount(), - FileDisplayActivity.this, - FileDisplayActivity.this, - getHandler(), - FileDisplayActivity.this); - - showLoadingDialog(); + FileFragment details = getSecondFragment(); + if (details != null && details instanceof FileDetailFragment && file.equals(details.getFile()) ) { + if (downloading || uploading) { + ((FileDetailFragment)details).updateFileDetails(file, getAccount()); + } else { + ((FileDetailFragment)details).updateFileDetails(false, true); } } } @@ -1593,7 +1474,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa RemoteOperation synchFolderOp = new SynchronizeFolderOperation( folder, currentSyncTime, false, - getFileOperationsHelper().isSharedSupported(this), + getFileOperationsHelper().isSharedSupported(), getStorageManager(), getAccount(), getApplicationContext() @@ -1603,17 +1484,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa setSupportProgressBarIndeterminateVisibility(true); } - /* - private void startGetShares() { - // Get shared files/folders - Intent intent = new Intent(this, OperationsService.class); - intent.putExtra(OperationsService.EXTRA_ACCOUNT, getAccount()); - startService(intent); - - mRefreshSharesInProgress = true; - } - */ - /** * Show untrusted cert dialog */ @@ -1625,6 +1495,22 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa dialog.show(ft, DIALOG_UNTRUSTED_CERT); } + private void requestForDownload(OCFile file) { + Account account = getAccount(); + if (!mDownloaderBinder.isDownloading(account, file)) { + Intent i = new Intent(this, FileDownloader.class); + i.putExtra(FileDownloader.EXTRA_ACCOUNT, account); + i.putExtra(FileDownloader.EXTRA_FILE, file); + startService(i); + } + } + + private void sendDownloadedFile(){ + getFileOperationsHelper().sendDownloadedFile(mWaitingToSend); + mWaitingToSend = null; + } + + /** * Requests the download of the received {@link OCFile} , updates the UI * to monitor the download progress and prepares the activity to send the file @@ -1632,7 +1518,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa * * @param file {@link OCFile} to download and preview. */ - @Override public void startDownloadForSending(OCFile file) { mWaitingToSend = file; requestForDownload(mWaitingToSend); @@ -1640,19 +1525,68 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa updateFragmentsVisibility(hasSecondFragment); } - private void requestForDownload(OCFile file) { + /** + * Opens the image gallery showing the image {@link OCFile} received as parameter. + * + * @param file Image {@link OCFile} to show. + */ + public void startImagePreview(OCFile file) { + Intent showDetailsIntent = new Intent(this, PreviewImageActivity.class); + showDetailsIntent.putExtra(EXTRA_FILE, file); + showDetailsIntent.putExtra(EXTRA_ACCOUNT, getAccount()); + startActivity(showDetailsIntent); + } + + /** + * Stars the preview of an already down media {@link OCFile}. + * + * @param file Media {@link OCFile} to preview. + * @param startPlaybackPosition Media position where the playback will be started, in milliseconds. + * @param autoplay When 'true', the playback will start without user interactions. + */ + public void startMediaPreview(OCFile file, int startPlaybackPosition, boolean autoplay) { + Fragment mediaFragment = new PreviewMediaFragment(file, getAccount(), startPlaybackPosition, autoplay); + setSecondFragment(mediaFragment); + updateFragmentsVisibility(true); + updateNavigationElementsInActionBar(file); + setFile(file); + } + + /** + * Requests the download of the received {@link OCFile} , updates the UI + * to monitor the download progress and prepares the activity to preview + * or open the file when the download finishes. + * + * @param file {@link OCFile} to download and preview. + */ + public void startDownloadForPreview(OCFile file) { + Fragment detailFragment = new FileDetailFragment(file, getAccount()); + setSecondFragment(detailFragment); + mWaitingToPreview = file; + requestForDownload(); + updateFragmentsVisibility(true); + updateNavigationElementsInActionBar(file); + setFile(file); + } + + + public void cancelTransference(OCFile file) { Account account = getAccount(); - if (!mDownloaderBinder.isDownloading(account, file)) { - Intent i = new Intent(this, FileDownloader.class); - i.putExtra(FileDownloader.EXTRA_ACCOUNT, account); - i.putExtra(FileDownloader.EXTRA_FILE, file); - startService(i); + if (mDownloaderBinder != null && mDownloaderBinder.isDownloading(account, file)) { + mDownloaderBinder.cancel(account, file); + refreshListOfFilesFragment(); + onTransferStateChanged(file, false, false); + + } else if (mUploaderBinder != null && mUploaderBinder.isUploading(account, file)) { + mUploaderBinder.cancel(account, file); + refreshListOfFilesFragment(); + if (!file.fileExists()) { + cleanSecondFragment(); + + } else { + onTransferStateChanged(file, false, false); + } } } - private void sendDownloadedFile(){ - getFileOperationsHelper().sendDownloadedFile(mWaitingToSend, this); - mWaitingToSend = null; - } - } diff --git a/src/com/owncloud/android/ui/activity/TransferServiceGetter.java b/src/com/owncloud/android/ui/activity/TransferServiceGetter.java deleted file mode 100644 index fbc348d9..00000000 --- a/src/com/owncloud/android/ui/activity/TransferServiceGetter.java +++ /dev/null @@ -1,42 +0,0 @@ -/* ownCloud Android client application - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 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.ui.activity; - -import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; -import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; - -public interface TransferServiceGetter { - - /** - * Callback method invoked when the parent activity is fully created to get a reference to the FileDownloader service API. - * - * @return Directory to list firstly. Can be NULL. - */ - public FileDownloaderBinder getFileDownloaderBinder(); - - - /** - * Callback method invoked when the parent activity is fully created to get a reference to the FileUploader service API. - * - * @return Directory to list firstly. Can be NULL. - */ - public FileUploaderBinder getFileUploaderBinder(); - - -} diff --git a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java index 8b4a41d2..db0802ba 100644 --- a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java +++ b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java @@ -36,10 +36,10 @@ import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.ActionBar.OnNavigationListener; import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.R; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; import com.owncloud.android.ui.dialog.IndeterminateProgressDialog; -import com.owncloud.android.ui.fragment.ConfirmationDialogFragment; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment.ConfirmationDialogFragmentListener; import com.owncloud.android.ui.fragment.LocalFileListFragment; -import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.Log_OC; diff --git a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java index 11449af8..38ade7c8 100644 --- a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java +++ b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java @@ -18,7 +18,7 @@ package com.owncloud.android.ui.adapter; import android.accounts.Account; -import android.content.Context; +import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -37,7 +37,7 @@ import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; -import com.owncloud.android.ui.activity.TransferServiceGetter; +import com.owncloud.android.ui.activity.ComponentsGetter; import com.owncloud.android.utils.DisplayUtils; @@ -52,15 +52,16 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter { private Context mContext; private OCFile mFile = null; private Vector mFiles = null; - private FileDataStorageManager mStorageManager; - private Account mAccount; - private TransferServiceGetter mTransferServiceGetter; + + private FileDataStorageManager mStorageManager; + private Account mAccount; + private ComponentsGetter mTransferServiceGetter; - public FileListListAdapter(Context context, TransferServiceGetter transferServiceGetter) { + public FileListListAdapter(Context context, ComponentsGetter transferServiceGetter) { mContext = context; mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext); mTransferServiceGetter = transferServiceGetter; - } + } @Override public boolean areAllItemsEnabled() { diff --git a/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java b/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java new file mode 100644 index 00000000..52c1ac48 --- /dev/null +++ b/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java @@ -0,0 +1,126 @@ +/* ownCloud Android client application + * Copyright (C) 2012 Bartek Przybylski + * Copyright (C) 2012-2013 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.ui.dialog; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockDialogFragment; +import com.owncloud.android.utils.Log_OC; + + +public class ConfirmationDialogFragment extends SherlockDialogFragment { + + public final static String ARG_CONF_RESOURCE_ID = "resource_id"; + public final static String ARG_CONF_ARGUMENTS = "string_array"; + + public final static String ARG_POSITIVE_BTN_RES = "positive_btn_res"; + public final static String ARG_NEUTRAL_BTN_RES = "neutral_btn_res"; + public final static String ARG_NEGATIVE_BTN_RES = "negative_btn_res"; + + public static final String FTAG_CONFIRMATION = "CONFIRMATION_FRAGMENT"; + + private ConfirmationDialogFragmentListener mListener; + + /** + * Public factory method to create new ConfirmationDialogFragment instances. + * + * @param string_id Resource id for a message to show in the dialog. + * @param arguments Arguments to complete the message, if it's a format string. + * @param posBtn Resource id for the text of the positive button. + * @param neuBtn Resource id for the text of the neutral button. + * @param negBtn Resource id for the text of the negative button. + * @return Dialog ready to show. + */ + public static ConfirmationDialogFragment newInstance(int string_id, String[] arguments, int posBtn, int neuBtn, int negBtn) { + ConfirmationDialogFragment frag = new ConfirmationDialogFragment(); + Bundle args = new Bundle(); + args.putInt(ARG_CONF_RESOURCE_ID, string_id); + args.putStringArray(ARG_CONF_ARGUMENTS, arguments); + args.putInt(ARG_POSITIVE_BTN_RES, posBtn); + args.putInt(ARG_NEUTRAL_BTN_RES, neuBtn); + args.putInt(ARG_NEGATIVE_BTN_RES, negBtn); + frag.setArguments(args); + return frag; + } + + public void setOnConfirmationListener(ConfirmationDialogFragmentListener listener) { + mListener = listener; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Object[] confirmationTarget = getArguments().getStringArray(ARG_CONF_ARGUMENTS); + int resourceId = getArguments().getInt(ARG_CONF_RESOURCE_ID, -1); + int posBtn = getArguments().getInt(ARG_POSITIVE_BTN_RES, -1); + int neuBtn = getArguments().getInt(ARG_NEUTRAL_BTN_RES, -1); + int negBtn = getArguments().getInt(ARG_NEGATIVE_BTN_RES, -1); + + if (confirmationTarget == null || resourceId == -1) { + Log_OC.wtf(getTag(), "Calling confirmation dialog without resource or arguments"); + return null; + } + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) + .setIcon(android.R.drawable.ic_dialog_alert) + .setMessage(String.format(getString(resourceId), confirmationTarget)) + .setTitle(android.R.string.dialog_alert_title); + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { + builder.setIconAttribute(android.R.attr.alertDialogIcon); + } + + if (posBtn != -1) + builder.setPositiveButton(posBtn, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + mListener.onConfirmation(getTag()); + dialog.dismiss(); + } + }); + if (neuBtn != -1) + builder.setNeutralButton(neuBtn, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + mListener.onNeutral(getTag()); + dialog.dismiss(); + } + }); + if (negBtn != -1) + builder.setNegativeButton(negBtn, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + mListener.onCancel(getTag()); + dialog.dismiss(); + } + }); + return builder.create(); + } + + + public interface ConfirmationDialogFragmentListener { + public void onConfirmation(String callerTag); + public void onNeutral(String callerTag); + public void onCancel(String callerTag); + } + +} + diff --git a/src/com/owncloud/android/ui/dialog/CreateFolderDialogFragment.java b/src/com/owncloud/android/ui/dialog/CreateFolderDialogFragment.java new file mode 100644 index 00000000..66af9d5f --- /dev/null +++ b/src/com/owncloud/android/ui/dialog/CreateFolderDialogFragment.java @@ -0,0 +1,122 @@ +/* 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.ui.dialog; + +import com.actionbarsherlock.app.SherlockDialogFragment; +import com.owncloud.android.R; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.lib.resources.files.FileUtils; +import com.owncloud.android.ui.activity.ComponentsGetter; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager.LayoutParams; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +/** + * Dialog to input the name for a new folder to create. + * + * Triggers the folder creation when name is confirmed. + * + * @author David A. Velasco + */ +public class CreateFolderDialogFragment +extends SherlockDialogFragment implements DialogInterface.OnClickListener { + + private static final String ARG_PARENT_FOLDER = "PARENT_FOLDER"; + + /** + * Public factory method to create new CreateFolderDialogFragment instances. + * + * @param file File to remove. + * @return Dialog ready to show. + */ + public static CreateFolderDialogFragment newInstance(OCFile parentFolder) { + CreateFolderDialogFragment frag = new CreateFolderDialogFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_PARENT_FOLDER, parentFolder); + frag.setArguments(args); + return frag; + + } + + private OCFile mParentFolder; + + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + mParentFolder = getArguments().getParcelable(ARG_PARENT_FOLDER); + + // Inflate the layout for the dialog + LayoutInflater inflater = getSherlockActivity().getLayoutInflater(); + View v = inflater.inflate(R.layout.edit_box_dialog, null); + + // Setup layout + EditText inputText = ((EditText)v.findViewById(R.id.user_input)); + inputText.setText(""); + inputText.requestFocus(); + + // Build the dialog + AlertDialog.Builder builder = new AlertDialog.Builder(getSherlockActivity()); + builder.setView(v) + .setPositiveButton(R.string.common_ok, this) + .setNegativeButton(R.string.common_cancel, this) + .setTitle(R.string.uploader_info_dirname); + Dialog d = builder.create(); + d.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE); + return d; + } + + + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == AlertDialog.BUTTON_POSITIVE) { + String newFolderName = + ((TextView)(getDialog().findViewById(R.id.user_input))) + .getText().toString().trim(); + + if (newFolderName.length() <= 0) { + Toast.makeText( + getSherlockActivity(), + R.string.filename_empty, + Toast.LENGTH_LONG).show(); + return; + } + + if (!FileUtils.isValidName(newFolderName)) { + Toast.makeText( + getSherlockActivity(), + R.string.filename_forbidden_characters, + Toast.LENGTH_LONG).show(); + return; + } + + String path = mParentFolder.getRemotePath(); + path += newFolderName + OCFile.PATH_SEPARATOR; + ((ComponentsGetter)getSherlockActivity()). + getFileOperationsHelper().createFolder(path, false); + } + } + +} diff --git a/src/com/owncloud/android/ui/dialog/EditNameDialog.java b/src/com/owncloud/android/ui/dialog/EditNameDialog.java deleted file mode 100644 index 0ab7e4da..00000000 --- a/src/com/owncloud/android/ui/dialog/EditNameDialog.java +++ /dev/null @@ -1,178 +0,0 @@ -/* ownCloud Android client application - * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2013 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.ui.dialog; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.DialogInterface; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.WindowManager.LayoutParams; -import android.widget.EditText; -import android.widget.TextView; -import android.widget.Toast; - -import com.actionbarsherlock.app.SherlockDialogFragment; -import com.owncloud.android.R; -import com.owncloud.android.lib.resources.files.FileUtils; - - -/** - * Dialog to request the user to input a name, optionally initialized with a former name. - * - * @author Bartek Przybylski - * @author David A. Velasco - */ -public class EditNameDialog extends SherlockDialogFragment implements DialogInterface.OnClickListener { - - public static final String TAG = EditNameDialog.class.getSimpleName(); - - protected static final String ARG_TITLE = "TITLE"; - protected static final String ARG_NAME = "NAME"; - protected static final String ARG_SELECTION_START = "SELECTION_START"; - protected static final String ARG_SELECTION_END = "SELECTION_END"; - - private String mNewFilename; - private boolean mResult; - private EditNameDialogListener mListener; - - /** - * Public factory method to get dialog instances. - * - * @param title Text to show as title in the dialog. - * @param name Optional text to include in the text input field when the dialog is shown. - * @param listener Instance to notify when the dialog is dismissed. - * @param selectionStart Index to the first character to be selected in the input field; negative value for none - * @param selectionEnd Index to the last character to be selected in the input field; negative value for none - * @return New dialog instance, ready to show. - */ - static public EditNameDialog newInstance(String title, String name, int selectionStart, int selectionEnd, EditNameDialogListener listener) { - EditNameDialog f = new EditNameDialog(); - Bundle args = new Bundle(); - args.putString(ARG_TITLE, title); - args.putString(ARG_NAME, name); - args.putInt(ARG_SELECTION_START, selectionStart); - args.putInt(ARG_SELECTION_END, selectionEnd); - f.setArguments(args); - f.setOnDismissListener(listener); - return f; - } - - - /** - * {@inheritDoc} - */ - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - String currentName = getArguments().getString(ARG_NAME); - if (currentName == null) - currentName = ""; - String title = getArguments().getString(ARG_TITLE); - - // Inflate the layout for the dialog - LayoutInflater inflater = getSherlockActivity().getLayoutInflater(); - View v = inflater.inflate(R.layout.edit_box_dialog, null); // null parent view because it will go in the dialog layout - EditText inputText = ((EditText)v.findViewById(R.id.user_input)); - inputText.setText(currentName); - - // Set it to the dialog - AlertDialog.Builder builder = new AlertDialog.Builder(getSherlockActivity()); - builder.setView(v) - .setPositiveButton(R.string.common_ok, this) - .setNegativeButton(R.string.common_cancel, this); - - if (title != null) { - builder.setTitle(title); - } - - mResult = false; - - Dialog d = builder.create(); - - inputText.requestFocus(); - int selectionStart = getArguments().getInt(ARG_SELECTION_START, -1); - int selectionEnd = getArguments().getInt(ARG_SELECTION_END, -1); - if (selectionStart >= 0 && selectionEnd >= 0) { - inputText.setSelection(Math.min(selectionStart, selectionEnd), Math.max(selectionStart, selectionEnd)); - } - d.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE); - return d; - } - - - /** - * Performs the corresponding action when a dialog button is clicked. - * - * Saves the text in the input field to be accessed through {@link #getNewFilename()} when the positive - * button is clicked. - * - * Notify the current listener in any case. - */ - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which) { - case AlertDialog.BUTTON_POSITIVE: { - mNewFilename = ((TextView)(getDialog().findViewById(R.id.user_input))).getText().toString(); - if (!FileUtils.isValidName(mNewFilename)) { - Toast.makeText(getSherlockActivity(), R.string.filename_forbidden_characters, Toast.LENGTH_LONG).show(); - return; - } - mResult = true; - } - case AlertDialog.BUTTON_NEGATIVE: { // fall through - dismiss(); - if (mListener != null) - mListener.onDismiss(this); - } - } - } - - protected void setOnDismissListener(EditNameDialogListener listener) { - mListener = listener; - } - - /** - * Returns the text in the input field after the user clicked the positive button. - * - * @return Text in the input field. - */ - public String getNewFilename() { - return mNewFilename; - } - - /** - * - * @return True when the user clicked the positive button. - */ - public boolean getResult() { - return mResult; - } - - - /** - * Interface to receive a notification when any button in the dialog is clicked. - */ - public interface EditNameDialogListener { - public void onDismiss(EditNameDialog dialog); - } - - -} - diff --git a/src/com/owncloud/android/ui/dialog/RemoveFileDialogFragment.java b/src/com/owncloud/android/ui/dialog/RemoveFileDialogFragment.java new file mode 100644 index 00000000..9020dd0f --- /dev/null +++ b/src/com/owncloud/android/ui/dialog/RemoveFileDialogFragment.java @@ -0,0 +1,114 @@ +/* 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.ui.dialog; + +/** + * Dialog requiring confirmation before removing a given OCFile. + * + * Triggers the removal according to the user response. + * + * @author David A. Velasco + */ +import com.owncloud.android.R; +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.ui.activity.ComponentsGetter; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment.ConfirmationDialogFragmentListener; + +import android.app.Dialog; +import android.os.Bundle; + +public class RemoveFileDialogFragment extends ConfirmationDialogFragment +implements ConfirmationDialogFragmentListener { + + private static final String ARG_TARGET_FILE = "TARGET_FILE"; + + /** + * Public factory method to create new RemoveFileDialogFragment instances. + * + * @param file File to remove. + * @return Dialog ready to show. + */ + public static RemoveFileDialogFragment newInstance(OCFile file) { + RemoveFileDialogFragment frag = new RemoveFileDialogFragment(); + Bundle args = new Bundle(); + + int messageStringId = R.string.confirmation_remove_alert; + + int posBtn = R.string.confirmation_remove_remote; + int neuBtn = -1; + if (file.isFolder()) { + messageStringId = R.string.confirmation_remove_folder_alert; + posBtn = R.string.confirmation_remove_remote_and_local; + neuBtn = R.string.confirmation_remove_folder_local; + } else if (file.isDown()) { + posBtn = R.string.confirmation_remove_remote_and_local; + neuBtn = R.string.confirmation_remove_local; + } + + + args.putInt(ARG_CONF_RESOURCE_ID, messageStringId); + args.putStringArray(ARG_CONF_ARGUMENTS, new String[]{file.getFileName()}); + args.putInt(ARG_POSITIVE_BTN_RES, posBtn); + args.putInt(ARG_NEUTRAL_BTN_RES, neuBtn); + args.putInt(ARG_NEGATIVE_BTN_RES, R.string.common_cancel); + args.putParcelable(ARG_TARGET_FILE, file); + frag.setArguments(args); + + return frag; + } + + private OCFile mTargetFile; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Dialog dialog = super.onCreateDialog(savedInstanceState); + mTargetFile = getArguments().getParcelable(ARG_TARGET_FILE); + + setOnConfirmationListener(this); + + return dialog; + } + + /** + * Performs the removal of the target file, both locally and in the server. + */ + @Override + public void onConfirmation(String callerTag) { + ComponentsGetter cg = (ComponentsGetter)getSherlockActivity(); + FileDataStorageManager storageManager = cg.getStorageManager(); + if (storageManager.getFileById(mTargetFile.getFileId()) != null) { + cg.getFileOperationsHelper().removeFile(mTargetFile, false); + } + } + + /** + * Performs the removal of the local copy of the taget file + */ + @Override + public void onNeutral(String callerTag) { + ((ComponentsGetter)getSherlockActivity()).getFileOperationsHelper() + .removeFile(mTargetFile, true); + } + + @Override + public void onCancel(String callerTag) { + // nothing to do here + } + +} diff --git a/src/com/owncloud/android/ui/dialog/RenameFileDialogFragment.java b/src/com/owncloud/android/ui/dialog/RenameFileDialogFragment.java new file mode 100644 index 00000000..530e920a --- /dev/null +++ b/src/com/owncloud/android/ui/dialog/RenameFileDialogFragment.java @@ -0,0 +1,136 @@ +/* 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.ui.dialog; + +/** + * Dialog to input a new name for an {@link OCFile} being renamed. + * + * Triggers the rename operation. + */ +import com.actionbarsherlock.app.SherlockDialogFragment; +import com.owncloud.android.R; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.lib.resources.files.FileUtils; +import com.owncloud.android.ui.activity.ComponentsGetter; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager.LayoutParams; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + + +/** + * Dialog to input a new name for a file or folder to rename. + * + * Triggers the rename operation when name is confirmed. + * + * @author David A. Velasco + */ +public class RenameFileDialogFragment +extends SherlockDialogFragment implements DialogInterface.OnClickListener { + + private static final String ARG_TARGET_FILE = "TARGET_FILE"; + + /** + * Public factory method to create new RenameFileDialogFragment instances. + * + * @param file File to rename. + * @return Dialog ready to show. + */ + public static RenameFileDialogFragment newInstance(OCFile file) { + RenameFileDialogFragment frag = new RenameFileDialogFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_TARGET_FILE, file); + frag.setArguments(args); + return frag; + + } + + private OCFile mTargetFile; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + mTargetFile = getArguments().getParcelable(ARG_TARGET_FILE); + + // Inflate the layout for the dialog + LayoutInflater inflater = getSherlockActivity().getLayoutInflater(); + View v = inflater.inflate(R.layout.edit_box_dialog, null); + + // Setup layout + String currentName = mTargetFile.getFileName(); + EditText inputText = ((EditText)v.findViewById(R.id.user_input)); + inputText.setText(currentName); + int selectionStart = 0; + int extensionStart = mTargetFile.isFolder() ? -1 : currentName.lastIndexOf("."); + int selectionEnd = (extensionStart >= 0) ? extensionStart : currentName.length(); + if (selectionStart >= 0 && selectionEnd >= 0) { + inputText.setSelection( + Math.min(selectionStart, selectionEnd), + Math.max(selectionStart, selectionEnd)); + } + inputText.requestFocus(); + + // Build the dialog + AlertDialog.Builder builder = new AlertDialog.Builder(getSherlockActivity()); + builder.setView(v) + .setPositiveButton(R.string.common_ok, this) + .setNegativeButton(R.string.common_cancel, this) + .setTitle(R.string.rename_dialog_title); + Dialog d = builder.create(); + d.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE); + return d; + } + + + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == AlertDialog.BUTTON_POSITIVE) { + String newFileName = + ((TextView)(getDialog().findViewById(R.id.user_input))) + .getText().toString().trim(); + + if (newFileName.length() <= 0) { + Toast.makeText( + getSherlockActivity(), + R.string.filename_empty, + Toast.LENGTH_LONG).show(); + return; + } + + if (!FileUtils.isValidName(newFileName)) { + Toast.makeText( + getSherlockActivity(), + R.string.filename_forbidden_characters, + Toast.LENGTH_LONG).show(); + return; + } + + ((ComponentsGetter)getSherlockActivity()). + getFileOperationsHelper().renameFile(mTargetFile, newFileName); + + + } + } + +} diff --git a/src/com/owncloud/android/ui/dialog/ShareLinkToDialog.java b/src/com/owncloud/android/ui/dialog/ShareLinkToDialog.java index 3076e27e..43ad2f8b 100644 --- a/src/com/owncloud/android/ui/dialog/ShareLinkToDialog.java +++ b/src/com/owncloud/android/ui/dialog/ShareLinkToDialog.java @@ -143,8 +143,9 @@ public class ShareLinkToDialog extends SherlockDialogFragment { } else { // Create a new share resource - FileOperationsHelper foh = new FileOperationsHelper(); - foh.shareFileWithLinkToApp(mFile, mIntent, (FileActivity)getSherlockActivity()); + FileOperationsHelper foh = + new FileOperationsHelper((FileActivity)getSherlockActivity()); + foh.shareFileWithLinkToApp(mFile, mIntent); } } }) diff --git a/src/com/owncloud/android/ui/fragment/ConfirmationDialogFragment.java b/src/com/owncloud/android/ui/fragment/ConfirmationDialogFragment.java deleted file mode 100644 index bb9adbe2..00000000 --- a/src/com/owncloud/android/ui/fragment/ConfirmationDialogFragment.java +++ /dev/null @@ -1,126 +0,0 @@ -/* ownCloud Android client application - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 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.ui.fragment; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.DialogInterface; -import android.os.Bundle; - -import com.actionbarsherlock.app.SherlockDialogFragment; -import com.owncloud.android.utils.Log_OC; - - -public class ConfirmationDialogFragment extends SherlockDialogFragment { - - public final static String ARG_CONF_RESOURCE_ID = "resource_id"; - public final static String ARG_CONF_ARGUMENTS = "string_array"; - - public final static String ARG_POSITIVE_BTN_RES = "positive_btn_res"; - public final static String ARG_NEUTRAL_BTN_RES = "neutral_btn_res"; - public final static String ARG_NEGATIVE_BTN_RES = "negative_btn_res"; - - public static final String FTAG_CONFIRMATION = "CONFIRMATION_FRAGMENT"; - - private ConfirmationDialogFragmentListener mListener; - - /** - * Public factory method to create new ConfirmationDialogFragment instances. - * - * @param string_id Resource id for a message to show in the dialog. - * @param arguments Arguments to complete the message, if it's a format string. - * @param posBtn Resource id for the text of the positive button. - * @param neuBtn Resource id for the text of the neutral button. - * @param negBtn Resource id for the text of the negative button. - * @return Dialog ready to show. - */ - public static ConfirmationDialogFragment newInstance(int string_id, String[] arguments, int posBtn, int neuBtn, int negBtn) { - ConfirmationDialogFragment frag = new ConfirmationDialogFragment(); - Bundle args = new Bundle(); - args.putInt(ARG_CONF_RESOURCE_ID, string_id); - args.putStringArray(ARG_CONF_ARGUMENTS, arguments); - args.putInt(ARG_POSITIVE_BTN_RES, posBtn); - args.putInt(ARG_NEUTRAL_BTN_RES, neuBtn); - args.putInt(ARG_NEGATIVE_BTN_RES, negBtn); - frag.setArguments(args); - return frag; - } - - public void setOnConfirmationListener(ConfirmationDialogFragmentListener listener) { - mListener = listener; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - Object[] confirmationTarget = getArguments().getStringArray(ARG_CONF_ARGUMENTS); - int resourceId = getArguments().getInt(ARG_CONF_RESOURCE_ID, -1); - int posBtn = getArguments().getInt(ARG_POSITIVE_BTN_RES, -1); - int neuBtn = getArguments().getInt(ARG_NEUTRAL_BTN_RES, -1); - int negBtn = getArguments().getInt(ARG_NEGATIVE_BTN_RES, -1); - - if (confirmationTarget == null || resourceId == -1) { - Log_OC.wtf(getTag(), "Calling confirmation dialog without resource or arguments"); - return null; - } - - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) - .setIcon(android.R.drawable.ic_dialog_alert) - .setMessage(String.format(getString(resourceId), confirmationTarget)) - .setTitle(android.R.string.dialog_alert_title); - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { - builder.setIconAttribute(android.R.attr.alertDialogIcon); - } - - if (posBtn != -1) - builder.setPositiveButton(posBtn, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - mListener.onConfirmation(getTag()); - dialog.dismiss(); - } - }); - if (neuBtn != -1) - builder.setNeutralButton(neuBtn, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - mListener.onNeutral(getTag()); - dialog.dismiss(); - } - }); - if (negBtn != -1) - builder.setNegativeButton(negBtn, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mListener.onCancel(getTag()); - dialog.dismiss(); - } - }); - return builder.create(); - } - - - public interface ConfirmationDialogFragmentListener { - public void onConfirmation(String callerTag); - public void onNeutral(String callerTag); - public void onCancel(String callerTag); - } - -} - diff --git a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java index dc8c9f62..c9d6b335 100644 --- a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java +++ b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java @@ -17,19 +17,11 @@ */ package com.owncloud.android.ui.fragment; -import java.io.File; import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; import android.accounts.Account; -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.os.Bundle; -import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; @@ -38,7 +30,6 @@ import android.widget.CheckBox; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; -import android.widget.Toast; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; @@ -46,24 +37,15 @@ import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.files.FileMenuFilter; import com.owncloud.android.files.services.FileObserverService; -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.network.OnDatatransferProgressListener; -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.RemoveFileOperation; -import com.owncloud.android.operations.RenameFileOperation; -import com.owncloud.android.operations.SynchronizeFileOperation; -import com.owncloud.android.ui.activity.ConflictsResolveActivity; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; -import com.owncloud.android.ui.dialog.EditNameDialog; -import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener; -import com.owncloud.android.ui.preview.PreviewImageFragment; +import com.owncloud.android.ui.dialog.RemoveFileDialogFragment; +import com.owncloud.android.ui.dialog.RenameFileDialogFragment; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.Log_OC; @@ -74,25 +56,17 @@ import com.owncloud.android.utils.Log_OC; * @author Bartek Przybylski * @author David A. Velasco */ -public class FileDetailFragment extends FileFragment implements - OnClickListener, - ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener, EditNameDialogListener { +public class FileDetailFragment extends FileFragment implements OnClickListener { - private FileFragment.ContainerActivity mContainerActivity; - private int mLayout; private View mView; private Account mAccount; - private FileDataStorageManager mStorageManager; - private UploadFinishReceiver mUploadFinishReceiver; public ProgressListener mProgressListener; - private Handler mHandler; - private RemoteOperation mLastRemoteOperation; - private static final String TAG = FileDetailFragment.class.getSimpleName(); public static final String FTAG_CONFIRMATION = "REMOVE_CONFIRMATION_FRAGMENT"; + public static final String FTAG_RENAME_FILE = "RENAME_FILE_FRAGMENT"; /** @@ -103,7 +77,6 @@ public class FileDetailFragment extends FileFragment implements public FileDetailFragment() { super(); mAccount = null; - mStorageManager = null; mLayout = R.layout.file_details_empty; mProgressListener = null; } @@ -119,16 +92,14 @@ public class FileDetailFragment extends FileFragment implements public FileDetailFragment(OCFile fileToDetail, Account ocAccount) { super(fileToDetail); mAccount = ocAccount; - mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment mLayout = R.layout.file_details_empty; mProgressListener = null; } @Override - public void onCreate(Bundle savedInstanceState) { + public void onActivityCreated(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mHandler = new Handler(); setHasOptionsMenu(true); } @@ -136,7 +107,6 @@ public class FileDetailFragment extends FileFragment implements @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - //super.onCreateView(inflater, container, savedInstanceState); if (savedInstanceState != null) { setFile((OCFile)savedInstanceState.getParcelable(FileActivity.EXTRA_FILE)); @@ -148,7 +118,6 @@ public class FileDetailFragment extends FileFragment implements } View view = null; - //view = inflater.inflate(mLayout, container, false); view = inflater.inflate(mLayout, null); mView = view; @@ -162,37 +131,6 @@ public class FileDetailFragment extends FileFragment implements updateFileDetails(false, false); return view; } - - /** - * {@inheritDoc} - */ - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - try { - mContainerActivity = (ContainerActivity) activity; - - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement " + FileDetailFragment.ContainerActivity.class.getSimpleName()); - } - } - - - /** - * {@inheritDoc} - */ - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - if (mAccount != null) { - mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver()); - OCFile file = mStorageManager.getFileByPath(getFile().getRemotePath()); - if (file != null) { - setFile(file); - } - } - } - @Override public void onSaveInstanceState(Bundle outState) { @@ -208,26 +146,6 @@ public class FileDetailFragment extends FileFragment implements } @Override - public void onResume() { - super.onResume(); - mUploadFinishReceiver = new UploadFinishReceiver(); - IntentFilter filter = new IntentFilter(FileUploader.getUploadFinishMessage()); - getActivity().registerReceiver(mUploadFinishReceiver, filter); - - } - - - @Override - public void onPause() { - super.onPause(); - if (mUploadFinishReceiver != null) { - getActivity().unregisterReceiver(mUploadFinishReceiver); - mUploadFinishReceiver = null; - } - } - - - @Override public void onStop() { super.onStop(); leaveTransferProgress(); @@ -247,26 +165,7 @@ public class FileDetailFragment extends FileFragment implements public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.file_actions_menu, menu); - MenuItem item = menu.findItem(R.id.action_see_details); - if (item != null) { - item.setVisible(false); - item.setEnabled(false); - } - - // Send file - item = menu.findItem(R.id.action_send_file); - boolean sendEnabled = getString(R.string.send_files_to_other_apps).equalsIgnoreCase("on"); - if (item != null) { - if (sendEnabled) { - item.setVisible(true); - item.setEnabled(true); - } else { - item.setVisible(false); - item.setEnabled(false); - - } - } - } + } /** @@ -276,80 +175,21 @@ public class FileDetailFragment extends FileFragment implements public void onPrepareOptionsMenu (Menu menu) { super.onPrepareOptionsMenu(menu); - List toHide = new ArrayList(); - List toShow = new ArrayList(); - OCFile file = getFile(); - - FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder(); - boolean downloading = downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file); - FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder(); - boolean uploading = uploaderBinder != null && uploaderBinder.isUploading(mAccount, getFile()); - - if (downloading || uploading) { - toHide.add(R.id.action_download_file); - toHide.add(R.id.action_rename_file); - toHide.add(R.id.action_remove_file); - toHide.add(R.id.action_open_file_with); - if (!downloading) { - toHide.add(R.id.action_cancel_download); - toShow.add(R.id.action_cancel_upload); - } else { - toHide.add(R.id.action_cancel_upload); - toShow.add(R.id.action_cancel_download); - } - - } else if (file != null && file.isDown()) { - toHide.add(R.id.action_download_file); - toHide.add(R.id.action_cancel_download); - toHide.add(R.id.action_cancel_upload); - - toShow.add(R.id.action_rename_file); - toShow.add(R.id.action_remove_file); - toShow.add(R.id.action_open_file_with); - toShow.add(R.id.action_sync_file); - - } else if (file != null) { - toHide.add(R.id.action_open_file_with); - toHide.add(R.id.action_cancel_download); - toHide.add(R.id.action_cancel_upload); - toHide.add(R.id.action_sync_file); - - toShow.add(R.id.action_rename_file); - toShow.add(R.id.action_remove_file); - toShow.add(R.id.action_download_file); - - } else { - toHide.add(R.id.action_open_file_with); - toHide.add(R.id.action_cancel_download); - toHide.add(R.id.action_cancel_upload); - toHide.add(R.id.action_sync_file); - toHide.add(R.id.action_download_file); - toHide.add(R.id.action_rename_file); - 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); + if (mContainerActivity.getStorageManager() != null) { + FileMenuFilter mf = new FileMenuFilter( + getFile(), + mContainerActivity.getStorageManager().getAccount(), + mContainerActivity, + getSherlockActivity() + ); + mf.filter(menu); } - MenuItem item = null; - for (int i : toHide) { - item = menu.findItem(i); - if (item != null) { - item.setVisible(false); - item.setEnabled(false); - } - } - for (int i : toShow) { - item = menu.findItem(i); - if (item != null) { - item.setVisible(true); - item.setEnabled(true); - } + // additional restriction for this fragment + MenuItem item = menu.findItem(R.id.action_see_details); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); } } @@ -361,44 +201,45 @@ public class FileDetailFragment extends FileFragment implements public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_share_file: { - FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); - activity.getFileOperationsHelper().shareFileWithLink(getFile(), activity); + mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile()); return true; } case R.id.action_unshare_file: { - FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); - activity.getFileOperationsHelper().unshareFileWithLink(getFile(), activity); + mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile()); return true; } case R.id.action_open_file_with: { - FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); - activity.getFileOperationsHelper().openFile(getFile(), activity); + mContainerActivity.getFileOperationsHelper().openFile(getFile()); return true; } case R.id.action_remove_file: { - removeFile(); + RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile()); + dialog.show(getFragmentManager(), FTAG_CONFIRMATION); return true; } case R.id.action_rename_file: { - renameFile(); + RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(getFile()); + dialog.show(getFragmentManager(), FTAG_RENAME_FILE); return true; } - case R.id.action_download_file: case R.id.action_cancel_download: - case R.id.action_cancel_upload: + case R.id.action_cancel_upload: { + ((FileDisplayActivity)mContainerActivity).cancelTransference(getFile()); + return true; + } + case R.id.action_download_file: case R.id.action_sync_file: { - synchronizeFile(); + mContainerActivity.getFileOperationsHelper().syncFile(getFile()); return true; } case R.id.action_send_file: { - FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); // Obtain the file if (!getFile().isDown()) { // Download the file Log_OC.d(TAG, getFile().getRemotePath() + " : File must be downloaded"); - activity.startDownloadForSending(getFile()); + ((FileDisplayActivity)mContainerActivity).startDownloadForSending(getFile()); } else { - activity.getFileOperationsHelper().sendDownloadedFile(getFile(), activity); + mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile()); } return true; } @@ -415,7 +256,7 @@ public class FileDetailFragment extends FileFragment implements break; } case R.id.fdCancelBtn: { - synchronizeFile(); + ((FileDisplayActivity)mContainerActivity).cancelTransference(getFile()); break; } default: @@ -428,7 +269,7 @@ public class FileDetailFragment extends FileFragment implements CheckBox cb = (CheckBox) getView().findViewById(R.id.fdKeepInSync); OCFile file = getFile(); file.setKeepInSync(cb.isChecked()); - mStorageManager.saveFile(file); + mContainerActivity.getStorageManager().saveFile(file); /// register the OCFile instance in the observer service to monitor local updates; /// if necessary, the file is download @@ -443,97 +284,10 @@ public class FileDetailFragment extends FileFragment implements getActivity().startService(intent); if (file.keepInSync()) { - synchronizeFile(); // force an immediate synchronization + mContainerActivity.getFileOperationsHelper().syncFile(getFile()); } } - private void removeFile() { - OCFile file = getFile(); - ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance( - R.string.confirmation_remove_alert, - new String[]{file.getFileName()}, - file.isDown() ? R.string.confirmation_remove_remote_and_local : R.string.confirmation_remove_remote, - file.isDown() ? R.string.confirmation_remove_local : -1, - R.string.common_cancel); - confDialog.setOnConfirmationListener(this); - confDialog.show(getFragmentManager(), FTAG_CONFIRMATION); - } - - - private void renameFile() { - OCFile file = getFile(); - String fileName = file.getFileName(); - int extensionStart = file.isFolder() ? -1 : fileName.lastIndexOf("."); - int selectionEnd = (extensionStart >= 0) ? extensionStart : fileName.length(); - EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), fileName, 0, selectionEnd, this); - dialog.show(getFragmentManager(), "nameeditdialog"); - } - - private void synchronizeFile() { - OCFile file = getFile(); - FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder(); - FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder(); - if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) { - downloaderBinder.cancel(mAccount, file); - if (file.isDown()) { - setButtonsForDown(); - } else { - setButtonsForRemote(); - } - - } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) { - uploaderBinder.cancel(mAccount, file); - if (!file.fileExists()) { - // TODO make something better - ((FileDisplayActivity)getActivity()).cleanSecondFragment(); - - } else if (file.isDown()) { - setButtonsForDown(); - } else { - setButtonsForRemote(); - } - - } else { - mLastRemoteOperation = new SynchronizeFileOperation(file, null, mStorageManager, mAccount, true, getActivity()); - mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity()); - - // update ui - ((FileDisplayActivity) getActivity()).showLoadingDialog(); - - } - } - - @Override - public void onConfirmation(String callerTag) { - OCFile file = getFile(); - if (callerTag.equals(FTAG_CONFIRMATION)) { - if (mStorageManager.getFileById(file.getFileId()) != null) { - mLastRemoteOperation = new RemoveFileOperation( file, - true, - mStorageManager); - mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity()); - - ((FileDisplayActivity) getActivity()).showLoadingDialog(); - } - } - } - - @Override - public void onNeutral(String callerTag) { - OCFile file = getFile(); - mStorageManager.removeFile(file, false, true); // TODO perform in background task / new thread - if (file.getStoragePath() != null) { - file.setStoragePath(null); - updateFileDetails(file, mAccount); - } - } - - @Override - public void onCancel(String callerTag) { - Log_OC.d(TAG, "REMOVAL CANCELED"); - } - - /** * Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be replaced. * @@ -551,12 +305,6 @@ public class FileDetailFragment extends FileFragment implements */ public void updateFileDetails(OCFile file, Account ocAccount) { setFile(file); - if (ocAccount != null && ( - mStorageManager == null || - (mAccount != null && !mAccount.equals(ocAccount)) - )) { - mStorageManager = new FileDataStorageManager(ocAccount, getActivity().getApplicationContext().getContentResolver()); - } mAccount = ocAccount; updateFileDetails(false, false); } @@ -566,20 +314,17 @@ public class FileDetailFragment extends FileFragment implements * * TODO Remove parameter when the transferring state of files is kept in database. * - * TODO REFACTORING! this method called 5 times before every time the fragment is shown! - * * @param transferring Flag signaling if the file should be considered as downloading or uploading, * although {@link FileDownloaderBinder#isDownloading(Account, OCFile)} and * {@link FileUploaderBinder#isUploading(Account, OCFile)} return false. * - * @param refresh If 'true', try to refresh the hold file from the database + * @param refresh If 'true', try to refresh the whole file from the database */ public void updateFileDetails(boolean transferring, boolean refresh) { - if (readyToShow()) { - - if (refresh && mStorageManager != null) { - setFile(mStorageManager.getFileByPath(getFile().getRemotePath())); + FileDataStorageManager storageManager = mContainerActivity.getStorageManager(); + if (refresh && storageManager != null) { + setFile(storageManager.getFileByPath(getFile().getRemotePath())); } OCFile file = getFile(); @@ -597,7 +342,6 @@ public class FileDetailFragment extends FileFragment implements cb.setChecked(file.keepInSync()); // configure UI for depending upon local state of the file - //if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath()) || FileUploader.isUploading(mAccount, mFile.getRemotePath())) { FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder(); FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder(); if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) || (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file))) { @@ -757,161 +501,6 @@ public class FileDetailFragment extends FileFragment implements } - /** - * Once the file upload has finished -> update view - * - * Being notified about the finish of an upload is necessary for the next sequence: - * 1. Upload a big file. - * 2. Force a synchronization; if it finished before the upload, the file in transfer will be included in the local database and in the file list - * of its containing folder; the the server includes it in the PROPFIND requests although it's not fully upload. - * 3. Click the file in the list to see its details. - * 4. Wait for the upload finishes; at this moment, the details view must be refreshed to enable the action buttons. - */ - private class UploadFinishReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME); - - if (!isEmpty() && accountName.equals(mAccount.name)) { - boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false); - String uploadRemotePath = intent.getStringExtra(FileUploader.EXTRA_REMOTE_PATH); - boolean renamedInUpload = getFile().getRemotePath().equals(intent.getStringExtra(FileUploader.EXTRA_OLD_REMOTE_PATH)); - if (getFile().getRemotePath().equals(uploadRemotePath) || - renamedInUpload) { - if (uploadWasFine) { - setFile(mStorageManager.getFileByPath(uploadRemotePath)); - } - if (renamedInUpload) { - String newName = (new File(uploadRemotePath)).getName(); - Toast msg = Toast.makeText(getActivity().getApplicationContext(), String.format(getString(R.string.filedetails_renamed_in_upload_msg), newName), Toast.LENGTH_LONG); - msg.show(); - } - getSherlockActivity().removeStickyBroadcast(intent); // not the best place to do this; a small refactorization of BroadcastReceivers should be done - - updateFileDetails(false, false); // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server - - // Force the preview if the file is an image - if (uploadWasFine && PreviewImageFragment.canBePreviewed(getFile())) { - ((FileDisplayActivity) mContainerActivity).startImagePreview(getFile()); - } - } - } - } - } - - - public void onDismiss(EditNameDialog dialog) { - if (dialog.getResult()) { - String newFilename = dialog.getNewFilename(); - Log_OC.d(TAG, "name edit dialog dismissed with new name " + newFilename); - mLastRemoteOperation = new RenameFileOperation( getFile(), - mAccount, - newFilename, - new FileDataStorageManager(mAccount, getActivity().getContentResolver())); - mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity()); - ((FileDisplayActivity) getActivity()).showLoadingDialog(); - } - } - - - /** - * {@inheritDoc} - */ - @Override - public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { - if (operation.equals(mLastRemoteOperation)) { - if (operation instanceof RemoveFileOperation) { - onRemoveFileOperationFinish((RemoveFileOperation)operation, result); - - } else if (operation instanceof RenameFileOperation) { - onRenameFileOperationFinish((RenameFileOperation)operation, result); - - } else if (operation instanceof SynchronizeFileOperation) { - onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result); - } - } - } - - - private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) { - ((FileDisplayActivity) getActivity()).dismissLoadingDialog(); - if (result.isSuccess()) { - Toast msg = Toast.makeText(getActivity().getApplicationContext(), R.string.remove_success_msg, Toast.LENGTH_LONG); - msg.show(); - ((FileDisplayActivity)getActivity()).cleanSecondFragment(); - - } else { - Toast msg = Toast.makeText(getActivity(), R.string.remove_fail_msg, Toast.LENGTH_LONG); - msg.show(); - if (result.isSslRecoverableException()) { - // TODO show the SSL warning dialog - } - } - } - - private void onRenameFileOperationFinish(RenameFileOperation operation, RemoteOperationResult result) { - ((FileDisplayActivity) getActivity()).dismissLoadingDialog(); - - if (result.isSuccess()) { - updateFileDetails(((RenameFileOperation)operation).getFile(), mAccount); - mContainerActivity.onFileStateChanged(); - - } else { - if (result.getCode().equals(ResultCode.INVALID_LOCAL_FILE_NAME)) { - Toast msg = Toast.makeText(getActivity(), R.string.rename_local_fail_msg, Toast.LENGTH_LONG); - msg.show(); - // TODO throw again the new rename dialog - } if (result.getCode().equals(ResultCode.INVALID_CHARACTER_IN_NAME)) { - Toast msg = Toast.makeText(getActivity(), R.string.filename_forbidden_characters, Toast.LENGTH_LONG); - msg.show(); - } else { - Toast msg = Toast.makeText(getActivity(), R.string.rename_server_fail_msg, Toast.LENGTH_LONG); - msg.show(); - if (result.isSslRecoverableException()) { - // TODO show the SSL warning dialog - } - } - } - } - - private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, RemoteOperationResult result) { - ((FileDisplayActivity) getActivity()).dismissLoadingDialog(); - OCFile file = getFile(); - if (!result.isSuccess()) { - if (result.getCode() == ResultCode.SYNC_CONFLICT) { - Intent i = new Intent(getActivity(), ConflictsResolveActivity.class); - i.putExtra(ConflictsResolveActivity.EXTRA_FILE, file); - i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, mAccount); - startActivity(i); - - } - - if (file.isDown()) { - setButtonsForDown(); - - } else { - setButtonsForRemote(); - } - - } else { - if (operation.transferWasRequested()) { - setButtonsForTransferring(); - mContainerActivity.onFileStateChanged(); // this is not working; FileDownloader won't do NOTHING at all until this method finishes, so - // checking the service to see if the file is downloading results in FALSE - } else { - Toast msg = Toast.makeText(getActivity(), R.string.sync_file_nothing_to_do_msg, Toast.LENGTH_LONG); - msg.show(); - if (file.isDown()) { - setButtonsForDown(); - - } else { - setButtonsForRemote(); - } - } - } - } - - public void listenForTransferProgress() { if (mProgressListener != null) { if (mContainerActivity.getFileDownloaderBinder() != null) { diff --git a/src/com/owncloud/android/ui/fragment/FileFragment.java b/src/com/owncloud/android/ui/fragment/FileFragment.java index 2f1a49b1..3e6fa31c 100644 --- a/src/com/owncloud/android/ui/fragment/FileFragment.java +++ b/src/com/owncloud/android/ui/fragment/FileFragment.java @@ -17,11 +17,15 @@ package com.owncloud.android.ui.fragment; +import android.accounts.Account; +import android.app.Activity; import android.support.v4.app.Fragment; import com.actionbarsherlock.app.SherlockFragment; import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.ui.activity.TransferServiceGetter; +import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; +import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; +import com.owncloud.android.ui.activity.ComponentsGetter; /** @@ -33,6 +37,8 @@ import com.owncloud.android.ui.activity.TransferServiceGetter; public class FileFragment extends SherlockFragment { private OCFile mFile; + + protected ContainerActivity mContainerActivity; /** @@ -66,35 +72,75 @@ public class FileFragment extends SherlockFragment { protected void setFile(OCFile file) { mFile = file; } - + + + /** + * {@inheritDoc} + */ + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + mContainerActivity = (ContainerActivity) activity; + + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + " must implement " + ContainerActivity.class.getSimpleName()); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void onDetach() { + mContainerActivity = null; + super.onDetach(); + } + + + /** + * Interface to implement by any Activity that includes some instance of FileListFragment * Interface to implement by any Activity that includes some instance of FileFragment * * @author David A. Velasco */ - public interface ContainerActivity extends TransferServiceGetter { + public interface ContainerActivity extends ComponentsGetter { /** - * Callback method invoked when the detail fragment wants to notice its container - * activity about a relevant state the file shown by the fragment. - * - * Added to notify to FileDisplayActivity about the need of refresh the files list. + * Request the parent activity to show the details of an {@link OCFile}. * - * Currently called when: - * - a download is started; - * - a rename is completed; - * - a deletion is completed; - * - the 'inSync' flag is changed; + * @param file File to show details */ - public void onFileStateChanged(); + public void showDetails(OCFile file); + + ///// TO UNIFY IN A SINGLE CALLBACK METHOD - EVENT NOTIFICATIONs -> something happened inside the fragment, MAYBE activity is interested --> unify in notification method /** - * Request the parent activity to show the details of an {@link OCFile}. + * Callback method invoked when a the user browsed into a different folder through the list of files + * + * @param file + */ + public void onBrowsedDownTo(OCFile folder); + + /** + * Callback method invoked when a the 'transfer state' of a file changes. * - * @param file File to show details + * This happens when a download or upload is started or ended for a file. + * + * This method is necessary by now to update the user interface of the double-pane layout in tablets + * because methods {@link FileDownloaderBinder#isDownloading(Account, OCFile)} and {@link FileUploaderBinder#isUploading(Account, OCFile)} + * won't provide the needed response before the method where this is called finishes. + * + * TODO Remove this when the transfer state of a file is kept in the database (other thing TODO) + * + * @param file OCFile which state changed. + * @param downloading Flag signaling if the file is now downloading. + * @param uploading Flag signaling if the file is now uploading. */ - public void showDetails(OCFile file); + public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading); + } - + } diff --git a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java index 95847ba2..7de0268d 100644 --- a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -19,33 +19,22 @@ package com.owncloud.android.ui.fragment; import java.io.File; import java.util.ArrayList; -import java.util.List; import com.owncloud.android.R; -import com.owncloud.android.authentication.AccountUtils; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; -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.operations.RemoveFileOperation; -import com.owncloud.android.operations.RenameFileOperation; -import com.owncloud.android.operations.SynchronizeFileOperation; -import com.owncloud.android.ui.activity.FileDisplayActivity; -import com.owncloud.android.ui.activity.TransferServiceGetter; +import com.owncloud.android.files.FileMenuFilter; import com.owncloud.android.ui.adapter.FileListListAdapter; -import com.owncloud.android.ui.dialog.EditNameDialog; -import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener; -import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener; +import com.owncloud.android.ui.activity.FileDisplayActivity; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; +import com.owncloud.android.ui.dialog.RemoveFileDialogFragment; +import com.owncloud.android.ui.dialog.RenameFileDialogFragment; import com.owncloud.android.ui.preview.PreviewImageFragment; import com.owncloud.android.ui.preview.PreviewMediaFragment; import com.owncloud.android.utils.Log_OC; -import android.accounts.Account; import android.app.Activity; import android.os.Bundle; -import android.os.Handler; import android.view.ContextMenu; import android.view.MenuInflater; import android.view.MenuItem; @@ -56,10 +45,13 @@ import android.widget.AdapterView.AdapterContextMenuInfo; /** * A Fragment that lists all files and folders in a given path. * - * @author Bartek Przybylski + * TODO refactorize to get rid of direct dependency on FileDisplayActivity * + * @author Bartek Przybylski + * @author masensio + * @author David A. Velasco */ -public class OCFileListFragment extends ExtendedListFragment implements EditNameDialogListener, ConfirmationDialogFragmentListener { +public class OCFileListFragment extends ExtendedListFragment { private static final String TAG = OCFileListFragment.class.getSimpleName(); @@ -71,12 +63,11 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName private static final String KEY_TOPS = "TOPS"; private static final String KEY_HEIGHT_CELL = "HEIGHT_CELL"; - private OCFileListFragment.ContainerActivity mContainerActivity; - + private FileFragment.ContainerActivity mContainerActivity; + private OCFile mFile = null; private FileListListAdapter mAdapter; - private Handler mHandler; private OCFile mTargetFile; // Save the state of the scroll in browsing @@ -94,12 +85,19 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName super.onAttach(activity); Log_OC.e(TAG, "onAttach"); try { - mContainerActivity = (ContainerActivity) activity; + mContainerActivity = (FileFragment.ContainerActivity) activity; } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement " + OCFileListFragment.ContainerActivity.class.getSimpleName()); + throw new ClassCastException(activity.toString() + " must implement " + + FileFragment.ContainerActivity.class.getSimpleName()); } } + + @Override + public void onDetach() { + mContainerActivity = null; + super.onDetach(); + } /** * {@inheritDoc} @@ -108,7 +106,8 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log_OC.e(TAG, "onActivityCreated() start"); - mAdapter = new FileListListAdapter(getActivity(), mContainerActivity); + mAdapter = new FileListListAdapter(getSherlockActivity(), mContainerActivity); + if (savedInstanceState != null) { mFile = savedInstanceState.getParcelable(EXTRA_FILE); mIndexes = savedInstanceState.getIntegerArrayList(KEY_INDEXES); @@ -124,14 +123,15 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName } + mAdapter = new FileListListAdapter(getSherlockActivity(), mContainerActivity); + setListAdapter(mAdapter); registerForContextMenu(getListView()); getListView().setOnCreateContextMenuListener(this); - mHandler = new Handler(); - - } + // mHandler = new Handler(); + } /** * Saves the current listed folder. @@ -182,7 +182,7 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName if (mFile != null) { listDirectory(mFile); - mContainerActivity.startSyncFolderOperation(mFile); + ((FileDisplayActivity)mContainerActivity).startSyncFolderOperation(mFile); // restore index and top position restoreIndexAndTopPosition(); @@ -259,20 +259,19 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName } else { /// Click on a file if (PreviewImageFragment.canBePreviewed(file)) { // preview image - it handles the download, if needed - mContainerActivity.startImagePreview(file); + ((FileDisplayActivity)mContainerActivity).startImagePreview(file); } else if (file.isDown()) { if (PreviewMediaFragment.canBePreviewed(file)) { // media preview - mContainerActivity.startMediaPreview(file, 0, true); + ((FileDisplayActivity)mContainerActivity).startMediaPreview(file, 0, true); } else { - FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); - activity.getFileOperationsHelper().openFile(file, activity); + mContainerActivity.getFileOperationsHelper().openFile(file); } } else { // automatic download, preview on finish - mContainerActivity.startDownloadForPreview(file); + ((FileDisplayActivity)mContainerActivity).startDownloadForPreview(file); } } @@ -289,85 +288,40 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName @Override public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); - MenuInflater inflater = getActivity().getMenuInflater(); + MenuInflater inflater = getSherlockActivity().getMenuInflater(); inflater.inflate(R.menu.file_actions_menu, menu); AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; OCFile targetFile = (OCFile) mAdapter.getItem(info.position); - List toHide = new ArrayList(); - List toDisable = new ArrayList(); - MenuItem item = null; - if (targetFile.isFolder()) { - // contextual menu for folders - toHide.add(R.id.action_open_file_with); - toHide.add(R.id.action_download_file); - toHide.add(R.id.action_cancel_download); - toHide.add(R.id.action_cancel_upload); - toHide.add(R.id.action_sync_file); - toHide.add(R.id.action_see_details); - toHide.add(R.id.action_send_file); - if ( mContainerActivity.getFileDownloaderBinder().isDownloading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile) || - mContainerActivity.getFileUploaderBinder().isUploading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile) ) { - toDisable.add(R.id.action_rename_file); - toDisable.add(R.id.action_remove_file); - - } - - } else { - // contextual menu for regular files - - // new design: 'download' and 'open with' won't be available anymore in context menu - toHide.add(R.id.action_download_file); - toHide.add(R.id.action_open_file_with); - - if (targetFile.isDown()) { - toHide.add(R.id.action_cancel_download); - toHide.add(R.id.action_cancel_upload); - - } else { - toHide.add(R.id.action_sync_file); - } - if ( mContainerActivity.getFileDownloaderBinder().isDownloading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile)) { - toHide.add(R.id.action_cancel_upload); - toDisable.add(R.id.action_rename_file); - toDisable.add(R.id.action_remove_file); - - } else if ( mContainerActivity.getFileUploaderBinder().isUploading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile)) { - toHide.add(R.id.action_cancel_download); - toDisable.add(R.id.action_rename_file); - toDisable.add(R.id.action_remove_file); - - } else { - toHide.add(R.id.action_cancel_download); - toHide.add(R.id.action_cancel_upload); - } + if (mContainerActivity.getStorageManager() != null) { + FileMenuFilter mf = new FileMenuFilter( + targetFile, + mContainerActivity.getStorageManager().getAccount(), + mContainerActivity, + getSherlockActivity() + ); + mf.filter(menu); } - // Options shareLink - if (!targetFile.isShareByLink()) { - toHide.add(R.id.action_unshare_file); + /// additional restrictions for this fragment + // TODO allow in the future 'open with' for previewable files + MenuItem item = menu.findItem(R.id.action_open_file_with); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); } - - // Send file - boolean sendEnabled = getString(R.string.send_files_to_other_apps).equalsIgnoreCase("on"); - if (!sendEnabled) { - toHide.add(R.id.action_send_file); - } - - for (int i : toHide) { - item = menu.findItem(i); + /// TODO break this direct dependency on FileDisplayActivity... if possible + FileFragment frag = ((FileDisplayActivity)getSherlockActivity()).getSecondFragment(); + if (frag != null && frag instanceof FileDetailFragment && + frag.getFile().getFileId() == targetFile.getFileId()) { + item = menu.findItem(R.id.action_see_details); if (item != null) { item.setVisible(false); item.setEnabled(false); } } - for (int i : toDisable) { - item = menu.findItem(i); - if (item != null) { - item.setEnabled(false); - } - } + } @@ -380,86 +334,45 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName mTargetFile = (OCFile) mAdapter.getItem(info.position); switch (item.getItemId()) { case R.id.action_share_file: { - FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); - activity.getFileOperationsHelper().shareFileWithLink(mTargetFile, activity); + mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile); return true; } case R.id.action_unshare_file: { - FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); - activity.getFileOperationsHelper().unshareFileWithLink(mTargetFile, activity); + mContainerActivity.getFileOperationsHelper().unshareFileWithLink(mTargetFile); return true; } case R.id.action_rename_file: { - String fileName = mTargetFile.getFileName(); - int extensionStart = mTargetFile.isFolder() ? -1 : fileName.lastIndexOf("."); - int selectionEnd = (extensionStart >= 0) ? extensionStart : fileName.length(); - EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), fileName, 0, selectionEnd, this); - dialog.show(getFragmentManager(), EditNameDialog.TAG); + RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(mTargetFile); + dialog.show(getFragmentManager(), FileDetailFragment.FTAG_RENAME_FILE); return true; } case R.id.action_remove_file: { - int messageStringId = R.string.confirmation_remove_alert; - int posBtnStringId = R.string.confirmation_remove_remote; - int neuBtnStringId = -1; - if (mTargetFile.isFolder()) { - messageStringId = R.string.confirmation_remove_folder_alert; - posBtnStringId = R.string.confirmation_remove_remote_and_local; - neuBtnStringId = R.string.confirmation_remove_folder_local; - } else if (mTargetFile.isDown()) { - posBtnStringId = R.string.confirmation_remove_remote_and_local; - neuBtnStringId = R.string.confirmation_remove_local; - } - ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance( - messageStringId, - new String[]{mTargetFile.getFileName()}, - posBtnStringId, - neuBtnStringId, - R.string.common_cancel); - confDialog.setOnConfirmationListener(this); - confDialog.show(getFragmentManager(), FileDetailFragment.FTAG_CONFIRMATION); + RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(mTargetFile); + dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION); return true; } + case R.id.action_download_file: case R.id.action_sync_file: { - Account account = AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()); - RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, getSherlockActivity()); - operation.execute(account, getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity()); - ((FileDisplayActivity) getSherlockActivity()).showLoadingDialog(); - return true; - } - case R.id.action_cancel_download: { - FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder(); - Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity()); - if (downloaderBinder != null && downloaderBinder.isDownloading(account, mTargetFile)) { - downloaderBinder.cancel(account, mTargetFile); - listDirectory(); - mContainerActivity.onTransferStateChanged(mTargetFile, false, false); - } + mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile); return true; } + case R.id.action_cancel_download: case R.id.action_cancel_upload: { - FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder(); - Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity()); - if (uploaderBinder != null && uploaderBinder.isUploading(account, mTargetFile)) { - uploaderBinder.cancel(account, mTargetFile); - listDirectory(); - mContainerActivity.onTransferStateChanged(mTargetFile, false, false); - } + ((FileDisplayActivity)mContainerActivity).cancelTransference(mTargetFile); return true; } case R.id.action_see_details: { - ((FileFragment.ContainerActivity)getActivity()).showDetails(mTargetFile); + mContainerActivity.showDetails(mTargetFile); return true; } case R.id.action_send_file: { // Obtain the file if (!mTargetFile.isDown()) { // Download the file Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded"); - mContainerActivity.startDownloadForSending(mTargetFile); + ((FileDisplayActivity)mContainerActivity).startDownloadForSending(mTargetFile); } else { - - FileDisplayActivity activity = (FileDisplayActivity) getSherlockActivity(); - activity.getFileOperationsHelper().sendDownloadedFile(mTargetFile, activity); + mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile); } return true; } @@ -521,98 +434,4 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName } } - - - /** - * Interface to implement by any Activity that includes some instance of FileListFragment - * - * @author David A. Velasco - */ - public interface ContainerActivity extends TransferServiceGetter, OnRemoteOperationListener { - - /** - * Callback method invoked when a the user browsed into a different folder through the list of files - * - * @param file - */ - public void onBrowsedDownTo(OCFile folder); - - public void startDownloadForPreview(OCFile file); - - public void startMediaPreview(OCFile file, int i, boolean b); - - public void startImagePreview(OCFile file); - - public void startSyncFolderOperation(OCFile folder); - - /** - * Getter for the current DataStorageManager in the container activity - */ - public FileDataStorageManager getStorageManager(); - - - /** - * Callback method invoked when a the 'transfer state' of a file changes. - * - * This happens when a download or upload is started or ended for a file. - * - * This method is necessary by now to update the user interface of the double-pane layout in tablets - * because methods {@link FileDownloaderBinder#isDownloading(Account, OCFile)} and {@link FileUploaderBinder#isUploading(Account, OCFile)} - * won't provide the needed response before the method where this is called finishes. - * - * TODO Remove this when the transfer state of a file is kept in the database (other thing TODO) - * - * @param file OCFile which state changed. - * @param downloading Flag signaling if the file is now downloading. - * @param uploading Flag signaling if the file is now uploading. - */ - public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading); - - void startDownloadForSending(OCFile file); - - } - - - @Override - public void onDismiss(EditNameDialog dialog) { - if (dialog.getResult()) { - String newFilename = dialog.getNewFilename(); - Log_OC.d(TAG, "name edit dialog dismissed with new name " + newFilename); - RemoteOperation operation = new RenameFileOperation(mTargetFile, - AccountUtils.getCurrentOwnCloudAccount(getActivity()), - newFilename, - mContainerActivity.getStorageManager()); - operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity()); - ((FileDisplayActivity) getActivity()).showLoadingDialog(); - } - } - - - @Override - public void onConfirmation(String callerTag) { - if (callerTag.equals(FileDetailFragment.FTAG_CONFIRMATION)) { - if (mContainerActivity.getStorageManager().getFileById(mTargetFile.getFileId()) != null) { - RemoteOperation operation = new RemoveFileOperation( mTargetFile, - true, - mContainerActivity.getStorageManager()); - operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity()); - - ((FileDisplayActivity) getActivity()).showLoadingDialog(); - } - } - } - - @Override - public void onNeutral(String callerTag) { - mContainerActivity.getStorageManager().removeFile(mTargetFile, false, true); // TODO perform in background task / new thread - listDirectory(); - mContainerActivity.onTransferStateChanged(mTargetFile, false, false); - } - - @Override - public void onCancel(String callerTag) { - Log_OC.d(TAG, "REMOVAL CANCELED"); - } - - } diff --git a/src/com/owncloud/android/ui/preview/FileDownloadFragment.java b/src/com/owncloud/android/ui/preview/FileDownloadFragment.java index c8fd2d29..65c5d872 100644 --- a/src/com/owncloud/android/ui/preview/FileDownloadFragment.java +++ b/src/com/owncloud/android/ui/preview/FileDownloadFragment.java @@ -26,7 +26,6 @@ import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.utils.Log_OC; import android.accounts.Account; -import android.app.Activity; import android.os.Bundle; import android.support.v4.app.FragmentStatePagerAdapter; import android.view.LayoutInflater; @@ -51,8 +50,6 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene public static final String EXTRA_ACCOUNT = "ACCOUNT"; private static final String EXTRA_ERROR = "ERROR"; - private FileFragment.ContainerActivity mContainerActivity; - private View mView; private Account mAccount; @@ -139,33 +136,6 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene } - /** - * {@inheritDoc} - */ - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - try { - mContainerActivity = (ContainerActivity) activity; - - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName()); - } - } - - - /** - * {@inheritDoc} - */ - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - if (mAccount != null) { - //mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());; - } - } - - @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/src/com/owncloud/android/ui/preview/PreviewImageActivity.java b/src/com/owncloud/android/ui/preview/PreviewImageActivity.java index d7cc36d6..d4e95cbd 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImageActivity.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageActivity.java @@ -26,9 +26,6 @@ import android.content.SharedPreferences; import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceManager; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; import android.view.MotionEvent; import android.view.View; @@ -50,11 +47,11 @@ 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.RemoveFileOperation; 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; -import com.owncloud.android.ui.dialog.LoadingDialog; import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.Log_OC; @@ -65,7 +62,9 @@ import com.owncloud.android.utils.Log_OC; * * @author David A. Velasco */ -public class PreviewImageActivity extends FileActivity implements FileFragment.ContainerActivity, ViewPager.OnPageChangeListener, OnTouchListener , OnRemoteOperationListener{ +public class PreviewImageActivity extends FileActivity implements +FileFragment.ContainerActivity, OnTouchListener, +ViewPager.OnPageChangeListener, OnRemoteOperationListener { public static final int DIALOG_SHORT_WAIT = 0; @@ -74,15 +73,9 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C public static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW"; private static final String KEY_WAITING_FOR_BINDER = "WAITING_FOR_BINDER"; - private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT"; - private ViewPager mViewPager; private PreviewImagePagerAdapter mPreviewImagePagerAdapter; - private FileDownloaderBinder mDownloaderBinder = null; - private ServiceConnection mDownloadConnection, mUploadConnection = null; - private FileUploaderBinder mUploaderBinder = null; - private boolean mRequestWaitingForBinder; private DownloadFinishReceiver mDownloadFinishReceiver; @@ -141,10 +134,6 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C @Override public void onStart() { super.onStart(); - mDownloadConnection = new PreviewImageServiceConnection(); - bindService(new Intent(this, FileDownloader.class), mDownloadConnection, Context.BIND_AUTO_CREATE); - mUploadConnection = new PreviewImageServiceConnection(); - bindService(new Intent(this, FileUploader.class), mUploadConnection, Context.BIND_AUTO_CREATE); } @Override @@ -163,6 +152,8 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C } else if (operation instanceof UnshareLinkOperation) { onUnshareLinkOperationFinish((UnshareLinkOperation) operation, result); + } else if (operation instanceof RemoveFileOperation) { + finish(); } } @@ -189,7 +180,12 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C invalidateOptionsMenu(); } } - + + @Override + protected ServiceConnection newTransferenceServiceConnection() { + return new PreviewImageServiceConnection(); + } + /** Defines callbacks for service binding, passed to bindService() */ private class PreviewImageServiceConnection implements ServiceConnection { @@ -229,14 +225,6 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C @Override public void onStop() { super.onStop(); - if (mDownloadConnection != null) { - unbindService(mDownloadConnection); - mDownloadConnection = null; - } - if (mUploadConnection != null) { - unbindService(mUploadConnection); - mUploadConnection = null; - } } @@ -291,53 +279,6 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C finish(); } - /** - * Show loading dialog - */ - public void showLoadingDialog() { - // Construct dialog - LoadingDialog loading = new LoadingDialog(getResources().getString(R.string.wait_a_moment)); - FragmentManager fm = getSupportFragmentManager(); - FragmentTransaction ft = fm.beginTransaction(); - loading.show(ft, DIALOG_WAIT_TAG); - - } - - /** - * Dismiss loading dialog - */ - public void dismissLoadingDialog(){ - Fragment frag = getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG); - if (frag != null) { - LoadingDialog loading = (LoadingDialog) frag; - loading.dismiss(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void onFileStateChanged() { - // nothing to do here! - } - - - /** - * {@inheritDoc} - */ - @Override - public FileDownloaderBinder getFileDownloaderBinder() { - return mDownloaderBinder; - } - - - @Override - public FileUploaderBinder getFileUploaderBinder() { - return mUploaderBinder; - } - - @Override public void showDetails(OCFile file) { Intent showDetailsIntent = new Intent(this, FileDisplayActivity.class); @@ -516,4 +457,16 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C } } + @Override + public void onBrowsedDownTo(OCFile folder) { + // TODO Auto-generated method stub + + } + + @Override + public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading) { + // TODO Auto-generated method stub + + } + } diff --git a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java index 3a374e08..fd22b3a9 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageFragment.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, @@ -17,48 +17,35 @@ package com.owncloud.android.ui.preview; import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; import android.accounts.Account; import android.annotation.SuppressLint; import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.graphics.Point; -import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; -import android.os.Handler; import android.support.v4.app.FragmentStatePagerAdapter; import android.view.Display; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup; -import android.webkit.MimeTypeMap; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; -import android.widget.Toast; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.R; -import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.lib.common.network.WebdavUtils; -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.operations.RemoveFileOperation; -import com.owncloud.android.ui.activity.FileActivity; -import com.owncloud.android.ui.fragment.ConfirmationDialogFragment; +import com.owncloud.android.files.FileMenuFilter; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; +import com.owncloud.android.ui.dialog.RemoveFileDialogFragment; import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.utils.Log_OC; @@ -72,23 +59,18 @@ import com.owncloud.android.utils.Log_OC; * * @author David A. Velasco */ -public class PreviewImageFragment extends FileFragment implements OnRemoteOperationListener, - ConfirmationDialogFragment.ConfirmationDialogFragmentListener { +public class PreviewImageFragment extends FileFragment { public static final String EXTRA_FILE = "FILE"; public static final String EXTRA_ACCOUNT = "ACCOUNT"; private View mView; private Account mAccount; - private FileDataStorageManager mStorageManager; private ImageView mImageView; private TextView mMessageView; private ProgressBar mProgressWheel; public Bitmap mBitmap = null; - private Handler mHandler; - private RemoteOperation mLastRemoteOperation; - private static final String TAG = PreviewImageFragment.class.getSimpleName(); private boolean mIgnoreFirstSavedState; @@ -106,7 +88,6 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper public PreviewImageFragment(OCFile fileToDetail, Account ocAccount, boolean ignoreFirstSavedState) { super(fileToDetail); mAccount = ocAccount; - mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment mIgnoreFirstSavedState = ignoreFirstSavedState; } @@ -121,7 +102,6 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper public PreviewImageFragment() { super(); mAccount = null; - mStorageManager = null; mIgnoreFirstSavedState = false; } @@ -132,7 +112,6 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mHandler = new Handler(); setHasOptionsMenu(true); } @@ -147,7 +126,7 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper mView = inflater.inflate(R.layout.preview_image_fragment, container, false); mImageView = (ImageView)mView.findViewById(R.id.image); mImageView.setVisibility(View.GONE); - mView.setOnTouchListener((OnTouchListener)getActivity()); // WATCH OUT THAT CAST + mView.setOnTouchListener((OnTouchListener)getActivity()); mMessageView = (TextView)mView.findViewById(R.id.message); mMessageView.setVisibility(View.GONE); mProgressWheel = (ProgressBar)mView.findViewById(R.id.progressWheel); @@ -162,8 +141,10 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper @Override public void onAttach(Activity activity) { super.onAttach(activity); - if (!(activity instanceof FileFragment.ContainerActivity)) - throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName()); + if (!(activity instanceof OnTouchListener)) { + throw new ClassCastException(activity.toString() + + " must implement " + OnTouchListener.class.getSimpleName()); + } } @@ -173,25 +154,11 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver()); if (savedInstanceState != null) { if (!mIgnoreFirstSavedState) { OCFile file = (OCFile)savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_FILE); + setFile(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; } @@ -235,35 +202,7 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.file_actions_menu, menu); - List toHide = new ArrayList(); - - MenuItem item = null; - toHide.add(R.id.action_cancel_download); - 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); - } - - // Send file - boolean sendEnabled = getString(R.string.send_files_to_other_apps).equalsIgnoreCase("on"); - if (!sendEnabled) { - toHide.add(R.id.action_send_file); - } - - for (int i : toHide) { - item = menu.findItem(i); - if (item != null) { - item.setVisible(false); - item.setEnabled(false); - } - } - } /** @@ -273,17 +212,23 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper 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()) { + if (mContainerActivity.getStorageManager() != null) { + FileMenuFilter mf = new FileMenuFilter( + getFile(), + mContainerActivity.getStorageManager().getAccount(), + mContainerActivity, + getSherlockActivity() + ); + mf.filter(menu); + } + + // additional restriction for this fragment + // TODO allow renaming in PreviewImageFragment + MenuItem item = menu.findItem(R.id.action_rename_file); + if (item != null) { item.setVisible(false); item.setEnabled(false); - } else { - item.setVisible(true); - item.setEnabled(true); } - } @@ -295,13 +240,11 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_share_file: { - FileActivity act = (FileActivity)getSherlockActivity(); - act.getFileOperationsHelper().shareFileWithLink(getFile(), act); + mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile()); return true; } case R.id.action_unshare_file: { - FileActivity act = (FileActivity)getSherlockActivity(); - act.getFileOperationsHelper().unshareFileWithLink(getFile(), act); + mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile()); return true; } case R.id.action_open_file_with: { @@ -309,7 +252,8 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper return true; } case R.id.action_remove_file: { - removeFile(); + RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile()); + dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION); return true; } case R.id.action_see_details: { @@ -317,8 +261,11 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper return true; } case R.id.action_send_file: { - FileActivity act = (FileActivity)getSherlockActivity(); - act.getFileOperationsHelper().sendDownloadedFile(getFile(), act); + mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile()); + return true; + } + case R.id.action_sync_file: { + mContainerActivity.getFileOperationsHelper().syncFile(getFile()); return true; } @@ -329,7 +276,7 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper private void seeDetails() { - ((FileFragment.ContainerActivity)getActivity()).showDetails(getFile()); + mContainerActivity.showDetails(getFile()); } @@ -356,113 +303,13 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper /** * Opens the previewed image with an external application. - * - * TODO - improve this; instead of prioritize the actions available for the MIME type in the server, - * we should get a list of available apps for MIME tpye in the server and join it with the list of - * available apps for the MIME type known from the file extension, to let the user choose */ private void openFile() { - OCFile file = getFile(); - String storagePath = file.getStoragePath(); - String encodedStoragePath = WebdavUtils.encodePath(storagePath); - try { - Intent i = new Intent(Intent.ACTION_VIEW); - i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype()); - i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - startActivity(i); - - } catch (Throwable t) { - Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + file.getMimetype()); - boolean toastIt = true; - String mimeType = ""; - try { - Intent i = new Intent(Intent.ACTION_VIEW); - mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1)); - if (mimeType == null || !mimeType.equals(file.getMimetype())) { - if (mimeType != null) { - i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType); - } else { - // desperate try - i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*-/*"); - } - i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - startActivity(i); - toastIt = false; - } - - } catch (IndexOutOfBoundsException e) { - Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath); - - } catch (ActivityNotFoundException e) { - Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension"); - - } catch (Throwable th) { - Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th); - - } finally { - if (toastIt) { - Toast.makeText(getActivity(), "There is no application to handle file " + file.getFileName(), Toast.LENGTH_SHORT).show(); - } - } - - } - finish(); - } - - - /** - * Starts a the removal of the previewed file. - * - * Shows a confirmation dialog. The action continues in {@link #onConfirmation(String)} , {@link #onNeutral(String)} or {@link #onCancel(String)}, - * depending upon the user selection in the dialog. - */ - private void removeFile() { - ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance( - R.string.confirmation_remove_alert, - new String[]{getFile().getFileName()}, - R.string.confirmation_remove_remote_and_local, - R.string.confirmation_remove_local, - R.string.common_cancel); - confDialog.setOnConfirmationListener(this); - confDialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION); - } - - - /** - * Performs the removal of the previewed file, both locally and in the server. - */ - @Override - public void onConfirmation(String callerTag) { - if (mStorageManager.getFileById(getFile().getFileId()) != null) { // check that the file is still there; - mLastRemoteOperation = new RemoveFileOperation( getFile(), // TODO we need to review the interface with RemoteOperations, and use OCFile IDs instead of OCFile objects as parameters - true, - mStorageManager); - mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity()); - - ((PreviewImageActivity) getActivity()).showLoadingDialog(); - } - } - - - /** - * Removes the file from local storage - */ - @Override - public void onNeutral(String callerTag) { - OCFile file = getFile(); - mStorageManager.removeFile(file, false, true); // TODO perform in background task / new thread + mContainerActivity.getFileOperationsHelper().openFile(getFile()); finish(); } - /** - * User cancelled the removal action. - */ - @Override - public void onCancel(String callerTag) { - // nothing to do here - } - private class BitmapLoader extends AsyncTask { /** @@ -647,33 +494,6 @@ public class PreviewImageFragment extends FileFragment implements OnRemoteOper /** - * {@inheritDoc} - */ - @Override - public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { - if (operation.equals(mLastRemoteOperation) && operation instanceof RemoveFileOperation) { - onRemoveFileOperationFinish((RemoveFileOperation)operation, result); - } - } - - private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) { - ((PreviewImageActivity) getActivity()).dismissLoadingDialog(); - - if (result.isSuccess()) { - Toast msg = Toast.makeText(getActivity().getApplicationContext(), R.string.remove_success_msg, Toast.LENGTH_LONG); - msg.show(); - finish(); - - } else { - Toast msg = Toast.makeText(getActivity(), R.string.remove_fail_msg, Toast.LENGTH_LONG); - msg.show(); - if (result.isSslRecoverableException()) { - // TODO show the SSL warning dialog - } - } - } - - /** * Finishes the preview */ private void finish() { diff --git a/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java b/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java index 7fa399ae..5f5ceaa6 100644 --- a/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java @@ -16,13 +16,9 @@ */ package com.owncloud.android.ui.preview; -import java.util.ArrayList; -import java.util.List; - import android.accounts.Account; import android.app.Activity; import android.app.AlertDialog; -import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; @@ -33,17 +29,14 @@ import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.media.MediaPlayer.OnPreparedListener; -import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.os.Handler; import android.os.IBinder; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup; -import android.webkit.MimeTypeMap; import android.widget.ImageView; import android.widget.Toast; import android.widget.VideoView; @@ -52,19 +45,14 @@ import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.R; -import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.files.FileMenuFilter; import com.owncloud.android.media.MediaControlView; import com.owncloud.android.media.MediaService; import com.owncloud.android.media.MediaServiceBinder; -import com.owncloud.android.lib.common.network.WebdavUtils; -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.operations.RemoveFileOperation; import com.owncloud.android.ui.activity.FileActivity; -import com.owncloud.android.ui.activity.FileDisplayActivity; -import com.owncloud.android.ui.fragment.ConfirmationDialogFragment; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; +import com.owncloud.android.ui.dialog.RemoveFileDialogFragment; import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.utils.Log_OC; @@ -79,8 +67,7 @@ import com.owncloud.android.utils.Log_OC; * @author David A. Velasco */ public class PreviewMediaFragment extends FileFragment implements - OnTouchListener, - ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener { + OnTouchListener { public static final String EXTRA_FILE = "FILE"; public static final String EXTRA_ACCOUNT = "ACCOUNT"; @@ -89,14 +76,10 @@ public class PreviewMediaFragment extends FileFragment implements private View mView; private Account mAccount; - private FileDataStorageManager mStorageManager; private ImageView mImagePreview; private VideoView mVideoPreview; private int mSavedPlaybackPosition; - private Handler mHandler; - private RemoteOperation mLastRemoteOperation; - private MediaServiceBinder mMediaServiceBinder = null; private MediaControlView mMediaController = null; private MediaServiceConnection mMediaServiceConnection = null; @@ -115,11 +98,15 @@ public class PreviewMediaFragment extends FileFragment implements * @param fileToDetail An {@link OCFile} to preview in the fragment * @param ocAccount An ownCloud account; needed to start downloads */ - public PreviewMediaFragment(OCFile fileToDetail, Account ocAccount, int startPlaybackPosition, boolean autoplay) { + public PreviewMediaFragment( + OCFile fileToDetail, + Account ocAccount, + int startPlaybackPosition, + boolean autoplay) { + super(fileToDetail); mAccount = ocAccount; mSavedPlaybackPosition = startPlaybackPosition; - mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment mAutoplay = autoplay; } @@ -127,15 +114,16 @@ public class PreviewMediaFragment extends FileFragment implements /** * Creates an empty fragment for previews. * - * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically (for instance, when the device is turned a aside). + * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically + * (for instance, when the device is turned a aside). * - * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful construction + * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful + * construction */ public PreviewMediaFragment() { super(); mAccount = null; mSavedPlaybackPosition = 0; - mStorageManager = null; mAutoplay = true; } @@ -146,7 +134,6 @@ public class PreviewMediaFragment extends FileFragment implements @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mHandler = new Handler(); setHasOptionsMenu(true); } @@ -177,49 +164,40 @@ public class PreviewMediaFragment extends FileFragment implements * {@inheritDoc} */ @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - Log_OC.e(TAG, "onAttach"); - - if (!(activity instanceof FileFragment.ContainerActivity)) - throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName()); - } - - - /** - * {@inheritDoc} - */ - @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log_OC.e(TAG, "onActivityCreated"); - mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver()); - if (savedInstanceState != null) { + OCFile file = getFile(); + if (savedInstanceState == null) { + if (file == null) { + throw new IllegalStateException("Instanced with a NULL OCFile"); + } + if (mAccount == null) { + throw new IllegalStateException("Instanced with a NULL ownCloud Account"); + } + if (!file.isDown()) { + throw new IllegalStateException("There is no local file to preview"); + } + + } else { setFile((OCFile)savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_FILE)); mAccount = savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_ACCOUNT); - mSavedPlaybackPosition = savedInstanceState.getInt(PreviewMediaFragment.EXTRA_PLAY_POSITION); + mSavedPlaybackPosition = + savedInstanceState.getInt(PreviewMediaFragment.EXTRA_PLAY_POSITION); mAutoplay = savedInstanceState.getBoolean(PreviewMediaFragment.EXTRA_PLAYING); } - OCFile file = getFile(); - if (file == null) { - throw new IllegalStateException("Instanced with a NULL OCFile"); - } - if (mAccount == null) { - throw new IllegalStateException("Instanced with a NULL ownCloud Account"); - } - if (!file.isDown()) { - throw new IllegalStateException("There is no local file to preview"); - } - if (file.isVideo()) { - mVideoPreview.setVisibility(View.VISIBLE); - mImagePreview.setVisibility(View.GONE); - prepareVideo(); + if (file != null && file.isDown()) { + if (file.isVideo()) { + mVideoPreview.setVisibility(View.VISIBLE); + mImagePreview.setVisibility(View.GONE); + prepareVideo(); - } else { - mVideoPreview.setVisibility(View.GONE); - mImagePreview.setVisibility(View.VISIBLE); + } else { + mVideoPreview.setVisibility(View.GONE); + mImagePreview.setVisibility(View.VISIBLE); + } } } @@ -242,8 +220,11 @@ public class PreviewMediaFragment extends FileFragment implements outState.putInt(PreviewMediaFragment.EXTRA_PLAY_POSITION , mSavedPlaybackPosition); outState.putBoolean(PreviewMediaFragment.EXTRA_PLAYING , mAutoplay); } else { - outState.putInt(PreviewMediaFragment.EXTRA_PLAY_POSITION , mMediaServiceBinder.getCurrentPosition()); - outState.putBoolean(PreviewMediaFragment.EXTRA_PLAYING , mMediaServiceBinder.isPlaying()); + outState.putInt( + PreviewMediaFragment.EXTRA_PLAY_POSITION , + mMediaServiceBinder.getCurrentPosition()); + outState.putBoolean( + PreviewMediaFragment.EXTRA_PLAYING , mMediaServiceBinder.isPlaying()); } } @@ -254,7 +235,7 @@ public class PreviewMediaFragment extends FileFragment implements Log_OC.e(TAG, "onStart"); OCFile file = getFile(); - if (file != null) { + if (file != null && file.isDown()) { if (file.isAudio()) { bindMediaService(); @@ -279,36 +260,7 @@ public class PreviewMediaFragment extends FileFragment implements @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.file_actions_menu, menu); - List toHide = new ArrayList(); - - MenuItem item = null; - toHide.add(R.id.action_cancel_download); - toHide.add(R.id.action_cancel_upload); - 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); - } - - // Send file - boolean sendEnabled = getString(R.string.send_files_to_other_apps).equalsIgnoreCase("on"); - if (!sendEnabled) { - toHide.add(R.id.action_send_file); - } - - for (int i : toHide) { - item = menu.findItem(i); - if (item != null) { - item.setVisible(false); - item.setEnabled(false); - } - } - } @@ -319,14 +271,22 @@ public class PreviewMediaFragment extends FileFragment implements public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - MenuItem item = menu.findItem(R.id.action_unshare_file); - // Options shareLink - if (!getFile().isShareByLink()) { + if (mContainerActivity.getStorageManager() != null) { + FileMenuFilter mf = new FileMenuFilter( + getFile(), + mContainerActivity.getStorageManager().getAccount(), + mContainerActivity, + getSherlockActivity() + ); + mf.filter(menu); + } + + // additional restriction for this fragment + // TODO allow renaming in PreviewImageFragment + MenuItem item = menu.findItem(R.id.action_rename_file); + if (item != null) { item.setVisible(false); item.setEnabled(false); - } else { - item.setVisible(true); - item.setEnabled(true); } } @@ -338,11 +298,13 @@ public class PreviewMediaFragment extends FileFragment implements public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_share_file: { - shareFileWithLink(); + stopPreview(false); + mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile()); return true; } case R.id.action_unshare_file: { - unshareFileWithLink(); + stopPreview(false); + mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile()); return true; } case R.id.action_open_file_with: { @@ -350,7 +312,8 @@ public class PreviewMediaFragment extends FileFragment implements return true; } case R.id.action_remove_file: { - removeFile(); + RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile()); + dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION); return true; } case R.id.action_see_details: { @@ -360,7 +323,11 @@ public class PreviewMediaFragment extends FileFragment implements case R.id.action_send_file: { sendFile(); } - + case R.id.action_sync_file: { + mContainerActivity.getFileOperationsHelper().syncFile(getFile()); + return true; + } + default: return false; } @@ -376,29 +343,15 @@ public class PreviewMediaFragment extends FileFragment implements setFile(file); } - private void unshareFileWithLink() { - stopPreview(false); - FileActivity activity = (FileActivity)((FileFragment.ContainerActivity)getActivity()); - activity.getFileOperationsHelper().unshareFileWithLink(getFile(), activity); - } - - private void shareFileWithLink() { - stopPreview(false); - FileActivity activity = (FileActivity)((FileFragment.ContainerActivity)getActivity()); - activity.getFileOperationsHelper().shareFileWithLink(getFile(), activity); - - } - private void sendFile() { stopPreview(false); - FileActivity activity = (FileActivity)((FileFragment.ContainerActivity)getActivity()); - activity.getFileOperationsHelper().sendDownloadedFile(getFile(), activity); + mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile()); } private void seeDetails() { stopPreview(false); - ((FileFragment.ContainerActivity)getActivity()).showDetails(getFile()); + mContainerActivity.showDetails(getFile()); } @@ -414,7 +367,8 @@ public class PreviewMediaFragment extends FileFragment implements // create and prepare control panel for the user mMediaController.setMediaPlayer(mVideoPreview); - // load the video file in the video player ; when done, VideoHelper#onPrepared() will be called + // load the video file in the video player ; + // when done, VideoHelper#onPrepared() will be called mVideoPreview.setVideoPath(getFile().getStoragePath()); } @@ -481,8 +435,9 @@ public class PreviewMediaFragment extends FileFragment implements @Override public boolean onError(MediaPlayer mp, int what, int extra) { if (mVideoPreview.getWindowToken() != null) { - String message = MediaService.getMessageForMediaError(getActivity(), what, extra); - new AlertDialog.Builder(getActivity()) + String message = MediaService.getMessageForMediaError( + getSherlockActivity(), what, extra); + new AlertDialog.Builder(getSherlockActivity()) .setMessage(message) .setPositiveButton(android.R.string.VideoView_error_button, new DialogInterface.OnClickListener() { @@ -529,7 +484,7 @@ public class PreviewMediaFragment extends FileFragment implements if (mMediaServiceBinder != null && mMediaController != null) { mMediaServiceBinder.unregisterMediaController(mMediaController); } - getActivity().unbindService(mMediaServiceConnection); + getSherlockActivity().unbindService(mMediaServiceConnection); mMediaServiceConnection = null; mMediaServiceBinder = null; } @@ -546,7 +501,7 @@ public class PreviewMediaFragment extends FileFragment implements private void startFullScreenVideo() { - Intent i = new Intent(getActivity(), PreviewVideoActivity.class); + Intent i = new Intent(getSherlockActivity(), PreviewVideoActivity.class); i.putExtra(FileActivity.EXTRA_ACCOUNT, mAccount); i.putExtra(FileActivity.EXTRA_FILE, getFile()); i.putExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, mVideoPreview.isPlaying()); @@ -565,7 +520,8 @@ public class PreviewMediaFragment extends FileFragment implements Log_OC.e(TAG, "onActivityResult " + this); super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { - mSavedPlaybackPosition = data.getExtras().getInt(PreviewVideoActivity.EXTRA_START_POSITION); + mSavedPlaybackPosition = data.getExtras().getInt( + PreviewVideoActivity.EXTRA_START_POSITION); mAutoplay = data.getExtras().getBoolean(PreviewVideoActivity.EXTRA_AUTOPLAY); } } @@ -591,7 +547,7 @@ public class PreviewMediaFragment extends FileFragment implements if (mMediaServiceConnection == null) { mMediaServiceConnection = new MediaServiceConnection(); } - getActivity().bindService( new Intent(getActivity(), + getSherlockActivity().bindService( new Intent(getSherlockActivity(), MediaService.class), mMediaServiceConnection, Context.BIND_AUTO_CREATE); @@ -603,8 +559,9 @@ public class PreviewMediaFragment extends FileFragment implements @Override public void onServiceConnected(ComponentName component, IBinder service) { - if (getActivity() != null) { - if (component.equals(new ComponentName(getActivity(), MediaService.class))) { + if (getSherlockActivity() != null) { + if (component.equals( + new ComponentName(getSherlockActivity(), MediaService.class))) { Log_OC.d(TAG, "Media service connected"); mMediaServiceBinder = (MediaServiceBinder) service; if (mMediaServiceBinder != null) { @@ -631,12 +588,15 @@ public class PreviewMediaFragment extends FileFragment implements @Override public void onServiceDisconnected(ComponentName component) { - if (component.equals(new ComponentName(getActivity(), MediaService.class))) { + if (component.equals(new ComponentName(getSherlockActivity(), MediaService.class))) { Log_OC.e(TAG, "Media service suddenly disconnected"); if (mMediaController != null) { mMediaController.setMediaPlayer(null); } else { - Toast.makeText(getActivity(), "No media controller to release when disconnected from media service", Toast.LENGTH_SHORT).show(); + Toast.makeText( + getSherlockActivity(), + "No media controller to release when disconnected from media service", + Toast.LENGTH_SHORT).show(); } mMediaServiceBinder = null; mMediaServiceConnection = null; @@ -648,118 +608,16 @@ public class PreviewMediaFragment extends FileFragment implements /** * Opens the previewed file with an external application. - * - * TODO - improve this; instead of prioritize the actions available for the MIME type in the server, - * we should get a list of available apps for MIME tpye in the server and join it with the list of - * available apps for the MIME type known from the file extension, to let the user choose */ private void openFile() { - OCFile file = getFile(); stopPreview(true); - String storagePath = file.getStoragePath(); - String encodedStoragePath = WebdavUtils.encodePath(storagePath); - try { - Intent i = new Intent(Intent.ACTION_VIEW); - i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype()); - i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - startActivity(i); - - } catch (Throwable t) { - Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + file.getMimetype()); - boolean toastIt = true; - String mimeType = ""; - try { - Intent i = new Intent(Intent.ACTION_VIEW); - mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1)); - if (mimeType == null || !mimeType.equals(file.getMimetype())) { - if (mimeType != null) { - i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType); - } else { - // desperate try - i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*-/*"); - } - i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - startActivity(i); - toastIt = false; - } - - } catch (IndexOutOfBoundsException e) { - Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath); - - } catch (ActivityNotFoundException e) { - Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension"); - - } catch (Throwable th) { - Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th); - - } finally { - if (toastIt) { - Toast.makeText(getActivity(), "There is no application to handle file " + file.getFileName(), Toast.LENGTH_SHORT).show(); - } - } - - } + mContainerActivity.getFileOperationsHelper().openFile(getFile()); finish(); } /** - * Starts a the removal of the previewed file. - * - * Shows a confirmation dialog. The action continues in {@link #onConfirmation(String)} , {@link #onNeutral(String)} or {@link #onCancel(String)}, - * depending upon the user selection in the dialog. - */ - private void removeFile() { - ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance( - R.string.confirmation_remove_alert, - new String[]{getFile().getFileName()}, - R.string.confirmation_remove_remote_and_local, - R.string.confirmation_remove_local, - R.string.common_cancel); - confDialog.setOnConfirmationListener(this); - confDialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION); - } - - - /** - * Performs the removal of the previewed file, both locally and in the server. - */ - @Override - public void onConfirmation(String callerTag) { - OCFile file = getFile(); - if (mStorageManager.getFileById(file.getFileId()) != null) { // check that the file is still there; - stopPreview(true); - mLastRemoteOperation = new RemoveFileOperation( file, // TODO we need to review the interface with RemoteOperations, and use OCFile IDs instead of OCFile objects as parameters - true, - mStorageManager); - mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity()); - - ((FileDisplayActivity) getActivity()).showLoadingDialog(); - } - } - - - /** - * Removes the file from local storage - */ - @Override - public void onNeutral(String callerTag) { - OCFile file = getFile(); - stopPreview(true); - mStorageManager.removeFile(file, false, true); // TODO perform in background task / new thread - finish(); - } - - /** - * User cancelled the removal action. - */ - @Override - public void onCancel(String callerTag) { - // nothing to do here - } - - - /** - * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewMediaFragment} to be previewed. + * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewMediaFragment} + * to be previewed. * * @param file File to test if can be previewed. * @return 'True' if the file can be handled by the fragment. @@ -767,36 +625,9 @@ public class PreviewMediaFragment extends FileFragment implements public static boolean canBePreviewed(OCFile file) { return (file != null && (file.isAudio() || file.isVideo())); } - - /** - * {@inheritDoc} - */ - @Override - public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { - if (operation.equals(mLastRemoteOperation)) { - if (operation instanceof RemoveFileOperation) { - onRemoveFileOperationFinish((RemoveFileOperation)operation, result); - } - } - } - private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) { - ((FileDisplayActivity) getActivity()).dismissLoadingDialog(); - if (result.isSuccess()) { - Toast msg = Toast.makeText(getActivity().getApplicationContext(), R.string.remove_success_msg, Toast.LENGTH_LONG); - msg.show(); - finish(); - - } else { - Toast msg = Toast.makeText(getActivity(), R.string.remove_fail_msg, Toast.LENGTH_LONG); - msg.show(); - if (result.isSslRecoverableException()) { - // TODO show the SSL warning dialog - } - } - } - private void stopPreview(boolean stopAudio) { + public void stopPreview(boolean stopAudio) { OCFile file = getFile(); if (file.isAudio() && stopAudio) { mMediaServiceBinder.pause(); @@ -812,7 +643,7 @@ public class PreviewMediaFragment extends FileFragment implements * Finishes the preview */ private void finish() { - getActivity().onBackPressed(); + getSherlockActivity().onBackPressed(); }