From: masensio Date: Wed, 9 Sep 2015 06:50:50 +0000 (+0200) Subject: Merge pull request #1124 from Kernald/new-filetype-icons X-Git-Tag: oc-android-1.8~14 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/84a4a086d614bd12fef58dd911f1312016013ecc?hp=502ff0a216e728b1552af5c55aad964ed3b87399 Merge pull request #1124 from Kernald/new-filetype-icons New filetype icons --- 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/layout/file_preview.xml b/res/layout/file_preview.xml index 2068224d..f7a697a0 100644 --- a/res/layout/file_preview.xml +++ b/res/layout/file_preview.xml @@ -25,9 +25,9 @@ android:layout_height="match_parent" android:background="@color/background_color" android:gravity="center" - tools:context=".ui.fragment.FilePreviewFragment" > + tools:context=".ui.fragment.FilePreviewFragment"> - + + + + \ No newline at end of file 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-af-rZA/strings.xml b/res/values-af-rZA/strings.xml index 696f88ec..7706aa76 100644 --- a/res/values-af-rZA/strings.xml +++ b/res/values-af-rZA/strings.xml @@ -16,6 +16,7 @@ OK Kanseleer Fout + Stuur Kies diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index 4201692c..ed93bc2e 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -269,7 +269,6 @@ inzibatçınızla əlaqə saxlayasınız. Bu fayla serverdə artıq uzun müddətdir ki, çatmaq mümkün deyil Hesablar Hesab əlavə et - Təhlükəsiz qoşulma, təhlükəsiz olmayan istiqamətə yönlədirilmişdir Jurnallar Tarixçəni göndər Jurnalların ötürülməsi üçün proqram təminatı tapılmadı! @@ -285,6 +284,7 @@ inzibatçınızla əlaqə saxlayasınız. Fayl artıq mənsəb qovluğunda mövcuddur Fayl və ya qovluğun köçürülməsi müddətində səhv baş verdi bu faylı köçürtmək + Fayl artıq mənsəb qovluğunda mövcuddur Anında yükləmələr Təhlükəsizlik Video ünvanını yüklə diff --git a/res/values-bg-rBG/strings.xml b/res/values-bg-rBG/strings.xml index 03158dd9..96334e49 100644 --- a/res/values-bg-rBG/strings.xml +++ b/res/values-bg-rBG/strings.xml @@ -300,6 +300,7 @@ Файлът вече съществува в отдалечената папка. Настъпи грешка при опита за преместване на този файл или папка. за да преместиш този файл + Файлът вече съществува в отдалечената папка. Незабавно качване Сигурност Качване на видео път diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml index 13cdb22d..d5833d32 100644 --- a/res/values-bn-rBD/strings.xml +++ b/res/values-bn-rBD/strings.xml @@ -249,6 +249,7 @@ সার্ভারে এই ফাইলটি আর প্রাপ্তব্য নয় একাউন্ট একাউন্ট যোগ কর + নিরাপদ সংযোগকে একটি অনিরাপদ পথে দিকবদল করা হয়েছে ভুল কুটশব্দ সরাও এখানে কিছু নেই। একটি ফোল্ডার যোগ করতে পারেন! diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 3c640d92..718efbf5 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -256,6 +256,7 @@ El fitxer ja no està disponible en el servidor Comptes Afegeix compte + La connexió segura està essent redirigida a través d\'una ruta insegura Carregant dades... Es requereix autenticació Contrasenya incorrecta diff --git a/res/values-cs-rCZ/strings.xml b/res/values-cs-rCZ/strings.xml index 718aa1ea..18db5bc4 100644 --- a/res/values-cs-rCZ/strings.xml +++ b/res/values-cs-rCZ/strings.xml @@ -290,7 +290,7 @@ správce systému. Tento soubor již není dostupný na serveru Účty Přidat účet - Bezpečné spojení je přesměrováno na nezabezpečenou trasu. + Zabezpečené spojení je přesměrováváno nezabezpečenou trasou. Logy Odeslat historii Nebyla nalezena žádná aplikace pro odesílání logů. Nainstalujte poÅ¡tovní aplikaci! @@ -306,6 +306,7 @@ správce systému. Soubor již v cílovém adresáři existuje Při pokusu o přesun tohoto souboru či složky nastala chyba pro přesun tohoto souboru + Soubor již v cílové složce existuje Okamžitá odesílání Zabezpečení Cesta pro nahrávání videí diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 3e70097d..80a60320 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -290,7 +290,7 @@ Filen er ikke længere tilgængelig pÃ¥ serveren Konti Tilføj konto - Sikker forbindelse videredirigeres til en usikker rute. + Sikker forbindelse videredirigeres gennem en usikker rute. Logge Send historik Der blev ikke fundet apps, der kan sende logge. Installér mail-app\'en! @@ -306,6 +306,11 @@ Filen findes allerede i destinationsmappen Der opstod en fejl under forsøg pÃ¥ at flytte denne mappe eller fil til at flytte denne fil + Kunne ikke kopiere. Tjek venligst om filerne findes + Det er ikke muligt at kopiere en mappe til én af dens undermapper + Filen findes allerede i destinationsmappen + Der opstod en fejl under forsøg pÃ¥ at kopiere denne fil eller mappe + til at kopiere denne fil Øjeblikkelige uploads Sikkerhed Sti til videoupload diff --git a/res/values-de-rDE/strings.xml b/res/values-de-rDE/strings.xml index fa67888c..7fe556bb 100644 --- a/res/values-de-rDE/strings.xml +++ b/res/values-de-rDE/strings.xml @@ -303,6 +303,7 @@ Die Datei ist bereits im Zielordner vorhanden Es ist ein Fehler beim Verschieben dieser Datei oder dieses Ordners aufgetreten. um diese Datei zu verschieben + Die Datei ist bereits im Zielordner vorhanden Sofortiges Hochladen Sicherheit Verzeichnis zum Hochladen der Videos diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 0f7d6144..8a34aeb3 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -287,7 +287,7 @@ Diese Datei steht auf dem Server nicht mehr zur Verfügung Konten Konto hinzufügen - Die gesicherte Verbindung wird auf eine unsichere Route weitergeleitet. + Die gesicherte Verbindung wird durch eine ungesicherte Route geleitet. Protokolle Verlauf senden Keine App zum Versenden der Meldungen gefunden. Bitte installiere die Mail-App! @@ -303,6 +303,7 @@ Die Datei ist bereits im Zielordner vorhanden Es ist ein Fehler beim Verschieben der Datei oder des Ordners aufgetreten. um diese Datei zu verschieben + Die Datei existiert bereits im Zielverzeichnis Sofortiges Hochladen Sicherheit Verzeichnis zum Hochladen der Videos diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index d7ffc33a..434d5fbf 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -274,7 +274,7 @@ Πρέπει να εισάγετε ένα κωδικό πρόσβασης. Αποστολή Αντιγραφή συνδέσμου - Αντιγραφθηκε στο πρόχειρο + Αντιγράφηκε στο πρόχειρο Κρίσιμο σφάλμα: αδύνατη η εκτέλεση λειτουργειών Ένα σφάλμα προέκυψε κατά τη σύνδεση με το διακομιστή. Ένα σφάλμα προέκυψε κατά την αναμονή για το διακομιστή, η λειτουργία δεν ήταν επιτυχής @@ -291,7 +291,7 @@ Αυτό το αρχείο δεν είναι πια διαθέσιμο στο διακομιστή Λογαριασμοί Προσθήκη λογαριασμού - Ασφαλής σύνδεση ανακατευθύνεται σε μια μη ασφαλή διαδρομή. + Ασφαλής σύνδεση ανακατευθύνεται μέσω μιας μη ασφαλούς διαδρομής. Αρχεία καταγραφών Αποστολή Ιστορικού Δεν εντοπίστηκε εφαρμογή αποστολής αναφορών συστήματος. Εγκαταστήστε την εφαρμογή Ηλ. Ταχυδρομείου!! @@ -307,6 +307,11 @@ Το αρχείο υπάρχει ήδη στο φάκελο προορισμού Ένα σφάλμα προέκυψε κατά την προσπάθεια μετακίνησης αυτού του αρχείου ή φακέλου για μετακίνηση αυτού του αρχείου + Αδύνατη η αντιγραφή. Παρακαλώ ελέγξτε αν το αρχείο υπάρχει + Δεν είναι δυνατό να αντιγραφεί ο φάκελος σε παράγωγό του φάκελο + Το αρχείο υπάρχει ήδη στο φάκελο προορισμού + Παρουσιάστηκε σφάλμα κατά την προσπάθεια αντιγραφής αυτού του αρχείου ή φακέλου + για αντιγραφή αυτού του αρχείου Στιγμιαίες Μεταφορτώσεις Ασφάλεια Διαδρομή Μεταφόρτωσης Βίντεο diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 486eb581..f0c7acde 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -278,7 +278,7 @@ The file is no longer available on the server Accounts Add account - Secure connection is redirected to an unsecured route. + Secure connection is redirected through an unsecured route. Logs Send History No app for sending logs found. Install mail app! @@ -294,6 +294,7 @@ The file exists already in the destination folder An error occurred whilst trying to move this file or folder to move this file + The file exists already in the destination folder Instant Uploads Security Upload Video Path diff --git a/res/values-eo/strings.xml b/res/values-eo/strings.xml index 4a919210..daf7c1fe 100644 --- a/res/values-eo/strings.xml +++ b/res/values-eo/strings.xml @@ -183,6 +183,7 @@ Movi Elekti La dosiero jam ekzistas en la cela dosierujo + La dosiero jam ekzistas en la cela dosierujo Sekuro Servila adreso diff --git a/res/values-es-rAR/strings.xml b/res/values-es-rAR/strings.xml index 5d91a8fc..f159bce2 100644 --- a/res/values-es-rAR/strings.xml +++ b/res/values-es-rAR/strings.xml @@ -260,7 +260,6 @@ El archivo no esta mas disponible en este Servidor Cuentas Añadir cuenta - Conexión segura redireccionada a una ruta insegura. Registro Enviar Historial Aplicación para enviar registros no encontrada. Instale una aplicación de correo! @@ -275,6 +274,7 @@ El archivo ya existe en la carpeta destino Un error ocurrió intentando mover el archivo o carpeta para mover este archivo + El archivo ya existe en la carpeta destino Subida Instantánea Seguridad Dirección de subida del video diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 8b0d0ad1..88566cd3 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -291,7 +291,7 @@ Este archivo ya no se encuentra en el servidor Cuentas Agregar cuenta - La conexión segura está siendo desviada por una ruta insegura. + La conexión segura está siendo redirigida por una ruta insegura. Registros Enviar historial No se ha encontrado una app para enviar logs. Instale la app mail! @@ -307,6 +307,11 @@ El archivo ya existe en la carpeta de destino Hubo un error al tratar de mover este archivo o carpeta para mover este archivo + No se puede copiar. Revise si el archivo existe + No se puede copiar una carpeta dentro de una de sus subcarpetas. + El fichero ya existe en el directorio de destino + Hubo un error al tratar de copiar este archivo o carpeta + para copiar este archivo Subidas instantáneas Seguridad Guardar videos subidos en la carpeta: diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml index 7c94bca4..a4841a42 100644 --- a/res/values-et-rEE/strings.xml +++ b/res/values-et-rEE/strings.xml @@ -206,6 +206,8 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Kas sa tõesti soovid eemaldada %1$s ja selle sisu? Ainult kohalik Ainult kohalik + Serverist + Kaugfail & kohalik Eemaldamine oli edukas Eemaldamine ebaõnnestus Sisesta uus nimi @@ -260,6 +262,8 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Failikonflikt Millist faili sa soovid säilitada? Kui valid mõlemad versioonid, siis lisatakse kohaliku faili nimele number. Säilita mõlemad + kohalik versioon + serveri versioon Pildi eelvaade Seda pilti ei saa näidata %1$s ei suudetud kopeerida kohalikku kataloogi %2$s @@ -291,7 +295,7 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Fail ei ole serveris enam kättesaadav Kontod Lisa konto - Turvaline ühendus suunatakse läbi turvamata ühenduse. + Turvalist ühendust suunatakse läbi turvamata ühenduse. Logid Saada ajalugu Logide saatmise rakendust ei leitud. Paigalda postirakendus! @@ -307,6 +311,11 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi See fail on juba sihtkaustas olemas Selle faili või kausta liigutamisel tekkis tõrge selle faili liigutamiseks + Kopeerimine ebaõnnestus. Palun kontrolli, kas fail on olemas + Kausta ei saa kopeerida tema enda alamkausta + See fail on juba sihtkaustas olemas + Selle faili või kausta kopeerimisel tekkis tõrge + et kopeerida seda faili Kohesed üleslaadimised Turvalisus Video üleslaadimise asukoht diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 8c14aefe..a532d2ca 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -259,7 +259,7 @@ Mesedez, baimendu berriz Fitxategia jadanik ez dago eskuragarri zerbitzarian Kontuak Gehitu kontua - Konexio segurua birbideratu da segurua ez den bide batera. + Konexio segurua birbideratu da segurua ez den bide batetik. Egunkariak Bidali Historia Egunkariak bidaltzeko aplikaziorik ez da aurkitu. Instalatu posta aplikazioa! @@ -274,6 +274,7 @@ Mesedez, baimendu berriz Fitxategia dagoeneko existitzen da helburuko karpetan Errore bat gertatu da fitxategi edo karpeta hau mugitzen saiatzerakoan fitxategi hau mugitzeko + Fitxategia dagoeneko existitzen da helburuko karpetan Berehalako Igoerak Segurtasuna Bideo Igoera Bidea diff --git a/res/values-fi-rFI/strings.xml b/res/values-fi-rFI/strings.xml index f12292e6..41d39371 100644 --- a/res/values-fi-rFI/strings.xml +++ b/res/values-fi-rFI/strings.xml @@ -290,6 +290,9 @@ Siirto ei onnistu. Tarkista, ettei tiedostoa ole jo olemassa Tiedosto on jo olemassa kohdekansiossa Tämän tiedoston tai kansion siirtoa yrittäessä tapahtui virhe + Kopiointi epäonnistui. Tarkista onko tiedostoa olemassa + Tiedosto on jo kohdekansiossa. + Tätä tiedostoa tai kansiota kopioitaessa tapahtui virhe Välittömät lähetykset Tietoturva jaettu diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index a502db5f..d241bd29 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -278,7 +278,7 @@ Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxq Vous devez saisir un mot de passe Envoyer Copier le lien - Copié dans le presse-papiers + Copié dans le presse-papier Erreur critique : impossible de réaliser des opérations Une erreur est survenue pendant la connexion au serveur. Une erreur est survenue pendant l\'attente du serveur. L\'opération n\'a pas pu être effectuée @@ -311,6 +311,11 @@ Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxq Le fichier existe déjà dans le dossier de destination Une erreur est survenue lors de la tentative de déplacement de ce fichier ou dossier de déplacer ce fichier + Impossible de copier. Vérifiez que le fichier existe + Il n\'est pas possible de copier un dossier vers un de ses descendants + Fichier déjà existant dans le dossier de destination + Une erreur est survenue lors de la tentative de copie de ce fichier ou dossier + de copier ce fichier Téléversement immédiat Sécurité Répertoire de téléversement des vidéos diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index 18ae1a9e..51aa4a40 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -291,7 +291,7 @@ Descárgueo de aquí: %2$s O ficheiro xa non está dispoñíbel no servidor Contas Engadir unha conta - A conexión segura está a ser redirixida a unha ruta non segura. + A conexión segura está a ser redirixida a través dunha ruta non segura. Rexistros Enviar o historial Non se atopou unha aplicación para enviar os rexistros. Instale unha aplicación de correo! @@ -307,6 +307,7 @@ Descárgueo de aquí: %2$s Este ficheiro xa existe no cartafol de destino Produciuse un erro ao tentar mover este ficheiro ou cartafol. para mover este ficheiro + Este ficheiro xa existe no cartafol de destino Envío instantáneo Seguridade Enviar a ruta do vídeo diff --git a/res/values-he/strings.xml b/res/values-he/strings.xml index f10f2d7d..1a62cc2d 100644 --- a/res/values-he/strings.xml +++ b/res/values-he/strings.xml @@ -250,6 +250,7 @@ הקובץ אינו זמין יותר על השרת חשבונות הוספת חשבון + חיבור מאובטח מנותב דרך נתיב לא מאובטח בחירה אבטחה כתובת שרת diff --git a/res/values-id/strings.xml b/res/values-id/strings.xml index a23b66e1..8515df22 100644 --- a/res/values-id/strings.xml +++ b/res/values-id/strings.xml @@ -291,7 +291,6 @@ Berkas tidak lagi tersedia pada server Akun Tambah akun - Sambungan aman dialihkan ke rute yang tidak aman. Log Kirim Riwayat Tidak ada apl untuk mengirim log. Instal apl mail! @@ -307,6 +306,7 @@ Berkas sudah ada didalam folder tujuan Terjadi kesalahan saat mencoba memindahkan berkas atau folder ini untuk memindahkan berkas ini + Berkas sudah ada didalam folder tujuan Unggah Cepat Keamanan Unggah Lokasi Video diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 09b89aaf..874bbe6f 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -291,7 +291,7 @@ Il file non è più disponibile sul server Account Aggiungi account - La connessione sicura è rediretta su un percorso non sicuro. + La connessione sicura è rediretta attraverso un percorso non sicuro. Registri Invia cronologia Non è stata trovata alcuna applicazione per l\'invio dei registri. Installa l\'applicazione mail! @@ -307,6 +307,11 @@ Il file esiste già nella cartella di destinazione Si è verificato un errore durante il tentativo di spostare il file o la cartella per spostare questo file + Impossibile copiare. Assicurati che il file esista + Impossibile copiare una cartella in una cartella inferiore + Il file esiste già nella cartella di destinazione + Si è verificato un errore durante il tentativo di copiare il file o la cartella + per copiare questo file Caricamenti istantanei Protezione Percorso di caricamento video diff --git a/res/values-ja-rJP/strings.xml b/res/values-ja-rJP/strings.xml index c6f90c20..b51e644b 100644 --- a/res/values-ja-rJP/strings.xml +++ b/res/values-ja-rJP/strings.xml @@ -288,7 +288,7 @@ ファイルはサーバー上で利用できません アカウント アカウントを追加 - 暗号化接続は非暗号化接続にリダイレクトされました。 + 暗号化されていない接続を経て、暗号化接続へリダイレクトされました。 ログ ログを送信 ログを送信するアプリが見つかりませんでした。メールアプリをインストールしてください。 @@ -304,6 +304,7 @@ そのファイルは宛先フォルダーにすでに存在します。 このファイルまたはフォルダーを移動する際にエラーが発生しました このファイルを移動 + そのファイルは宛先フォルダーにすでに存在します。 自動アップロード セキュリティ 動画のアップロードパス diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index efc3c1a2..d3a813ac 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -284,7 +284,6 @@ 이 파일을 서버에서 더 이상 사용할 수 없습니다 계정 계정 추가 - 보안 연결이 안전하지 않은 경로로 넘어갑니다. 로그 과거 기록 보내기 로그를 보낼 앱이 없습니다. 메일 앱을 설치하십시오! @@ -300,6 +299,7 @@ 파일이 이미 대상 폴더에 존재합니다 이 파일이나 폴더를 이동하는 중 오류가 발생하였습니다 이 파일을 이동할 + 파일이 이미 대상 폴더에 존재합니다 즉시 업로드 보안 동영상 업로드 경로 diff --git a/res/values-lb/strings.xml b/res/values-lb/strings.xml index 99468420..80ccbff0 100644 --- a/res/values-lb/strings.xml +++ b/res/values-lb/strings.xml @@ -211,7 +211,6 @@ De Fichier ass net méi um Server disponibel Konten Kont dobäisetzen - Sécher Connectioun gëtt op eng onsécher Route ëmgeleet. Protokoller Historique schécken Keng App fonnt fir d\'Protokoller ze schécken. Installéier eng Mail-App! @@ -227,6 +226,7 @@ De Fichier existéiert schonn am Zildossier Beim Réckele vun dësem Fichier oder Dossier ass e Feeler opgetrueden fir dëse Fichier ze réckelen + De Fichier existéiert schonn am Zildossier Direkt eropgeluede Fichieren Sécherheet Pad fir d\'Eropluede vun de Videoen diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 8c842a2f..1c6f96fd 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -276,7 +276,6 @@ Датотеката веќе не е достапна на серверот Сметки Додади сметка - Сигурната конекција е преусмерена на несигурна рута. Логови Прати историја Нема апликација за праќање на логови. Инсталирајте апликација за пошта! @@ -292,6 +291,7 @@ Датотеката веќе постои во целната папка Се случи грешка кога пробував да ја преместам оваа датотека или папка да ја преместам оваа датотека + Датотеката веќе постои во целната папка Инстант прикачувања Безбедност Прикачи патека на видео diff --git a/res/values-nb-rNO/strings.xml b/res/values-nb-rNO/strings.xml index cb99ece7..43b1ba84 100644 --- a/res/values-nb-rNO/strings.xml +++ b/res/values-nb-rNO/strings.xml @@ -285,7 +285,7 @@ Filen finnes ikke pÃ¥ serveren lenger Kontoer Legg til en konto - Sikker forbindelse er omdirigert til en usikker rute. + Sikker tilkobling videresendes gjennom en usikker rute. Logger Send historikk Ingen app for sending av logger funnet. Installer epost-app! @@ -301,6 +301,7 @@ Filen finnes allerede i mÃ¥lmappen En feil oppstod ved flytting av denne filen eller mappen Ã¥ flytte denne filen + Filen finnes allerede i mÃ¥lmappen Umiddelbare opplastinger Sikkerhet Sti til video-opplasting diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 8e1e5eb1..88eef421 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -294,7 +294,7 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar Dit bestand is niet langer beschikbaar op de server Accounts Toevoegen account - De beveiligde verbinding is omgeleid naar een onveilige route. + De beveiligde verbinding is omgeleid via een onveilige route. Logs Verstuur geschiedenis Geen app voor versturen van logs gevonden. Installeer de mail app! @@ -310,6 +310,11 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar Het bestand bestaat al in de doelmap Er trad een fout op bij uw poging dit bestand of deze map te verplaatsen om dit bestand te verplaatsen + Kan niet kopiëren. Ga na of het bestand wel bestaat + De map kan niet naar een onderliggende map worden gekopieerd + Het bestand bestaat al in de doelmap + Er trad een fout op bij uw poging dit bestand of deze map te kopiëren + om dit bestand te kopiëren Directe uploads Beveiliging Upload Video Pad diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 869c16e9..95168bdc 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 @@ -295,11 +304,19 @@ Plik istnieje już w folderze docelowym Pojawił się błąd podczas próby przeniesienia tego pliku lub folderu aby przenieść ten plik + Plik istnieje już w folderze docelowym Automatyczne wysyłanie 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-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml index 013757ca..8102092d 100644 --- a/res/values-pt-rBR/strings.xml +++ b/res/values-pt-rBR/strings.xml @@ -273,7 +273,7 @@ Digite uma senha Você deve digitar uma senha Enviar - Copiar o link + Copiar link Copiado para área de transferência Erro crítico: não pode executar operações Ocorreu um erro durante a conexão com o servidor. @@ -291,7 +291,7 @@ Este arquivo não mais está disponível neste servidor Contas Adicionar uma conta - Conexão segura esta redirecionada para uma rota não segura. + A conexão segura está redirecionada através de uma rota insegura. Logs Enviar Histórico Não foi encontrado nenhum app para envio de logs. Instale o mail app! @@ -307,6 +307,11 @@ O arquivo já existe na pasta de destino Ocorreu um erro ao tentar mover este arquivo ou pasta mover este arquivo + Não é possível copiar. Por favor verifique se o arquivo existe + Não é possível copiar uma pasta em uma descendente + O arquivo já existe na pasta de destino + Ocorreu um erro ao tentar copiar este arquivo ou pasta + para copiar este arquivo Envios Instantâneos Segurança Enviar o Caminho do Vídeo diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 83c1f5d4..1d91a6b2 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -201,6 +201,8 @@ Deseja realmente remover %1$s e o seu conteúdo? Apenas localmente Apenas localmente + Do servidor + Remoto & local Removido com sucesso Não foi possível remover Introduza um novo nome @@ -255,6 +257,8 @@ Conflito de ficheiro Quais os ficheiros que pretende manter? Se selecionar ambas as versões, o ficheiro local irá ter um número adicionado ao seu nome. Manter ambos + versão local + versão servidor Pré-Visualizar imagem Esta imagem não pode ser mostrada Não foi possível copiar %1$s para a pasta local %2$s @@ -285,7 +289,7 @@ O ficheiro não está mais disponível no servidor Contas Adicionar conta - Ligação segura é redireccionada para um caminho inseguro. + Uma ligação segura foi redireccionada por uma rota insegura. Registos de Alterações Enviar Histórico Não foi encontrado o aplicativo para envio de registos . Instale app e-mail! @@ -301,6 +305,7 @@ O ficheiro já existe na pasta de destino Ocorreu um ocorreu quando tentava mover este ficheiro ou pasta para mover este ficheiro + O ficheiro já existe na pasta de destino Envios Instantâneos Segurança Envio do Caminho do Vídeo diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index 8be2ea06..e5399242 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -271,7 +271,7 @@ A apărut o eroare în timp ce încerca să departajeze sau unshare acest fișier sau folder IntroduceÅ£i parola Trebuie să introduci o parolă - Expediază + Trimite Link copiat Copiat în clipboard Eroare critică: nu se pot executa operațiunile @@ -290,7 +290,6 @@ Fișierul nu mai este disponibil pe server Conturi Adaugă cont - Conexiunea securizată este redirecționată către un traseu neasigurat. Înregistrări Trimite Istoria App-ul de trimitere a inregistrărilor nu a fost găsit. Instalează mail app-ul! @@ -306,6 +305,7 @@ Fișierul există deja în dosarul de destinație O eroare apare la transferarea acestui fișier sau dosar pentru a muta acest fișier + Fișierul există deja în dosarul de destinație Încărcări instante Securitate Calea de încărcare Video @@ -313,6 +313,7 @@ partajat cu tine %1$s a partajat fișierul \"%2$s\" cu tine + „%1$s” a fost partajat cu dumneavoastră Reîmprospătează conexiunea Adresa server-ului Memorie insuficientă diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index fdad0bef..5e4e3e36 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -288,7 +288,7 @@ Этот файл больше недоступен на сервере Учётные записи Добавить учетную запись - Защищённое соединение перенаправлено по небезопасному маршруту + Безопасное соединение перенаправлено через небезопасный маршрут. Журналы История Отправлений Приложение для отправки журнала не найдено. Установите почтовое приложение! @@ -304,6 +304,7 @@ Файл уже существует в каталоге назначения Произошла ошибка при попытке перемещения этого файла или каталога для перемещения этого файла + Файл уже существует в каталоге назначения Мгновенные загрузки Безопасность Путь для загрузки Видео diff --git a/res/values-sk-rSK/strings.xml b/res/values-sk-rSK/strings.xml index 7cc28c22..eb5fdf5e 100644 --- a/res/values-sk-rSK/strings.xml +++ b/res/values-sk-rSK/strings.xml @@ -277,7 +277,7 @@ Súbor už na serveri nie je dostupný Účty PridaÅ¥ účet - Zabezpečené pripojenie je presmerované na nezabezpečenú trasu. + Zabezpečené spojenie je presmerované nezabezpečenou cestou. Logy OdoslaÅ¥ históriu Nebola nájdená aplikácia pre odosielanie log protokolov. NainÅ¡talujte si mailovú aplikáciu! @@ -293,6 +293,7 @@ Súbor už v cieľovom priečinku existuje Pri pokuse o presun tohoto súboru alebo priečinka nastala chyba pre presun tohoto súboru + Súbor už v cieľovom priečinku existuje Okamžité nahratie Zabezpečenie Cesta pre nahrávanie videí diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 2351338b..e58ba5b7 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -307,6 +307,7 @@ Datoteka v ciljni mapi že obstaja. PriÅ¡lo je do napake med premikanjem datoteke v mapo med premikanjem datoteke + Datoteka v ciljni mapi že obstaja. TakojÅ¡nje poÅ¡iljanje v oblak Varnost Pot videa za poÅ¡iljanje diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 01dfce6c..4ed55083 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -285,7 +285,6 @@ Фајл није више доступан на серверу Налози Додај налог - Безбедна веза је преусмерена на небезбедну руту Записници Историјат слања Нема начина за слање записника. Инсталирајте апликацију е-поште! @@ -301,6 +300,7 @@ Фајл већ постоји у одредишној фасцикли Дошло је до грешке при премештању фајла или фасцикле да преместите овај фајл + Фајл већ постоји у одредишној фасцикли Тренутна отпремања Безбедност Путања отпремања видеа diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 98de6de6..5a6cdba2 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -265,7 +265,6 @@ Filen är inte längre tillgänglig pÃ¥ servern Konton Lägg till konto - Säker anslutning är omdirigerad till en osäker väg. Loggar Skickat historik Ingen app för att skicka loggar hittades. Installera mail appen! @@ -281,6 +280,7 @@ Filen existerar redan i destinationsmappen Ett fel uppstod vid försök att flytta denna fil eller mapp att flytta den här filen + Filen existerar redan i destinationsmappen Direktuppladning Säkerhet Uppladdnings-sökväg för video diff --git a/res/values-th-rTH/strings.xml b/res/values-th-rTH/strings.xml index c13c48ee..836a2af2 100644 --- a/res/values-th-rTH/strings.xml +++ b/res/values-th-rTH/strings.xml @@ -289,7 +289,6 @@ ไฟล์ไม่พร้อมใช้งานบนเซิร์ฟเวอร์ บัญชี เพิ่มบัญชี - การเชื่อมต่อที่ปลอดภัยถูกเปลี่ยนเส้นทางไปยังเส้นทางที่ไม่ปลอดภัย บันทึก ส่งประวัติ ไม่พบการส่งบันทึกของแอพฯ ติดตั้งแอพฯเมล! @@ -305,6 +304,7 @@ มีไฟล์อยู่แล้วในโฟลเดอร์ปลายทาง เกิดข้อผิดพลาดขณะพยายามที่จะย้ายไฟล์หรือโฟลเดอร์นี้ เพื่อย้ายไฟล์นี้ + มีไฟล์อยู่แล้วในโฟลเดอร์ปลายทาง อัพโหลดทันที ความปลอดภัย อัพโหลดเส้นทางวิดีโอ diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index a9879619..d682fe65 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -202,6 +202,8 @@ Gerçekten %1$s ve içeriğini kaldırmak istediğinizden emin misiniz? Sadece yerel Sadece yerel + Sunucudan + Uzak ve yerel Kaldırma başarılı Kaldırma başarısız Yeni bir isim girin @@ -253,7 +255,11 @@ Fotoğrafları sadece kablosuzda (WiFi) yükle Videoları sadece kablosuzda (WiFi) yükle /AnındaYükle + Dosya çakışması + Hangi dosyaları saklamak istiyorsunuz? Her ikisini de saklamayı seçerseniz yerel dosyanın adına bir sayı eklenecek. İkisini de koru + yerel sürüm + sunucu sürümü Resim önizleme Bu resim gösterilemiyor %1$s, %2$s yerel klasörüne kopyalanamadı @@ -285,7 +291,7 @@ Bu dosya artık sunucuda mevcut değil Hesaplar Hesap ekle - Güvenli bağlantı, güvenli olmayan bir rotaya yönlendirildi. + Güvenli bağlantı, güvenli olmayan bir rotaya yönlendiriliyor. Günlükler Geçmişi Gönder Kayıtları göndermek için uygulama bulunamadı. E-posta uygulamasını yükleyin! @@ -301,6 +307,7 @@ Dosya zaten hedef klasörde mevcut Bu dosya veya klasörü taşımaya çalışılırken bir hata oluştu bu dosyayı taşımak için + Dosya zaten hedef klasörde mevcut Anında Yüklemeler Güvenlik Video Yükleme Yolu @@ -308,6 +315,7 @@ sizinle paylaştı %1$s, sizinle \"%2$s\" paylaşımını yaptı + \"%1$s\" sizinle paylaşıldı Bağlantıyı yenile Sunucu adresi Yeterli hafıza yok diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index d036312f..c3bd6a09 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -288,6 +288,7 @@ Файл вже існує в теці призначення Виникла помилка при спробі перемістити файл або теку перемістити цей файл + Файл вже існує в теці призначення Миттєво завантаження Безпека Шлях завантаження відео diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index fc58f953..ca8e51a2 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 @@ -286,7 +290,7 @@ 该文件在服务器上不可用 账号 添加账号 - 安全连接被重定向到非安全路径. + 安全连接是通过一个非安全路由定向的。 日志 发送历史 未找到可以发送日志的程序。请安装 mail! @@ -302,6 +306,7 @@ 该文件已经存在在目标文件夹 尝试移动该文件或文件夹时发生错误 移动该文件 + 该文件已经存在在目标文件夹 即时上传 安全 视频上传路径 diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index 21b43f13..7810b88c 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -72,7 +72,7 @@ 389 KB 2012/05/18 12:23 PM 12:23:45 - 傳送 + 發送 複製連結 帳號 diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 69701a58..db564b16 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -291,7 +291,6 @@ 這個檔案已經不存在於伺服器中 帳號 新增帳號 - 安全連線被轉向到一個非安全的連線 紀錄 傳送歷史記錄 找不到可以傳送記錄的電子郵件程式. 請安裝電子郵件軟體! @@ -307,6 +306,7 @@ 這個檔案已經存在於目的目錄中 在移動檔案或目錄時發生了錯誤 移動這個檔案 + 這個檔案已經存在於目的目錄中 即時上傳 安全性 影片上傳路徑 diff --git a/res/values/strings.xml b/res/values/strings.xml index cc3587d1..8f1aec21 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,31 @@ Enter a password You must enter a password - Send + Send + + Copy link + Copied to clipboard - Copy link - Copied to clipboard + Critical error: cannot perform operations - 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 + 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 + 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 +325,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/datamodel/OCFile.java b/src/com/owncloud/android/datamodel/OCFile.java index 2aa5dbc0..4baf1ea5 100644 --- a/src/com/owncloud/android/datamodel/OCFile.java +++ b/src/com/owncloud/android/datamodel/OCFile.java @@ -22,9 +22,9 @@ package com.owncloud.android.datamodel; import android.os.Parcel; import android.os.Parcelable; +import android.webkit.MimeTypeMap; import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.utils.FileStorageUtils; import java.io.File; @@ -289,11 +289,13 @@ public class OCFile implements Parcelable, Comparable { /** * Sets the name of the file *

- * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root directory + * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root + * directory */ public void setFileName(String name) { Log_OC.d(TAG, "OCFile name changin from " + mRemotePath); - if (name != null && name.length() > 0 && !name.contains(PATH_SEPARATOR) && !mRemotePath.equals(ROOT_PATH)) { + if (name != null && name.length() > 0 && !name.contains(PATH_SEPARATOR) && + !mRemotePath.equals(ROOT_PATH)) { String parent = (new File(getRemotePath())).getParent(); parent = (parent.endsWith(PATH_SEPARATOR)) ? parent : parent + PATH_SEPARATOR; mRemotePath = parent + name; @@ -454,7 +456,7 @@ public class OCFile implements Parcelable, Comparable { @Override public int describeContents() { - return ((Object) this).hashCode(); + return super.hashCode(); } @Override @@ -483,8 +485,11 @@ public class OCFile implements Parcelable, Comparable { @Override public String toString() { - String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, parentId=%s, favorite=%s etag=%s]"; - asString = String.format(asString, Long.valueOf(mId), getFileName(), mMimeType, isDown(), mLocalPath, mRemotePath, Long.valueOf(mParentId), Boolean.valueOf(mFavorite), mEtag); + String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, " + + "parentId=%s, favorite=%s etag=%s]"; + asString = String.format(asString, Long.valueOf(mId), getFileName(), mMimeType, isDown(), + mLocalPath, mRemotePath, Long.valueOf(mParentId), Boolean.valueOf(mFavorite), + mEtag); return asString; } @@ -540,7 +545,26 @@ public class OCFile implements Parcelable, Comparable { */ public boolean isImage() { return ((mMimeType != null && mMimeType.startsWith("image/")) || - FileStorageUtils.getMimeTypeFromName(mRemotePath).startsWith("image/")); + getMimeTypeFromName().startsWith("image/")); + } + + /** + * @return 'True' if the file is simple text (e.g. not application-dependent, like .doc or .docx) + */ + public boolean isText() { + return ((mMimeType != null && mMimeType.startsWith("text/")) || + getMimeTypeFromName().startsWith("text/")); + } + + public String getMimeTypeFromName() { + String extension = ""; + int pos = mRemotePath.lastIndexOf('.'); + if (pos >= 0) { + extension = mRemotePath.substring(pos + 1); + } + String result = MimeTypeMap.getSingleton(). + getMimeTypeFromExtension(extension.toLowerCase()); + return (result != null) ? result : ""; } /** diff --git a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index 362106e6..ce8bfd4a 100644 --- a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@ -34,8 +34,8 @@ import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.Canvas; -import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.ThumbnailUtils; import android.net.Uri; @@ -290,9 +290,6 @@ public class ThumbnailsCacheManager { GetMethod get = new GetMethod(uri); int status = mClient.executeMethod(get); if (status == HttpStatus.SC_OK) { -// byte[] bytes = get.getResponseBody(); -// Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, -// bytes.length); InputStream inputStream = get.getResponseBodyAsStream(); Bitmap bitmap = BitmapFactory.decodeStream(inputStream); thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); @@ -326,16 +323,9 @@ public class ThumbnailsCacheManager { px, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(resultBitmap); - Bitmap checker = BitmapFactory.decodeResource(MainApp.getAppContext().getResources(), - R.drawable.checker_16_16); - - BitmapDrawable background; - background = new BitmapDrawable(MainApp.getAppContext().getResources(), checker); - - background.setBounds(0, 0, px, px); - background.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); - background.draw(c); + c.drawColor(MainApp.getAppContext().getResources(). + getColor(R.color.background_color)); c.drawBitmap(bitmap, 0, 0, null); return resultBitmap; 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 9c1d0661..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; @@ -98,6 +99,7 @@ import com.owncloud.android.ui.fragment.OCFileListFragment; import com.owncloud.android.ui.preview.PreviewImageActivity; import com.owncloud.android.ui.preview.PreviewImageFragment; import com.owncloud.android.ui.preview.PreviewMediaFragment; +import com.owncloud.android.ui.preview.PreviewTextFragment; import com.owncloud.android.ui.preview.PreviewVideoActivity; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.ErrorMessageAdapter; @@ -106,7 +108,6 @@ import com.owncloud.android.utils.UriUtils; import java.io.File; - /** * Displays, what files the user has available in his ownCloud. */ @@ -115,6 +116,8 @@ public class FileDisplayActivity extends HookActivity implements FileFragment.ContainerActivity, OnSslUntrustedCertListener, OnEnforceableRefreshListener { + + private SyncBroadcastReceiver mSyncBroadcastReceiver; private UploadFinishReceiver mUploadFinishReceiver; private DownloadFinishReceiver mDownloadFinishReceiver; @@ -134,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(); @@ -141,7 +145,7 @@ public class FileDisplayActivity extends HookActivity private static final String TAG_SECOND_FRAGMENT = "SECOND_FRAGMENT"; private OCFile mWaitingToPreview; - + private boolean mSyncInProgress = false; private static String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT"; @@ -164,7 +168,7 @@ public class FileDisplayActivity extends HookActivity Intent initObserversIntent = FileObserverService.makeInitIntent(this); startService(initObserversIntent); } - + /// Load of saved instance state if(savedInstanceState != null) { mWaitingToPreview = (OCFile) savedInstanceState.getParcelable( @@ -172,18 +176,17 @@ public class FileDisplayActivity extends HookActivity mSyncInProgress = savedInstanceState.getBoolean(KEY_SYNC_IN_PROGRESS); mWaitingToSend = (OCFile) savedInstanceState.getParcelable( FileDisplayActivity.KEY_WAITING_TO_SEND); - } else { mWaitingToPreview = null; mSyncInProgress = false; mWaitingToSend = null; - } + } /// USER INTERFACE // Inflate and set the layout view setContentView(R.layout.files); - + // Navigation Drawer initDrawer(); @@ -210,7 +213,7 @@ public class FileDisplayActivity extends HookActivity mProgressBar.setIndeterminate(mSyncInProgress); // always AFTER setContentView(...) ; to work around bug in its implementation - + setBackgroundText(); Log_OC.v(TAG, "onCreate() end"); @@ -231,8 +234,8 @@ public class FileDisplayActivity extends HookActivity } /** - * Called when the ownCloud {@link Account} associated to the Activity was just updated. - */ + * Called when the ownCloud {@link Account} associated to the Activity was just updated. + */ @Override protected void onAccountSet(boolean stateWasRecovered) { super.onAccountSet(stateWasRecovered); @@ -276,7 +279,7 @@ public class FileDisplayActivity extends HookActivity if (file.isFolder()) { startSyncFolderOperation(file, false); } - + } else { updateFragmentsVisibility(!file.isFolder()); updateActionBarTitleAndHomeButton(file.isFolder() ? null : file); @@ -284,36 +287,38 @@ public class FileDisplayActivity extends HookActivity } } - private void createMinFragments() { OCFileListFragment listOfFiles = new OCFileListFragment(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.left_fragment_container, listOfFiles, TAG_LIST_OF_FILES); transaction.commit(); } - + private void initFragmentsWithFile() { if (getAccount() != null && getFile() != null) { /// First fragment - OCFileListFragment listOfFiles = getListOfFilesFragment(); + OCFileListFragment listOfFiles = getListOfFilesFragment(); if (listOfFiles != null) { listOfFiles.listDirectory(getCurrentDir()); // TODO Enable when "On Device" is recovered // listOfFiles.listDirectory(getCurrentDir(), MainApp.getOnlyOnDevice()); + } else { Log_OC.e(TAG, "Still have a chance to lose the initializacion of list fragment >("); } - + /// Second fragment - OCFile file = getFile(); + OCFile file = getFile(); Fragment secondFragment = chooseInitialSecondFragment(file); if (secondFragment != null) { setSecondFragment(secondFragment); updateFragmentsVisibility(true); updateActionBarTitleAndHomeButton(file); - + } else { cleanSecondFragment(); + if (file.isDown() && PreviewTextFragment.canBePreviewed(file)) + startTextPreview(file); } } else { @@ -330,7 +335,7 @@ public class FileDisplayActivity extends HookActivity private Fragment chooseInitialSecondFragment(OCFile file) { Fragment secondFragment = null; if (file != null && !file.isFolder()) { - if (file.isDown() && PreviewMediaFragment.canBePreviewed(file) + if (file.isDown() && PreviewMediaFragment.canBePreviewed(file) && file.getLastSyncDateForProperties() > 0 // temporal fix ) { int startPlaybackPosition = @@ -340,9 +345,11 @@ public class FileDisplayActivity extends HookActivity secondFragment = new PreviewMediaFragment(file, getAccount(), startPlaybackPosition, autoplay); + } else if (file.isDown() && PreviewTextFragment.canBePreviewed(file)) { + secondFragment = null; } else { - secondFragment = FileDetailFragment.newInstance(file, getAccount()); - } + secondFragment = FileDetailFragment.newInstance(file, getAccount()); + } } return secondFragment; } @@ -351,10 +358,10 @@ public class FileDisplayActivity extends HookActivity /** * Replaces the second fragment managed by the activity with the received as * a parameter. - * - * Assumes never will be more than two fragments managed at the same time. - * - * @param fragment New second Fragment to set. + *

+ * Assumes never will be more than two fragments managed at the same time. + * + * @param fragment New second Fragment to set. */ private void setSecondFragment(Fragment fragment) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); @@ -395,7 +402,7 @@ public class FileDisplayActivity extends HookActivity Fragment listOfFiles = getSupportFragmentManager().findFragmentByTag( FileDisplayActivity.TAG_LIST_OF_FILES); if (listOfFiles != null) { - return (OCFileListFragment)listOfFiles; + return (OCFileListFragment) listOfFiles; } Log_OC.wtf(TAG, "Access to unexisting list of files fragment!!"); return null; @@ -405,7 +412,7 @@ public class FileDisplayActivity extends HookActivity Fragment second = getSupportFragmentManager().findFragmentByTag( FileDisplayActivity.TAG_SECOND_FRAGMENT); if (second != null) { - return (FileFragment)second; + return (FileFragment) second; } return null; } @@ -459,6 +466,9 @@ public class FileDisplayActivity extends HookActivity if (PreviewMediaFragment.canBePreviewed(mWaitingToPreview)) { startMediaPreview(mWaitingToPreview, 0, true); detailsFragmentChanged = true; + } else if (PreviewTextFragment.canBePreviewed(mWaitingToPreview)) { + startTextPreview(mWaitingToPreview); + detailsFragmentChanged = true; } else { getFileOperationsHelper().openFile(mWaitingToPreview); } @@ -501,6 +511,7 @@ public class FileDisplayActivity extends HookActivity dialog.show(getSupportFragmentManager(), DIALOG_CREATE_FOLDER); break; } + case R.id.action_sync_account: { startSynchronization(); break; @@ -509,7 +520,6 @@ public class FileDisplayActivity extends HookActivity UploadSourceDialogFragment dialog = UploadSourceDialogFragment.newInstance(getAccount()); dialog.show(getSupportFragmentManager(), DIALOG_UPLOAD_SOURCE); - break; } case android.R.id.home: { @@ -617,17 +627,30 @@ public class FileDisplayActivity extends HookActivity requestMultipleUpload(data, resultCode); } else if (requestCode == ACTION_MOVE_FILES && resultCode == RESULT_OK){ + final Intent fData = data; + final int fResultCode = resultCode; + getHandler().postDelayed( + new Runnable() { + @Override + public void run() { + requestMoveOperation(fData, fResultCode); + } + }, + DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS + ); + + } else if (requestCode == ACTION_COPY_FILES && resultCode == RESULT_OK) { final Intent fData = data; - final int fResultCode = resultCode; + final int fResultCode = resultCode; getHandler().postDelayed( - new Runnable() { - @Override - public void run() { - requestMoveOperation(fData, fResultCode); - } - }, - DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS + new Runnable() { + @Override + public void run() { + requestCopyOperation(fData, fResultCode); + } + }, + DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS ); } else { @@ -735,9 +758,9 @@ public class FileDisplayActivity extends HookActivity /** * Request the operation for moving the file/folder from one path to another - * - * @param data Intent received - * @param resultCode Result code received + * + * @param data Intent received + * @param resultCode Result code received */ private void requestMoveOperation(Intent data, int resultCode) { OCFile folderToMoveAt = (OCFile) data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER); @@ -745,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()){ @@ -782,18 +817,15 @@ public class FileDisplayActivity extends HookActivity Log_OC.v(TAG, "onSaveInstanceState() end"); } - @Override protected void onResume() { Log_OC.v(TAG, "onResume() start"); super.onResume(); - // refresh Navigation Drawer account list mNavigationDrawerAdapter.updateAccountList(); - // refresh list of files refreshListOfFilesFragment(); @@ -819,8 +851,9 @@ public class FileDisplayActivity extends HookActivity downloadIntentFilter.addAction(FileDownloader.getDownloadFinishMessage()); mDownloadFinishReceiver = new DownloadFinishReceiver(); registerReceiver(mDownloadFinishReceiver, downloadIntentFilter); - + Log_OC.v(TAG, "onResume() end"); + } @@ -840,7 +873,7 @@ public class FileDisplayActivity extends HookActivity unregisterReceiver(mDownloadFinishReceiver); mDownloadFinishReceiver = null; } - + super.onPause(); Log_OC.v(TAG, "onPause() end"); } @@ -864,12 +897,12 @@ public class FileDisplayActivity extends HookActivity FileSyncAdapter.EXTRA_RESULT); boolean sameAccount = (getAccount() != null && accountName.equals(getAccount().name) && getStorageManager() != null); - + if (sameAccount) { - + if (FileSyncAdapter.EVENT_FULL_SYNC_START.equals(event)) { mSyncInProgress = true; - + } else { OCFile currentFile = (getFile() == null) ? null : getStorageManager().getFileByPath(getFile().getRemotePath()); @@ -885,8 +918,9 @@ public class FileDisplayActivity extends HookActivity synchFolderRemotePath), Toast.LENGTH_LONG) .show(); + browseToRoot(); - + } else { if (currentFile == null && !getFile().isFolder()) { // currently selected file was removed in the server, and now we @@ -907,19 +941,19 @@ public class FileDisplayActivity extends HookActivity } setFile(currentFile); } - + mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED .equals(event)); if (RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED. - equals(event) && - /// TODO refactor and make common - synchResult != null && !synchResult.isSuccess() && - (synchResult.getCode() == ResultCode.UNAUTHORIZED || - synchResult.isIdPRedirection() || - (synchResult.isException() && synchResult.getException() - instanceof AuthenticatorException))) { + equals(event) &&/// TODO refactor and make common + + synchResult != null && !synchResult.isSuccess() && + (synchResult.getCode() == ResultCode.UNAUTHORIZED || + synchResult.isIdPRedirection() || + (synchResult.isException() && synchResult.getException() + instanceof AuthenticatorException))) { try { @@ -928,7 +962,6 @@ public class FileDisplayActivity extends HookActivity new OwnCloudAccount(getAccount(), context); client = (OwnCloudClientManagerFactory.getDefaultSingleton(). removeClientFor(ocAccount)); - if (client != null) { OwnCloudCredentials cred = client.getCredentials(); if (cred != null) { @@ -959,9 +992,9 @@ public class FileDisplayActivity extends HookActivity /*|| mRefreshSharesInProgress*/ //); setBackgroundText(); - + } - + if (synchResult != null) { if (synchResult.getCode().equals( RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED)) { @@ -975,7 +1008,7 @@ public class FileDisplayActivity extends HookActivity } } } - + /** * Show a text message on screen view for notifying user if content is * loading or folder is empty @@ -1000,7 +1033,8 @@ public class FileDisplayActivity extends HookActivity private class UploadFinishReceiver extends BroadcastReceiver { /** * Once the file upload has finished -> update view - * @author David A. Velasco + * + * @author David A. Velasco * {@link BroadcastReceiver} to enable upload feedback in UI */ @Override @@ -1010,23 +1044,23 @@ public class FileDisplayActivity extends HookActivity String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME); boolean sameAccount = getAccount() != null && accountName.equals(getAccount().name); OCFile currentDir = getCurrentDir(); - boolean isDescendant = (currentDir != null) && (uploadedRemotePath != null) && + boolean isDescendant = (currentDir != null) && (uploadedRemotePath != null) && (uploadedRemotePath.startsWith(currentDir.getRemotePath())); - + if (sameAccount && isDescendant) { refreshListOfFilesFragment(); } - + boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false); boolean renamedInUpload = getFile().getRemotePath(). equals(intent.getStringExtra(FileUploader.EXTRA_OLD_REMOTE_PATH)); - boolean sameFile = getFile().getRemotePath().equals(uploadedRemotePath) || + boolean sameFile = getFile().getRemotePath().equals(uploadedRemotePath) || renamedInUpload; FileFragment details = getSecondFragment(); - boolean detailFragmentIsShown = (details != null && + boolean detailFragmentIsShown = (details != null && details instanceof FileDetailFragment); - + if (sameAccount && sameFile && detailFragmentIsShown) { if (uploadWasFine) { setFile(getStorageManager().getFileByPath(uploadedRemotePath)); @@ -1034,23 +1068,28 @@ public class FileDisplayActivity extends HookActivity if (renamedInUpload) { String newName = (new File(uploadedRemotePath)).getName(); Toast msg = Toast.makeText( - context, + context, String.format( - getString(R.string.filedetails_renamed_in_upload_msg), - newName), + getString(R.string.filedetails_renamed_in_upload_msg), + newName), Toast.LENGTH_LONG); msg.show(); } if (uploadWasFine || getFile().fileExists()) { - ((FileDetailFragment)details).updateFileDetails(false, true); + ((FileDetailFragment) details).updateFileDetails(false, true); } else { cleanSecondFragment(); } - - // Force the preview if the file is an image - if (uploadWasFine && PreviewImageFragment.canBePreviewed(getFile())) { - startImagePreview(getFile()); - } // TODO what about other kind of previews? + + // Force the preview if the file is an image or text file + if (uploadWasFine) { + OCFile ocFile = getFile(); + if (PreviewImageFragment.canBePreviewed(ocFile)) + startImagePreview(getFile()); + else if (PreviewTextFragment.canBePreviewed(ocFile)) + startTextPreview(ocFile); + // TODO what about other kind of previews? + } } mProgressBar.setIndeterminate(false); @@ -1059,15 +1098,15 @@ public class FileDisplayActivity extends HookActivity removeStickyBroadcast(intent); } } - + } - + } /** * Class waiting for broadcast events from the {@link FileDownloader} service. - * + * * Updates the UI when a download is started or finished, provided that it is relevant for the * current folder. */ @@ -1095,15 +1134,15 @@ public class FileDisplayActivity extends HookActivity intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false) ); } - + if (mWaitingToSend != null) { mWaitingToSend = getStorageManager().getFileByPath(mWaitingToSend.getRemotePath()); - if (mWaitingToSend.isDown()) { + if (mWaitingToSend.isDown()) { sendDownloadedFile(); } } - + } finally { if (intent != null) { removeStickyBroadcast(intent); @@ -1134,10 +1173,10 @@ public class FileDisplayActivity extends HookActivity accountName.equals(getAccount().name)); } } - - + + public void browseToRoot() { - OCFileListFragment listOfFiles = getListOfFilesFragment(); + OCFileListFragment listOfFiles = getListOfFilesFragment(); if (listOfFiles != null) { // should never be null, indeed OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH); listOfFiles.listDirectory(root); @@ -1147,13 +1186,12 @@ public class FileDisplayActivity extends HookActivity startSyncFolderOperation(root, false); } cleanSecondFragment(); - } /** * {@inheritDoc} - * + *

* Updates action bar and second fragment, if in dual pane mode. */ @Override @@ -1165,10 +1203,10 @@ public class FileDisplayActivity extends HookActivity } /** - * Shows the information of the {@link OCFile} received as a + * Shows the information of the {@link OCFile} received as a * parameter in the second fragment. - * - * @param file {@link OCFile} whose details will be shown + * + * @param file {@link OCFile} whose details will be shown */ @Override public void showDetails(OCFile file) { @@ -1196,7 +1234,9 @@ public class FileDisplayActivity extends HookActivity return new ListServiceConnection(); } - /** Defines callbacks for service binding, passed to bindService() */ + /** + * Defines callbacks for service binding, passed to bindService() + */ private class ListServiceConnection implements ServiceConnection { @Override @@ -1213,7 +1253,7 @@ public class FileDisplayActivity extends HookActivity if (!mWaitingToPreview.isDown()) { requestForDownload(); } - } + } } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) { @@ -1224,7 +1264,7 @@ public class FileDisplayActivity extends HookActivity } // a new chance to get the mDownloadBinder through // getFileDownloadBinder() - THIS IS A MESS - OCFileListFragment listOfFiles = getListOfFilesFragment(); + OCFileListFragment listOfFiles = getListOfFilesFragment(); if (listOfFiles != null) { listOfFiles.listDirectory(); // TODO Enable when "On Device" is recovered ? @@ -1232,7 +1272,7 @@ public class FileDisplayActivity extends HookActivity } FileFragment secondFragment = getSecondFragment(); if (secondFragment != null && secondFragment instanceof FileDetailFragment) { - FileDetailFragment detailFragment = (FileDetailFragment)secondFragment; + FileDetailFragment detailFragment = (FileDetailFragment) secondFragment; detailFragment.listenForTransferProgress(); detailFragment.updateFileDetails(false, false); } @@ -1250,7 +1290,7 @@ public class FileDisplayActivity extends HookActivity mUploaderBinder = null; } } - }; + } @Override public void onSavedCertificate() { @@ -1274,39 +1314,40 @@ public class FileDisplayActivity extends HookActivity /** * Updates the view associated to the activity after the finish of some operation over files * in the current account. - * - * @param operation Removal operation performed. - * @param result Result of the removal. + * + * @param operation Removal operation performed. + * @param result Result of the removal. */ @Override public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { super.onRemoteOperationFinish(operation, result); - + if (operation instanceof RemoveFileOperation) { onRemoveFileOperationFinish((RemoveFileOperation) operation, result); } else if (operation instanceof RenameFileOperation) { - onRenameFileOperationFinish((RenameFileOperation)operation, result); + onRenameFileOperationFinish((RenameFileOperation) operation, result); } else if (operation instanceof SynchronizeFileOperation) { - onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result); + onSynchronizeFileOperationFinish((SynchronizeFileOperation) operation, result); } else if (operation instanceof CreateFolderOperation) { - onCreateFolderOperationFinish((CreateFolderOperation)operation, result); - + onCreateFolderOperationFinish((CreateFolderOperation) operation, result); + } else if (operation instanceof CreateShareOperation) { onCreateShareOperationFinish((CreateShareOperation) operation, result); - + } else if (operation instanceof UnshareLinkOperation) { - onUnshareLinkOperationFinish((UnshareLinkOperation)operation, result); - + onUnshareLinkOperationFinish((UnshareLinkOperation) operation, result); + } else if (operation instanceof MoveFileOperation) { - onMoveFileOperationFinish((MoveFileOperation)operation, result); + onMoveFileOperationFinish((MoveFileOperation) operation, result); + + } else if (operation instanceof CopyFileOperation) { + onCopyFileOperationFinish((CopyFileOperation) operation, result); } - - } - + } private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) { if (result.isSuccess()) { @@ -1315,36 +1356,38 @@ public class FileDisplayActivity extends HookActivity } } - private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) { if (result.isSuccess()) { refreshShowDetails(); refreshListOfFilesFragment(); - + } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND) { cleanSecondFragment(); refreshListOfFilesFragment(); } } - + private void refreshShowDetails() { FileFragment details = getSecondFragment(); if (details != null) { OCFile file = details.getFile(); if (file != null) { - file = getStorageManager().getFileByPath(file.getRemotePath()); + file = getStorageManager().getFileByPath(file.getRemotePath()); if (details instanceof PreviewMediaFragment) { // Refresh OCFile of the fragment ((PreviewMediaFragment) details).updateFile(file); + } else if (details instanceof PreviewTextFragment) { + // Refresh OCFile of the fragment + ((PreviewTextFragment) details).updateFile(file); } else { showDetails(file); - } + } } invalidateOptionsMenu(); - } + } } - + /** * Updates the view associated to the activity after the finish of an operation trying to * remove a file. @@ -1355,23 +1398,23 @@ 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); + Toast.LENGTH_LONG); msg.show(); - + if (result.isSuccess()) { OCFile removedFile = operation.getFile(); FileFragment second = getSecondFragment(); if (second != null && removedFile.equals(second.getFile())) { if (second instanceof PreviewMediaFragment) { - ((PreviewMediaFragment)second).stopPreview(true); + ((PreviewMediaFragment) second).stopPreview(true); } setFile(getStorageManager().getFileById(removedFile.getParentId())); cleanSecondFragment(); } - if (getStorageManager().getFileById(removedFile.getParentId()).equals(getCurrentDir())) { + if (getStorageManager().getFileById(removedFile.getParentId()).equals(getCurrentDir())){ refreshListOfFilesFragment(); } invalidateOptionsMenu(); @@ -1382,14 +1425,14 @@ public class FileDisplayActivity extends HookActivity } } } - - + + /** - * Updates the view associated to the activity after the finish of an operation trying to move a + * Updates the view associated to the activity after the finish of an operation trying to move a * file. - * - * @param operation Move operation performed. - * @param result Result of the move operation. + * + * @param operation Move operation performed. + * @param result Result of the move operation. */ private void onMoveFileOperationFinish(MoveFileOperation operation, RemoteOperationResult result) { @@ -1399,17 +1442,41 @@ public class FileDisplayActivity extends HookActivity } else { dismissLoadingDialog(); try { - Toast msg = Toast.makeText(FileDisplayActivity.this, - ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), - Toast.LENGTH_LONG); + 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); + 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 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 @@ -1434,14 +1501,22 @@ public class FileDisplayActivity extends HookActivity renamedFile.equals(details.getFile())) { ((PreviewMediaFragment) details).updateFile(renamedFile); if (PreviewMediaFragment.canBePreviewed(renamedFile)) { - int position = ((PreviewMediaFragment)details).getPosition(); + int position = ((PreviewMediaFragment) details).getPosition(); startMediaPreview(renamedFile, position, true); } else { getFileOperationsHelper().openFile(renamedFile); } + } else if (details instanceof PreviewTextFragment && + renamedFile.equals(details.getFile())) { + ((PreviewTextFragment) details).updateFile(renamedFile); + if (PreviewTextFragment.canBePreviewed(renamedFile)) { + startTextPreview(renamedFile); + } else { + getFileOperationsHelper().openFile(renamedFile); + } } } - + if (getStorageManager().getFileById(renamedFile.getParentId()).equals(getCurrentDir())){ refreshListOfFilesFragment(); } @@ -1449,9 +1524,9 @@ public class FileDisplayActivity extends HookActivity } else { Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), - Toast.LENGTH_LONG); + Toast.LENGTH_LONG); msg.show(); - + if (result.isSslRecoverableException()) { mLastSslUntrustedServerResult = result; showUntrustedCertDialog(mLastSslUntrustedServerResult); @@ -1485,18 +1560,18 @@ public class FileDisplayActivity extends HookActivity } else { dismissLoadingDialog(); try { - Toast msg = Toast.makeText(FileDisplayActivity.this, - ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), - Toast.LENGTH_LONG); + 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); + Log_OC.e(TAG, "Error while trying to show fail message ", e); } } } - + /** * {@inheritDoc} */ @@ -1507,16 +1582,16 @@ public class FileDisplayActivity extends HookActivity if (details != null && details instanceof FileDetailFragment && file.equals(details.getFile()) ) { if (downloading || uploading) { - ((FileDetailFragment)details).updateFileDetails(file, getAccount()); + ((FileDetailFragment) details).updateFileDetails(file, getAccount()); } else { if (!file.fileExists()) { cleanSecondFragment(); } else { - ((FileDetailFragment)details).updateFileDetails(false, true); + ((FileDetailFragment) details).updateFileDetails(false, true); } } } - + } @@ -1545,12 +1620,12 @@ public class FileDisplayActivity extends HookActivity } return null; } - + public void startSyncFolderOperation(OCFile folder, boolean ignoreETag) { - long currentSyncTime = System.currentTimeMillis(); - + long currentSyncTime = System.currentTimeMillis(); + mSyncInProgress = true; - + // perform folder synchronization RemoteOperation synchFolderOp = new RefreshFolderOperation( folder, currentSyncTime, @@ -1562,13 +1637,14 @@ public class FileDisplayActivity extends HookActivity getApplicationContext() ); synchFolderOp.execute(getAccount(), MainApp.getAppContext(), this, null, null); + mProgressBar.setIndeterminate(true); setBackgroundText(); } /** - * Show untrusted cert dialog + * Show untrusted cert dialog */ public void showUntrustedCertDialog(RemoteOperationResult result) { // Show a dialog with the certificate info @@ -1578,7 +1654,7 @@ public class FileDisplayActivity extends HookActivity FragmentTransaction ft = fm.beginTransaction(); dialog.show(ft, DIALOG_UNTRUSTED_CERT); } - + private void requestForDownload(OCFile file) { Account account = getAccount(); if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) { @@ -1588,43 +1664,42 @@ public class FileDisplayActivity extends HookActivity startService(i); } } - - private void sendDownloadedFile(){ + + private void sendDownloadedFile() { getFileOperationsHelper().sendDownloadedFile(mWaitingToSend); mWaitingToSend = null; } - + /** * Requests the download of the received {@link OCFile} , updates the UI * to monitor the download progress and prepares the activity to send the file * when the download finishes. - * - * @param file {@link OCFile} to download and preview. + * + * @param file {@link OCFile} to download and preview. */ public void startDownloadForSending(OCFile file) { mWaitingToSend = file; requestForDownload(mWaitingToSend); - boolean hasSecondFragment = (getSecondFragment()!= null); + boolean hasSecondFragment = (getSecondFragment() != null); updateFragmentsVisibility(hasSecondFragment); } - + /** * Opens the image gallery showing the image {@link OCFile} received as parameter. - * - * @param file Image {@link OCFile} to show. + * + * @param file Image {@link OCFile} to show. */ public void startImagePreview(OCFile file) { Intent showDetailsIntent = new Intent(this, PreviewImageActivity.class); showDetailsIntent.putExtra(EXTRA_FILE, file); showDetailsIntent.putExtra(EXTRA_ACCOUNT, getAccount()); startActivity(showDetailsIntent); - } /** * Stars the preview of an already down media {@link OCFile}. - * + * * @param file Media {@link OCFile} to preview. * @param startPlaybackPosition Media position where the playback will be started, * in milliseconds. @@ -1641,11 +1716,28 @@ public class FileDisplayActivity extends HookActivity } /** + * Stars the preview of a text file {@link OCFile}. + * + * @param file Text {@link OCFile} to preview. + */ + public void startTextPreview(OCFile file) { + Bundle args = new Bundle(); + args.putParcelable(EXTRA_FILE, file); + args.putParcelable(EXTRA_ACCOUNT, getAccount()); + Fragment textPreviewFragment = Fragment.instantiate(getApplicationContext(), + PreviewTextFragment.class.getName(), args); + setSecondFragment(textPreviewFragment); + updateFragmentsVisibility(true); + //updateNavigationElementsInActionBar(file); + setFile(file); + } + + /** * Requests the download of the received {@link OCFile} , updates the UI * to monitor the download progress and prepares the activity to preview * or open the file when the download finishes. - * - * @param file {@link OCFile} to download and preview. + * + * @param file {@link OCFile} to download and preview. */ public void startDownloadForPreview(OCFile file) { Fragment detailFragment = FileDetailFragment.newInstance(file, getAccount()); @@ -1660,7 +1752,7 @@ public class FileDisplayActivity extends HookActivity public void cancelTransference(OCFile file) { getFileOperationsHelper().cancelTransference(file); - if (mWaitingToPreview != null && + if (mWaitingToPreview != null && mWaitingToPreview.getRemotePath().equals(file.getRemotePath())) { mWaitingToPreview = null; } @@ -1693,15 +1785,15 @@ public class FileDisplayActivity extends HookActivity } } - private void sortByDate(boolean ascending){ + private void sortByDate(boolean ascending) { getListOfFilesFragment().sortByDate(ascending); } - private void sortBySize(boolean ascending){ + private void sortBySize(boolean ascending) { getListOfFilesFragment().sortBySize(ascending); } - private void sortByName(boolean ascending){ + private void sortByName(boolean ascending) { getListOfFilesFragment().sortByName(ascending); } diff --git a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java index 0c72052a..27fc8c15 100644 --- a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java +++ b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java @@ -4,6 +4,7 @@ * @author Bartek Przybylski * @author Tobias Kaminsky * @author David A. Velasco + * @author masensio * Copyright (C) 2011 Bartek Przybylski * Copyright (C) 2015 ownCloud Inc. * @@ -30,7 +31,6 @@ import android.accounts.Account; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; import android.os.Build; import android.preference.PreferenceManager; import android.text.format.DateUtils; @@ -322,12 +322,12 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter { } } - if (file.getMimetype().equalsIgnoreCase("image/png")){ - Drawable backrepeat = mContext.getResources(). - getDrawable(R.drawable.backrepeat); - fileIcon.setBackground(backrepeat); + if (file.getMimetype().equalsIgnoreCase("image/png")) { + fileIcon.setBackgroundColor(mContext.getResources() + .getColor(R.color.background_color)); } + } else { fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName())); @@ -335,6 +335,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter { } else { // Folder + if (checkIfFileIsSharedWithMe(file)) { fileIcon.setImageResource(R.drawable.shared_with_me_folder); } else if (file.isShareByLink()) { 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 5ec5c52c..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,12 +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 { @@ -69,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; @@ -94,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); @@ -140,7 +140,7 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi mJustFolders, getActivity(), mContainerActivity - ); + ); setListAdapter(mAdapter); registerLongClickListener(); @@ -203,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 { @@ -235,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 @@ -246,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()*/); @@ -267,48 +267,49 @@ 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 ((FileDisplayActivity)mContainerActivity).startImagePreview(file); - + } else if (PreviewTextFragment.canBePreviewed(file)){ + ((FileDisplayActivity)mContainerActivity).startTextPreview(file); } 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, @@ -403,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; } @@ -426,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 */ @@ -445,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*/) { @@ -458,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/ui/preview/PreviewTextFragment.java b/src/com/owncloud/android/ui/preview/PreviewTextFragment.java new file mode 100644 index 00000000..6595bf72 --- /dev/null +++ b/src/com/owncloud/android/ui/preview/PreviewTextFragment.java @@ -0,0 +1,419 @@ +package com.owncloud.android.ui.preview; + +import android.accounts.Account; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.owncloud.android.R; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.files.FileMenuFilter; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.ui.activity.FileDisplayActivity; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; +import com.owncloud.android.ui.dialog.LoadingDialog; +import com.owncloud.android.ui.dialog.RemoveFileDialogFragment; +import com.owncloud.android.ui.fragment.FileFragment; + +import java.io.BufferedWriter; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.lang.ref.WeakReference; +import java.util.LinkedList; +import java.util.List; +import java.util.Scanner; + +public class PreviewTextFragment extends FileFragment { + private static final String EXTRA_FILE = "FILE"; + private static final String EXTRA_ACCOUNT = "ACCOUNT"; + private static final String TAG = PreviewTextFragment.class.getSimpleName(); + + private Account mAccount; + private TextView mTextPreview; + private TextLoadAsyncTask mTextLoadTask; + + /** + * 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 PreviewTextFragment() { + super(); + mAccount = null; + } + + /** + * {@inheritDoc} + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + Log_OC.e(TAG, "onCreateView"); + + + View ret = inflater.inflate(R.layout.text_file_preview, container, false); + + mTextPreview = (TextView) ret.findViewById(R.id.text_preview); + + return ret; + } + + /** + * {@inheritDoc} + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + OCFile file = getFile(); + + Bundle args = getArguments(); + + if (file == null) { + file = args.getParcelable(FileDisplayActivity.EXTRA_FILE); + } + + if (mAccount == null) { + mAccount = args.getParcelable(FileDisplayActivity.EXTRA_ACCOUNT); + } + + if (savedInstanceState == null) { + if (file == null) { + throw new IllegalStateException("Instanced with a NULL OCFile"); + } + if (mAccount == null) { + throw new IllegalStateException("Instanced with a NULL ownCloud Account"); + } + } else { + file = savedInstanceState.getParcelable(EXTRA_FILE); + mAccount = savedInstanceState.getParcelable(EXTRA_ACCOUNT); + } + setFile(file); + setHasOptionsMenu(true); + } + + /** + * {@inheritDoc} + */ + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putParcelable(PreviewTextFragment.EXTRA_FILE, getFile()); + outState.putParcelable(PreviewTextFragment.EXTRA_ACCOUNT, mAccount); + } + + @Override + public void onStart() { + super.onStart(); + Log_OC.e(TAG, "onStart"); + + loadAndShowTextPreview(); + } + + private void loadAndShowTextPreview() { + mTextLoadTask = new TextLoadAsyncTask(new WeakReference(mTextPreview)); + mTextLoadTask.execute(getFile().getStoragePath()); + } + + + /** + * Reads the file to preview and shows its contents. Too critical to be anonymous. + */ + private class TextLoadAsyncTask extends AsyncTask { + private final String DIALOG_WAIT_TAG = "DIALOG_WAIT"; + private final WeakReference mTextViewReference; + + private TextLoadAsyncTask(WeakReference textView) { + mTextViewReference = textView; + } + + + @Override + protected void onPreExecute() { + showLoadingDialog(); + } + + @Override + protected StringWriter doInBackground(java.lang.Object... params) { + if (params.length != 1) { + throw new IllegalArgumentException("The parameter to " + TextLoadAsyncTask.class.getName() + " must be (1) the file location"); + } + final String location = (String) params[0]; + + FileInputStream inputStream = null; + Scanner sc = null; + StringWriter source = new StringWriter(); + BufferedWriter bufferedWriter = new BufferedWriter(source); + try { + inputStream = new FileInputStream(location); + sc = new Scanner(inputStream); + while (sc.hasNextLine()) { + bufferedWriter.append(sc.nextLine()); + if (sc.hasNextLine()) bufferedWriter.append("\n"); + } + bufferedWriter.close(); + IOException exc = sc.ioException(); + if (exc != null) throw exc; + } catch (IOException e) { + Log_OC.e(TAG, e.getMessage(), e); + finish(); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + Log_OC.e(TAG, e.getMessage(), e); + finish(); + } + } + if (sc != null) { + sc.close(); + } + } + return source; + } + + @Override + protected void onPostExecute(final StringWriter stringWriter) { + final TextView textView = mTextViewReference.get(); + + if (textView != null) { + textView.setText(new String(stringWriter.getBuffer())); + textView.setVisibility(View.VISIBLE); + } + + dismissLoadingDialog(); + } + + /** + * Show loading dialog + */ + public void showLoadingDialog() { + // only once + Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG); + LoadingDialog loading = null; + if (frag == null) { + // Construct dialog + loading = new LoadingDialog(getResources().getString(R.string.wait_a_moment)); + FragmentManager fm = getActivity().getSupportFragmentManager(); + FragmentTransaction ft = fm.beginTransaction(); + loading.show(ft, DIALOG_WAIT_TAG); + } else { + loading = (LoadingDialog) frag; + loading.setShowsDialog(true); + } + + } + + /** + * Dismiss loading dialog + */ + public void dismissLoadingDialog() { + final Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG); + if (frag != null) { + LoadingDialog loading = (LoadingDialog) frag; + loading.dismiss(); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + 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) { + super.onPrepareOptionsMenu(menu); + + if (mContainerActivity.getStorageManager() != null) { + FileMenuFilter mf = new FileMenuFilter( + getFile(), + mContainerActivity.getStorageManager().getAccount(), + mContainerActivity, + getActivity() + ); + mf.filter(menu); + } + + // additional restriction for this fragment + MenuItem item = menu.findItem(R.id.action_rename_file); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + + // additional restriction for this fragment + item = menu.findItem(R.id.action_move); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + + // this one doesn't make sense since the file has to be down in order to be previewed + item = menu.findItem(R.id.action_download_file); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + + item = menu.findItem(R.id.action_sync_file); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + + item = menu.findItem(R.id.action_sync_account); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_share_file: { + mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile()); + return true; + } + case R.id.action_unshare_file: { + mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile()); + return true; + } + case R.id.action_open_file_with: { + openFile(); + return true; + } + case R.id.action_remove_file: { + RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile()); + dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION); + return true; + } + case R.id.action_see_details: { + seeDetails(); + return true; + } + case R.id.action_send_file: { + sendFile(); + return true; + } + case R.id.action_sync_file: { + mContainerActivity.getFileOperationsHelper().syncFile(getFile()); + return true; + } + + default: + return false; + } + } + + /** + * Update the file of the fragment with file value + * + * @param file The new file to set + */ + public void updateFile(OCFile file) { + setFile(file); + } + + private void sendFile() { + mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile()); + } + + private void seeDetails() { + mContainerActivity.showDetails(getFile()); + } + + @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() { + super.onStop(); + Log_OC.e(TAG, "onStop"); + if (mTextLoadTask != null) + mTextLoadTask.cancel(Boolean.TRUE); + } + + /** + * Opens the previewed file with an external application. + */ + private void openFile() { + mContainerActivity.getFileOperationsHelper().openFile(getFile()); + finish(); + } + + /** + * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewTextFragment} 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) { + final List unsupportedTypes = new LinkedList(); + unsupportedTypes.add("text/richtext"); + unsupportedTypes.add("text/rtf"); + unsupportedTypes.add("text/vnd.abc"); + unsupportedTypes.add("text/vnd.fmi.flexstor"); + unsupportedTypes.add("text/vnd.rn-realtext"); + unsupportedTypes.add("text/vnd.wap.wml"); + unsupportedTypes.add("text/vnd.wap.wmlscript"); + return (file != null && file.isDown() && file.isText() && + !unsupportedTypes.contains(file.getMimetype()) && + !unsupportedTypes.contains(file.getMimeTypeFromName()) + ); + } + + /** + * Finishes the preview + */ + private void finish() { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + getActivity().onBackPressed(); + } + }); + } +} 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; } }