From: masensio Date: Fri, 4 Sep 2015 12:31:10 +0000 (+0200) Subject: Merge branch 'master' into text_file_preview_pr_707_with_develop X-Git-Tag: oc-android-1.8~17^2~3 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/fc5c4d899c1e51af26ee1d0c5818c4580386181c?hp=6b84d83b3544f8de4e56186f6ecbccd3d612702b Merge branch 'master' into text_file_preview_pr_707_with_develop Conflicts: src/com/owncloud/android/ui/activity/FileDisplayActivity.java src/com/owncloud/android/ui/fragment/OCFileListFragment.java --- diff --git a/.gitmodules b/.gitmodules index 7ccbef03..882f3c27 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,3 @@ - [submodule "owncloud-android-library"] path = owncloud-android-library url = git://github.com/owncloud/android-library.git diff --git a/AndroidManifest.xml b/AndroidManifest.xml index fc701a94..a072d788 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,5 +1,4 @@ - - - + @@ -172,12 +160,12 @@ - + - + @@ -187,11 +175,11 @@ android:label="@string/copy_link" android:icon="@drawable/copy_link"/> - - diff --git a/build.gradle b/build.gradle index 576eb82d..a0db0184 100644 --- a/build.gradle +++ b/build.gradle @@ -58,12 +58,6 @@ android { abortOnError false } } - - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } productFlavors { } diff --git a/owncloud-android-library b/owncloud-android-library index dbc8c325..17bb724b 160000 --- a/owncloud-android-library +++ b/owncloud-android-library @@ -1 +1 @@ -Subproject commit dbc8c325d74f3f7e8da8236c5abe77a141ae4019 +Subproject commit 17bb724b4207142d631a5f1c70d1e80c447e2310 diff --git a/res/menu/file_actions_menu.xml b/res/menu/file_actions_menu.xml index 9074b98e..3e6f4cd4 100644 --- a/res/menu/file_actions_menu.xml +++ b/res/menu/file_actions_menu.xml @@ -1,5 +1,4 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 869c16e9..d9c5320e 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -21,8 +21,12 @@ Biggest - Smallest--> + Wszystkie pliki + Ustawienia + Logi + Zamknij Otwórz Ogólne Więcej @@ -66,6 +70,7 @@ Wysyłanie sekund temu Pusto. Wyślij coś! + Wczytywanie... Nie ma plików w tym folderze. Dotknij plik aby wyświetlić dodatkowe informacje Rozmiar: @@ -197,6 +202,7 @@ Czy naprawdę chcesz usunąć %1$s i jego zawartość? Tylko lokalnie Tylko lokalnie + Z serwera Usunięto Nie można usunąć Wprowadź nową nazwę @@ -247,7 +253,10 @@ Wysyłaj zdjęcia tylko przez WiFi Aktualizuj filmy tylko przez WiFi /InstantUpload + Konflikt pliku Zatrzymaj oba + lokalna wersja + wersja zdalna Podgląd Ten obrazek nie może zostać wyświetlony %1$s nie może zostać skopiowany do lokalnego folderu %2$s @@ -299,7 +308,14 @@ Bezpieczeństwo Katalog wysyłania dla wideo Pobieranie %1$s katalogu nie może zostać ukończone + udostępniony + z tobą Odśwież połączenie Adres Serwera Brak wystarczającej pamięci + Użytkownik + 1 folder + %1$d folderów + 1 plik + 1 plik , 1 folder diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index fc58f953..f29976da 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -202,6 +202,8 @@ 您确定要删除 %1$s 及其内容吗? 仅本地 仅本地 + 来自服务器 + 远程 & 本地 成功删除 无法完成删除 请输出新的名字 @@ -256,6 +258,8 @@ 文件冲突 您想要保留哪个文件?如果您同时选中了两个版本,本地的文件的文件名将被加上一个数字 保留两者 + 本地版本 + 服务器版本 图片预览 无法显示图片 无法复制 %1$s 到本地目录 %2$s diff --git a/res/values/strings.xml b/res/values/strings.xml index cc3587d1..00058946 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -122,14 +122,14 @@ Synchronization failed, you need to relogin Synchronization of %1$s could not be completed Invalid password for %1$s - Conflicts found - %1$d kept-in-sync files could not be sync\'ed + Conflicts found + %1$d kept-in-sync files could not be sync\'ed Kept-in-sync files failed Contents of %1$d files could not be sync\'ed (%2$d conflicts) Some local files were forgotten %1$d files out of the %2$s folder could not be copied into As of version 1.3.16, files uploaded from this device are copied into the local %1$s folder to prevent data loss when a single file is synced with multiple accounts.\n\nDue to this change, all files uploaded in previous versions of this app were copied into the %2$s folder. However, an error prevented the completion of this operation during account synchronization. You may either leave the file(s) as is and remove the link to %3$s, or move the file(s) into the %1$s folder and retain the link to %4$s.\n\nListed below are the local file(s), and the remote file(s) in %5$s they were linked to. - Folder %1$s does not exist anymore + Folder %1$s does not exist anymore "Move all" "All files were moved" "Some files could not be moved" @@ -152,20 +152,20 @@ "%1$s (loading)" "%1$s playback finished" No media file found - No account provided - File not in a valid account - Unsupported media codec - Media file could not be read - Media file not correctly encoded - Timed out while trying to play - Media file cannot be streamed - Media file cannot be played with the stock media player - Security error trying to play %1$s - Input error trying to play %1$s - Unexpected error trying to play %1$s - Rewind button - Play or pause button - Fast forward button + No account provided + File not in a valid account + Unsupported media codec + Media file could not be read + Media file not correctly encoded + Timed out while trying to play + Media file cannot be streamed + Media file cannot be played with the stock media player + Security error trying to play %1$s + Input error trying to play %1$s + Unexpected error trying to play %1$s + Rewind button + Play or pause button + Fast forward button Getting authorization… Trying to login… @@ -250,19 +250,19 @@ Location: Validity: From: - To: - Signature: - Algorithm: - The certificate could not be shown. - - No information about the error - + To: + Signature: + Algorithm: + The certificate could not be shown. + - No information about the error + This is a placeholder placeholder.txt PNG Image 389 KB 2012/05/18 12:23 PM 12:23:45 - + Upload pictures via WiFi only Upload videos via WiFi only /InstantUpload @@ -274,7 +274,7 @@ Image preview This image cannot be shown - + %1$s could not be copied to %2$s local folder Upload Path @@ -287,32 +287,24 @@ Enter a password You must enter a password - Send + An error occurred while connecting with the server. + An error occurred while waiting for the server, the operation couldn\'t have been done + An error occurred while waiting for the server, the operation couldn\'t have been done + The operation couldn\'t be completed, server is unavailable + - Copy link - Copied to clipboard + You do not have permission %s + to rename this file + to delete this file + to share this file + to unshare this file + to create the file + to upload in this folder + The file is no longer available on the server - Critical error: cannot perform operations - - An error occurred while connecting with the server. - An error occurred while waiting for the server, the operation couldn\'t have been done - An error occurred while waiting for the server, the operation couldn\'t have been done - The operation couldn\'t be completed, server is unavailable - - - - You do not have permission %s - to rename this file - to delete this file - to share this file - to unshare this file - to create the file - to upload in this folder - The file is no longer available on the server - - Accounts - Add account - Secure connection is redirected to an unsecured route. + Accounts + Add account + Secure connection is redirected through an unsecured route. Logs Send History @@ -326,13 +318,20 @@ Nothing in here. You can add a folder! Choose - Unable to move. Please check whether the file exists - It is not possible to move a folder into a descendant - The file exists already in the destination folder - An error occurred while trying to move this file or folder - to move this file + Unable to move. Please check whether the file exists + It is not possible to move a folder into a descendant + The file exists already in the destination folder + An error occurred while trying to move this file or folder + to move this file + + + Unable to copy. Please check whether the file exists + It is not possible to copy a folder into a descendant + The file exists already in the destination folder + An error occurred while trying to copy this file or folder + to copy this file - Instant Uploads + Instant Uploads Security Upload Video Path diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index c5fc94d1..29a11c42 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -50,6 +50,12 @@ import com.owncloud.android.lib.resources.shares.OCShare; import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.utils.FileStorageUtils; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + public class FileDataStorageManager { public static final int ROOT_PARENT_ID = 0; @@ -60,7 +66,7 @@ public class FileDataStorageManager { private static String TAG = FileDataStorageManager.class.getSimpleName(); - + public FileDataStorageManager(Account account, ContentResolver cr) { mContentProviderClient = null; mContentResolver = cr; @@ -73,7 +79,7 @@ public class FileDataStorageManager { mAccount = account; } - + public void setAccount(Account account) { mAccount = account; } @@ -97,7 +103,7 @@ public class FileDataStorageManager { public ContentProviderClient getContentProviderClient() { return mContentProviderClient; } - + public OCFile getFileByPath(String path) { Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path); @@ -141,7 +147,7 @@ public class FileDataStorageManager { return fileExists(ProviderTableMeta.FILE_PATH, path); } - + public Vector getFolderContent(OCFile f/*, boolean onlyOnDevice*/) { if (f != null && f.isFolder() && f.getFileId() != -1) { // TODO Enable when "On Device" is recovered ? @@ -151,8 +157,8 @@ public class FileDataStorageManager { return new Vector(); } } - - + + public Vector getFolderImages(OCFile folder/*, boolean onlyOnDevice*/) { Vector ret = new Vector(); if (folder != null) { @@ -183,7 +189,7 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype()); cv.put(ProviderTableMeta.FILE_NAME, file.getFileName()); //if (file.getParentId() != DataStorageManager.ROOT_PARENT_ID) - cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId()); + cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId()); cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath()); if (!file.isFolder()) cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); @@ -200,8 +206,7 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading()); boolean sameRemotePath = fileExists(file.getRemotePath()); - if (sameRemotePath || - fileExists(file.getFileId()) ) { // for renamed files + if (sameRemotePath || fileExists(file.getFileId())) { // for renamed files; no more delete and create OCFile oldFile = null; if (sameRemotePath) { @@ -215,12 +220,12 @@ public class FileDataStorageManager { if (getContentResolver() != null) { getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?", - new String[] { String.valueOf(file.getFileId()) }); + new String[]{String.valueOf(file.getFileId())}); } else { try { getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?", - new String[] { String.valueOf(file.getFileId()) }); + new String[]{String.valueOf(file.getFileId())}); } catch (RemoteException e) { Log_OC.e(TAG, "Fail to insert insert file to database " @@ -246,7 +251,7 @@ public class FileDataStorageManager { long new_id = Long.parseLong(result_uri.getPathSegments() .get(1)); file.setFileId(new_id); - } + } } // if (file.isFolder()) { @@ -254,17 +259,17 @@ public class FileDataStorageManager { // } else { // updateFolderSize(file.getParentId()); // } - + return overriden; } /** * Inserts or updates the list of files contained in a given folder. - * + *

* CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD. * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED - * + * * @param folder * @param updatedFiles * @param filesToRemove @@ -314,9 +319,9 @@ public class FileDataStorageManager { // updating an existing file operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). withValues(cv). - withSelection( ProviderTableMeta._ID + "=?", - new String[] { String.valueOf(file.getFileId()) }) - .build()); + withSelection(ProviderTableMeta._ID + "=?", + new String[]{String.valueOf(file.getFileId())}) + .build()); } else { // adding a new file @@ -324,9 +329,9 @@ public class FileDataStorageManager { withValues(cv).build()); } } - + // prepare operations to remove files in the given folder - String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + + String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?"; String [] whereArgs = null; for (OCFile file : filesToRemove) { @@ -351,7 +356,7 @@ public class FileDataStorageManager { ProviderTableMeta.CONTENT_URI_FILE, file.getFileId() ) ).withSelection(where, whereArgs).build()); - + if (file.isDown()) { String path = file.getStoragePath(); new File(path).delete(); @@ -360,7 +365,7 @@ public class FileDataStorageManager { } } } - + // update metadata of folder ContentValues cv = new ContentValues(); cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp()); @@ -383,12 +388,12 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink()); cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions()); cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId()); - + operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). withValues(cv). - withSelection( ProviderTableMeta._ID + "=?", - new String[] { String.valueOf(folder.getFileId()) }) - .build()); + withSelection(ProviderTableMeta._ID + "=?", + new String[]{String.valueOf(folder.getFileId())}) + .build()); // apply operations in batch ContentProviderResult[] results = null; @@ -413,7 +418,7 @@ public class FileDataStorageManager { long newId; Iterator filesIt = updatedFiles.iterator(); OCFile file = null; - for (int i=0; i 0); + success &= (deleted > 0); } String localPath = file.getStoragePath(); if (removeLocalCopy && file.isDown() && localPath != null && success) { @@ -509,12 +511,12 @@ public class FileDataStorageManager { } return success; } - + public boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) { boolean success = true; if (folder != null && folder.isFolder()) { - if (removeDBData && folder.getFileId() != -1) { + if (removeDBData && folder.getFileId() != -1) { success = removeFolderInDb(folder); } if (removeLocalContent && success) { @@ -525,7 +527,7 @@ public class FileDataStorageManager { } private boolean removeFolderInDb(OCFile folder) { - Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, "" + + 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 + "=?"; @@ -538,7 +540,7 @@ public class FileDataStorageManager { e.printStackTrace(); } } else { - deleted = getContentResolver().delete(folder_uri, where, whereArgs); + deleted = getContentResolver().delete(folder_uri, where, whereArgs); } return deleted > 0; } @@ -597,54 +599,54 @@ public class FileDataStorageManager { /** * Updates database and file system for a file or folder that was moved to a different location. - * + * * TODO explore better (faster) implementations * TODO throw exceptions up ! */ public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) { if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) { - + OCFile targetParent = getFileByPath(targetParentPath); if (targetParent == null) { throw new IllegalStateException("Parent folder of the target path does not exist!!"); } - + /// 1. get all the descendants of the moved element in a single QUERY Cursor c = null; if (getContentProviderClient() != null) { try { c = getContentProviderClient().query( - ProviderTableMeta.CONTENT_URI, - null, - ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + - ProviderTableMeta.FILE_PATH + " LIKE ? ", - new String[] { - mAccount.name, - file.getRemotePath() + "%" - }, - ProviderTableMeta.FILE_PATH + " ASC " + ProviderTableMeta.CONTENT_URI, + null, + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + + ProviderTableMeta.FILE_PATH + " LIKE ? ", + new String[]{ + mAccount.name, + file.getRemotePath() + "%" + }, + ProviderTableMeta.FILE_PATH + " ASC " ); } catch (RemoteException e) { Log_OC.e(TAG, e.getMessage()); } - + } else { c = getContentResolver().query( - ProviderTableMeta.CONTENT_URI, - null, - ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + - ProviderTableMeta.FILE_PATH + " LIKE ? ", - new String[] { - mAccount.name, - file.getRemotePath() + "%" - }, - ProviderTableMeta.FILE_PATH + " ASC " + ProviderTableMeta.CONTENT_URI, + null, + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + + ProviderTableMeta.FILE_PATH + " LIKE ? ", + new String[]{ + mAccount.name, + file.getRemotePath() + "%" + }, + ProviderTableMeta.FILE_PATH + " ASC " ); } /// 2. prepare a batch of update operations to change all the descendants - ArrayList operations = + ArrayList operations = new ArrayList(c.getCount()); String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name); List originalPathsToTriggerMediaScan = new ArrayList(); @@ -656,13 +658,13 @@ public class FileDataStorageManager { ContentValues cv = new ContentValues(); // keep construction in the loop OCFile child = createFileInstance(c); cv.put( - ProviderTableMeta.FILE_PATH, - targetPath + child.getRemotePath().substring(lengthOfOldPath) + ProviderTableMeta.FILE_PATH, + targetPath + child.getRemotePath().substring(lengthOfOldPath) ); - if (child.getStoragePath() != null && + if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) { // update link to downloaded content - but local move is not done here! - String targetLocalPath = defaultSavePath + targetPath + + String targetLocalPath = defaultSavePath + targetPath + child.getStoragePath().substring(lengthOfOldStoragePath); cv.put(ProviderTableMeta.FILE_STORAGE_PATH, targetLocalPath); @@ -675,17 +677,17 @@ public class FileDataStorageManager { cv.put( ProviderTableMeta.FILE_PARENT, targetParent.getFileId() - ); + ); } operations.add( - ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). - withValues(cv). - withSelection( - ProviderTableMeta._ID + "=?", - new String[] { String.valueOf(child.getFileId()) } + ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). + withValues(cv). + withSelection( + ProviderTableMeta._ID + "=?", + new String[]{String.valueOf(child.getFileId())} ) - .build()); - + .build()); + } while (c.moveToNext()); } c.close(); @@ -730,9 +732,60 @@ public class FileDataStorageManager { } } } - + } - + + public void copyLocalFile(OCFile file, String targetPath) { + + if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) { + String localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file); + File localFile = new File(localPath); + boolean copied = false; + String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name); + if (localFile.exists()) { + File targetFile = new File(defaultSavePath + targetPath); + File targetFolder = targetFile.getParentFile(); + if (!targetFolder.exists()) { + targetFolder.mkdirs(); + } + copied = copyFile(localFile, targetFile); + } + Log_OC.d(TAG, "Local file COPIED : " + copied); + } + } + + private boolean copyFile(File src, File target) { + boolean ret = true; + + InputStream in = null; + OutputStream out = null; + + try { + in = new FileInputStream(src); + out = new FileOutputStream(target); + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + } catch (IOException ex) { + ret = false; + } finally { + if (in != null) try { + in.close(); + } catch (IOException e) { + e.printStackTrace(System.err); + } + if (out != null) try { + out.close(); + } catch (IOException e) { + e.printStackTrace(System.err); + } + } + + return ret; + } + private Vector getFolderContent(long parentId/*, boolean onlyOnDevice*/) { @@ -745,17 +798,17 @@ public class FileDataStorageManager { if (getContentProviderClient() != null) { try { - c = getContentProviderClient().query(req_uri, null, - ProviderTableMeta.FILE_PARENT + "=?" , - new String[] { String.valueOf(parentId)}, null); + c = getContentProviderClient().query(req_uri, null, + ProviderTableMeta.FILE_PARENT + "=?", + new String[]{String.valueOf(parentId)}, null); } catch (RemoteException e) { Log_OC.e(TAG, e.getMessage()); return ret; } } else { - c = getContentResolver().query(req_uri, null, - ProviderTableMeta.FILE_PARENT + "=?" , - new String[] { String.valueOf(parentId)}, null); + c = getContentResolver().query(req_uri, null, + ProviderTableMeta.FILE_PARENT + "=?", + new String[]{String.valueOf(parentId)}, null); } if (c.moveToFirst()) { @@ -774,8 +827,8 @@ public class FileDataStorageManager { return ret; } - - + + private OCFile createRootDir() { OCFile file = new OCFile(OCFile.ROOT_PATH); file.setMimetype("DIR"); @@ -793,7 +846,7 @@ public class FileDataStorageManager { cmp_key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", - new String[] { value, mAccount.name }, null); + new String[]{value, mAccount.name}, null); } else { try { c = getContentProviderClient().query( @@ -801,7 +854,7 @@ public class FileDataStorageManager { null, cmp_key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", - new String[] { value, mAccount.name }, null); + new String[]{value, mAccount.name}, null); } catch (RemoteException e) { Log_OC.e(TAG, "Couldn't determine file existance, assuming non existance: " @@ -823,14 +876,14 @@ public class FileDataStorageManager { key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", - new String[] { value, mAccount.name }, null); + new String[]{value, mAccount.name}, null); } else { try { c = getContentProviderClient().query( ProviderTableMeta.CONTENT_URI, null, key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER - + "=?", new String[] { value, mAccount.name }, + + "=?", new String[]{value, mAccount.name}, null); } catch (RemoteException e) { Log_OC.e(TAG, "Could not get file details: " + e.getMessage()); @@ -839,7 +892,7 @@ public class FileDataStorageManager { } return c; } - + private OCFile createFileInstance(Cursor c) { OCFile file = null; @@ -893,10 +946,11 @@ public class FileDataStorageManager { } return file; } - + /** * Returns if the file/folder is shared by link or not - * @param path Path of the file/folder + * + * @param path Path of the file/folder * @return */ public boolean isShareByLink(String path) { @@ -908,10 +962,11 @@ public class FileDataStorageManager { c.close(); return file.isShareByLink(); } - + /** * Returns the public link of the file/folder - * @param path Path of the file/folder + * + * @param path Path of the file/folder * @return */ public String getPublicLink(String path) { @@ -923,8 +978,8 @@ public class FileDataStorageManager { c.close(); return file.getPublicLink(); } - - + + // Methods for Shares public boolean saveShare(OCShare share) { boolean overriden = false; @@ -946,19 +1001,18 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId()); cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared()); cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name); - - if (shareExists(share.getIdRemoteShared())) { // for renamed files + if (shareExists(share.getIdRemoteShared())) { // for renamed files; no more delete and create overriden = true; if (getContentResolver() != null) { getContentResolver().update(ProviderTableMeta.CONTENT_URI_SHARE, cv, ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", - new String[] { String.valueOf(share.getIdRemoteShared()) }); + new String[]{String.valueOf(share.getIdRemoteShared())}); } else { try { getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_SHARE, cv, ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", - new String[] { String.valueOf(share.getIdRemoteShared()) }); + new String[]{String.valueOf(share.getIdRemoteShared())}); } catch (RemoteException e) { Log_OC.e(TAG, "Fail to insert insert file to database " @@ -984,7 +1038,7 @@ public class FileDataStorageManager { long new_id = Long.parseLong(result_uri.getPathSegments() .get(1)); share.setId(new_id); - } + } } return overriden; @@ -1000,7 +1054,7 @@ public class FileDataStorageManager { ProviderTableMeta.OCSHARES_PATH + "=? AND " + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?", - new String[] { path, Integer.toString(type.getValue()), mAccount.name }, + new String[]{path, Integer.toString(type.getValue()), mAccount.name}, null); } else { try { @@ -1010,7 +1064,7 @@ public class FileDataStorageManager { ProviderTableMeta.OCSHARES_PATH + "=? AND " + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?", - new String[] { path, Integer.toString(type.getValue()), mAccount.name }, + new String[]{path, Integer.toString(type.getValue()), mAccount.name}, null); } catch (RemoteException e) { @@ -1025,7 +1079,7 @@ public class FileDataStorageManager { c.close(); return share; } - + private OCShare createShareInstance(Cursor c) { OCShare share = null; if (c != null) { @@ -1047,12 +1101,9 @@ public class FileDataStorageManager { share.setSharedWithDisplayName(c.getString(c .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME))); share.setIsFolder(c.getInt( - c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1 ? true : false); + c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1); share.setUserId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID))); - share.setIdRemoteShared( - c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)) - ); - + share.setIdRemoteShared(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED))); } return share; } @@ -1066,7 +1117,7 @@ public class FileDataStorageManager { cmp_key + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?", - new String[] { value, mAccount.name }, null); + new String[]{value, mAccount.name}, null); } else { try { c = getContentProviderClient().query( @@ -1074,7 +1125,7 @@ public class FileDataStorageManager { null, cmp_key + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?", - new String[] { value, mAccount.name }, null); + new String[]{value, mAccount.name}, null); } catch (RemoteException e) { Log_OC.e(TAG, "Couldn't determine file existance, assuming non existance: " @@ -1086,7 +1137,7 @@ public class FileDataStorageManager { c.close(); return retval; } - + private boolean shareExists(long remoteId) { return shareExists(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, String.valueOf(remoteId)); } @@ -1096,17 +1147,14 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false); cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, ""); String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?"; - String [] whereArgs = new String[]{mAccount.name}; - + String[] whereArgs = new String[]{mAccount.name}; + if (getContentResolver() != null) { getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); } else { try { - getContentProviderClient().update( - ProviderTableMeta.CONTENT_URI, cv, where, whereArgs - ); - + getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); } catch (RemoteException e) { Log_OC.e(TAG, "Exception in cleanSharedFiles" + e.getMessage()); } @@ -1117,7 +1165,7 @@ public class FileDataStorageManager { ContentValues cv = new ContentValues(); cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false); cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, ""); - String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + + String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PARENT + "=?"; String [] whereArgs = new String[] { mAccount.name , String.valueOf(folder.getFileId()) }; @@ -1126,10 +1174,7 @@ public class FileDataStorageManager { } else { try { - getContentProviderClient().update( - ProviderTableMeta.CONTENT_URI, cv, where, whereArgs - ); - + getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); } catch (RemoteException e) { Log_OC.e(TAG, "Exception in cleanSharedFilesInFolder " + e.getMessage()); } @@ -1138,23 +1183,20 @@ public class FileDataStorageManager { private void cleanShares() { String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; - String [] whereArgs = new String[]{mAccount.name}; - + String[] whereArgs = new String[]{mAccount.name}; + if (getContentResolver() != null) { getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs); } else { try { - getContentProviderClient().delete( - ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs - ); - + getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs); } catch (RemoteException e) { Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage()); } } } - + public void saveShares(Collection shares) { cleanShares(); if (shares != null) { @@ -1187,13 +1229,9 @@ public class FileDataStorageManager { operations.add( ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE). withValues(cv). - withSelection( - ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", - new String[] { String.valueOf(share.getIdRemoteShared()) } - ). - build() - ); - + withSelection(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", + new String[]{String.valueOf(share.getIdRemoteShared())}) + .build()); } else { // adding a new file operations.add( @@ -1203,7 +1241,7 @@ public class FileDataStorageManager { ); } } - + // apply operations in batch if (operations.size() > 0) { @SuppressWarnings("unused") @@ -1212,28 +1250,25 @@ public class FileDataStorageManager { " operations to FileContentProvider"); try { if (getContentResolver() != null) { - results = getContentResolver().applyBatch( - MainApp.getAuthority(), operations - ); - + results = getContentResolver().applyBatch(MainApp.getAuthority(), operations); } else { results = getContentProviderClient().applyBatch(operations); } - + } catch (OperationApplicationException e) { Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage()); - + } catch (RemoteException e) { Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage()); } } } - + } - + public void updateSharedFiles(Collection sharedFiles) { cleanSharedFiles(); - + if (sharedFiles != null) { ArrayList operations = new ArrayList(sharedFiles.size()); @@ -1282,11 +1317,9 @@ public class FileDataStorageManager { operations.add( ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). withValues(cv). - withSelection( - ProviderTableMeta._ID + "=?", - new String[] { String.valueOf(file.getFileId()) } - ).build() - ); + withSelection(ProviderTableMeta._ID + "=?", + new String[]{String.valueOf(file.getFileId())}) + .build()); } else { // adding a new file @@ -1297,7 +1330,7 @@ public class FileDataStorageManager { ); } } - + // apply operations in batch if (operations.size() > 0) { @SuppressWarnings("unused") @@ -1306,28 +1339,25 @@ public class FileDataStorageManager { " operations to FileContentProvider"); try { if (getContentResolver() != null) { - results = getContentResolver().applyBatch( - MainApp.getAuthority(), operations - ); - + results = getContentResolver().applyBatch(MainApp.getAuthority(), operations); } else { results = getContentProviderClient().applyBatch(operations); } - + } catch (OperationApplicationException e) { Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage()); - + } catch (RemoteException e) { Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage()); } } } - - } - - public void removeShare(OCShare share){ + + } + + public void removeShare(OCShare share) { Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE; - String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " + + String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?"; String [] whereArgs = new String[]{mAccount.name, share.getPath()}; if (getContentProviderClient() != null) { @@ -1337,10 +1367,10 @@ public class FileDataStorageManager { e.printStackTrace(); } } else { - getContentResolver().delete(share_uri, where, whereArgs); + getContentResolver().delete(share_uri, where, whereArgs); } } - + public void saveSharesDB(ArrayList shares) { saveShares(shares); @@ -1351,7 +1381,7 @@ public class FileDataStorageManager { String path = share.getPath(); if (share.isFolder()) { path = path + FileUtils.PATH_SEPARATOR; - } + } // Update OCFile with data from share: ShareByLink and publicLink OCFile file = getFileByPath(path); @@ -1360,18 +1390,18 @@ public class FileDataStorageManager { file.setShareByLink(true); sharedFiles.add(file); } - } + } } - + updateSharedFiles(sharedFiles); } - + public void saveSharesInFolder(ArrayList shares, OCFile folder) { cleanSharedFilesInFolder(folder); ArrayList operations = new ArrayList(); operations = prepareRemoveSharesInFolder(folder, operations); - + if (shares != null) { // prepare operations to insert or update files to save in the given folder for (OCShare share : shares) { @@ -1415,7 +1445,7 @@ public class FileDataStorageManager { //} } } - + // apply operations in batch if (operations.size() > 0) { @SuppressWarnings("unused") @@ -1437,13 +1467,13 @@ public class FileDataStorageManager { } } //} - + } private ArrayList prepareRemoveSharesInFolder( OCFile folder, ArrayList preparedOperations) { if (folder != null) { - String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND " + String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; String [] whereArgs = new String[]{ "", mAccount.name }; diff --git a/src/com/owncloud/android/files/FileMenuFilter.java b/src/com/owncloud/android/files/FileMenuFilter.java index 2c2754cc..f7fee626 100644 --- a/src/com/owncloud/android/files/FileMenuFilter.java +++ b/src/com/owncloud/android/files/FileMenuFilter.java @@ -39,7 +39,7 @@ import com.owncloud.android.services.OperationsService.OperationsServiceBinder; import com.owncloud.android.ui.activity.ComponentsGetter; /** - * Filters out the file actions available in a given {@link Menu} for a given {@link OCFile} + * Filters out the file actions available in a given {@link Menu} for a given {@link OCFile} * according to the current state of the latest. */ public class FileMenuFilter { @@ -48,10 +48,10 @@ public class FileMenuFilter { 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 access the @@ -64,20 +64,20 @@ public class FileMenuFilter { 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(); - + List toShow = new ArrayList(); + List toHide = new ArrayList(); + filter(toShow, toHide); - + MenuItem item = null; for (int i : toShow) { item = menu.findItem(i); @@ -86,7 +86,7 @@ public class FileMenuFilter { item.setEnabled(true); } } - + for (int i : toHide) { item = menu.findItem(i); if (item != null) { @@ -99,10 +99,10 @@ public class FileMenuFilter { /** * 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 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) { @@ -116,71 +116,72 @@ public class FileMenuFilter { 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.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); } - // MOVE + // MOVE & COPY if (mFile == null || downloading || uploading) { toHide.add(R.id.action_move); - + toHide.add(R.id.action_copy); } else { toShow.add(R.id.action_move); + toShow.add(R.id.action_copy); } - + // 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) { 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? boolean shareAllowed = (mContext != null && @@ -190,7 +191,7 @@ public class FileMenuFilter { } else { toShow.add(R.id.action_share_file); } - + // UNSHARE FILE // TODO add check on SHARE available on server side? if ( !shareAllowed || (mFile == null || !mFile.isShareByLink())) { @@ -205,7 +206,7 @@ public class FileMenuFilter { } else { toShow.add(R.id.action_see_details); } - + // SEND boolean sendAllowed = (mContext != null && mContext.getString(R.string.send_files_to_other_apps).equalsIgnoreCase("on")); diff --git a/src/com/owncloud/android/files/FileOperationsHelper.java b/src/com/owncloud/android/files/FileOperationsHelper.java index ddee2050..22370289 100644 --- a/src/com/owncloud/android/files/FileOperationsHelper.java +++ b/src/com/owncloud/android/files/FileOperationsHelper.java @@ -21,8 +21,6 @@ package com.owncloud.android.files; -import org.apache.http.protocol.HTTP; - import android.accounts.Account; import android.content.Intent; import android.net.Uri; @@ -35,7 +33,6 @@ import com.owncloud.android.authentication.AccountUtils; 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.network.WebdavUtils; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.status.OwnCloudVersion; @@ -44,20 +41,22 @@ import com.owncloud.android.services.observer.FileObserverService; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.dialog.ShareLinkToDialog; +import org.apache.http.protocol.HTTP; + /** * */ public class FileOperationsHelper { private static final String TAG = FileOperationsHelper.class.getName(); - - private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG"; + + 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 FileOperationsHelper(FileActivity fileActivity) { mFileActivity = fileActivity; } @@ -67,7 +66,7 @@ public class FileOperationsHelper { if (file != null) { String storagePath = file.getStoragePath(); String encodedStoragePath = WebdavUtils.encodePath(storagePath); - + Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW); intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype()); intentForSavedMimeType.setFlags( @@ -94,29 +93,29 @@ public class FileOperationsHelper { } else { chooserIntent = Intent.createChooser(intentForSavedMimeType, mFileActivity.getString(R.string.actionbar_open_with)); } - + mFileActivity.startActivity(chooserIntent); - + } else { Log_OC.wtf(TAG, "Trying to open a NULL OCFile"); } } - - + + public void shareFileWithLink(OCFile file) { - + if (isSharedSupported()) { if (file != null) { String link = "https://fake.url"; Intent intent = createShareWithLinkIntent(link); - String[] packagesToExclude = new String[] { mFileActivity.getPackageName() }; + String[] packagesToExclude = new String[]{mFileActivity.getPackageName()}; DialogFragment chooserDialog = ShareLinkToDialog.newInstance(intent, packagesToExclude, file); chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG); - + } else { Log_OC.wtf(TAG, "Trying to share a NULL OCFile"); } - + } else { // Show a Message Toast t = Toast.makeText( @@ -125,13 +124,13 @@ public class FileOperationsHelper { t.show(); } } - - + + public void shareFileWithLinkToApp(OCFile file, String password, Intent sendIntent) { if (file != null) { mFileActivity.showLoadingDialog(); - + Intent service = new Intent(mFileActivity, OperationsService.class); service.setAction(OperationsService.ACTION_CREATE_SHARE); service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); @@ -144,18 +143,18 @@ public class FileOperationsHelper { Log_OC.wtf(TAG, "Trying to open a NULL OCFile"); } } - - + + private Intent createShareWithLinkIntent(String link) { Intent intentToShareLink = new Intent(Intent.ACTION_SEND); intentToShareLink.putExtra(Intent.EXTRA_TEXT, link); intentToShareLink.setType(HTTP.PLAIN_TEXT_TYPE); - return intentToShareLink; + return intentToShareLink; } - - + + /** - * @return 'True' if the server supports the Share API + * @return 'True' if the server supports the Share API */ public boolean isSharedSupported() { if (mFileActivity.getAccount() != null) { @@ -164,10 +163,10 @@ public class FileOperationsHelper { } return false; } - - + + public void unshareFileWithLink(OCFile file) { - + if (isSharedSupported()) { // Unshare the file Intent service = new Intent(mFileActivity, OperationsService.class); @@ -177,15 +176,15 @@ public class FileOperationsHelper { mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service); mFileActivity.showLoadingDialog(); - + } else { // Show a Message 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) { if (file != null) { String storagePath = file.getStoragePath(); @@ -197,7 +196,7 @@ public class FileOperationsHelper { sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action // Show dialog, without the own app - String[] packagesToExclude = new String[] { mFileActivity.getPackageName() }; + String[] packagesToExclude = new String[]{mFileActivity.getPackageName()}; DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file); chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG); @@ -205,10 +204,10 @@ public class FileOperationsHelper { Log_OC.wtf(TAG, "Trying to send a NULL OCFile"); } } - - + + public void syncFile(OCFile file) { - + if (!file.isFolder()){ Intent intent = new Intent(mFileActivity, OperationsService.class); intent.setAction(OperationsService.ACTION_SYNC_FILE); @@ -269,8 +268,8 @@ public class FileOperationsHelper { mFileActivity.showLoadingDialog(); } - - + + public void createFolder(String remotePath, boolean createFullPath) { // Create Folder Intent service = new Intent(mFileActivity, OperationsService.class); @@ -317,8 +316,9 @@ public class FileOperationsHelper { /** * Start move file operation - * @param newfile File where it is going to be moved - * @param currentFile File with the previous info + * + * @param newfile File where it is going to be moved + * @param currentFile File with the previous info */ public void moveFile(OCFile newfile, OCFile currentFile) { // Move files @@ -332,6 +332,23 @@ public class FileOperationsHelper { mFileActivity.showLoadingDialog(); } + /** + * Start copy file operation + * + * @param newfile File where it is going to be moved + * @param currentFile File with the previous info + */ + public void copyFile(OCFile newfile, OCFile currentFile) { + // Copy files + Intent service = new Intent(mFileActivity, OperationsService.class); + service.setAction(OperationsService.ACTION_COPY_FILE); + service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath()); + service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath()); + service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service); + + mFileActivity.showLoadingDialog(); + } public long getOpIdWaitingFor() { return mWaitingForOpId; @@ -341,7 +358,7 @@ public class FileOperationsHelper { public void setOpIdWaitingFor(long waitingForOpId) { mWaitingForOpId = waitingForOpId; } - + /** * @return 'True' if the server doesn't need to check forbidden characters */ diff --git a/src/com/owncloud/android/operations/CopyFileOperation.java b/src/com/owncloud/android/operations/CopyFileOperation.java new file mode 100644 index 00000000..77a9a071 --- /dev/null +++ b/src/com/owncloud/android/operations/CopyFileOperation.java @@ -0,0 +1,103 @@ +/* ownCloud Android client application + * 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, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.owncloud.android.operations; + +import android.accounts.Account; +import android.content.Context; + +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.resources.files.CopyRemoteFileOperation; +import com.owncloud.android.operations.common.SyncOperation; + + +/** + * Operation copying an {@link OCFile} to a different folder. + * + * @author David A. Velasco + */ +public class CopyFileOperation extends SyncOperation { + + //private static final String TAG = MoveFileOperation.class.getSimpleName(); + + private String mSrcPath; + private String mTargetParentPath; + + private OCFile mFile; + + + /** + * Constructor + * + * @param srcPath Remote path of the {@link OCFile} to move. + * @param targetParentPath Path to the folder where the file will be copied into. + * @param account OwnCloud account containing both the file and the target folder + */ + public CopyFileOperation(String srcPath, String targetParentPath, Account account) { + mSrcPath = srcPath; + mTargetParentPath = targetParentPath; + if (!mTargetParentPath.endsWith(OCFile.PATH_SEPARATOR)) { + mTargetParentPath += OCFile.PATH_SEPARATOR; + } + + mFile = null; + } + + /** + * Performs the operation. + * + * @param client Client object to communicate with the remote ownCloud server. + */ + @Override + protected RemoteOperationResult run(OwnCloudClient client) { + RemoteOperationResult result; + + /// 1. check copy validity + if (mTargetParentPath.startsWith(mSrcPath)) { + return new RemoteOperationResult(ResultCode.INVALID_COPY_INTO_DESCENDANT); + } + mFile = getStorageManager().getFileByPath(mSrcPath); + if (mFile == null) { + return new RemoteOperationResult(ResultCode.FILE_NOT_FOUND); + } + + /// 2. remote copy + String targetPath = mTargetParentPath + mFile.getFileName(); + if (mFile.isFolder()) { + targetPath += OCFile.PATH_SEPARATOR; + } + CopyRemoteFileOperation operation = new CopyRemoteFileOperation( + mSrcPath, + targetPath, + false + ); + result = operation.execute(client); + + /// 3. local copy + if (result.isSuccess()) { + getStorageManager().copyLocalFile(mFile, targetPath); + } + // TODO handle ResultCode.PARTIAL_COPY_DONE in client Activity, for the moment + + return result; + } + + +} diff --git a/src/com/owncloud/android/services/OperationsService.java b/src/com/owncloud/android/services/OperationsService.java index 2514c4de..099bd087 100644 --- a/src/com/owncloud/android/services/OperationsService.java +++ b/src/com/owncloud/android/services/OperationsService.java @@ -19,11 +19,21 @@ package com.owncloud.android.services; -import java.io.IOException; -import java.util.Iterator; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ConcurrentMap; +import android.accounts.Account; +import android.accounts.AccountsException; +import android.accounts.AuthenticatorException; +import android.accounts.OperationCanceledException; +import android.app.Service; +import android.content.Intent; +import android.net.Uri; +import android.os.Binder; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.Process; +import android.util.Pair; import com.owncloud.android.MainApp; import com.owncloud.android.R; @@ -42,7 +52,7 @@ import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.lib.resources.users.GetRemoteUserNameOperation; -import com.owncloud.android.operations.common.SyncOperation; +import com.owncloud.android.operations.CopyFileOperation; import com.owncloud.android.operations.CreateFolderOperation; import com.owncloud.android.operations.CreateShareOperation; import com.owncloud.android.operations.GetServerInfoOperation; @@ -53,28 +63,18 @@ 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.operations.common.SyncOperation; -import android.accounts.Account; -import android.accounts.AccountManager; -import android.accounts.AccountsException; -import android.accounts.AuthenticatorException; -import android.accounts.OperationCanceledException; -import android.app.Service; -import android.content.Intent; -import android.net.Uri; -import android.os.Binder; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Process; -import android.util.Pair; +import java.io.IOException; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentMap; public class OperationsService extends Service { - + private static final String TAG = OperationsService.class.getSimpleName(); - + public static final String EXTRA_ACCOUNT = "ACCOUNT"; public static final String EXTRA_SERVER_URL = "SERVER_URL"; public static final String EXTRA_OAUTH2_QUERY_PARAMETERS = "OAUTH2_QUERY_PARAMETERS"; @@ -90,7 +90,7 @@ public class OperationsService extends Service { public static final String EXTRA_PASSWORD_SHARE = "PASSWORD_SHARE"; public static final String EXTRA_COOKIE = "COOKIE"; - + public static final String ACTION_CREATE_SHARE = "CREATE_SHARE"; public static final String ACTION_UNSHARE = "UNSHARE"; public static final String ACTION_GET_SERVER_INFO = "GET_SERVER_INFO"; @@ -102,22 +102,24 @@ public class OperationsService extends Service { public static final String ACTION_SYNC_FILE = "SYNC_FILE"; public static final String ACTION_SYNC_FOLDER = "SYNC_FOLDER";//for the moment, just to download public static final String ACTION_MOVE_FILE = "MOVE_FILE"; - + public static final String ACTION_COPY_FILE = "COPY_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 ConcurrentMap> - mUndispatchedFinishedOperations = + + private ConcurrentMap> + mUndispatchedFinishedOperations = new ConcurrentHashMap>(); - + private static class Target { public Uri mServerUrl = null; public Account mAccount = null; public String mCookie = null; - + public Target(Account account, Uri serverUrl, String cookie) { mAccount = account; mServerUrl = serverUrl; @@ -151,11 +153,11 @@ public class OperationsService extends Service { mSyncFolderHandler = new SyncFolderHandler(thread.getLooper(), this); } - + /** * Entry point to add a new operation to the queue of operations. - * - * New operations are added calling to startService(), resulting in a call to this method. + *

+ * New operations are added calling to startService(), resulting in a call to this method. * This ensures the service will keep on working although the caller activity goes away. */ @Override @@ -200,8 +202,8 @@ public class OperationsService extends Service { // Saving cookies try { OwnCloudClientManagerFactory.getDefaultSingleton(). - saveAllClients(this, MainApp.getAccountType()); - + saveAllClients(this, MainApp.getAccountType()); + // TODO - get rid of these exceptions } catch (AccountNotFoundException e) { e.printStackTrace(); @@ -212,7 +214,7 @@ public class OperationsService extends Service { } catch (IOException e) { e.printStackTrace(); } - + mUndispatchedFinishedOperations.clear(); mOperationsBinder = null; @@ -227,8 +229,8 @@ public class OperationsService extends Service { } /** - * Provides a binder object that clients can use to perform actions on the queue of operations, - * except the addition of new operations. + * Provides a binder object that clients can use to perform actions on the queue of operations, + * except the addition of new operations. */ @Override public IBinder onBind(Intent intent) { @@ -236,7 +238,7 @@ public class OperationsService extends Service { return mOperationsBinder; } - + /** * Called when ALL the bound clients were unbound. */ @@ -248,20 +250,20 @@ public class OperationsService extends Service { /** - * Binder to let client components to perform actions on the queue of operations. - * - * It provides by itself the available operations. + * Binder to let client components to perform actions on the queue of operations. + *

+ * It provides by itself the available operations. */ public class OperationsServiceBinder extends Binder /* implements OnRemoteOperationListener */ { - - /** + + /** * Map of listeners that will be reported about the end of operations from a * {@link OperationsServiceBinder} instance */ - private ConcurrentMap mBoundListeners = + private final ConcurrentMap mBoundListeners = new ConcurrentHashMap(); - - private ServiceHandler mServiceHandler = null; + + private ServiceHandler mServiceHandler = null; public OperationsServiceBinder(ServiceHandler serviceHandler) { mServiceHandler = serviceHandler; @@ -280,15 +282,15 @@ public class OperationsService extends Service { public void clearListeners() { - + mBoundListeners.clear(); } - + /** * Adds a listener interested in being reported about the end of operations. - * - * @param listener Object to notify about the end of operations. + * + * @param listener Object to notify about the end of operations. * @param callbackHandler {@link Handler} to access the listener without * breaking Android threading protection. */ @@ -298,15 +300,15 @@ public class OperationsService extends Service { mBoundListeners.put(listener, callbackHandler); } } - - + + /** * Removes a listener from the list of objects interested in the being reported about * the end of operations. * * @param listener Object to notify about progress of transfer. */ - public void removeOperationListener (OnRemoteOperationListener listener) { + public void removeOperationListener(OnRemoteOperationListener listener) { synchronized (mBoundListeners) { mBoundListeners.remove(listener); } @@ -314,8 +316,8 @@ public class OperationsService extends Service { /** - * TODO - IMPORTANT: update implementation when more operations are moved into the service - * + * TODO - IMPORTANT: update implementation when more operations are moved into the service + * * @return 'True' when an operation that enforces the user to wait for completion is * in process. */ @@ -343,8 +345,8 @@ public class OperationsService extends Service { return Long.MAX_VALUE; } } - - + + public boolean dispatchResultIfFinished(int operationId, OnRemoteOperationListener listener) { Pair undispatched = @@ -378,8 +380,8 @@ public class OperationsService extends Service { /** - * Operations worker. Performs the pending operations in the order they were requested. - * + * Operations worker. Performs the pending operations in the order they were requested. + * * Created with the Looper of a new thread, started in {@link OperationsService#onCreate()}. */ private static class ServiceHandler extends Handler { @@ -388,8 +390,8 @@ public class OperationsService extends Service { OperationsService mService; - - + + private ConcurrentLinkedQueue> mPendingOperations = new ConcurrentLinkedQueue>(); private RemoteOperation mCurrentOperation = null; @@ -412,7 +414,7 @@ public class OperationsService extends Service { Log_OC.d(TAG, "Stopping after command with id " + msg.arg1); mService.stopSelf(msg.arg1); } - + /** * Performs the next operation in the queue @@ -475,7 +477,7 @@ 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 authorization for a NULL account", @@ -515,9 +517,9 @@ public class OperationsService extends Service { } - + } - + /** * Creates a new operation, as described by operationIntent. @@ -535,7 +537,7 @@ public class OperationsService extends Service { if (!operationIntent.hasExtra(EXTRA_ACCOUNT) && !operationIntent.hasExtra(EXTRA_SERVER_URL)) { Log_OC.e(TAG, "Not enough information provided in intent"); - + } else { Account account = operationIntent.getParcelableExtra(EXTRA_ACCOUNT); String serverUrl = operationIntent.getStringExtra(EXTRA_SERVER_URL); @@ -556,7 +558,7 @@ public class OperationsService extends Service { ShareType.PUBLIC_LINK, "", false, password, 1, sendIntent); } - + } else if (action.equals(ACTION_UNSHARE)) { // Unshare file String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); if (remotePath.length() > 0) { @@ -568,7 +570,7 @@ public class OperationsService extends Service { } else if (action.equals(ACTION_GET_SERVER_INFO)) { // check OC server and get basic information from it operation = new GetServerInfoOperation(serverUrl, OperationsService.this); - + } else if (action.equals(ACTION_OAUTH2_GET_ACCESS_TOKEN)) { /// GET ACCESS TOKEN to the OAuth server String oauth2QueryParameters = @@ -578,7 +580,7 @@ public class OperationsService extends Service { getString(R.string.oauth2_redirect_uri), getString(R.string.oauth2_grant_type), oauth2QueryParameters); - + } else if (action.equals(ACTION_GET_USER_NAME)) { // Get User Name operation = new GetRemoteUserNameOperation(); @@ -602,7 +604,7 @@ public class OperationsService extends Service { 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); @@ -626,9 +628,14 @@ public class OperationsService extends Service { // Move file/folder String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); String newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH); - operation = new MoveFileOperation(remotePath,newParentPath,account); + operation = new MoveFileOperation(remotePath, newParentPath, account); + + } else if (action.equals(ACTION_COPY_FILE)) { + // Copy file/folder + String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + String newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH); + operation = new CopyFileOperation(remotePath, newParentPath, account); } - } } catch (IllegalArgumentException e) { @@ -642,11 +649,11 @@ public class OperationsService extends Service { return null; } } - + /** * Sends a broadcast when a new operation is added to the queue. - * + * * Local broadcasts are only delivered to activities in the same process, but can't be * done sticky :\ * @@ -656,43 +663,43 @@ public class OperationsService extends Service { private void sendBroadcastNewOperation(Target target, RemoteOperation operation) { Intent intent = new Intent(ACTION_OPERATION_ADDED); if (target.mAccount != null) { - intent.putExtra(EXTRA_ACCOUNT, target.mAccount); + intent.putExtra(EXTRA_ACCOUNT, target.mAccount); } else { - intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl); + intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl); } //LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); //lbm.sendBroadcast(intent); sendStickyBroadcast(intent); } - + // TODO - maybe add a notification for real start of operations - + /** * Sends a LOCAL broadcast when an operations finishes in order to the interested activities c * an update their view * * Local broadcasts are only delivered to activities in the same process. - * - * @param target Account or URL pointing to an OC server. - * @param operation Finished operation. - * @param result Result of the operation. + * + * @param target Account or URL pointing to an OC server. + * @param operation Finished operation. + * @param result Result of the operation. */ private void sendBroadcastOperationFinished(Target target, RemoteOperation operation, RemoteOperationResult result) { Intent intent = new Intent(ACTION_OPERATION_FINISHED); intent.putExtra(EXTRA_RESULT, result); if (target.mAccount != null) { - intent.putExtra(EXTRA_ACCOUNT, target.mAccount); + intent.putExtra(EXTRA_ACCOUNT, target.mAccount); } else { - intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl); + intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl); } //LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); //lbm.sendBroadcast(intent); sendStickyBroadcast(intent); } - + /** * Notifies the currently subscribed listeners about the end of an operation. * @@ -720,9 +727,9 @@ public class OperationsService extends Service { } if (count == 0) { //mOperationResults.put(operation.hashCode(), result); - Pair undispatched = + Pair undispatched = new Pair(operation, result); - mUndispatchedFinishedOperations.put(operation.hashCode(), undispatched); + mUndispatchedFinishedOperations.put(((Runnable) operation).hashCode(), undispatched); } Log_OC.d(TAG, "Called " + count + " listeners"); } diff --git a/src/com/owncloud/android/ui/activity/FileActivity.java b/src/com/owncloud/android/ui/activity/FileActivity.java index f1508c28..1c21cab4 100644 --- a/src/com/owncloud/android/ui/activity/FileActivity.java +++ b/src/com/owncloud/android/ui/activity/FileActivity.java @@ -510,7 +510,7 @@ public class FileActivity extends AppCompatActivity */ private void swapToDefaultAccount() { // default to the most recently used account - Account newAccount = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext()); + Account newAccount = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext()); if (newAccount == null) { /// no account available: force account creation createFirstAccount(); @@ -602,7 +602,7 @@ public class FileActivity extends AppCompatActivity } /** - * @return 'True' when the Activity is finishing to enforce the setup of a new account. + * @return 'True' when the Activity is finishing to enforce the setup of a new account. */ protected boolean isRedirectingToSetupAccount() { return mRedirectingToSetupAccount; @@ -752,6 +752,7 @@ public class FileActivity extends AppCompatActivity } + private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) { dismissLoadingDialog(); @@ -857,7 +858,7 @@ public class FileActivity extends AppCompatActivity /** * Dismiss loading dialog */ - public void dismissLoadingDialog(){ + public void dismissLoadingDialog() { Fragment frag = getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG); if (frag != null) { LoadingDialog loading = (LoadingDialog) frag; diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index ede00340..20bcdce4 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -77,6 +77,7 @@ 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.common.utils.Log_OC; +import com.owncloud.android.operations.CopyFileOperation; import com.owncloud.android.operations.CreateFolderOperation; import com.owncloud.android.operations.CreateShareOperation; import com.owncloud.android.operations.MoveFileOperation; @@ -136,6 +137,7 @@ public class FileDisplayActivity extends HookActivity public static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; public static final int ACTION_SELECT_MULTIPLE_FILES = 2; public static final int ACTION_MOVE_FILES = 3; + public static final int ACTION_COPY_FILES = 4; private static final String TAG = FileDisplayActivity.class.getSimpleName(); @@ -184,7 +186,7 @@ public class FileDisplayActivity extends HookActivity // Inflate and set the layout view setContentView(R.layout.files); - + // Navigation Drawer initDrawer(); @@ -624,8 +626,7 @@ public class FileDisplayActivity extends HookActivity resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) { requestMultipleUpload(data, resultCode); - } else if (requestCode == ACTION_MOVE_FILES && resultCode == RESULT_OK) { - + } else if (requestCode == ACTION_MOVE_FILES && resultCode == RESULT_OK){ final Intent fData = data; final int fResultCode = resultCode; getHandler().postDelayed( @@ -638,6 +639,20 @@ public class FileDisplayActivity extends HookActivity DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS ); + } else if (requestCode == ACTION_COPY_FILES && resultCode == RESULT_OK) { + + final Intent fData = data; + final int fResultCode = resultCode; + getHandler().postDelayed( + new Runnable() { + @Override + public void run() { + requestCopyOperation(fData, fResultCode); + } + }, + DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS + ); + } else { super.onActivityResult(requestCode, resultCode, data); } @@ -753,6 +768,18 @@ public class FileDisplayActivity extends HookActivity getFileOperationsHelper().moveFile(folderToMoveAt, targetFile); } + /** + * Request the operation for copying the file/folder from one path to another + * + * @param data Intent received + * @param resultCode Result code received + */ + private void requestCopyOperation(Intent data, int resultCode) { + OCFile folderToMoveAt = data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER); + OCFile targetFile = data.getParcelableExtra(FolderPickerActivity.EXTRA_FILE); + getFileOperationsHelper().copyFile(folderToMoveAt, targetFile); + } + @Override public void onBackPressed() { if (!isDrawerOpen()){ @@ -824,6 +851,7 @@ public class FileDisplayActivity extends HookActivity downloadIntentFilter.addAction(FileDownloader.getDownloadFinishMessage()); mDownloadFinishReceiver = new DownloadFinishReceiver(); registerReceiver(mDownloadFinishReceiver, downloadIntentFilter); + Log_OC.v(TAG, "onResume() end"); } @@ -920,6 +948,7 @@ public class FileDisplayActivity extends HookActivity if (RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED. equals(event) &&/// TODO refactor and make common + synchResult != null && !synchResult.isSuccess() && (synchResult.getCode() == ResultCode.UNAUTHORIZED || synchResult.isIdPRedirection() || @@ -1021,6 +1050,7 @@ public class FileDisplayActivity extends HookActivity if (sameAccount && isDescendant) { refreshListOfFilesFragment(); } + boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false); boolean renamedInUpload = getFile().getRemotePath(). @@ -1312,10 +1342,12 @@ public class FileDisplayActivity extends HookActivity } else if (operation instanceof MoveFileOperation) { onMoveFileOperationFinish((MoveFileOperation) operation, result); + + } else if (operation instanceof CopyFileOperation) { + onCopyFileOperationFinish((CopyFileOperation) operation, result); } } - private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) { if (result.isSuccess()) { @@ -1348,8 +1380,9 @@ public class FileDisplayActivity extends HookActivity } else if (details instanceof PreviewTextFragment) { // Refresh OCFile of the fragment ((PreviewTextFragment) details).updateFile(file); - } else + } else { showDetails(file); + } } invalidateOptionsMenu(); } @@ -1365,6 +1398,7 @@ public class FileDisplayActivity extends HookActivity private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) { dismissLoadingDialog(); + Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), Toast.LENGTH_LONG); @@ -1419,6 +1453,30 @@ public class FileDisplayActivity extends HookActivity } } + /** + * Updates the view associated to the activity after the finish of an operation trying to copy a + * file. + * + * @param operation Copy operation performed. + * @param result Result of the copy operation. + */ + private void onCopyFileOperationFinish(CopyFileOperation operation, RemoteOperationResult result) { + if (result.isSuccess()) { + dismissLoadingDialog(); + refreshListOfFilesFragment(); + } else { + dismissLoadingDialog(); + try { + Toast msg = Toast.makeText(FileDisplayActivity.this, + ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), + Toast.LENGTH_LONG); + msg.show(); + + } catch (NotFoundException e) { + Log_OC.e(TAG, "Error while trying to show fail message ", e); + } + } + } /** * Updates the view associated to the activity after the finish of an operation trying to rename @@ -1458,7 +1516,7 @@ public class FileDisplayActivity extends HookActivity } } } - + if (getStorageManager().getFileById(renamedFile.getParentId()).equals(getCurrentDir())){ refreshListOfFilesFragment(); } @@ -1641,7 +1699,7 @@ public class FileDisplayActivity extends HookActivity /** * 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. diff --git a/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java b/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java index 937a50d0..24015d08 100644 --- a/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java +++ b/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java @@ -71,8 +71,8 @@ public class ExtendedListFragment extends Fragment private ArrayList mTops; private int mHeightCell = 0; - private OnEnforceableRefreshListener mOnRefreshListener = null; - + private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = null; + protected AbsListView mCurrentListView; private ExtendedListView mListView; private View mListFooterView; @@ -352,7 +352,7 @@ public class ExtendedListFragment extends Fragment mRefreshEmptyLayout.setRefreshing(false); if (mOnRefreshListener != null) { - mOnRefreshListener.onRefresh(ignoreETag); + mOnRefreshListener.onRefresh(); } } diff --git a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java index 68ee6771..24f7248f 100644 --- a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java +++ b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java @@ -21,10 +21,7 @@ */ package com.owncloud.android.ui.fragment; -import java.lang.ref.WeakReference; - import android.accounts.Account; -import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; @@ -46,13 +43,14 @@ 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.utils.Log_OC; -import com.owncloud.android.services.observer.FileObserverService; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; import com.owncloud.android.ui.dialog.RemoveFileDialogFragment; import com.owncloud.android.ui.dialog.RenameFileDialogFragment; import com.owncloud.android.utils.DisplayUtils; +import java.lang.ref.WeakReference; + /** * This Fragment is used to display the details about a file. @@ -62,9 +60,9 @@ public class FileDetailFragment extends FileFragment implements OnClickListener private int mLayout; private View mView; private Account mAccount; - + public ProgressListener mProgressListener; - + 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,14 +101,14 @@ public class FileDetailFragment extends FileFragment implements OnClickListener mLayout = R.layout.file_details_empty; mProgressListener = null; } - + @Override public void onActivityCreated(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } - + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -120,14 +118,14 @@ public class FileDetailFragment extends FileFragment implements OnClickListener mAccount = getArguments().getParcelable(ARG_ACCOUNT); if (savedInstanceState != null) { - setFile((OCFile)savedInstanceState.getParcelable(FileActivity.EXTRA_FILE)); + setFile((OCFile) savedInstanceState.getParcelable(FileActivity.EXTRA_FILE)); mAccount = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT); } - - if(getFile() != null && mAccount != null) { + + if (getFile() != null && mAccount != null) { mLayout = R.layout.file_details_fragment; } - + mView = inflater.inflate(mLayout, null); if (mLayout == R.layout.file_details_fragment) { @@ -154,20 +152,20 @@ public class FileDetailFragment extends FileFragment implements OnClickListener super.onStart(); listenForTransferProgress(); } - + @Override public void onStop() { leaveTransferProgress(); super.onStop(); } - + @Override public View getView() { return super.getView() == null ? mView : super.getView(); } - + /** * {@inheritDoc} */ @@ -175,16 +173,16 @@ public class FileDetailFragment extends FileFragment implements OnClickListener public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.file_actions_menu, menu); - } + } + - /** * {@inheritDoc} */ @Override - public void onPrepareOptionsMenu (Menu menu) { + public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - + if (mContainerActivity.getStorageManager() != null) { FileMenuFilter mf = new FileMenuFilter( getFile(), @@ -194,7 +192,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener ); mf.filter(menu); } - + // additional restriction for this fragment MenuItem item = menu.findItem(R.id.action_see_details); if (item != null) { @@ -208,9 +206,16 @@ public class FileDetailFragment extends FileFragment implements OnClickListener item.setVisible(false); item.setEnabled(false); } + + // additional restriction for this fragment + item = menu.findItem(R.id.action_copy); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } } - + /** * {@inheritDoc} */ @@ -241,10 +246,10 @@ public class FileDetailFragment extends FileFragment implements OnClickListener } case R.id.action_cancel_download: case R.id.action_cancel_upload: { - ((FileDisplayActivity)mContainerActivity).cancelTransference(getFile()); + ((FileDisplayActivity) mContainerActivity).cancelTransference(getFile()); return true; } - case R.id.action_download_file: + case R.id.action_download_file: case R.id.action_sync_file: { mContainerActivity.getFileOperationsHelper().syncFile(getFile()); return true; @@ -253,9 +258,10 @@ public class FileDetailFragment extends FileFragment implements OnClickListener // Obtain the file if (!getFile().isDown()) { // Download the file Log_OC.d(TAG, getFile().getRemotePath() + " : File must be downloaded"); - ((FileDisplayActivity)mContainerActivity).startDownloadForSending(getFile()); - - } else { + ((FileDisplayActivity) mContainerActivity).startDownloadForSending(getFile()); + + } + else { mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile()); } return true; @@ -282,7 +288,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener break; } case R.id.fdCancelBtn: { - ((FileDisplayActivity)mContainerActivity).cancelTransference(getFile()); + ((FileDisplayActivity) mContainerActivity).cancelTransference(getFile()); break; } default: @@ -293,17 +299,17 @@ public class FileDetailFragment extends FileFragment implements OnClickListener /** * Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be replaced. - * - * @return True when the fragment was created with the empty layout. + * + * @return True when the fragment was created with the empty layout. */ public boolean isEmpty() { return (mLayout == R.layout.file_details_empty || getFile() == null || mAccount == null); } - + /** * Use this method to signal this Activity that it shall update its view. - * + * * @param file : An {@link OCFile} */ public void updateFileDetails(OCFile file, Account ocAccount) { @@ -314,14 +320,13 @@ public class FileDetailFragment extends FileFragment implements OnClickListener /** * Updates the view with all relevant details about that file. + *

+ * TODO Remove parameter when the transferring state of files is kept in database. * - * TODO Remove parameter when the transferring state of files is kept in database. - * - * @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 whole file from the database + * @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 whole file from the database */ public void updateFileDetails(boolean transferring, boolean refresh) { if (readyToShow()) { @@ -330,7 +335,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener setFile(storageManager.getFileByPath(getFile().getRemotePath())); } OCFile file = getFile(); - + // set file details setFilename(file.getFileName()); setFiletype(file.getMimetype(), file.getFileName()); @@ -349,7 +354,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) ) { setButtonsForTransferring(); - + } else if (file.isDown()) { setButtonsForDown(); @@ -362,25 +367,27 @@ public class FileDetailFragment extends FileFragment implements OnClickListener } getView().invalidate(); } - + /** * Checks if the fragment is ready to show details of a OCFile - * - * @return 'True' when the fragment is ready to show details of a file + * + * @return 'True' when the fragment is ready to show details of a file */ private boolean readyToShow() { - return (getFile() != null && mAccount != null && mLayout == R.layout.file_details_fragment); + return (getFile() != null && mAccount != null && mLayout == R.layout.file_details_fragment); } /** * Updates the filename in view + * * @param filename to set */ private void setFilename(String filename) { TextView tv = (TextView) getView().findViewById(R.id.fdFilename); - if (tv != null) + if (tv != null) { tv.setText(filename); + } } /** @@ -402,25 +409,28 @@ public class FileDetailFragment extends FileFragment implements OnClickListener /** * Updates the file size in view + * * @param filesize in bytes to set */ private void setFilesize(long filesize) { TextView tv = (TextView) getView().findViewById(R.id.fdSize); - if (tv != null) + if (tv != null) { tv.setText(DisplayUtils.bytesToHumanReadable(filesize)); + } } - + /** * Updates the time that the file was last modified + * * @param milliseconds Unix time to set */ - private void setTimeModified(long milliseconds){ + private void setTimeModified(long milliseconds) { TextView tv = (TextView) getView().findViewById(R.id.fdModified); - if(tv != null){ + if (tv != null) { tv.setText(DisplayUtils.unixTimeToHumanReadable(milliseconds)); } } - + /** * Enables or disables buttons for a file being downloaded */ @@ -431,21 +441,24 @@ public class FileDetailFragment extends FileFragment implements OnClickListener // show the progress bar for the transfer getView().findViewById(R.id.fdProgressBlock).setVisibility(View.VISIBLE); - TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText); + TextView progressText = (TextView) getView().findViewById(R.id.fdProgressText); progressText.setVisibility(View.VISIBLE); FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder(); FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder(); //if (getFile().isDownloading()) { if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, getFile())) { progressText.setText(R.string.downloader_download_in_progress_ticker); - } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, getFile())) { - progressText.setText(R.string.uploader_upload_in_progress_ticker); + } + else { + if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, getFile())) { + progressText.setText(R.string.uploader_upload_in_progress_ticker); + } } } } /** - * Enables or disables buttons for a file locally available + * Enables or disables buttons for a file locally available */ private void setButtonsForDown() { if (!isEmpty()) { @@ -453,13 +466,13 @@ public class FileDetailFragment extends FileFragment implements OnClickListener // hides the progress bar getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE); - TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText); + TextView progressText = (TextView) getView().findViewById(R.id.fdProgressText); progressText.setVisibility(View.GONE); } } /** - * Enables or disables buttons for a file not locally available + * Enables or disables buttons for a file not locally available */ private void setButtonsForRemote() { if (!isEmpty()) { @@ -467,11 +480,11 @@ public class FileDetailFragment extends FileFragment implements OnClickListener // hides the progress bar getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE); - TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText); + TextView progressText = (TextView) getView().findViewById(R.id.fdProgressText); progressText.setVisibility(View.GONE); } } - + public void listenForTransferProgress() { if (mProgressListener != null) { @@ -485,8 +498,8 @@ public class FileDetailFragment extends FileFragment implements OnClickListener } } } - - + + public void leaveTransferProgress() { if (mProgressListener != null) { if (mContainerActivity.getFileDownloaderBinder() != null) { @@ -501,7 +514,6 @@ public class FileDetailFragment extends FileFragment implements OnClickListener } - /** * Helper class responsible for updating the progress bar shown for file uploading or * downloading @@ -509,11 +521,11 @@ public class FileDetailFragment extends FileFragment implements OnClickListener private class ProgressListener implements OnDatatransferProgressListener { int mLastPercent = 0; WeakReference mProgressBar = null; - + ProgressListener(ProgressBar progressBar) { mProgressBar = new WeakReference(progressBar); } - + @Override public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) { diff --git a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java index e0004b17..0c96ea2c 100644 --- a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -22,8 +22,6 @@ */ package com.owncloud.android.ui.fragment; -import java.io.File; - import android.app.Activity; import android.content.Intent; import android.os.Bundle; @@ -55,13 +53,14 @@ 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.DialogMenuItem; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.ui.preview.PreviewTextFragment; +import java.io.File; + /** * A Fragment that lists all files and folders in a given path. - * + * * TODO refactor to get rid of direct dependency on FileDisplayActivity */ public class OCFileListFragment extends ExtendedListFragment implements FileActionsDialogFragment.FileActionsDialogFragmentListener { @@ -70,14 +69,14 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi private static final String MY_PACKAGE = OCFileListFragment.class.getPackage() != null ? OCFileListFragment.class.getPackage().getName() : "com.owncloud.android.ui.fragment"; - + public final static String ARG_JUST_FOLDERS = MY_PACKAGE + ".JUST_FOLDERS"; public final static String ARG_ALLOW_CONTEXTUAL_ACTIONS = MY_PACKAGE + ".ALLOW_CONTEXTUAL"; - + private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE"; private FileFragment.ContainerActivity mContainerActivity; - + private OCFile mFile = null; private FileListListAdapter mAdapter; private boolean mJustFolders; @@ -95,21 +94,21 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi Log_OC.e(TAG, "onAttach"); try { mContainerActivity = (FileFragment.ContainerActivity) activity; - + } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement " + + throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName()); } try { setOnRefreshListener((OnEnforceableRefreshListener) activity); } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement " + + throw new ClassCastException(activity.toString() + " must implement " + SwipeRefreshLayout.OnRefreshListener.class.getSimpleName()); } } - + @Override public void onDetach() { setOnRefreshListener(null); @@ -141,7 +140,7 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi mJustFolders, getActivity(), mContainerActivity - ); + ); setListAdapter(mAdapter); registerLongClickListener(); @@ -204,31 +203,31 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi * Saves the current listed folder. */ @Override - public void onSaveInstanceState (Bundle outState) { + public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable(KEY_FILE, mFile); } - + /** * Call this, when the user presses the up button. - * + * * Tries to move up the current folder one level. If the parent folder was removed from the * database, it continues browsing up until finding an existing folders. - * + *

* return Count of folder levels browsed up. */ public int onBrowseUp() { OCFile parentDir = null; int moveCount = 0; - - if(mFile != null){ + + if (mFile != null) { FileDataStorageManager storageManager = mContainerActivity.getStorageManager(); - + String parentPath = null; if (mFile.getParentId() != FileDataStorageManager.ROOT_PARENT_ID) { parentPath = new File(mFile.getRemotePath()).getParent(); - parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : - parentPath + OCFile.PATH_SEPARATOR; + parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : + parentPath + OCFile.PATH_SEPARATOR; parentDir = storageManager.getFileByPath(parentPath); moveCount++; } else { @@ -236,8 +235,8 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi } while (parentDir == null) { parentPath = new File(parentPath).getParent(); - parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : - parentPath + OCFile.PATH_SEPARATOR; + parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : + parentPath + OCFile.PATH_SEPARATOR; parentDir = storageManager.getFileByPath(parentPath); moveCount++; } // exit is granted because storageManager.getFileByPath("/") never returns null @@ -247,20 +246,20 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi listDirectory(mFile /*, MainApp.getOnlyOnDevice()*/); onRefresh(false); - + // restore index and top position restoreIndexAndTopPosition(); - + } // else - should never happen now - + return moveCount; } - + @Override public void onItemClick(AdapterView l, View v, int position, long id) { OCFile file = (OCFile) mAdapter.getItem(position); if (file != null) { - if (file.isFolder()) { + if (file.isFolder()) { // update state and view of this fragment // TODO Enable when "On Device" is recovered ? listDirectory(file/*, MainApp.getOnlyOnDevice()*/); @@ -268,7 +267,7 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi mContainerActivity.onBrowsedDownTo(file); // save index and top position saveIndexAndTopPosition(position); - + } else { /// Click on a file if (PreviewImageFragment.canBePreviewed(file)) { // preview image - it handles the download, if needed @@ -278,39 +277,39 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi } else if (file.isDown()) { if (PreviewMediaFragment.canBePreviewed(file)) { // media preview - ((FileDisplayActivity)mContainerActivity).startMediaPreview(file, 0, true); + ((FileDisplayActivity) mContainerActivity).startMediaPreview(file, 0, true); } else { mContainerActivity.getFileOperationsHelper().openFile(file); } - + } else { // automatic download, preview on finish - ((FileDisplayActivity)mContainerActivity).startDownloadForPreview(file); + ((FileDisplayActivity) mContainerActivity).startDownloadForPreview(file); } - + } - + } else { Log_OC.d(TAG, "Null object in ListAdapter!!"); } - + } - + /** * {@inheritDoc} */ @Override - public void onCreateContextMenu ( + public void onCreateContextMenu( ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { Bundle args = getArguments(); - boolean allowContextualActions = - (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true); + boolean allowContextualActions = + (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true); if (allowContextualActions) { MenuInflater inflater = getActivity().getMenuInflater(); inflater.inflate(R.menu.file_actions_menu, menu); AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; OCFile targetFile = (OCFile) mAdapter.getItem(info.position); - + if (mContainerActivity.getStorageManager() != null) { FileMenuFilter mf = new FileMenuFilter( targetFile, @@ -405,6 +404,13 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false); return true; } + case R.id.action_copy: + Intent action = new Intent(getActivity(), FolderPickerActivity.class); + + // Pass mTargetFile that contains info of selected file/folder + action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile); + getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES); + return true; default: return false; } @@ -428,12 +434,13 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi /** * Use this to query the {@link OCFile} that is currently * being displayed by this fragment + * * @return The currently viewed OCFile */ - public OCFile getCurrentFile(){ + public OCFile getCurrentFile() { return mFile; } - + /** * Calls {@link OCFileListFragment#listDirectory(OCFile)} with a null parameter */ @@ -447,12 +454,12 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi // TODO Enable when "On Device" is recovered ? listDirectory(getCurrentFile()/*, MainApp.getOnlyOnDevice()*/); } - + /** * Lists the given directory on the view. When the input parameter is null, * it will either refresh the last known directory. list the root * if there never was a directory. - * + * * @param directory File to be listed */ public void listDirectory(OCFile directory/*, boolean onlyOnDevice*/) { @@ -460,18 +467,18 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi if (storageManager != null) { // Check input parameters for null - if(directory == null){ - if(mFile != null){ + if (directory == null) { + if (mFile != null) { directory = mFile; } else { directory = storageManager.getFileByPath("/"); if (directory == null) return; // no files, wait for sync } } - - + + // If that's not a directory -> List its parent - if(!directory.isFolder()){ + if (!directory.isFolder()) { Log_OC.w(TAG, "You see, that is not a directory -> " + directory.toString()); directory = storageManager.getFileById(directory.getParentId()); } diff --git a/src/com/owncloud/android/ui/preview/FileDownloadFragment.java b/src/com/owncloud/android/ui/preview/FileDownloadFragment.java index dd78a039..e63b3245 100644 --- a/src/com/owncloud/android/ui/preview/FileDownloadFragment.java +++ b/src/com/owncloud/android/ui/preview/FileDownloadFragment.java @@ -59,9 +59,9 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene public ProgressListener mProgressListener; private boolean mListening; - + private static final String TAG = FileDownloadFragment.class.getSimpleName(); - + private boolean mIgnoreFirstSavedState; private boolean mError; @@ -118,19 +118,20 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene mIgnoreFirstSavedState = args.getBoolean(ARG_IGNORE_FIRST); mAccount = args.getParcelable(ARG_ACCOUNT); } - + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); - + if (savedInstanceState != null) { if (!mIgnoreFirstSavedState) { - setFile((OCFile)savedInstanceState.getParcelable(FileDownloadFragment.EXTRA_FILE)); + setFile((OCFile) savedInstanceState.getParcelable(FileDownloadFragment.EXTRA_FILE)); mAccount = savedInstanceState.getParcelable(FileDownloadFragment.EXTRA_ACCOUNT); mError = savedInstanceState.getBoolean(FileDownloadFragment.EXTRA_ERROR); - } else { + } + else { mIgnoreFirstSavedState = false; } } @@ -140,7 +141,7 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.progressBar); DisplayUtils.colorPreLollipopHorizontalProgressBar(progressBar); mProgressListener = new ProgressListener(progressBar); - + (mView.findViewById(R.id.cancelBtn)).setOnClickListener(this); (mView.findViewById(R.id.fileDownloadLL)).setOnClickListener(new OnClickListener() { @@ -152,13 +153,14 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene if (mError) { setButtonsForRemote(); - } else { + } + else { setButtonsForTransferring(); } - + return mView; } - + @Override public void onSaveInstanceState(Bundle outState) { @@ -173,7 +175,7 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene super.onStart(); listenForTransferProgress(); } - + @Override public void onResume() { super.onResume(); @@ -185,19 +187,19 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene super.onPause(); } - + @Override public void onStop() { leaveTransferProgress(); super.onStop(); } - + @Override public void onDestroy() { super.onDestroy(); } - - + + @Override public View getView() { if (!mListening) { @@ -206,7 +208,7 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene return super.getView() == null ? mView : super.getView(); } - + @Override public void onClick(View v) { switch (v.getId()) { @@ -220,53 +222,52 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene } } - + /** * Enables or disables buttons for a file being downloaded */ private void setButtonsForTransferring() { getView().findViewById(R.id.cancelBtn).setVisibility(View.VISIBLE); - + // show the progress bar for the transfer getView().findViewById(R.id.progressBar).setVisibility(View.VISIBLE); - TextView progressText = (TextView)getView().findViewById(R.id.progressText); + TextView progressText = (TextView) getView().findViewById(R.id.progressText); progressText.setText(R.string.downloader_download_in_progress_ticker); progressText.setVisibility(View.VISIBLE); - + // hides the error icon getView().findViewById(R.id.errorText).setVisibility(View.GONE); getView().findViewById(R.id.error_image).setVisibility(View.GONE); } - /** - * Enables or disables buttons for a file locally available + * Enables or disables buttons for a file locally available */ private void setButtonsForDown() { getView().findViewById(R.id.cancelBtn).setVisibility(View.GONE); - + // hides the progress bar getView().findViewById(R.id.progressBar).setVisibility(View.GONE); - + // updates the text message - TextView progressText = (TextView)getView().findViewById(R.id.progressText); + TextView progressText = (TextView) getView().findViewById(R.id.progressText); progressText.setText(R.string.common_loading); progressText.setVisibility(View.VISIBLE); - + // hides the error icon getView().findViewById(R.id.errorText).setVisibility(View.GONE); getView().findViewById(R.id.error_image).setVisibility(View.GONE); } - + /** - * Enables or disables buttons for a file not locally available - * + * Enables or disables buttons for a file not locally available + *

* Currently, this is only used when a download was failed */ private void setButtonsForRemote() { getView().findViewById(R.id.cancelBtn).setVisibility(View.GONE); - + // hides the progress bar and message getView().findViewById(R.id.progressBar).setVisibility(View.GONE); getView().findViewById(R.id.progressText).setVisibility(View.GONE); @@ -275,7 +276,7 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene getView().findViewById(R.id.errorText).setVisibility(View.VISIBLE); getView().findViewById(R.id.error_image).setVisibility(View.VISIBLE); } - + public void listenForTransferProgress() { if (mProgressListener != null && !mListening) { @@ -288,8 +289,8 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene } } } - - + + public void leaveTransferProgress() { if (mProgressListener != null) { if (mContainerActivity.getFileDownloaderBinder() != null) { @@ -308,11 +309,11 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene private class ProgressListener implements OnDatatransferProgressListener { int mLastPercent = 0; WeakReference mProgressBar = null; - + ProgressListener(ProgressBar progressBar) { mProgressBar = new WeakReference(progressBar); } - + @Override public void onTransferProgress( long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename @@ -333,8 +334,9 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene public void setError(boolean error) { mError = error; - }; - + } + + ; } diff --git a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java index 6ce592a7..b6f36823 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java @@ -75,11 +75,11 @@ public class PreviewImageFragment extends FileFragment { private ProgressBar mProgressWheel; public Bitmap mBitmap = null; - + private static final String TAG = PreviewImageFragment.class.getSimpleName(); private boolean mIgnoreFirstSavedState; - + private LoadBitmapTask mLoadBitmapTask = null; @@ -106,7 +106,7 @@ public class PreviewImageFragment extends FileFragment { return frag; } - + /** * Creates an empty fragment for image previews. @@ -120,8 +120,8 @@ public class PreviewImageFragment extends FileFragment { public PreviewImageFragment() { mIgnoreFirstSavedState = false; } - - + + /** * {@inheritDoc} */ @@ -136,14 +136,14 @@ public class PreviewImageFragment extends FileFragment { mIgnoreFirstSavedState = args.getBoolean(ARG_IGNORE_FIRST); setHasOptionsMenu(true); } - + /** * {@inheritDoc} */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.preview_image_fragment, container, false); mImageView = (TouchImageViewCustom) view.findViewById(R.id.image); @@ -183,7 +183,7 @@ public class PreviewImageFragment extends FileFragment { throw new IllegalStateException("There is no local file to preview"); } } - + /** * {@inheritDoc} @@ -193,7 +193,7 @@ public class PreviewImageFragment extends FileFragment { super.onSaveInstanceState(outState); outState.putParcelable(PreviewImageFragment.EXTRA_FILE, getFile()); } - + @Override public void onStart() { @@ -205,8 +205,8 @@ public class PreviewImageFragment extends FileFragment { mLoadBitmapTask.execute(getFile()); } } - - + + @Override public void onStop() { Log_OC.d(TAG, "onStop starts"); @@ -216,7 +216,7 @@ public class PreviewImageFragment extends FileFragment { } super.onStop(); } - + /** * {@inheritDoc} */ @@ -232,11 +232,11 @@ public class PreviewImageFragment extends FileFragment { @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - + if (mContainerActivity.getStorageManager() != null) { // Update the file setFile(mContainerActivity.getStorageManager().getFileById(getFile().getFileId())); - + FileMenuFilter mf = new FileMenuFilter( getFile(), mContainerActivity.getStorageManager().getAccount(), @@ -245,7 +245,7 @@ public class PreviewImageFragment extends FileFragment { ); mf.filter(menu); } - + // additional restriction for this fragment // TODO allow renaming in PreviewImageFragment MenuItem item = menu.findItem(R.id.action_rename_file); @@ -253,7 +253,7 @@ public class PreviewImageFragment extends FileFragment { item.setVisible(false); item.setEnabled(false); } - + // additional restriction for this fragment // TODO allow refresh file in PreviewImageFragment item = menu.findItem(R.id.action_sync_file); @@ -268,11 +268,17 @@ public class PreviewImageFragment extends FileFragment { item.setVisible(false); item.setEnabled(false); } - + + // additional restriction for this fragment + item = menu.findItem(R.id.action_copy); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + } - - + /** * {@inheritDoc} */ @@ -320,10 +326,10 @@ public class PreviewImageFragment extends FileFragment { return false; } } - + private void seeDetails() { - mContainerActivity.showDetails(getFile()); + mContainerActivity.showDetails(getFile()); } @@ -350,7 +356,7 @@ public class PreviewImageFragment extends FileFragment { super.onDestroy(); } - + /** * Opens the previewed image with an external application. */ @@ -358,7 +364,7 @@ public class PreviewImageFragment extends FileFragment { mContainerActivity.getFileOperationsHelper().openFile(getFile()); finish(); } - + private class LoadBitmapTask extends AsyncTask { @@ -378,7 +384,7 @@ public class PreviewImageFragment extends FileFragment { */ private final WeakReference mMessageViewRef; - + /** * Weak reference to the target {@link ProgressBar} shown while the load is in progress. * @@ -387,17 +393,17 @@ public class PreviewImageFragment extends FileFragment { */ private final WeakReference mProgressWheelRef; - + /** - * Error message to show when a load fails + * Error message to show when a load fails */ private int mErrorMessageId; - - + + /** * Constructor. - * - * @param imageView Target {@link ImageView} where the bitmap will be loaded into. + * + * @param imageView Target {@link ImageView} where the bitmap will be loaded into. */ public LoadBitmapTask(ImageViewCustom imageView, TextView messageView, ProgressBar progressWheel) { @@ -405,7 +411,7 @@ public class PreviewImageFragment extends FileFragment { mMessageViewRef = new WeakReference(messageView); mProgressWheelRef = new WeakReference(progressWheel); } - + @Override protected LoadImage doInBackground(OCFile... params) { Bitmap result = null; @@ -456,17 +462,18 @@ public class PreviewImageFragment extends FileFragment { } catch (NoSuchFieldError e) { mErrorMessageId = R.string.common_error_unknown; - Log_OC.e(TAG, "Error from access to unexisting field despite protection; file " - + storagePath, e); - + Log_OC.e(TAG, "Error from access to unexisting field despite protection; file " + + storagePath, e); + } catch (Throwable t) { mErrorMessageId = R.string.common_error_unknown; Log_OC.e(TAG, "Unexpected error loading " + getFile().getStoragePath(), t); - + } + return new LoadImage(result, ocFile); } - + @Override protected void onCancelled(LoadImage result) { if (result.bitmap != null) { @@ -479,7 +486,8 @@ public class PreviewImageFragment extends FileFragment { hideProgressWheel(); if (result.bitmap != null) { showLoadedImage(result); - } else { + } + else { showErrorMessage(); } if (result.bitmap != null && mBitmap != result.bitmap) { @@ -487,7 +495,7 @@ public class PreviewImageFragment extends FileFragment { result.bitmap.recycle(); } } - + @SuppressLint("InlinedApi") private void showLoadedImage(LoadImage result) { final ImageViewCustom imageView = mImageViewRef.get(); @@ -511,7 +519,7 @@ public class PreviewImageFragment extends FileFragment { messageView.setVisibility(View.GONE); } // else , silently finish, the fragment was destroyed } - + private void showErrorMessage() { final ImageView imageView = mImageViewRef.get(); if (imageView != null) { @@ -525,14 +533,14 @@ public class PreviewImageFragment extends FileFragment { messageView.setVisibility(View.VISIBLE); } // else , silently finish, the fragment was destroyed } - + private void hideProgressWheel() { final ProgressBar progressWheel = mProgressWheelRef.get(); if (progressWheel != null) { progressWheel.setVisibility(View.GONE); } } - + } /** @@ -546,7 +554,7 @@ public class PreviewImageFragment extends FileFragment { return (file != null && file.isImage()); } - + /** * Finishes the preview */ @@ -554,7 +562,7 @@ public class PreviewImageFragment extends FileFragment { Activity container = getActivity(); container.finish(); } - + public TouchImageViewCustom getImageView() { return mImageView; } diff --git a/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java b/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java index b197a855..0dbb1a32 100644 --- a/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java @@ -49,7 +49,6 @@ import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.Toast; import android.widget.VideoView; @@ -68,7 +67,7 @@ import com.owncloud.android.ui.fragment.FileFragment; /** * This fragment shows a preview of a downloaded media file (audio or video). - * + * * Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will * produce an {@link IllegalStateException}. * @@ -88,46 +87,46 @@ public class PreviewMediaFragment extends FileFragment implements private ImageView mImagePreview; private VideoView mVideoPreview; private int mSavedPlaybackPosition; - + private MediaServiceBinder mMediaServiceBinder = null; private MediaControlView mMediaController = null; private MediaServiceConnection mMediaServiceConnection = null; private VideoHelper mVideoHelper; private boolean mAutoplay; public boolean mPrepared; - + private static final String TAG = PreviewMediaFragment.class.getSimpleName(); - + /** * Creates a fragment to preview a file. - * + *

* When 'fileToDetail' or 'ocAccount' are null - * - * @param fileToDetail An {@link OCFile} to preview in the fragment - * @param ocAccount An ownCloud account; needed to start downloads + * + * @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, + OCFile fileToDetail, + Account ocAccount, + int startPlaybackPosition, boolean autoplay) { - + super(fileToDetail); mAccount = ocAccount; mSavedPlaybackPosition = startPlaybackPosition; mAutoplay = autoplay; } - - + + /** - * 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). - * - * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful - * construction + * 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). + *

+ * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful + * construction */ public PreviewMediaFragment() { super(); @@ -135,8 +134,8 @@ public class PreviewMediaFragment extends FileFragment implements mSavedPlaybackPosition = 0; mAutoplay = true; } - - + + /** * {@inheritDoc} */ @@ -145,29 +144,29 @@ public class PreviewMediaFragment extends FileFragment implements super.onCreate(savedInstanceState); setHasOptionsMenu(true); } - + /** * {@inheritDoc} */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); Log_OC.e(TAG, "onCreateView"); - + mView = inflater.inflate(R.layout.file_preview, container, false); - - mImagePreview = (ImageView)mView.findViewById(R.id.image_preview); - mVideoPreview = (VideoView)mView.findViewById(R.id.video_preview); + + mImagePreview = (ImageView) mView.findViewById(R.id.image_preview); + mVideoPreview = (VideoView) mView.findViewById(R.id.video_preview); mVideoPreview.setOnTouchListener(this); - - mMediaController = (MediaControlView)mView.findViewById(R.id.media_controller); - + + mMediaController = (MediaControlView) mView.findViewById(R.id.media_controller); + return mView; } - + /** * {@inheritDoc} @@ -188,29 +187,31 @@ public class PreviewMediaFragment extends FileFragment implements if (!file.isDown()) { throw new IllegalStateException("There is no local file to preview"); } - - } else { - file = (OCFile)savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_FILE); + + } + else { + file = (OCFile) savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_FILE); setFile(file); mAccount = savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_ACCOUNT); - mSavedPlaybackPosition = + mSavedPlaybackPosition = savedInstanceState.getInt(PreviewMediaFragment.EXTRA_PLAY_POSITION); mAutoplay = savedInstanceState.getBoolean(PreviewMediaFragment.EXTRA_PLAYING); - + } if (file != null && file.isDown()) { if (file.isVideo()) { mVideoPreview.setVisibility(View.VISIBLE); mImagePreview.setVisibility(View.GONE); prepareVideo(); - - } else { + + } + else { mVideoPreview.setVisibility(View.GONE); mImagePreview.setVisibility(View.VISIBLE); extractAndSetCoverArt(file); } } - + } /** @@ -244,24 +245,25 @@ public class PreviewMediaFragment extends FileFragment implements public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Log_OC.e(TAG, "onSaveInstanceState"); - + outState.putParcelable(PreviewMediaFragment.EXTRA_FILE, getFile()); outState.putParcelable(PreviewMediaFragment.EXTRA_ACCOUNT, mAccount); - + if (getFile().isVideo()) { mSavedPlaybackPosition = mVideoPreview.getCurrentPosition(); mAutoplay = mVideoPreview.isPlaying(); - outState.putInt(PreviewMediaFragment.EXTRA_PLAY_POSITION , mSavedPlaybackPosition); - outState.putBoolean(PreviewMediaFragment.EXTRA_PLAYING , mAutoplay); - } else { + outState.putInt(PreviewMediaFragment.EXTRA_PLAY_POSITION, mSavedPlaybackPosition); + outState.putBoolean(PreviewMediaFragment.EXTRA_PLAYING, mAutoplay); + } + else { outState.putInt( - PreviewMediaFragment.EXTRA_PLAY_POSITION , + PreviewMediaFragment.EXTRA_PLAY_POSITION, mMediaServiceBinder.getCurrentPosition()); outState.putBoolean( - PreviewMediaFragment.EXTRA_PLAYING , mMediaServiceBinder.isPlaying()); + PreviewMediaFragment.EXTRA_PLAYING, mMediaServiceBinder.isPlaying()); } } - + @Override public void onStart() { @@ -270,17 +272,20 @@ public class PreviewMediaFragment extends FileFragment implements OCFile file = getFile(); if (file != null && file.isDown()) { - if (file.isAudio()) { - bindMediaService(); - - } else if (file.isVideo()) { - stopAudio(); - playVideo(); - } + if (file.isAudio()) { + bindMediaService(); + + } + else { + if (file.isVideo()) { + stopAudio(); + playVideo(); + } + } } } - - + + private void stopAudio() { Intent i = new Intent(getActivity(), MediaService.class); i.setAction(MediaService.ACTION_STOP_ALL); @@ -304,7 +309,7 @@ public class PreviewMediaFragment extends FileFragment implements @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - + if (mContainerActivity.getStorageManager() != null) { FileMenuFilter mf = new FileMenuFilter( getFile(), @@ -329,9 +334,16 @@ public class PreviewMediaFragment extends FileFragment implements item.setVisible(false); item.setEnabled(false); } + + // additional restriction for this fragment + item = menu.findItem(R.id.action_copy); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } } - - + + /** * {@inheritDoc} */ @@ -381,26 +393,26 @@ public class PreviewMediaFragment extends FileFragment implements return false; } } - /** * Update the file of the fragment with file value + * * @param file */ - public void updateFile(OCFile file){ + public void updateFile(OCFile file) { setFile(file); } - + private void sendFile() { stopPreview(false); mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile()); - + } private void seeDetails() { stopPreview(false); - mContainerActivity.showDetails(getFile()); + mContainerActivity.showDetails(getFile()); } @@ -411,77 +423,80 @@ public class PreviewMediaFragment extends FileFragment implements mVideoPreview.setOnCompletionListener(mVideoHelper); mVideoPreview.setOnErrorListener(mVideoHelper); } - + @SuppressWarnings("static-access") private void playVideo() { // 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 Uri uri = Uri.parse(getFile().getStoragePath()); mVideoPreview.setVideoPath(uri.encode(getFile().getStoragePath())); } - + private class VideoHelper implements OnCompletionListener, OnPreparedListener, OnErrorListener { - - /** + + /** * Called when the file is ready to be played. - * + *

* Just starts the playback. - * + * * @param vp {@link MediaPlayer} instance performing the playback. */ @Override public void onPrepared(MediaPlayer vp) { Log_OC.e(TAG, "onPrepared"); mVideoPreview.seekTo(mSavedPlaybackPosition); - if (mAutoplay) { + if (mAutoplay) { mVideoPreview.start(); } mMediaController.setEnabled(true); mMediaController.updatePausePlay(); mPrepared = true; } - - + + /** * Called when the file is finished playing. - * + *

* Finishes the activity. - * - * @param mp {@link MediaPlayer} instance performing the playback. + * + * @param mp {@link MediaPlayer} instance performing the playback. */ @Override - public void onCompletion(MediaPlayer mp) { + public void onCompletion(MediaPlayer mp) { Log_OC.e(TAG, "completed"); if (mp != null) { mVideoPreview.seekTo(0); // next lines are necessary to work around undesired video loops if (Build.VERSION.SDK_INT == Build.VERSION_CODES.GINGERBREAD) { - mVideoPreview.pause(); - - } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.GINGERBREAD_MR1) { - // mVideePreview.pause() is not enough - - mMediaController.setEnabled(false); - mVideoPreview.stopPlayback(); - mAutoplay = false; - mSavedPlaybackPosition = 0; - mVideoPreview.setVideoPath(getFile().getStoragePath()); + mVideoPreview.pause(); + + } + else { + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.GINGERBREAD_MR1) { + // mVideePreview.pause() is not enough + + mMediaController.setEnabled(false); + mVideoPreview.stopPlayback(); + mAutoplay = false; + mSavedPlaybackPosition = 0; + mVideoPreview.setVideoPath(getFile().getStoragePath()); + } } } // else : called from onError() mMediaController.updatePausePlay(); } - - + + /** * Called when an error in playback occurs. - * - * @param mp {@link MediaPlayer} instance performing the playback. - * @param what Type of error - * @param extra Extra code specific to the error + * + * @param mp {@link MediaPlayer} instance performing the playback. + * @param what Type of error + * @param extra Extra code specific to the error */ @Override public boolean onError(MediaPlayer mp, int what, int extra) { @@ -502,28 +517,28 @@ public class PreviewMediaFragment extends FileFragment implements } return true; } - + } - + @Override public void onPause() { Log_OC.e(TAG, "onPause"); super.onPause(); } - + @Override public void onResume() { super.onResume(); Log_OC.e(TAG, "onResume"); } - + @Override public void onDestroy() { Log_OC.e(TAG, "onDestroy"); super.onDestroy(); } - + @Override public void onStop() { Log_OC.e(TAG, "onStop"); @@ -538,10 +553,10 @@ public class PreviewMediaFragment extends FileFragment implements mMediaServiceConnection = null; mMediaServiceBinder = null; } - + super.onStop(); } - + @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN && v == mVideoPreview) { @@ -554,7 +569,7 @@ public class PreviewMediaFragment extends FileFragment implements return false; } - + private void startFullScreenVideo() { Intent i = new Intent(getActivity(), PreviewVideoActivity.class); i.putExtra(FileActivity.EXTRA_ACCOUNT, mAccount); @@ -566,29 +581,30 @@ public class PreviewMediaFragment extends FileFragment implements } @Override - public void onConfigurationChanged (Configuration newConfig) { + public void onConfigurationChanged(Configuration newConfig) { Log_OC.e(TAG, "onConfigurationChanged " + this); } - + @Override - public void onActivityResult (int requestCode, int resultCode, Intent data) { + public void onActivityResult(int requestCode, int resultCode, Intent data) { Log_OC.e(TAG, "onActivityResult " + this); super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { mSavedPlaybackPosition = data.getExtras().getInt( PreviewVideoActivity.EXTRA_START_POSITION); - mAutoplay = data.getExtras().getBoolean(PreviewVideoActivity.EXTRA_AUTOPLAY); + mAutoplay = data.getExtras().getBoolean(PreviewVideoActivity.EXTRA_AUTOPLAY); } } - + private void playAudio() { OCFile file = getFile(); if (!mMediaServiceBinder.isPlaying(file)) { Log_OC.d(TAG, "starting playback of " + file.getStoragePath()); mMediaServiceBinder.start(mAccount, file, mAutoplay, mSavedPlaybackPosition); - - } else { + + } + else { if (!mMediaServiceBinder.isPlaying() && mAutoplay) { mMediaServiceBinder.start(); mMediaController.updatePausePlay(); @@ -625,7 +641,8 @@ public class PreviewMediaFragment extends FileFragment implements Log_OC.d(TAG, "Successfully bound to MediaService, MediaController ready"); - } else { + } + else { Log_OC.e(TAG, "Unexpected response from MediaService while binding"); } } @@ -647,7 +664,8 @@ public class PreviewMediaFragment extends FileFragment implements Log_OC.e(TAG, "Media service suddenly disconnected"); if (mMediaController != null) { mMediaController.setMediaPlayer(null); - } else { + } + else { Toast.makeText( getActivity(), "No media controller to release when disconnected from media service", @@ -657,9 +675,8 @@ public class PreviewMediaFragment extends FileFragment implements mMediaServiceConnection = null; } } - } + } - /** * Opens the previewed file with an external application. @@ -669,31 +686,33 @@ public class PreviewMediaFragment extends FileFragment implements mContainerActivity.getFileOperationsHelper().openFile(getFile()); finish(); } - + /** * 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. + * to be previewed. + * + * @param file File to test if can be previewed. + * @return 'True' if the file can be handled by the fragment. */ public static boolean canBePreviewed(OCFile file) { return (file != null && (file.isAudio() || file.isVideo())); } - + public void stopPreview(boolean stopAudio) { OCFile file = getFile(); if (file.isAudio() && stopAudio) { mMediaServiceBinder.pause(); - - } else if (file.isVideo()) { - mVideoPreview.stopPlayback(); + + } + else { + if (file.isVideo()) { + mVideoPreview.stopPlayback(); + } } } - /** * Finishes the preview */ @@ -709,12 +728,12 @@ public class PreviewMediaFragment extends FileFragment implements Log_OC.e(TAG, "getting position: " + mSavedPlaybackPosition); return mSavedPlaybackPosition; } - + public boolean isPlaying() { if (mPrepared) { mAutoplay = mVideoPreview.isPlaying(); } return mAutoplay; } - + } diff --git a/src/com/owncloud/android/utils/ErrorMessageAdapter.java b/src/com/owncloud/android/utils/ErrorMessageAdapter.java index 75736e53..b80cc573 100644 --- a/src/com/owncloud/android/utils/ErrorMessageAdapter.java +++ b/src/com/owncloud/android/utils/ErrorMessageAdapter.java @@ -21,17 +21,13 @@ package com.owncloud.android.utils; -import java.io.File; -import java.net.SocketTimeoutException; - -import org.apache.commons.httpclient.ConnectTimeoutException; - import android.content.res.Resources; import com.owncloud.android.R; 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.CopyFileOperation; import com.owncloud.android.operations.CreateFolderOperation; import com.owncloud.android.operations.CreateShareOperation; import com.owncloud.android.operations.DownloadFileOperation; @@ -43,6 +39,11 @@ import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.operations.UploadFileOperation; +import org.apache.commons.httpclient.ConnectTimeoutException; + +import java.io.File; +import java.net.SocketTimeoutException; + /** * Class to choose proper error messages to show to the user depending on the results of operations, * always following the same policy @@ -51,16 +52,16 @@ import com.owncloud.android.operations.UploadFileOperation; public class ErrorMessageAdapter { public ErrorMessageAdapter() { - + } public static String getErrorCauseMessage(RemoteOperationResult result, RemoteOperation operation, Resources res) { String message = null; - + if (operation instanceof UploadFileOperation) { - + if (result.isSuccess()) { message = String.format( res.getString(R.string.uploader_upload_succeeded_content_single), @@ -76,7 +77,7 @@ public class ErrorMessageAdapter { } else if (result.getCode() == ResultCode.QUOTA_EXCEEDED) { message = res.getString(R.string.failed_upload_quota_exceeded_text); */ - + } else if (result.getCode() == ResultCode.FORBIDDEN) { message = String.format(res.getString(R.string.forbidden_permissions), res.getString(R.string.uploader_upload_forbidden_permissions)); @@ -90,14 +91,14 @@ public class ErrorMessageAdapter { ((UploadFileOperation) operation).getFileName()); } } - + } else if (operation instanceof DownloadFileOperation) { - + if (result.isSuccess()) { message = String.format( res.getString(R.string.downloader_download_succeeded_content), new File(((DownloadFileOperation) operation).getSavePath()).getName()); - + } else { if (result.getCode() == ResultCode.FILE_NOT_FOUND) { message = res.getString(R.string.downloader_download_file_not_found); @@ -108,11 +109,11 @@ public class ErrorMessageAdapter { ((DownloadFileOperation) operation).getSavePath()).getName()); } } - + } else if (operation instanceof RemoveFileOperation) { if (result.isSuccess()) { message = res.getString(R.string.remove_success_msg); - + } else { if (result.getCode().equals(ResultCode.FORBIDDEN)) { // Error --> No permissions @@ -120,7 +121,7 @@ public class ErrorMessageAdapter { res.getString(R.string.forbidden_permissions_delete)); } else if (isNetworkError(result.getCode())) { message = getErrorMessage(result, res); - + } else { message = res.getString(R.string.remove_fail_msg); } @@ -140,19 +141,19 @@ public class ErrorMessageAdapter { } else if (isNetworkError(result.getCode())) { message = getErrorMessage(result, res); - + } else if (result.getCode() == ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER) { message = res.getString(R.string.filename_forbidden_charaters_from_server); } else { - message = res.getString(R.string.rename_server_fail_msg); + message = res.getString(R.string.rename_server_fail_msg); } - + } else if (operation instanceof SynchronizeFileOperation) { if (!((SynchronizeFileOperation) operation).transferWasRequested()) { message = res.getString(R.string.sync_file_nothing_to_do_msg); } - + } else if (operation instanceof CreateFolderOperation) { if (result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME) { message = res.getString(R.string.filename_forbidden_characters); @@ -163,7 +164,7 @@ public class ErrorMessageAdapter { } else if (isNetworkError(result.getCode())) { message = getErrorMessage(result, res); - + } else if (result.getCode() == ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER) { message = res.getString(R.string.filename_forbidden_charaters_from_server); } else { @@ -172,7 +173,7 @@ public class ErrorMessageAdapter { } else if (operation instanceof CreateShareOperation) { if (result.getCode() == ResultCode.SHARE_NOT_FOUND) { // Error --> SHARE_NOT_FOUND message = res.getString(R.string.share_link_file_no_exist); - + } else if (result.getCode() == ResultCode.SHARE_FORBIDDEN) { // Error --> No permissions message = String.format(res.getString(R.string.forbidden_permissions), @@ -180,17 +181,17 @@ public class ErrorMessageAdapter { } else if (isNetworkError(result.getCode())) { message = getErrorMessage(result, res); - + } else { // Generic error // Show a Message, operation finished without success message = res.getString(R.string.share_link_file_error); } - + } else if (operation instanceof UnshareLinkOperation) { - + if (result.getCode() == ResultCode.SHARE_NOT_FOUND) { // Error --> SHARE_NOT_FOUND message = res.getString(R.string.unshare_link_file_no_exist); - + } else if (result.getCode() == ResultCode.SHARE_FORBIDDEN) { // Error --> No permissions message = String.format(res.getString(R.string.forbidden_permissions), @@ -198,17 +199,18 @@ public class ErrorMessageAdapter { } else if (isNetworkError(result.getCode())) { message = getErrorMessage(result, res); - + } else { // Generic error // Show a Message, operation finished without success message = res.getString(R.string.unshare_link_file_error); } } else if (operation instanceof MoveFileOperation) { - if (result.getCode() == ResultCode.FILE_NOT_FOUND) { + if(isNetworkError(result.getCode())){ + message = getErrorMessage(result, res); + } else if (result.getCode() == ResultCode.FILE_NOT_FOUND) { message = res.getString(R.string.move_file_not_found); - - } else if (result.getCode() == ResultCode.INVALID_MOVE_INTO_DESCENDANT) { + } else if (result.getCode() == ResultCode.INVALID_MOVE_INTO_DESCENDANT) { message = res.getString(R.string.move_file_invalid_into_descendent); } else if (result.getCode() == ResultCode.INVALID_OVERWRITE) { @@ -240,44 +242,62 @@ public class ErrorMessageAdapter { folderPathName); } } + } else if (operation instanceof CopyFileOperation) { + if(isNetworkError(result.getCode())){ + message = getErrorMessage(result, res); + } else if (result.getCode() == ResultCode.FILE_NOT_FOUND) { + message = res.getString(R.string.copy_file_not_found); + } else if (result.getCode() == ResultCode.INVALID_COPY_INTO_DESCENDANT) { + message = res.getString(R.string.copy_file_invalid_into_descendent); + + } else if (result.getCode() == ResultCode.INVALID_OVERWRITE) { + message = res.getString(R.string.copy_file_invalid_overwrite); + + } else if (result.getCode() == ResultCode.FORBIDDEN) { + message = String.format(res.getString(R.string.forbidden_permissions), + res.getString(R.string.forbidden_permissions_copy)); + + } else { // Generic error + // Show a Message, operation finished without success + message = res.getString(R.string.copy_file_error); + } } - + return message; } - - private static String getErrorMessage(RemoteOperationResult result , Resources res) { - + + private static String getErrorMessage(RemoteOperationResult result, Resources res) { + String message = null; - + if (!result.isSuccess()) { - + if (result.getCode() == ResultCode.WRONG_CONNECTION) { message = res.getString(R.string.network_error_socket_exception); - + } else if (result.getCode() == ResultCode.TIMEOUT) { message = res.getString(R.string.network_error_socket_exception); - + if (result.getException() instanceof SocketTimeoutException) { message = res.getString(R.string.network_error_socket_timeout_exception); - } else if(result.getException() instanceof ConnectTimeoutException) { + } else if (result.getException() instanceof ConnectTimeoutException) { message = res.getString(R.string.network_error_connect_timeout_exception); - } - + } + } else if (result.getCode() == ResultCode.HOST_NOT_AVAILABLE) { message = res.getString(R.string.network_host_not_available); } } - + return message; } - + private static boolean isNetworkError(RemoteOperationResult.ResultCode code) { - if (code == ResultCode.WRONG_CONNECTION || - code == ResultCode.TIMEOUT || + if (code == ResultCode.WRONG_CONNECTION || + code == ResultCode.TIMEOUT || code == ResultCode.HOST_NOT_AVAILABLE) { return true; - } - else + } else return false; } }