Browse Source

Merge branch 'master' of https://github.com/owncloud/android into material_buttons

Andy Scherzinger 9 years ago
parent
commit
f72289f7bf
98 changed files with 724 additions and 1126 deletions
  1. 1 0
      .travis.yml
  2. 1 1
      owncloud-android-library
  3. BIN
      res/drawable/conflict_file_indicator.png
  4. BIN
      res/drawable/synchronizing_file_indicator.png
  5. 2 7
      res/menu/file_actions_menu.xml
  6. 0 3
      res/values-ar/strings.xml
  7. 0 4
      res/values-az/strings.xml
  8. 0 4
      res/values-bg-rBG/strings.xml
  9. 0 3
      res/values-bn-rBD/strings.xml
  10. 0 1
      res/values-bs/strings.xml
  11. 0 3
      res/values-ca/strings.xml
  12. 3 4
      res/values-cs-rCZ/strings.xml
  13. 0 2
      res/values-cy-rGB/strings.xml
  14. 0 4
      res/values-da/strings.xml
  15. 0 3
      res/values-de-rAT/strings.xml
  16. 0 4
      res/values-de-rDE/strings.xml
  17. 0 4
      res/values-de/strings.xml
  18. 0 4
      res/values-el/strings.xml
  19. 0 4
      res/values-en-rGB/strings.xml
  20. 0 2
      res/values-eo/strings.xml
  21. 0 4
      res/values-es-rAR/strings.xml
  22. 0 3
      res/values-es-rCL/strings.xml
  23. 0 3
      res/values-es-rMX/strings.xml
  24. 0 4
      res/values-es/strings.xml
  25. 0 4
      res/values-et-rEE/strings.xml
  26. 0 4
      res/values-eu/strings.xml
  27. 0 4
      res/values-fa/strings.xml
  28. 3 3
      res/values-fi-rFI/strings.xml
  29. 3 4
      res/values-fr/strings.xml
  30. 0 4
      res/values-gl/strings.xml
  31. 0 3
      res/values-he/strings.xml
  32. 0 1
      res/values-hr/strings.xml
  33. 0 3
      res/values-hu-rHU/strings.xml
  34. 17 0
      res/values-hy/strings.xml
  35. 0 1
      res/values-ia/strings.xml
  36. 0 4
      res/values-id/strings.xml
  37. 0 1
      res/values-is/strings.xml
  38. 3 4
      res/values-it/strings.xml
  39. 0 4
      res/values-ja-rJP/strings.xml
  40. 0 2
      res/values-ka-rGE/strings.xml
  41. 0 2
      res/values-km/strings.xml
  42. 0 1
      res/values-kn/strings.xml
  43. 0 4
      res/values-ko/strings.xml
  44. 0 4
      res/values-lb/strings.xml
  45. 0 4
      res/values-lt-rLT/strings.xml
  46. 31 3
      res/values-lv/strings.xml
  47. 0 4
      res/values-mk/strings.xml
  48. 0 1
      res/values-ms-rMY/strings.xml
  49. 1 4
      res/values-nb-rNO/strings.xml
  50. 3 4
      res/values-nl/strings.xml
  51. 0 2
      res/values-nn-rNO/strings.xml
  52. 0 4
      res/values-oc/strings.xml
  53. 0 3
      res/values-pa/strings.xml
  54. 0 4
      res/values-pl/strings.xml
  55. 3 4
      res/values-pt-rBR/strings.xml
  56. 4 4
      res/values-pt-rPT/strings.xml
  57. 0 4
      res/values-ro/strings.xml
  58. 0 4
      res/values-ru/strings.xml
  59. 0 1
      res/values-si-rLK/strings.xml
  60. 0 4
      res/values-sk-rSK/strings.xml
  61. 0 4
      res/values-sl/strings.xml
  62. 3 4
      res/values-sq/strings.xml
  63. 0 1
      res/values-sr-rSP/strings.xml
  64. 0 4
      res/values-sr/strings.xml
  65. 0 4
      res/values-sv/strings.xml
  66. 0 2
      res/values-ta-rLK/strings.xml
  67. 0 4
      res/values-th-rTH/strings.xml
  68. 0 4
      res/values-tr/strings.xml
  69. 0 1
      res/values-ug/strings.xml
  70. 0 4
      res/values-uk/strings.xml
  71. 0 3
      res/values-vi/strings.xml
  72. 0 4
      res/values-zh-rCN/strings.xml
  73. 0 2
      res/values-zh-rHK/strings.xml
  74. 0 4
      res/values-zh-rTW/strings.xml
  75. 3 4
      res/values/strings.xml
  76. 144 124
      src/com/owncloud/android/datamodel/FileDataStorageManager.java
  77. 14 25
      src/com/owncloud/android/datamodel/OCFile.java
  78. 3 2
      src/com/owncloud/android/db/ProviderMeta.java
  79. 25 28
      src/com/owncloud/android/files/FileMenuFilter.java
  80. 9 13
      src/com/owncloud/android/files/FileOperationsHelper.java
  81. 19 85
      src/com/owncloud/android/files/services/FileDownloader.java
  82. 117 125
      src/com/owncloud/android/files/services/FileUploader.java
  83. 9 4
      src/com/owncloud/android/operations/DownloadFileOperation.java
  84. 61 162
      src/com/owncloud/android/operations/RefreshFolderOperation.java
  85. 14 11
      src/com/owncloud/android/operations/SynchronizeFileOperation.java
  86. 52 72
      src/com/owncloud/android/operations/SynchronizeFolderOperation.java
  87. 44 45
      src/com/owncloud/android/operations/UploadFileOperation.java
  88. 22 55
      src/com/owncloud/android/providers/FileContentProvider.java
  89. 3 5
      src/com/owncloud/android/services/OperationsService.java
  90. 9 28
      src/com/owncloud/android/syncadapter/FileSyncAdapter.java
  91. 17 5
      src/com/owncloud/android/ui/activity/FileDisplayActivity.java
  92. 34 51
      src/com/owncloud/android/ui/adapter/FileListListAdapter.java
  93. 0 29
      src/com/owncloud/android/ui/dialog/RemoveFileDialogFragment.java
  94. 2 4
      src/com/owncloud/android/ui/fragment/FileDetailFragment.java
  95. 2 3
      src/com/owncloud/android/ui/fragment/OCFileListFragment.java
  96. 11 14
      src/com/owncloud/android/utils/DisplayUtils.java
  97. 1 1
      src/com/owncloud/android/utils/ErrorMessageAdapter.java
  98. 31 4
      src/com/owncloud/android/utils/FileStorageUtils.java

+ 1 - 0
.travis.yml

@@ -1,3 +1,4 @@
+sudo: false
 language: android
 android:
   components:

+ 1 - 1
owncloud-android-library

@@ -1 +1 @@
-Subproject commit ecc3415e3e3c13fa8f73fdd51a88c1ab7087b199
+Subproject commit f02dffb1d3c46305c70d246f696cde7b8c3b0971

BIN
res/drawable/conflict_file_indicator.png


BIN
res/drawable/synchronizing_file_indicator.png


+ 2 - 7
res/menu/file_actions_menu.xml

@@ -44,13 +44,8 @@
         android:icon="@drawable/ic_action_refresh"
         android:orderInCategory="1" />
     <item
-        android:id="@+id/action_cancel_download"
-        android:title="@string/common_cancel_download"
-        android:icon="@android:drawable/ic_menu_close_clear_cancel"
-        android:orderInCategory="1" />
-    <item
-        android:id="@+id/action_cancel_upload"
-        android:title="@string/common_cancel_upload"
+        android:id="@+id/action_cancel_sync"
+        android:title="@string/common_cancel_sync"
         android:icon="@android:drawable/ic_menu_close_clear_cancel"
         android:orderInCategory="1" />
     <item

+ 0 - 3
res/values-ar/strings.xml

@@ -77,15 +77,12 @@
   <string name="filedetails_created">انشئ في :</string>
   <string name="filedetails_modified">عُدل في :</string>
   <string name="filedetails_download">تحميل</string>
-  <string name="filedetails_sync_file">تحديث الملف</string>
   <string name="filedetails_renamed_in_upload_msg">تم تغيير اسم الملف إلى  %1$s أثناء الرفع</string>
   <string name="action_share_file">شارك الرابط</string>
   <string name="action_unshare_file">الغاء مشاركة الرابط</string>
   <string name="common_yes">نعم</string>
   <string name="common_no">لا</string>
   <string name="common_ok">تم</string>
-  <string name="common_cancel_download">إلغاء التحميل</string>
-  <string name="common_cancel_upload">إلغاء الرفع</string>
   <string name="common_cancel">إلغاء</string>
   <string name="common_save_exit">حفظ + خروج</string>
   <string name="common_error">خطأ</string>

+ 0 - 4
res/values-az/strings.xml

@@ -72,15 +72,12 @@
   <string name="filedetails_created">Yaradıldı:</string>
   <string name="filedetails_modified">Dəyişdirildi:</string>
   <string name="filedetails_download">Yüklə</string>
-  <string name="filedetails_sync_file">Faylı yenilə</string>
   <string name="filedetails_renamed_in_upload_msg">Yüklənmə müddətində fayl buna %1$s yeniləndi</string>
   <string name="action_share_file">Linki yayımla</string>
   <string name="action_unshare_file">Link yayımlanmasını dayandır</string>
   <string name="common_yes">Bəli</string>
   <string name="common_no">Xeyir</string>
   <string name="common_ok">Oldu</string>
-  <string name="common_cancel_download">Endirimi dayandır</string>
-  <string name="common_cancel_upload">Yüklənməni dayandır</string>
   <string name="common_cancel">Dayandır</string>
   <string name="common_save_exit">Saxla &amp; Çıx</string>
   <string name="common_error">Səhv</string>
@@ -288,7 +285,6 @@ inzibatçınızla əlaqə saxlayasınız.</string>
   <string name="prefs_category_instant_uploading">Anında yükləmələr</string>
   <string name="prefs_category_security">Təhlükəsizlik</string>
   <string name="prefs_instant_video_upload_path_title">Video ünvanını yüklə</string>
-  <string name="download_folder_failed_content">Qovluğun endirilməsinin %1$s hissəsi tamamlana bilməz </string>
   <string name="auth_refresh_button">Qoşulmanı yenilə</string>
   <string name="auth_host_address">Server ünvanı</string>
 </resources>

+ 0 - 4
res/values-bg-rBG/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">Създаден на:</string>
   <string name="filedetails_modified">Променен на:</string>
   <string name="filedetails_download">Изтегляне</string>
-  <string name="filedetails_sync_file">Обновяване на файла</string>
   <string name="filedetails_renamed_in_upload_msg">Файлът беше преименуван на %1$s по време на качването.</string>
   <string name="list_layout">Списък с изгледи</string>
   <string name="action_share_file">Връзка за споделяне</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Да</string>
   <string name="common_no">Не</string>
   <string name="common_ok">ОК</string>
-  <string name="common_cancel_download">Отказване на тегленето</string>
-  <string name="common_cancel_upload">Отказване на качването</string>
   <string name="common_cancel">Отказ</string>
   <string name="common_save_exit">Запазване и изход</string>
   <string name="common_error">Грешка</string>
@@ -304,7 +301,6 @@
   <string name="prefs_category_instant_uploading">Незабавно качване</string>
   <string name="prefs_category_security">Сигурност</string>
   <string name="prefs_instant_video_upload_path_title">Качване на видео път</string>
-  <string name="download_folder_failed_content">Свалянето на директорията %1$s не може да бъде завършено</string>
   <string name="shared_subject_header">споделен</string>
   <string name="with_you_subject_header">с теб</string>
   <string name="subject_token">%1$s споделен \"%2$s\" с теб</string>

+ 0 - 3
res/values-bn-rBD/strings.xml

@@ -63,15 +63,12 @@
   <string name="filedetails_created">তৈরীর নির্ঘন্টঃ</string>
   <string name="filedetails_modified">পরিবর্তিতঃ</string>
   <string name="filedetails_download">ডাউনলোড</string>
-  <string name="filedetails_sync_file">ফাইল নবোদ্যম করুন</string>
   <string name="filedetails_renamed_in_upload_msg">আপলোডের সময় ফাইলের পূণঃনামকরণ করা হয়েছে %1$s</string>
   <string name="action_share_file">লিংক ভাগাভাগি করেন</string>
   <string name="action_unshare_file">লিংক ছিনন করেন</string>
   <string name="common_yes">হ্যাঁ</string>
   <string name="common_no">না</string>
   <string name="common_ok">তথাস্তু</string>
-  <string name="common_cancel_download">ডাউনলোড বাতিল করেন</string>
-  <string name="common_cancel_upload">আপলোড বাতিল কর</string>
   <string name="common_cancel">বাতিল</string>
   <string name="common_save_exit">সংরক্ষণ কর এবং &amp;প্রস্থান</string>
   <string name="common_error">সমস্যা</string>

+ 0 - 1
res/values-bs/strings.xml

@@ -24,7 +24,6 @@
   <string name="common_yes">Da</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">Ok</string>
-  <string name="common_cancel_upload">Prekini učitavanje</string>
   <string name="common_cancel">Odustani</string>
   <string name="common_error">Greška</string>
   <string name="common_error_unknown">Nepoznata greška</string>

+ 0 - 3
res/values-ca/strings.xml

@@ -72,15 +72,12 @@
   <string name="filedetails_created">Creat:</string>
   <string name="filedetails_modified">Modificat:</string>
   <string name="filedetails_download">Baixa</string>
-  <string name="filedetails_sync_file">Actualitza el fitxer</string>
   <string name="filedetails_renamed_in_upload_msg">L\'arxiu s\'ha canviat de nom a %1$s durant la càrrega</string>
   <string name="action_share_file">Enllaç de compartició</string>
   <string name="action_unshare_file">Deixa de compartir l\'enllaç</string>
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">D\'acord</string>
-  <string name="common_cancel_download">Cancelar la descàrrega</string>
-  <string name="common_cancel_upload">Cancel·la la pujada</string>
   <string name="common_cancel">Cancel·la</string>
   <string name="common_save_exit">Desa &amp; Surt</string>
   <string name="common_error">Error</string>

+ 3 - 4
res/values-cs-rCZ/strings.xml

@@ -79,7 +79,7 @@
   <string name="filedetails_created">Vytvořen:</string>
   <string name="filedetails_modified">Upraven:</string>
   <string name="filedetails_download">Stáhnout</string>
-  <string name="filedetails_sync_file">Obnovit soubor</string>
+  <string name="filedetails_sync_file">Synchronizovat</string>
   <string name="filedetails_renamed_in_upload_msg">Soubor byl v průběhu odesílání přejmenován na %1$s</string>
   <string name="list_layout">Náhled seznamu</string>
   <string name="action_share_file">Sdílet odkaz</string>
@@ -87,8 +87,7 @@
   <string name="common_yes">Ano</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Zrušit stahování</string>
-  <string name="common_cancel_upload">Zrušit odesílání</string>
+  <string name="common_cancel_sync">Zrušit synchronizaci</string>
   <string name="common_cancel">Zrušit</string>
   <string name="common_save_exit">Uložit a ukončit</string>
   <string name="common_error">Chyba</string>
@@ -315,7 +314,7 @@ správce systému.</string>
   <string name="prefs_category_instant_uploading">Okamžitá odesílání</string>
   <string name="prefs_category_security">Zabezpečení</string>
   <string name="prefs_instant_video_upload_path_title">Cesta pro nahrávání videí</string>
-  <string name="download_folder_failed_content">Stažení adresáře %1$s nemohlo být dokončeno</string>
+  <string name="sync_folder_failed_content">Synchronizaci adresáře %1$s nelze dokončit</string>
   <string name="shared_subject_header">sdílené</string>
   <string name="with_you_subject_header">s vámi</string>
   <string name="subject_token">%1$s s vámi sdílí \"%2$s\"</string>

+ 0 - 2
res/values-cy-rGB/strings.xml

@@ -42,8 +42,6 @@
   <string name="common_yes">Ie</string>
   <string name="common_no">Na</string>
   <string name="common_ok">Iawn</string>
-  <string name="common_cancel_download">Diddymu llwytho i lawr</string>
-  <string name="common_cancel_upload">Diddymu llwytho i fyny</string>
   <string name="common_cancel">Diddymu</string>
   <string name="common_save_exit">Cadw &amp; Gadael</string>
   <string name="common_error">Gwall</string>

+ 0 - 4
res/values-da/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">Oprettet:</string>
   <string name="filedetails_modified">Ændret:</string>
   <string name="filedetails_download">Hent</string>
-  <string name="filedetails_sync_file">Genopfrisk fil</string>
   <string name="filedetails_renamed_in_upload_msg">Filen blev omdøbt til %1$s under upload</string>
   <string name="list_layout">Listevisning</string>
   <string name="action_share_file">Del link</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Ja</string>
   <string name="common_no">Nej</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Afbryd download</string>
-  <string name="common_cancel_upload">Fortryd upload</string>
   <string name="common_cancel">Annuller</string>
   <string name="common_save_exit">Gem &amp; Afslut</string>
   <string name="common_error">Fejl</string>
@@ -314,7 +311,6 @@
   <string name="prefs_category_instant_uploading">Øjeblikkelige uploads</string>
   <string name="prefs_category_security">Sikkerhed</string>
   <string name="prefs_instant_video_upload_path_title">Sti til videoupload</string>
-  <string name="download_folder_failed_content">Download af %1$s mappe kunne ikke fuldføres</string>
   <string name="shared_subject_header">delt</string>
   <string name="with_you_subject_header">med dig</string>
   <string name="subject_token">%1$s delte \"%2$s\" med dig</string>

+ 0 - 3
res/values-de-rAT/strings.xml

@@ -59,14 +59,11 @@
   <string name="filedetails_created">Erstellt am:</string>
   <string name="filedetails_modified">Verändert am:</string>
   <string name="filedetails_download">Herunterladen</string>
-  <string name="filedetails_sync_file">Datei neu laden</string>
   <string name="action_share_file">Link teilen</string>
   <string name="action_unshare_file">Link nicht mehr teilen</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nein</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Herunterladen abbrechen</string>
-  <string name="common_cancel_upload">Hochladen abbrechen</string>
   <string name="common_cancel">Abbrechen</string>
   <string name="common_save_exit">Speichern &amp; Schließen</string>
   <string name="common_error">Fehler</string>

+ 0 - 4
res/values-de-rDE/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">Erstellt:</string>
   <string name="filedetails_modified">Geändert:</string>
   <string name="filedetails_download">Herunterladen</string>
-  <string name="filedetails_sync_file">Datei aktualisieren</string>
   <string name="filedetails_renamed_in_upload_msg">Datei wurde wärend des Uploads zu %1$s umbenannt</string>
   <string name="list_layout">Listen-Layout</string>
   <string name="action_share_file">Link teilen</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Ja</string>
   <string name="common_no">Nein</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Download abbrechen</string>
-  <string name="common_cancel_upload">Upload abbrechen</string>
   <string name="common_cancel">Abbrechen</string>
   <string name="common_save_exit">Speichern &amp; Schließen</string>
   <string name="common_error">Fehler</string>
@@ -307,7 +304,6 @@
   <string name="prefs_category_instant_uploading">Sofortiges Hochladen</string>
   <string name="prefs_category_security">Sicherheit</string>
   <string name="prefs_instant_video_upload_path_title">Verzeichnis zum Hochladen der Videos</string>
-  <string name="download_folder_failed_content">Herunterladen des %1$s - Ordners konnte nicht abgeschlossen werden</string>
   <string name="shared_subject_header">geteilt</string>
   <string name="with_you_subject_header">Mit Ihnen</string>
   <string name="subject_token">%1$s hat \"%2$s\" mit Ihnen geteilt</string>

+ 0 - 4
res/values-de/strings.xml

@@ -79,7 +79,6 @@
   <string name="filedetails_created">Erstellt:</string>
   <string name="filedetails_modified">Geändert:</string>
   <string name="filedetails_download">Herunterladen</string>
-  <string name="filedetails_sync_file">Datei aktualisieren</string>
   <string name="filedetails_renamed_in_upload_msg">Datei wurde wärend des Uploads zu %1$s umbenannt</string>
   <string name="list_layout">Listen-Layout</string>
   <string name="action_share_file">Link teilen</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">Ja</string>
   <string name="common_no">Nein</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Download abbrechen</string>
-  <string name="common_cancel_upload">Upload abbrechen</string>
   <string name="common_cancel">Abbrechen</string>
   <string name="common_save_exit">Speichern &amp; schließen</string>
   <string name="common_error">Fehler</string>
@@ -316,7 +313,6 @@
   <string name="prefs_category_instant_uploading">Sofortiges Hochladen</string>
   <string name="prefs_category_security">Sicherheit</string>
   <string name="prefs_instant_video_upload_path_title">Verzeichnis zum Hochladen der Videos</string>
-  <string name="download_folder_failed_content">Herunterladen des %1$s - Ordners konnte nicht abgeschlossen werden</string>
   <string name="shared_subject_header">geteilt</string>
   <string name="with_you_subject_header">Mit Dir</string>
   <string name="subject_token">%1$s hat \"%2$s\" mit Dir geteilt</string>

+ 0 - 4
res/values-el/strings.xml

@@ -79,7 +79,6 @@
   <string name="filedetails_created">Δημιουργήθηκε:</string>
   <string name="filedetails_modified">Τροποποιήθηκε:</string>
   <string name="filedetails_download">Λήψη</string>
-  <string name="filedetails_sync_file">Ανανέωση αρχείου</string>
   <string name="filedetails_renamed_in_upload_msg">Το αρχείο μετονομάστηκε σε %1$s κατά τη μεταφόρτωση</string>
   <string name="list_layout">Διάταξη Λίστας</string>
   <string name="action_share_file">Διαμοιρασμός συνδέσμου</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">Ναι</string>
   <string name="common_no">Όχι</string>
   <string name="common_ok">ΟΚ</string>
-  <string name="common_cancel_download">Ακύρωση λήψης</string>
-  <string name="common_cancel_upload">Ακύρωση μεταφόρτωσης</string>
   <string name="common_cancel">Άκυρο</string>
   <string name="common_save_exit">Αποθήκευση &amp; Έξοδος</string>
   <string name="common_error">Σφάλμα</string>
@@ -316,7 +313,6 @@
   <string name="prefs_category_instant_uploading">Στιγμιαίες Μεταφορτώσεις</string>
   <string name="prefs_category_security">Ασφάλεια</string>
   <string name="prefs_instant_video_upload_path_title">Διαδρομή Μεταφόρτωσης Βίντεο</string>
-  <string name="download_folder_failed_content">Η λήψη του φακέλου %1$s δεν ολοκληρώθηκε με επιτυχία.</string>
   <string name="shared_subject_header">διαμοιρασμένα</string>
   <string name="with_you_subject_header">με εσάς</string>
   <string name="subject_token">Ο %1$s διαμοιράστηκε το \"%2$s\" με εσάς</string>

+ 0 - 4
res/values-en-rGB/strings.xml

@@ -73,15 +73,12 @@
   <string name="filedetails_created">Created:</string>
   <string name="filedetails_modified">Modified:</string>
   <string name="filedetails_download">Download</string>
-  <string name="filedetails_sync_file">Refresh file</string>
   <string name="filedetails_renamed_in_upload_msg">File was renamed to %1$s during upload</string>
   <string name="action_share_file">Share link</string>
   <string name="action_unshare_file">Unshare link</string>
   <string name="common_yes">Yes</string>
   <string name="common_no">No</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Cancel download</string>
-  <string name="common_cancel_upload">Cancel upload</string>
   <string name="common_cancel">Cancel</string>
   <string name="common_save_exit">Save &amp; Exit</string>
   <string name="common_error">Error</string>
@@ -298,7 +295,6 @@
   <string name="prefs_category_instant_uploading">Instant Uploads</string>
   <string name="prefs_category_security">Security</string>
   <string name="prefs_instant_video_upload_path_title">Upload Video Path</string>
-  <string name="download_folder_failed_content">Download of %1$s folder could not be completed</string>
   <string name="auth_refresh_button">Refresh connection</string>
   <string name="auth_host_address">Server address</string>
   <string name="common_error_out_memory">Not enough memory</string>

+ 0 - 2
res/values-eo/strings.xml

@@ -53,8 +53,6 @@
   <string name="common_yes">Jes</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">Akcepti</string>
-  <string name="common_cancel_download">Nuligi elŝuton</string>
-  <string name="common_cancel_upload">Nuligi alŝuton</string>
   <string name="common_cancel">Nuligi</string>
   <string name="common_save_exit">Konservi kaj forlasi</string>
   <string name="common_error">Eraro</string>

+ 0 - 4
res/values-es-rAR/strings.xml

@@ -72,15 +72,12 @@
   <string name="filedetails_created">Creado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Descargar</string>
-  <string name="filedetails_sync_file">Actualizar archivo</string>
   <string name="filedetails_renamed_in_upload_msg">El archivo fue renombrado como %1$s durante la subida</string>
   <string name="action_share_file">Compartir vínculo</string>
   <string name="action_unshare_file">Dejar de compartir vínculo</string>
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">Aceptar</string>
-  <string name="common_cancel_download">Cancelar descarga</string>
-  <string name="common_cancel_upload">Cancelar subida</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Guardar y salir</string>
   <string name="common_error">Error</string>
@@ -278,6 +275,5 @@
   <string name="prefs_category_instant_uploading">Subida Instantánea </string>
   <string name="prefs_category_security">Seguridad</string>
   <string name="prefs_instant_video_upload_path_title">Dirección de subida del video</string>
-  <string name="download_folder_failed_content">La descarga de la carpeta %1$s no pudo ser completada</string>
   <string name="auth_host_address">Dirección del servidor</string>
 </resources>

+ 0 - 3
res/values-es-rCL/strings.xml

@@ -43,13 +43,10 @@
   <string name="filedetails_created">Creado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Descargar</string>
-  <string name="filedetails_sync_file">refrescar archivo</string>
   <string name="filedetails_renamed_in_upload_msg">El archivo fue renombrado a %1$s durante la subida</string>
   <string name="common_yes">Si</string>
   <string name="common_no">No</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">cancelar bajada</string>
-  <string name="common_cancel_upload">cancelar subida</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Guardar&amp;Salir</string>
   <string name="common_error">Error</string>

+ 0 - 3
res/values-es-rMX/strings.xml

@@ -58,14 +58,11 @@
   <string name="filedetails_created">Creado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Descargar</string>
-  <string name="filedetails_sync_file">Actualizar archivo</string>
   <string name="filedetails_renamed_in_upload_msg">El archivo fue renombrado como %1$s durante la subida</string>
   <string name="action_share_file">Enlace compartido</string>
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">Aceptar</string>
-  <string name="common_cancel_download">Cancelar descarga</string>
-  <string name="common_cancel_upload">Cancelar subida</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Guardar &amp; Salir</string>
   <string name="common_error">Error</string>

+ 0 - 4
res/values-es/strings.xml

@@ -79,7 +79,6 @@
   <string name="filedetails_created">Creado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Descargar</string>
-  <string name="filedetails_sync_file">Actualizar archivo</string>
   <string name="filedetails_renamed_in_upload_msg">El fichero fue renombrado como %1$s durante la subida</string>
   <string name="list_layout">Diseño de lista</string>
   <string name="action_share_file">Compartir con enlace</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">Aceptar</string>
-  <string name="common_cancel_download">Cancelar descarga</string>
-  <string name="common_cancel_upload">Cancelar subida</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Guardar &amp; Salir</string>
   <string name="common_error">Error</string>
@@ -316,7 +313,6 @@
   <string name="prefs_category_instant_uploading">Subidas instantáneas</string>
   <string name="prefs_category_security">Seguridad</string>
   <string name="prefs_instant_video_upload_path_title">Guardar videos subidos en la carpeta:</string>
-  <string name="download_folder_failed_content">La descarga de la carpeta %1$s no ha podido ser completada</string>
   <string name="shared_subject_header">compartido</string>
   <string name="with_you_subject_header">con usted</string>
   <string name="subject_token">%1$s compartió \"%2$s\" conmigo</string>

+ 0 - 4
res/values-et-rEE/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">Loodud:</string>
   <string name="filedetails_modified">Muudetud:</string>
   <string name="filedetails_download">Lae alla</string>
-  <string name="filedetails_sync_file">Värskenda faili</string>
   <string name="filedetails_renamed_in_upload_msg">Fail nimetati üleslaadimise käigus ümber %1$ </string>
   <string name="list_layout">Nimekirja paigutus</string>
   <string name="action_share_file">Jaga linki</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Jah</string>
   <string name="common_no">Ei</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Tühista allalaadimine</string>
-  <string name="common_cancel_upload">Tühista üleslaadimine</string>
   <string name="common_cancel">Loobu</string>
   <string name="common_save_exit">Salvesta &amp; Välju</string>
   <string name="common_error">Viga</string>
@@ -319,7 +316,6 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi
   <string name="prefs_category_instant_uploading">Kohesed üleslaadimised</string>
   <string name="prefs_category_security">Turvalisus</string>
   <string name="prefs_instant_video_upload_path_title">Video üleslaadimise asukoht</string>
-  <string name="download_folder_failed_content">Kausta %1$s  allalaadimine ei õnnestunud</string>
   <string name="shared_subject_header">jagatud</string>
   <string name="with_you_subject_header">sinuga</string>
   <string name="subject_token">%1$s jagas sinuga \"%2$s\"</string>

+ 0 - 4
res/values-eu/strings.xml

@@ -70,15 +70,12 @@
   <string name="filedetails_created">Sortuta:</string>
   <string name="filedetails_modified">Aldatuta:</string>
   <string name="filedetails_download">Deskargatu</string>
-  <string name="filedetails_sync_file">Freskatu fitxaegia</string>
   <string name="filedetails_renamed_in_upload_msg">Fitxategiaren izena %1$sra aldatu da igotzean</string>
   <string name="action_share_file">Elkarbanatu lotura</string>
   <string name="action_unshare_file">Lotura partekatzeari utzi</string>
   <string name="common_yes">Bai</string>
   <string name="common_no">Ez</string>
   <string name="common_ok">Ados</string>
-  <string name="common_cancel_download">Utzi deskarga bertan behera </string>
-  <string name="common_cancel_upload">Ezeztatu igoera</string>
   <string name="common_cancel">Ezeztatu</string>
   <string name="common_save_exit">Gorde eta Irten</string>
   <string name="common_error">Errorea</string>
@@ -278,6 +275,5 @@ Mesedez, baimendu berriz</string>
   <string name="prefs_category_instant_uploading">Berehalako Igoerak</string>
   <string name="prefs_category_security">Segurtasuna</string>
   <string name="prefs_instant_video_upload_path_title">Bideo Igoera Bidea</string>
-  <string name="download_folder_failed_content">%1$s karpetaren deskarga ezin izan da burutu</string>
   <string name="auth_host_address">Zerbitzariaren helbidea</string>
 </resources>

+ 0 - 4
res/values-fa/strings.xml

@@ -70,15 +70,12 @@
   <string name="filedetails_created">ایجاد شده توسط:</string>
   <string name="filedetails_modified">تغییر یافته توسط:</string>
   <string name="filedetails_download">بارگیری</string>
-  <string name="filedetails_sync_file">بازنمایی فایل</string>
   <string name="filedetails_renamed_in_upload_msg">فایل در هنگام بارگزاری به %1$s تغییر نام یافت</string>
   <string name="action_share_file">اشتراک گذاشتن لینک</string>
   <string name="action_unshare_file">لغو اشتراک گذاشتن لینک</string>
   <string name="common_yes">بله</string>
   <string name="common_no">نه</string>
   <string name="common_ok">باشه</string>
-  <string name="common_cancel_download">قطع دانلود</string>
-  <string name="common_cancel_upload">متوقف کردن بار گذاری</string>
   <string name="common_cancel">منصرف شدن</string>
   <string name="common_save_exit">ذخیره سازی و خروج</string>
   <string name="common_error">خطا</string>
@@ -282,7 +279,6 @@
   <string name="prefs_category_instant_uploading">آپلودهای فوری</string>
   <string name="prefs_category_security">امنیت</string>
   <string name="prefs_instant_video_upload_path_title">مسیر آپلود ویدئو</string>
-  <string name="download_folder_failed_content">امکان تکمیل دانلود پوشه  %1$s وجود ندارد</string>
   <string name="shared_subject_header">به اشتراک گذاشته شد</string>
   <string name="with_you_subject_header">با تو</string>
   <string name="subject_token">\"%2$s\" توسط %1$s با شما به اشتراک گذاشته شد</string>

+ 3 - 3
res/values-fi-rFI/strings.xml

@@ -79,7 +79,7 @@
   <string name="filedetails_created">Luotu:</string>
   <string name="filedetails_modified">Muokattu:</string>
   <string name="filedetails_download">Lataa</string>
-  <string name="filedetails_sync_file">Päivitä tiedosto</string>
+  <string name="filedetails_sync_file">Synkronoi</string>
   <string name="filedetails_renamed_in_upload_msg">Tiedoston nimeksi muutettiin %1$s siirron yhteydessä</string>
   <string name="list_layout">Luettelon asettelu</string>
   <string name="action_share_file">Jaa linkki</string>
@@ -87,8 +87,7 @@
   <string name="common_yes">Kyllä</string>
   <string name="common_no">Ei</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Peru lataus</string>
-  <string name="common_cancel_upload">Peru lähetys</string>
+  <string name="common_cancel_sync">Peru synkronointi</string>
   <string name="common_cancel">Peru</string>
   <string name="common_save_exit">Tallenna ja poistu</string>
   <string name="common_error">Virhe</string>
@@ -296,6 +295,7 @@
   <string name="copy_file_error">Tätä tiedostoa tai kansiota kopioitaessa tapahtui virhe</string>
   <string name="prefs_category_instant_uploading">Välittömät lähetykset</string>
   <string name="prefs_category_security">Tietoturva</string>
+  <string name="sync_folder_failed_content">Kansion %1$s synkronointia ei voitu suorittaa kokonaan</string>
   <string name="shared_subject_header">jaettu</string>
   <string name="with_you_subject_header">kanssasi</string>
   <string name="subject_token">%1$s jakoi kohteen \"%2$s\" kanssasi</string>

+ 3 - 4
res/values-fr/strings.xml

@@ -80,7 +80,7 @@ Téléchargez-le ici : %2$s</string>
   <string name="filedetails_created">Créé le :</string>
   <string name="filedetails_modified">Modifié le :</string>
   <string name="filedetails_download">Télécharger</string>
-  <string name="filedetails_sync_file">Actualiser le fichier</string>
+  <string name="filedetails_sync_file">Synchroniser</string>
   <string name="filedetails_renamed_in_upload_msg">Le fichier a été renommé en %s pendant le téléversement</string>
   <string name="list_layout">Affichage en liste</string>
   <string name="action_share_file">Partager le lien</string>
@@ -88,8 +88,7 @@ Téléchargez-le ici : %2$s</string>
   <string name="common_yes">Oui</string>
   <string name="common_no">Non</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Annuler le téléchargement</string>
-  <string name="common_cancel_upload">Annuler le téléversement</string>
+  <string name="common_cancel_sync">Annuler la synchronisation</string>
   <string name="common_cancel">Annuler</string>
   <string name="common_save_exit">Sauvegarder &amp; Quitter</string>
   <string name="common_error">Erreur</string>
@@ -320,7 +319,7 @@ Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxq
   <string name="prefs_category_instant_uploading">Téléversement immédiat</string>
   <string name="prefs_category_security">Sécurité</string>
   <string name="prefs_instant_video_upload_path_title">Répertoire de téléversement des vidéos</string>
-  <string name="download_folder_failed_content">Le téléchargement du dossier %1$s n\'a pas pu être achevé</string>
+  <string name="sync_folder_failed_content">La synchronisation du dossier %1$s n\'a pas pu être terminée</string>
   <string name="shared_subject_header">a partagé</string>
   <string name="with_you_subject_header">avec vous</string>
   <string name="subject_token">%1$s a partagé \"%2$s\" avec vous</string>

+ 0 - 4
res/values-gl/strings.xml

@@ -79,7 +79,6 @@ Descárgueo de aquí: %2$s</string>
   <string name="filedetails_created">Creado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Descargar</string>
-  <string name="filedetails_sync_file">Actualizar o ficheiro</string>
   <string name="filedetails_renamed_in_upload_msg">O ficheiro foi renomeado a %1$s durante o envío</string>
   <string name="list_layout">Deseño da lista</string>
   <string name="action_share_file">Ligazón para compartir</string>
@@ -87,8 +86,6 @@ Descárgueo de aquí: %2$s</string>
   <string name="common_yes">Si</string>
   <string name="common_no">Non</string>
   <string name="common_ok">Aceptar</string>
-  <string name="common_cancel_download">Cancelar a descarga</string>
-  <string name="common_cancel_upload">Cancelar o envío</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Gardar e saír</string>
   <string name="common_error">Erro</string>
@@ -311,7 +308,6 @@ Descárgueo de aquí: %2$s</string>
   <string name="prefs_category_instant_uploading">Envío instantáneo</string>
   <string name="prefs_category_security">Seguridade</string>
   <string name="prefs_instant_video_upload_path_title">Enviar a ruta do vídeo</string>
-  <string name="download_folder_failed_content">Non foi posíbel completar a descarga do cartafol %1$s</string>
   <string name="shared_subject_header">compartido</string>
   <string name="with_you_subject_header">con vostede</string>
   <string name="subject_token">%1$s compartiu «%2$s» con vostede</string>

+ 0 - 3
res/values-he/strings.xml

@@ -63,15 +63,12 @@
   <string name="filedetails_created">מועד היצירה:</string>
   <string name="filedetails_modified">מועד השינוי:</string>
   <string name="filedetails_download">הורדה</string>
-  <string name="filedetails_sync_file">רענון קובץ</string>
   <string name="filedetails_renamed_in_upload_msg">שם הקובץ השתנה ל־ %1$s במהלך ההעלאה</string>
   <string name="action_share_file">קישור לשיתוף</string>
   <string name="action_unshare_file">ביטול קישור לשיתוף</string>
   <string name="common_yes">כן</string>
   <string name="common_no">לא</string>
   <string name="common_ok">אישור</string>
-  <string name="common_cancel_download">ביטול ההורדה</string>
-  <string name="common_cancel_upload">ביטול ההעלאה</string>
   <string name="common_cancel">ביטול</string>
   <string name="common_save_exit">לשמור ולצאת</string>
   <string name="common_error">שגיאה</string>

+ 0 - 1
res/values-hr/strings.xml

@@ -47,7 +47,6 @@
   <string name="common_yes">Da</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">U redu</string>
-  <string name="common_cancel_upload">Prekini upload</string>
   <string name="common_cancel">Odustani</string>
   <string name="common_error">Greška</string>
   <string name="common_error_unknown">Nepoznata pogreška</string>

+ 0 - 3
res/values-hu-rHU/strings.xml

@@ -74,15 +74,12 @@
   <string name="filedetails_created">Készült:</string>
   <string name="filedetails_modified">Módosítva:</string>
   <string name="filedetails_download">Letöltés</string>
-  <string name="filedetails_sync_file">File frissítése</string>
   <string name="filedetails_renamed_in_upload_msg">A feltöltés során az állmányt erre neveztük át: %1$s</string>
   <string name="action_share_file">Megosztás hivatkozással</string>
   <string name="action_unshare_file">Megosztás visszavonása</string>
   <string name="common_yes">Igen</string>
   <string name="common_no">Nem</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">A letöltés megszakítása</string>
-  <string name="common_cancel_upload">A feltöltés megszakítása</string>
   <string name="common_cancel">Mégsem</string>
   <string name="common_save_exit">Mentés &amp; Kilépés</string>
   <string name="common_error">Hiba</string>

+ 17 - 0
res/values-hy/strings.xml

@@ -1,5 +1,6 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <resources>
+  <string name="about_version">տարբերակ %1$s</string>
   <string name="actionbar_upload_files">Ֆայլեր</string>
   <string name="actionbar_mkdir">Նոր պանակ</string>
   <string name="actionbar_send_file">Ուղարկել</string>
@@ -9,15 +10,31 @@
   <!--<string name="drawer_item_accounts">Accounts</string>-->
   <!--TODO re-enable when "On Device" is available
     <string name="drawer_item_on_device">On device</string>-->
+  <string name="drawer_close">Փակել</string>
   <string name="drawer_open">Բացել</string>
   <string name="auth_password">Գաղտնաբառ</string>
   <string name="sync_string_files">Ֆայլեր</string>
   <string name="uploader_btn_new_folder_text">Նոր պանակ</string>
+  <string name="file_list_seconds_ago">վրկ. առաջ</string>
+  <string name="filedetails_size">Չափս.</string>
   <string name="filedetails_download">Բեռնել</string>
   <string name="action_share_file">Կիսվել հղմամբ</string>
+  <string name="common_yes">Այո</string>
+  <string name="common_no">Ոչ</string>
   <string name="common_cancel">Չեղարկել</string>
   <string name="common_rename">Վերանվանել</string>
   <string name="ssl_validator_label_C">Երկիր.</string>
+  <string name="ssl_validator_label_validity_from">Ումից.</string>
+  <string name="ssl_validator_label_validity_to">Ում.</string>
+  <string name="placeholder_filesize">389 ԿԲ</string>
   <string name="activity_chooser_send_file_title">Ուղարկել</string>
   <string name="empty"></string>
+  <string name="file_list__footer__folder">1 պանակ</string>
+  <string name="file_list__footer__folders">%1$d պանակ</string>
+  <string name="file_list__footer__file">1 ֆայլ</string>
+  <string name="file_list__footer__file_and_folder">1 ֆայլ, 1 պանակ</string>
+  <string name="file_list__footer__file_and_folders">1 ֆայլ, %1$d պանակ</string>
+  <string name="file_list__footer__files">%1$d ֆայլ</string>
+  <string name="file_list__footer__files_and_folder">%1$d ֆայլ, 1 պանակ</string>
+  <string name="file_list__footer__files_and_folders">%1$d ֆայլ, %2$d պանակ</string>
 </resources>

+ 0 - 1
res/values-ia/strings.xml

@@ -33,7 +33,6 @@
   <string name="common_yes">Si</string>
   <string name="common_no">No</string>
   <string name="common_ok">Ok</string>
-  <string name="common_cancel_download">Cancellar discarga</string>
   <string name="common_cancel">Cancellar</string>
   <string name="common_error">Error</string>
   <string name="common_error_unknown">Error Incognite</string>

+ 0 - 4
res/values-id/strings.xml

@@ -79,7 +79,6 @@
   <string name="filedetails_created">Dibuat:</string>
   <string name="filedetails_modified">Diubah:</string>
   <string name="filedetails_download">Unduh</string>
-  <string name="filedetails_sync_file">Segarkan berkas</string>
   <string name="filedetails_renamed_in_upload_msg">Berkas diubah namanya menjadi %1$s saat pengunggahan</string>
   <string name="list_layout">Daftar Tata Letak</string>
   <string name="action_share_file">Bagikan tautan</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">Ya</string>
   <string name="common_no">Tidak</string>
   <string name="common_ok">Oke</string>
-  <string name="common_cancel_download">Batal mengunduh</string>
-  <string name="common_cancel_upload">Batal mengunggah</string>
   <string name="common_cancel">Batal</string>
   <string name="common_save_exit">Simpan &amp; Keluar</string>
   <string name="common_error">Kesalahan</string>
@@ -316,7 +313,6 @@
   <string name="prefs_category_instant_uploading">Unggah Cepat</string>
   <string name="prefs_category_security">Keamanan</string>
   <string name="prefs_instant_video_upload_path_title">Unggah Lokasi Video</string>
-  <string name="download_folder_failed_content">Mengunduh folder %1$s  tidak selesai</string>
   <string name="shared_subject_header">dibagikan</string>
   <string name="with_you_subject_header">kepada Anda</string>
   <string name="subject_token">%1$s dibagikan \"%2$s\" kepada Anda</string>

+ 0 - 1
res/values-is/strings.xml

@@ -24,7 +24,6 @@
   <string name="common_yes">Já</string>
   <string name="common_no">Nei</string>
   <string name="common_ok">Í lagi</string>
-  <string name="common_cancel_upload">Hætta við innsendingu</string>
   <string name="common_cancel">Hætta við</string>
   <string name="common_error"><strong>Villa</strong></string>
   <string name="change_password">Breyta lykilorði</string>

+ 3 - 4
res/values-it/strings.xml

@@ -79,7 +79,7 @@
   <string name="filedetails_created">Creato:</string>
   <string name="filedetails_modified">Modificato:</string>
   <string name="filedetails_download">Scarica</string>
-  <string name="filedetails_sync_file">Aggiorna file</string>
+  <string name="filedetails_sync_file">Sincronizza</string>
   <string name="filedetails_renamed_in_upload_msg">Il file è stato rinominato in %1$s durante il caricamento</string>
   <string name="list_layout">Struttura elenco</string>
   <string name="action_share_file">Condividi collegamento</string>
@@ -87,8 +87,7 @@
   <string name="common_yes">Sì</string>
   <string name="common_no">No</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Annulla lo scaricamento</string>
-  <string name="common_cancel_upload">Annulla caricamento</string>
+  <string name="common_cancel_sync">Annulla sincronizzazione</string>
   <string name="common_cancel">Annulla</string>
   <string name="common_save_exit">Salva ed esci</string>
   <string name="common_error">Errore</string>
@@ -316,7 +315,7 @@
   <string name="prefs_category_instant_uploading">Caricamenti istantanei</string>
   <string name="prefs_category_security">Protezione</string>
   <string name="prefs_instant_video_upload_path_title">Percorso di caricamento video</string>
-  <string name="download_folder_failed_content">Lo scaricamento della cartella %1$s non può essere completato</string>
+  <string name="sync_folder_failed_content">La sincronizzazione della cartella %1$s non può essere completata</string>
   <string name="shared_subject_header">condiviso</string>
   <string name="with_you_subject_header">con te</string>
   <string name="subject_token">%1$s ha condiviso \"%2$s\" con te</string>

+ 0 - 4
res/values-ja-rJP/strings.xml

@@ -79,7 +79,6 @@
   <string name="filedetails_created">作成:</string>
   <string name="filedetails_modified">更新:</string>
   <string name="filedetails_download">ダウンロード</string>
-  <string name="filedetails_sync_file">ファイルを同期</string>
   <string name="filedetails_renamed_in_upload_msg">アップロード中にファイル名を %1$s に変更しました</string>
   <string name="list_layout">リストレイアウト</string>
   <string name="action_share_file">URLで共有</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">はい</string>
   <string name="common_no">いいえ</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">ダウンロードをキャンセル</string>
-  <string name="common_cancel_upload">アップロードをキャンセル</string>
   <string name="common_cancel">キャンセル</string>
   <string name="common_save_exit">保存して終了</string>
   <string name="common_error">エラー</string>
@@ -308,7 +305,6 @@
   <string name="prefs_category_instant_uploading">自動アップロード</string>
   <string name="prefs_category_security">セキュリティ</string>
   <string name="prefs_instant_video_upload_path_title">動画のアップロードパス</string>
-  <string name="download_folder_failed_content">%1$s フォルダーのダウンロードが完了しませんでした</string>
   <string name="shared_subject_header">共有中</string>
   <string name="with_you_subject_header">あなたと</string>
   <string name="subject_token">%1$s は \"%2$s\" をあなたと共有しました</string>

+ 0 - 2
res/values-ka-rGE/strings.xml

@@ -46,8 +46,6 @@
   <string name="common_yes">კი</string>
   <string name="common_no">არა</string>
   <string name="common_ok">დიახ</string>
-  <string name="common_cancel_download">ჩამოტვირთვის შეჩერება</string>
-  <string name="common_cancel_upload">ატვირთვის გაუქმება</string>
   <string name="common_cancel">გაუქმება</string>
   <string name="common_save_exit">შენახვა &amp;გამოსვლა</string>
   <string name="common_error">შეცდომა</string>

+ 0 - 2
res/values-km/strings.xml

@@ -58,8 +58,6 @@
   <string name="common_yes">ព្រម</string>
   <string name="common_no">ទេ</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">បោះបង់ការទាញយក</string>
-  <string name="common_cancel_upload">បោះបង់​ការ​ផ្ទុកឡើង</string>
   <string name="common_cancel">លើកលែង</string>
   <string name="common_save_exit">រក្សាទុក &amp; ចាកចេញ</string>
   <string name="common_error">កំហុស</string>

+ 0 - 1
res/values-kn/strings.xml

@@ -25,7 +25,6 @@
   <string name="common_yes">ಹೌದು</string>
   <string name="common_no">ಇಲ್ಲ</string>
   <string name="common_ok">ಸರಿ</string>
-  <string name="common_cancel_upload">ವರ್ಗಾವಣೆ ರದ್ದು ಮಾಡಿ</string>
   <string name="common_cancel">ರದ್ದು</string>
   <string name="common_error">ತಪ್ಪಾಗಿದೆ</string>
   <string name="common_error_unknown">ಗೊತ್ತಿಲ್ಲದ ದೋಷ</string>

+ 0 - 4
res/values-ko/strings.xml

@@ -79,7 +79,6 @@
   <string name="filedetails_created">만든 날짜:</string>
   <string name="filedetails_modified">수정한 날짜:</string>
   <string name="filedetails_download">다운로드</string>
-  <string name="filedetails_sync_file">파일 새로 고침</string>
   <string name="filedetails_renamed_in_upload_msg">업로드 중 파일 이름을 %1$s(으)로 변경하였습니다</string>
   <string name="list_layout">목록 레이아웃</string>
   <string name="action_share_file">링크 공유</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">예</string>
   <string name="common_no">아니요</string>
   <string name="common_ok">확인</string>
-  <string name="common_cancel_download">다운로드 취소</string>
-  <string name="common_cancel_upload">업로드 취소</string>
   <string name="common_cancel">취소</string>
   <string name="common_save_exit">저장하고 끝내기</string>
   <string name="common_error">오류</string>
@@ -315,7 +312,6 @@
   <string name="prefs_category_instant_uploading">즉시 업로드</string>
   <string name="prefs_category_security">보안</string>
   <string name="prefs_instant_video_upload_path_title">동영상 업로드 경로</string>
-  <string name="download_folder_failed_content">폴더 %1$s을(를) 다운로드할 수 없음</string>
   <string name="shared_subject_header">공유됨</string>
   <string name="with_you_subject_header">여러분과</string>
   <string name="subject_token">%1$s 님이 \"%2$s\" 항목을 여러분과 공유하였습니다</string>

+ 0 - 4
res/values-lb/strings.xml

@@ -62,13 +62,10 @@
   <string name="filedetails_created">Erstallt:</string>
   <string name="filedetails_modified">Geännert:</string>
   <string name="filedetails_download">Eroflueden</string>
-  <string name="filedetails_sync_file">Fichier opfrëschen</string>
   <string name="action_share_file">Link deelen</string>
   <string name="common_yes">Jo</string>
   <string name="common_no">Nee</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Eroflueden ofbriechen</string>
-  <string name="common_cancel_upload">Eroplueden ofbriechen</string>
   <string name="common_cancel">Ofbriechen</string>
   <string name="common_save_exit">Späicheren an Zoumaachen</string>
   <string name="common_error">Feeler</string>
@@ -230,7 +227,6 @@
   <string name="prefs_category_instant_uploading">Direkt eropgeluede Fichieren</string>
   <string name="prefs_category_security">Sécherheet</string>
   <string name="prefs_instant_video_upload_path_title">Pad fir d\'Eropluede vun de Videoen</string>
-  <string name="download_folder_failed_content">D\'Erofluede vum %1$s-Dossier konnt net ofgeschloss ginn</string>
   <string name="auth_refresh_button">Connectioun opfrëschen</string>
   <string name="auth_host_address">Server-Adress</string>
 </resources>

+ 0 - 4
res/values-lt-rLT/strings.xml

@@ -79,7 +79,6 @@
   <string name="filedetails_created">Sukurta:</string>
   <string name="filedetails_modified">Modifikuota:</string>
   <string name="filedetails_download">Atsisiųsti</string>
-  <string name="filedetails_sync_file">Atnaujinti failą</string>
   <string name="filedetails_renamed_in_upload_msg">Įkėlimo metu failas buvo pervadintas į %1$s</string>
   <string name="list_layout">Sąrašo išdėstymas</string>
   <string name="action_share_file">Dalintis nuoroda</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">Taip</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">Gerai</string>
-  <string name="common_cancel_download">Atšaukti parsiuntimą</string>
-  <string name="common_cancel_upload">Atšaukti siuntimą</string>
   <string name="common_cancel">Atšaukti</string>
   <string name="common_save_exit">Išsaugoti ir Išeiti</string>
   <string name="common_error">Klaida</string>
@@ -313,7 +310,6 @@
   <string name="prefs_category_instant_uploading">Momentinis įkėlimas</string>
   <string name="prefs_category_security">Saugumas</string>
   <string name="prefs_instant_video_upload_path_title">Vaizdo įrašų įkėlimo kelias</string>
-  <string name="download_folder_failed_content">Nepavyko baigti %1$s atsiuntimo</string>
   <string name="shared_subject_header">Dalinamasi</string>
   <string name="with_you_subject_header">su jumis</string>
   <string name="subject_token">%1$s dalinamasi \"%2$s\" su jumis</string>

+ 31 - 3
res/values-lv/strings.xml

@@ -21,8 +21,11 @@
     	<item>Biggest - Smallest</item>-->
   <!--TODO re-enable when "Accounts" is available in Navigation Drawer-->
   <!--<string name="drawer_item_accounts">Accounts</string>-->
+  <string name="drawer_item_all_files">Visas datnes</string>
   <!--TODO re-enable when "On Device" is available
     <string name="drawer_item_on_device">On device</string>-->
+  <string name="drawer_item_settings">Iestatījumi</string>
+  <string name="drawer_close">Aizvērt</string>
   <string name="drawer_open">Atvērt</string>
   <string name="prefs_category_general">Vispārīgi</string>
   <string name="prefs_category_more">Vairāk</string>
@@ -40,6 +43,8 @@
   <string name="prefs_help">Palīdzība</string>
   <string name="prefs_recommend">Ieteikt draugam</string>
   <string name="prefs_feedback">Atsauksmes</string>
+  <string name="recommend_subject">Izmēģini %1$s uz savu viedtālruni!</string>
+  <string name="auth_check_server">Pārbaudīt serveri</string>
   <string name="auth_username">Lietotājvārds</string>
   <string name="auth_password">Parole</string>
   <string name="sync_string_files">Datnes</string>
@@ -56,6 +61,7 @@
   <string name="uploader_info_uploading">Augšupielādē</string>
   <string name="file_list_seconds_ago">sekundes atpakaļ</string>
   <string name="file_list_empty">Te vēl nekas nav. Rīkojies, sāc augšupielādēt!</string>
+  <string name="file_list_loading">Ielādē…</string>
   <string name="local_file_list_empty">Šajā mapē nav failu</string>
   <string name="filedetails_select_file">Uzsitiet uz datnes, lai redzētu papildinformāciju.</string>
   <string name="filedetails_size">Izmērs:</string>
@@ -63,13 +69,12 @@
   <string name="filedetails_created">Izveidota:</string>
   <string name="filedetails_modified">Modificēta:</string>
   <string name="filedetails_download">Lejupielādēt</string>
-  <string name="filedetails_sync_file">Atsvaidzināt failu</string>
   <string name="filedetails_renamed_in_upload_msg">Datne tika pārsaukta uz %1$s augšupielādes laikā</string>
+  <string name="action_share_file">Dalīt saiti</string>
+  <string name="action_unshare_file">Pārtraukt dalīt saiti</string>
   <string name="common_yes">Jā</string>
   <string name="common_no">Nē</string>
   <string name="common_ok">Labi</string>
-  <string name="common_cancel_download">Atcelt lejupielādi</string>
-  <string name="common_cancel_upload">Atcelt augšupielādi</string>
   <string name="common_cancel">Atcelt</string>
   <string name="common_save_exit">Saglabāt un iziet</string>
   <string name="common_error">Kļūda</string>
@@ -119,6 +124,7 @@
   <string name="common_remove">Izņemt</string>
   <string name="confirmation_remove_local">Tikai lokālos</string>
   <string name="confirmation_remove_folder_local">Tikai lokālos</string>
+  <string name="confirmation_remove_remote">No servera</string>
   <string name="remove_success_msg">Veiksmīgi izņemts</string>
   <string name="remove_fail_msg">Neizdevās izņemt</string>
   <string name="rename_dialog_title">Ievadīt jaunu nosaukumu</string>
@@ -126,6 +132,7 @@
   <string name="rename_server_fail_msg">Nevarēja pabeigt pārsaukšanu</string>
   <string name="sync_file_fail_msg">Nevarēja atzīmēt attālinātas datnes</string>
   <string name="sync_file_nothing_to_do_msg">Datnes saturs jau ir sinhronizēts</string>
+  <string name="create_dir_fail_msg">Mapi nevarēja izveidot</string>
   <string name="wait_a_moment">Uzgaidīt brīdi</string>
   <string name="filedisplay_unexpected_bad_get_content">Negaidīta problēma; lūdzu, izvēlieties datni no citas lietotnes</string>
   <string name="filedisplay_no_file_selected">Netika izvēlēta neviena datne</string>
@@ -151,14 +158,35 @@
   <string name="ssl_validator_label_validity_to">Kam:</string>
   <string name="ssl_validator_label_signature">Paraksts:</string>
   <string name="ssl_validator_label_signature_algorithm">Algoritms:</string>
+  <string name="placeholder_filetype">PNG attēls</string>
   <string name="instant_upload_on_wifi">Attēlus augšupielādēt tikai caur WiFi</string>
   <string name="instant_upload_path">/TūlītējaAugšupielāde</string>
   <string name="conflict_keep_both">Paturēt abas</string>
+  <string name="preview_image_error_unknown_format">Šo attēlu nevar attēlot</string>
+  <string name="share_link_password_title">Ievadiet paroli</string>
+  <string name="share_link_empty_password">Jums ir jāievada paroli</string>
   <string name="activity_chooser_send_file_title">Sūtīt</string>
+  <string name="copy_link">Kopēt saiti</string>
   <string name="empty"></string>
+  <string name="forbidden_permissions_rename">lai pārsauktu šo datni</string>
+  <string name="forbidden_permissions_delete">lai dzēstu šo datni</string>
+  <string name="share_link_forbidden_permissions">lai dalītu šo datni</string>
+  <string name="unshare_link_forbidden_permissions">lai pārtrauktu šis datnes dalīšanu</string>
+  <string name="forbidden_permissions_create">lai izveidotu datni</string>
   <string name="prefs_category_accounts">Konti</string>
+  <string name="prefs_add_account">Pievienot kontu</string>
+  <string name="log_progress_dialog_text">Ielādē datus…</string>
   <string name="saml_authentication_wrong_pass">Nepareiza parole</string>
+  <string name="actionbar_move">Pārvietot</string>
+  <string name="file_list_empty_moving">Šeit nekā nav. Jūs varat pievienot mapi!</string>
   <string name="folder_picker_choose_button_text">Izvēlieties</string>
+  <string name="forbidden_permissions_move">lai pārvietotu šo datni</string>
+  <string name="forbidden_permissions_copy">lai kopētu šo datni</string>
   <string name="prefs_category_security">Drošība</string>
+  <string name="shared_subject_header">koplietots</string>
+  <string name="with_you_subject_header">ar jums</string>
   <string name="auth_host_address">Servera adrese</string>
+  <string name="username">Lietotājvārds</string>
+  <string name="file_list__footer__folder">1 mape</string>
+  <string name="file_list__footer__file">1 datne</string>
 </resources>

+ 0 - 4
res/values-mk/strings.xml

@@ -73,15 +73,12 @@
   <string name="filedetails_created">Создадено:</string>
   <string name="filedetails_modified">Изменето:</string>
   <string name="filedetails_download">Преземање</string>
-  <string name="filedetails_sync_file">Освежи ја датотеката</string>
   <string name="filedetails_renamed_in_upload_msg">Датотеката беше преименувана во %1$s за време на префрлањето</string>
   <string name="action_share_file">Сподели ја врската</string>
   <string name="action_unshare_file">Тргнете го споделувањето на врската</string>
   <string name="common_yes">Да</string>
   <string name="common_no">Не</string>
   <string name="common_ok">Во ред</string>
-  <string name="common_cancel_download">Откажи превземање</string>
-  <string name="common_cancel_upload">Откажи прикачување</string>
   <string name="common_cancel">Откажи</string>
   <string name="common_save_exit">Сними &amp; Излез</string>
   <string name="common_error">Грешка</string>
@@ -295,7 +292,6 @@
   <string name="prefs_category_instant_uploading">Инстант прикачувања</string>
   <string name="prefs_category_security">Безбедност</string>
   <string name="prefs_instant_video_upload_path_title">Прикачи патека на видео</string>
-  <string name="download_folder_failed_content">Превземањето на папката %1$s не може да се заврши</string>
   <string name="auth_refresh_button">Освежи ја конекцијата</string>
   <string name="auth_host_address">Адреса на сервер</string>
 </resources>

+ 0 - 1
res/values-ms-rMY/strings.xml

@@ -41,7 +41,6 @@
   <string name="common_yes">Ya</string>
   <string name="common_no">Tidak</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_upload">Batal muat naik</string>
   <string name="common_cancel">Batal</string>
   <string name="common_save_exit">Simpan &amp; Keluar</string>
   <string name="common_error">Ralat</string>

+ 1 - 4
res/values-nb-rNO/strings.xml

@@ -71,6 +71,7 @@
   <string name="file_list_seconds_ago">for få sekunder siden</string>
   <string name="file_list_empty">Ingenting her. Last opp noe!</string>
   <string name="file_list_loading">Laster...</string>
+  <string name="file_list_no_app_for_file_type">Ingen app funnet for filtypen!</string>
   <string name="local_file_list_empty">Det er ingen filer i denne mappen.</string>
   <string name="filedetails_select_file">Trykk på en fil for å vise ekstra informasjon.</string>
   <string name="filedetails_size">Størrelse:</string>
@@ -78,7 +79,6 @@
   <string name="filedetails_created">Opprettet:</string>
   <string name="filedetails_modified">Endret:</string>
   <string name="filedetails_download">Last ned</string>
-  <string name="filedetails_sync_file">Oppdater fil</string>
   <string name="filedetails_renamed_in_upload_msg">Filnavnet ble endret til  %1$s under opplasting</string>
   <string name="list_layout">Listeoppsett</string>
   <string name="action_share_file">Del lenke</string>
@@ -86,8 +86,6 @@
   <string name="common_yes">Ja</string>
   <string name="common_no">Nei</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Avbryt nedlasting</string>
-  <string name="common_cancel_upload">Avbryt opplasting</string>
   <string name="common_cancel">Avbryt</string>
   <string name="common_save_exit">Lagre og avslutt</string>
   <string name="common_error">Feil</string>
@@ -315,7 +313,6 @@
   <string name="prefs_category_instant_uploading">Umiddelbare opplastinger</string>
   <string name="prefs_category_security">Sikkerhet</string>
   <string name="prefs_instant_video_upload_path_title">Sti til video-opplasting</string>
-  <string name="download_folder_failed_content">Nedlasting av %1$s mappen kunne ikke fullføres</string>
   <string name="shared_subject_header">delte</string>
   <string name="with_you_subject_header">med deg</string>
   <string name="subject_token">%1$s delte \"%2$s\" med deg</string>

+ 3 - 4
res/values-nl/strings.xml

@@ -80,7 +80,7 @@ Download hier: %2$s</string>
   <string name="filedetails_created">Aangemaakt:</string>
   <string name="filedetails_modified">Aangepast:</string>
   <string name="filedetails_download">Download</string>
-  <string name="filedetails_sync_file">Bestand verversen</string>
+  <string name="filedetails_sync_file">Synchroniseren</string>
   <string name="filedetails_renamed_in_upload_msg">Bestand is tijdens het uploaden hernoemd naar %1$s</string>
   <string name="list_layout">Lijst layout</string>
   <string name="action_share_file">Deel link</string>
@@ -88,8 +88,7 @@ Download hier: %2$s</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nee</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Annuleer download</string>
-  <string name="common_cancel_upload">Upload afbreken</string>
+  <string name="common_cancel_sync">Annuleren synchronisatie</string>
   <string name="common_cancel">Annuleren</string>
   <string name="common_save_exit">Opslaan &amp; Afsluiten</string>
   <string name="common_error">Fout</string>
@@ -319,7 +318,7 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar
   <string name="prefs_category_instant_uploading">Directe uploads</string>
   <string name="prefs_category_security">Beveiliging</string>
   <string name="prefs_instant_video_upload_path_title">Upload Video Pad</string>
-  <string name="download_folder_failed_content">Download van %1$s map kon niet worden voltooid</string>
+  <string name="sync_folder_failed_content">Synchronisatie van map %1$s kon niet worden voltooid</string>
   <string name="shared_subject_header">gedeeld</string>
   <string name="with_you_subject_header">met u</string>
   <string name="subject_token">%1$s deelde \"%2$s\" met u</string>

+ 0 - 2
res/values-nn-rNO/strings.xml

@@ -62,8 +62,6 @@
   <string name="common_yes">Ja</string>
   <string name="common_no">Nei</string>
   <string name="common_ok">Greitt</string>
-  <string name="common_cancel_download">Avbryt nedlasting</string>
-  <string name="common_cancel_upload">Avbryt opplasting</string>
   <string name="common_cancel">Avbryt</string>
   <string name="common_save_exit">Lagra &amp; avslutt</string>
   <string name="common_error">Feil</string>

+ 0 - 4
res/values-oc/strings.xml

@@ -80,7 +80,6 @@ Telecargatz-lo aicí : %2$s</string>
   <string name="filedetails_created">Creat lo :</string>
   <string name="filedetails_modified">Modificat lo :</string>
   <string name="filedetails_download">Telecargar</string>
-  <string name="filedetails_sync_file">Actualizar lo fichièr</string>
   <string name="filedetails_renamed_in_upload_msg">Lo fichièr es estat renomenat en %s pendent lo mandadís</string>
   <string name="list_layout">Afichatge en lista</string>
   <string name="action_share_file">Partejar lo ligam</string>
@@ -88,8 +87,6 @@ Telecargatz-lo aicí : %2$s</string>
   <string name="common_yes">Òc</string>
   <string name="common_no">Non</string>
   <string name="common_ok">D\'acòrdi</string>
-  <string name="common_cancel_download">Anullar lo telecargament</string>
-  <string name="common_cancel_upload">Anullar lo mandadís</string>
   <string name="common_cancel">Anullar</string>
   <string name="common_save_exit">Salvar &amp; Quitar</string>
   <string name="common_error">Error</string>
@@ -320,7 +317,6 @@ En rason d\'aquesta modificacion, totes los fichièrs mandats amb de versions an
   <string name="prefs_category_instant_uploading">Mandadís immediat</string>
   <string name="prefs_category_security">Seguretat</string>
   <string name="prefs_instant_video_upload_path_title">Repertòri de mandadís de las vidèos</string>
-  <string name="download_folder_failed_content">Lo telecargament del dorsièr %1$s a pas pogut èsser acabat</string>
   <string name="shared_subject_header">a partejat</string>
   <string name="with_you_subject_header">amb vos</string>
   <string name="subject_token">%1$s a partejat \"%2$s\" amb vos</string>

+ 0 - 3
res/values-pa/strings.xml

@@ -40,12 +40,9 @@
   <string name="filedetails_created">ਬਣਾਈ:</string>
   <string name="filedetails_modified">ਸੋਧ ਕੀਤੀ:</string>
   <string name="filedetails_download">ਡਾਊਨਲੋਡ</string>
-  <string name="filedetails_sync_file">ਫਾਇਲ ਤਾਜ਼ਾ ਕਰੋ</string>
   <string name="common_yes">ਹਾਂ</string>
   <string name="common_no">ਨਹੀਂ</string>
   <string name="common_ok">ਠੀਕ ਹੈ</string>
-  <string name="common_cancel_download">ਡਾਊਨਲੋਡ ਕਰਨਾ ਰੱਦ ਕਰੋ</string>
-  <string name="common_cancel_upload">ਅੱਪਲੋਡ ਰੱਦ ਕਰੋ</string>
   <string name="common_cancel">ਰੱਦ ਕਰੋ</string>
   <string name="common_save_exit">ਸੰਭਾਲੋ ਅਤੇ ਬੰਦ ਕਰੋ</string>
   <string name="common_error">ਗਲਤੀ</string>

+ 0 - 4
res/values-pl/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">Utworzono:</string>
   <string name="filedetails_modified">Zmodyfikowano:</string>
   <string name="filedetails_download">Pobierz</string>
-  <string name="filedetails_sync_file">Odśwież plik</string>
   <string name="filedetails_renamed_in_upload_msg">Podczas wysyłania nazwa pliku została zmieniona na %1$s</string>
   <string name="list_layout">Lista szablonów wyglądu</string>
   <string name="action_share_file">Udostępnij link</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Tak</string>
   <string name="common_no">Nie</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Anuluj pobieranie</string>
-  <string name="common_cancel_upload">Anuluj wysyłanie</string>
   <string name="common_cancel">Anuluj</string>
   <string name="common_save_exit">Zapisz i wyjdź</string>
   <string name="common_error">Błąd</string>
@@ -308,7 +305,6 @@
   <string name="prefs_category_instant_uploading">Automatyczne wysyłanie</string>
   <string name="prefs_category_security">Bezpieczeństwo</string>
   <string name="prefs_instant_video_upload_path_title">Katalog wysyłania dla wideo</string>
-  <string name="download_folder_failed_content">Pobieranie %1$s katalogu nie może zostać ukończone</string>
   <string name="shared_subject_header">udostępniony</string>
   <string name="with_you_subject_header">z tobą</string>
   <string name="auth_refresh_button">Odśwież połączenie</string>

+ 3 - 4
res/values-pt-rBR/strings.xml

@@ -79,7 +79,7 @@
   <string name="filedetails_created">Criado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Baixar</string>
-  <string name="filedetails_sync_file">Atualizar arquivo</string>
+  <string name="filedetails_sync_file">Sincronizar</string>
   <string name="filedetails_renamed_in_upload_msg">Arquivo foi renomeado para %1$s durante o envio</string>
   <string name="list_layout">Lista de Layout</string>
   <string name="action_share_file">Compartilhar link</string>
@@ -87,8 +87,7 @@
   <string name="common_yes">Sim</string>
   <string name="common_no">Não</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Cancelar o download</string>
-  <string name="common_cancel_upload">Cancelar envio</string>
+  <string name="common_cancel_sync">Cancelar a sincronização</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Salvar &amp; Sair</string>
   <string name="common_error">Erro</string>
@@ -316,7 +315,7 @@
   <string name="prefs_category_instant_uploading">Envios Instantâneos</string>
   <string name="prefs_category_security">Segurança</string>
   <string name="prefs_instant_video_upload_path_title">Enviar o Caminho do Vídeo</string>
-  <string name="download_folder_failed_content">Baixar %1$s da pasta não pode ser completado</string>
+  <string name="sync_folder_failed_content">A sincronização da pasta %1$s não pode ser finalizada</string>
   <string name="shared_subject_header">compartilhado</string>
   <string name="with_you_subject_header">com você</string>
   <string name="subject_token">%1$s compartilhado \"%2$s\" com você</string>

+ 4 - 4
res/values-pt-rPT/strings.xml

@@ -71,6 +71,7 @@
   <string name="file_list_seconds_ago">segundos atrás</string>
   <string name="file_list_empty">Aqui não existe nada. Envie alguma coisa!</string>
   <string name="file_list_loading">A carregar...</string>
+  <string name="file_list_no_app_for_file_type">Nenhuma App encontrada por tipo de ficheiro!</string>
   <string name="local_file_list_empty">Não existem ficheiros nesta pasta.</string>
   <string name="filedetails_select_file">Toque num ficheiro para visualizar a informação adicional.</string>
   <string name="filedetails_size">Tamanho:</string>
@@ -78,7 +79,7 @@
   <string name="filedetails_created">Criado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Transferir</string>
-  <string name="filedetails_sync_file">Atualizar ficheiro</string>
+  <string name="filedetails_sync_file">Sincronizar</string>
   <string name="filedetails_renamed_in_upload_msg">O ficheiro foi renomeado para %1$s durante o envio.</string>
   <string name="list_layout">Apresentação da Lista</string>
   <string name="action_share_file">Partilhar a hiperligação</string>
@@ -86,8 +87,7 @@
   <string name="common_yes">Sim</string>
   <string name="common_no">Não</string>
   <string name="common_ok">ACEITAR</string>
-  <string name="common_cancel_download">Cancelar a transferência</string>
-  <string name="common_cancel_upload">Cancelar o envio</string>
+  <string name="common_cancel_sync">Cancelar sincronização</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Guardar &amp; Sair</string>
   <string name="common_error">Erro</string>
@@ -313,7 +313,7 @@
   <string name="prefs_category_instant_uploading">Envios Instantâneos</string>
   <string name="prefs_category_security">Segurança</string>
   <string name="prefs_instant_video_upload_path_title">Envio do Caminho do Vídeo</string>
-  <string name="download_folder_failed_content">Não foi possível completar o download da pasta %1$s</string>
+  <string name="sync_folder_failed_content">Não foi possível completar a sincronização da pasta %1$s</string>
   <string name="shared_subject_header">partilhado</string>
   <string name="with_you_subject_header">consigo</string>
   <string name="subject_token">%1$s partilhou \"%2$s\" consigo</string>

+ 0 - 4
res/values-ro/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">Creat:</string>
   <string name="filedetails_modified">Modificat:</string>
   <string name="filedetails_download">Descarcă</string>
-  <string name="filedetails_sync_file">Împrospătare fișier</string>
   <string name="filedetails_renamed_in_upload_msg">Fișierul a fost redenumit %1$s în timpul încărcării</string>
   <string name="list_layout">Aspect listă</string>
   <string name="action_share_file">Partajază legătură</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Da</string>
   <string name="common_no">Nu</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Anulează descărcarea</string>
-  <string name="common_cancel_upload">Anulează încărcarea</string>
   <string name="common_cancel">Anulează</string>
   <string name="common_save_exit">Salvare și ieșire</string>
   <string name="common_error">Eroare</string>
@@ -309,7 +306,6 @@
   <string name="prefs_category_instant_uploading">Încărcări instante</string>
   <string name="prefs_category_security">Securitate</string>
   <string name="prefs_instant_video_upload_path_title">Calea de încărcare Video</string>
-  <string name="download_folder_failed_content">Descărcarea fișierului %1$s nu s-a finisat</string>
   <string name="shared_subject_header">partajat</string>
   <string name="with_you_subject_header">cu tine</string>
   <string name="subject_token">%1$s a partajat fișierul \"%2$s\" cu tine</string>

+ 0 - 4
res/values-ru/strings.xml

@@ -80,7 +80,6 @@
   <string name="filedetails_created">Создан:</string>
   <string name="filedetails_modified">Изменён:</string>
   <string name="filedetails_download">Скачать</string>
-  <string name="filedetails_sync_file">Обновить файл</string>
   <string name="filedetails_renamed_in_upload_msg">Файл был переименован в %1$s во время загрузки</string>
   <string name="list_layout">Макет списка</string>
   <string name="action_share_file">Поделиться ссылкой</string>
@@ -88,8 +87,6 @@
   <string name="common_yes">Да</string>
   <string name="common_no">Нет</string>
   <string name="common_ok">ОК</string>
-  <string name="common_cancel_download">Отменить скачивание</string>
-  <string name="common_cancel_upload">Отменить загрузку</string>
   <string name="common_cancel">Отмена</string>
   <string name="common_save_exit">Сохранить и выйти</string>
   <string name="common_error">Ошибка</string>
@@ -317,7 +314,6 @@
   <string name="prefs_category_instant_uploading">Мгновенные загрузки</string>
   <string name="prefs_category_security">Безопасность</string>
   <string name="prefs_instant_video_upload_path_title">Путь для загрузки Видео</string>
-  <string name="download_folder_failed_content">Не удалось завершить скачивание каталога %1$s</string>
   <string name="shared_subject_header">поделился</string>
   <string name="with_you_subject_header">с вами</string>
   <string name="subject_token">%1$s предоставил вам доступ к \"%2$s\"</string>

+ 0 - 1
res/values-si-rLK/strings.xml

@@ -36,7 +36,6 @@
   <string name="common_yes">ඔව්</string>
   <string name="common_no">එපා</string>
   <string name="common_ok">හරි</string>
-  <string name="common_cancel_upload">උඩුගත කිරීම අත් හරින්න</string>
   <string name="common_cancel">එපා</string>
   <string name="common_save_exit">සුරැක &amp; පිටවන්න</string>
   <string name="common_error">දෝශය</string>

+ 0 - 4
res/values-sk-rSK/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">Vytvorený:</string>
   <string name="filedetails_modified">Zmenený:</string>
   <string name="filedetails_download">Stiahnuť</string>
-  <string name="filedetails_sync_file">Obnoviť súbor</string>
   <string name="filedetails_renamed_in_upload_msg">Súbor bol premenovaný na %1$s počas nahrávania</string>
   <string name="list_layout">Rozvrhnutie zoznamu</string>
   <string name="action_share_file">Zdieľať linku</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Áno</string>
   <string name="common_no">Nie</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Zrušiť sťahovanie</string>
-  <string name="common_cancel_upload">Zrušiť odosielanie</string>
   <string name="common_cancel">Zrušiť</string>
   <string name="common_save_exit">Uložiť a ukončiť</string>
   <string name="common_error">Chyba</string>
@@ -315,7 +312,6 @@
   <string name="prefs_category_instant_uploading">Okamžité nahratie</string>
   <string name="prefs_category_security">Zabezpečenie</string>
   <string name="prefs_instant_video_upload_path_title">Cesta pre nahrávanie videí</string>
-  <string name="download_folder_failed_content">Sťahovanie %1$s priečinka nebolo dokončené</string>
   <string name="shared_subject_header">zdieľané</string>
   <string name="with_you_subject_header">s vami</string>
   <string name="subject_token">%1$s vám zdieľal \"%2$s\"</string>

+ 0 - 4
res/values-sl/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">Ustvarjeno:</string>
   <string name="filedetails_modified">Spremenjeno:</string>
   <string name="filedetails_download">Prejmi</string>
-  <string name="filedetails_sync_file">Osveži datoteko</string>
   <string name="filedetails_renamed_in_upload_msg">Datoteka je bila med nalaganjem preimenovana v %1$s</string>
   <string name="list_layout">Postavitev seznama</string>
   <string name="action_share_file">Povezava za souporabo</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Da</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">V redu</string>
-  <string name="common_cancel_download">Prekliči prejem</string>
-  <string name="common_cancel_upload">Prekliči pošiljanje</string>
   <string name="common_cancel">Prekliči</string>
   <string name="common_save_exit">Shrani in končaj</string>
   <string name="common_error">Napaka</string>
@@ -311,7 +308,6 @@
   <string name="prefs_category_instant_uploading">Takojšnje pošiljanje v oblak</string>
   <string name="prefs_category_security">Varnost</string>
   <string name="prefs_instant_video_upload_path_title">Pot videa za pošiljanje</string>
-  <string name="download_folder_failed_content">Imenika %1$s  ni mogoče prejeti v celoti</string>
   <string name="shared_subject_header">v souporabi</string>
   <string name="with_you_subject_header">z vami</string>
   <string name="subject_token">Uporabnik %1$s je omogočil souporabo \"%2$s\" z vami</string>

+ 3 - 4
res/values-sq/strings.xml

@@ -79,7 +79,7 @@
   <string name="filedetails_created">Krijuar më:</string>
   <string name="filedetails_modified">Ndryshuar më:</string>
   <string name="filedetails_download">Shkarkoje</string>
-  <string name="filedetails_sync_file">Rifreskoje kartelën</string>
+  <string name="filedetails_sync_file">Njëkohëso</string>
   <string name="filedetails_renamed_in_upload_msg">Kartela u riemërtua si %1$s gjatë ngarkimit</string>
   <string name="list_layout">Skemë Liste</string>
   <string name="action_share_file">Ndajeni lidhjen me të tjerët</string>
@@ -87,8 +87,7 @@
   <string name="common_yes">Po</string>
   <string name="common_no">Jo</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Anulojeni shkarkimin</string>
-  <string name="common_cancel_upload">Anulojeni ngarkimin</string>
+  <string name="common_cancel_sync">Anuloje njëkohësimin</string>
   <string name="common_cancel">Anuloje</string>
   <string name="common_save_exit">Ruaje &amp; Dil</string>
   <string name="common_error">Gabim</string>
@@ -312,7 +311,7 @@
   <string name="prefs_category_instant_uploading">Ngarkime të Menjëhershme</string>
   <string name="prefs_category_security">Siguri</string>
   <string name="prefs_instant_video_upload_path_title">Shteg Ngarkimi Videosh</string>
-  <string name="download_folder_failed_content">S\’u plotësua dot shkarkimi i dosjes %1$s</string>
+  <string name="sync_folder_failed_content">Njëkohësimi i dosjes %1$s s’u plotësua dot</string>
   <string name="shared_subject_header">ndarë</string>
   <string name="with_you_subject_header">me ju</string>
   <string name="subject_token">%1$s ndau me ju \"%2$s\"</string>

+ 0 - 1
res/values-sr-rSP/strings.xml

@@ -34,7 +34,6 @@
   <string name="common_yes">Da</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">Ok</string>
-  <string name="common_cancel_upload">Otkaži otpremanje</string>
   <string name="common_cancel">Otkaži</string>
   <string name="common_error">Greška</string>
   <string name="common_error_unknown">Nepoznata greška</string>

+ 0 - 4
res/values-sr/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">Направљен:</string>
   <string name="filedetails_modified">Измењен:</string>
   <string name="filedetails_download">Преузми</string>
-  <string name="filedetails_sync_file">Освежи фајл</string>
   <string name="filedetails_renamed_in_upload_msg">Фајл је преименован у %1$s током отпремања</string>
   <string name="list_layout">Распоред листе</string>
   <string name="action_share_file">Веза дељења</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Да</string>
   <string name="common_no">Не</string>
   <string name="common_ok">У реду</string>
-  <string name="common_cancel_download">Откажи преузимање</string>
-  <string name="common_cancel_upload">Откажи отпремање</string>
   <string name="common_cancel">Откажи</string>
   <string name="common_save_exit">Сачувај и изађи</string>
   <string name="common_error">Грешка</string>
@@ -305,7 +302,6 @@
   <string name="prefs_category_instant_uploading">Тренутна отпремања</string>
   <string name="prefs_category_security">Безбедност</string>
   <string name="prefs_instant_video_upload_path_title">Путања отпремања видеа</string>
-  <string name="download_folder_failed_content">Преузимање фасцикле %1$s не може бити довршено</string>
   <string name="shared_subject_header">дељено</string>
   <string name="with_you_subject_header">са вама</string>
   <string name="subject_token">%1$s подели „%2$s“ са вама</string>

+ 0 - 4
res/values-sv/strings.xml

@@ -72,15 +72,12 @@
   <string name="filedetails_created">Skapad:</string>
   <string name="filedetails_modified">Ändrad:</string>
   <string name="filedetails_download">Ladda ner</string>
-  <string name="filedetails_sync_file">Ladda om fil</string>
   <string name="filedetails_renamed_in_upload_msg">Filen bytte namn till %1$s under uppladdningen</string>
   <string name="action_share_file">Dela länk</string>
   <string name="action_unshare_file">Sluta dela länk</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nej</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Avbryt nedladdning</string>
-  <string name="common_cancel_upload">Avbryt uppladdning</string>
   <string name="common_cancel">Avbryt</string>
   <string name="common_save_exit">Spara &amp; Avsluta</string>
   <string name="common_error">Fel</string>
@@ -284,6 +281,5 @@
   <string name="prefs_category_instant_uploading">Direktuppladning</string>
   <string name="prefs_category_security">Säkerhet</string>
   <string name="prefs_instant_video_upload_path_title">Uppladdnings-sökväg för video</string>
-  <string name="download_folder_failed_content">Neddladning utav %1$s mappen kunde inte slutföras</string>
   <string name="auth_host_address">Serveradress</string>
 </resources>

+ 0 - 2
res/values-ta-rLK/strings.xml

@@ -42,8 +42,6 @@
   <string name="common_yes">ஆம்</string>
   <string name="common_no">இல்லை</string>
   <string name="common_ok">சரி </string>
-  <string name="common_cancel_download">பதிவிறக்கலை இரத்துசெய்க</string>
-  <string name="common_cancel_upload">பதிவேற்றலை இரத்து செய்க</string>
   <string name="common_cancel">இரத்து செய்க</string>
   <string name="common_save_exit">சேமிக்க மற்றும் amp; வெளியேறு</string>
   <string name="common_error">வழு</string>

+ 0 - 4
res/values-th-rTH/strings.xml

@@ -79,7 +79,6 @@
   <string name="filedetails_created">สร้างเมื่อ:</string>
   <string name="filedetails_modified">แก้ไขเมื่อ:</string>
   <string name="filedetails_download">ดาวน์โหลด</string>
-  <string name="filedetails_sync_file">ฟื้นฟูไฟล์</string>
   <string name="filedetails_renamed_in_upload_msg">ไฟล์ได้ถูกเปลี่ยนชื่อเป็น %1$s ในระหว่างการอัพโหลด</string>
   <string name="list_layout">เค้าโครงรายการ</string>
   <string name="action_share_file">แชร์ลิงค์</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">ตกลง</string>
   <string name="common_no">ไม่ตกลง</string>
   <string name="common_ok">ตกลง</string>
-  <string name="common_cancel_download">ยกเลิกการดาวน์โหลด</string>
-  <string name="common_cancel_upload">ยกเลิกการอัพโหลด</string>
   <string name="common_cancel">ยกเลิก</string>
   <string name="common_save_exit">บันทึก &amp; ออก</string>
   <string name="common_error">ข้อผิดพลาด</string>
@@ -314,7 +311,6 @@
   <string name="prefs_category_instant_uploading">อัพโหลดทันที</string>
   <string name="prefs_category_security">ความปลอดภัย</string>
   <string name="prefs_instant_video_upload_path_title">อัพโหลดเส้นทางวิดีโอ</string>
-  <string name="download_folder_failed_content">การดาวน์โหลดโฟลเดอร์ %1$s อาจไม่สำเร็จ</string>
   <string name="shared_subject_header">ถูกแชร์</string>
   <string name="with_you_subject_header">กับคุณ</string>
   <string name="subject_token">%1$s ได้แชร์ \"%2$s\" กับคุณ</string>

+ 0 - 4
res/values-tr/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">Oluşturulma:</string>
   <string name="filedetails_modified">Değiştirilme:</string>
   <string name="filedetails_download">İndir</string>
-  <string name="filedetails_sync_file">Dosyayı yenile</string>
   <string name="filedetails_renamed_in_upload_msg">Dosya adı, yükleme sırasında %1$s olarak değiştirildi</string>
   <string name="list_layout">Liste Yerleşimi</string>
   <string name="action_share_file">Paylaşma bağlantısı</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Evet</string>
   <string name="common_no">Hayır</string>
   <string name="common_ok">Tamam</string>
-  <string name="common_cancel_download">İndirmeyi iptal et</string>
-  <string name="common_cancel_upload">Yüklemeyi iptal et</string>
   <string name="common_cancel">İptal</string>
   <string name="common_save_exit">Kaydet ve Çık</string>
   <string name="common_error">Hata</string>
@@ -315,7 +312,6 @@
   <string name="prefs_category_instant_uploading">Anında Yüklemeler</string>
   <string name="prefs_category_security">Güvenlik</string>
   <string name="prefs_instant_video_upload_path_title">Video Yükleme Yolu</string>
-  <string name="download_folder_failed_content">%1$s klasörün indirilmesi tamamlanamadı</string>
   <string name="shared_subject_header">sizinle</string>
   <string name="with_you_subject_header">paylaştı</string>
   <string name="subject_token">%1$s, sizinle \"%2$s\" paylaşımını yaptı</string>

+ 0 - 1
res/values-ug/strings.xml

@@ -36,7 +36,6 @@
   <string name="common_yes">ھەئە</string>
   <string name="common_no">ياق</string>
   <string name="common_ok">جەزملە</string>
-  <string name="common_cancel_upload">يۈكلەشتىن ۋاز كەچ</string>
   <string name="common_cancel">ۋاز كەچ</string>
   <string name="common_save_exit">ساقلاپ چېكىن</string>
   <string name="common_error">خاتالىق</string>

+ 0 - 4
res/values-uk/strings.xml

@@ -79,7 +79,6 @@
   <string name="filedetails_created">Створено:</string>
   <string name="filedetails_modified">Змінено:</string>
   <string name="filedetails_download">Завантажити</string>
-  <string name="filedetails_sync_file">Оновити файл</string>
   <string name="filedetails_renamed_in_upload_msg">Файл був переіменований в %1$s протягом вивантаження</string>
   <string name="list_layout">Вигляд списку</string>
   <string name="action_share_file">Опублікувати посилання</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">Так</string>
   <string name="common_no">Ні</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Скасувати завантаження</string>
-  <string name="common_cancel_upload">Перервати завантаження</string>
   <string name="common_cancel">Відмінити</string>
   <string name="common_save_exit">Зберегти &amp; Вихід</string>
   <string name="common_error">Помилка</string>
@@ -315,7 +312,6 @@
   <string name="prefs_category_instant_uploading">Миттєво завантаження</string>
   <string name="prefs_category_security">Безпека</string>
   <string name="prefs_instant_video_upload_path_title">Шлях завантаження відео</string>
-  <string name="download_folder_failed_content">Скачування теки %1$s не може бути завершено</string>
   <string name="shared_subject_header">поширений</string>
   <string name="with_you_subject_header">з Вами</string>
   <string name="subject_token">%1$s поділився \"%2$s\" з вами</string>

+ 0 - 3
res/values-vi/strings.xml

@@ -57,15 +57,12 @@
   <string name="filedetails_created">Đã tạo:</string>
   <string name="filedetails_modified">Đã chỉnh sửa:</string>
   <string name="filedetails_download">Tải về</string>
-  <string name="filedetails_sync_file">Cập nhật lại tập tin</string>
   <string name="filedetails_renamed_in_upload_msg">Tập tin đã bị đổi tên thành %1$s trong quá trình tải lên</string>
   <string name="action_share_file">Chia sẻ liên kết</string>
   <string name="action_unshare_file">Liên kết không chia sẻ</string>
   <string name="common_yes">Yes</string>
   <string name="common_no">Không</string>
   <string name="common_ok">Chấp nhận</string>
-  <string name="common_cancel_download">Hủy tải về</string>
-  <string name="common_cancel_upload">Hủy upload</string>
   <string name="common_cancel">Hủy</string>
   <string name="common_save_exit">Lưu &amp; Thoát</string>
   <string name="common_error">Lỗi</string>

+ 0 - 4
res/values-zh-rCN/strings.xml

@@ -79,7 +79,6 @@
   <string name="filedetails_created">创建于:</string>
   <string name="filedetails_modified">修改于:</string>
   <string name="filedetails_download">下载</string>
-  <string name="filedetails_sync_file">刷新文件</string>
   <string name="filedetails_renamed_in_upload_msg">上传过程中文件被更名为了 %1$s</string>
   <string name="list_layout">列表布局</string>
   <string name="action_share_file">分享链接</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">是</string>
   <string name="common_no">否</string>
   <string name="common_ok">确定</string>
-  <string name="common_cancel_download">取消下载</string>
-  <string name="common_cancel_upload">取消上传</string>
   <string name="common_cancel">取消</string>
   <string name="common_save_exit">保存并退出</string>
   <string name="common_error">错误</string>
@@ -315,7 +312,6 @@
   <string name="prefs_category_instant_uploading">即时上传</string>
   <string name="prefs_category_security">安全</string>
   <string name="prefs_instant_video_upload_path_title">视频上传路径</string>
-  <string name="download_folder_failed_content">%1$s 文件夹的下载无法完成</string>
   <string name="shared_subject_header">已共享</string>
   <string name="with_you_subject_header">与你</string>
   <string name="subject_token">%1$s和你分享了“%2$s”</string>

+ 0 - 2
res/values-zh-rHK/strings.xml

@@ -43,8 +43,6 @@
   <string name="common_yes">是</string>
   <string name="common_no">否</string>
   <string name="common_ok">確定</string>
-  <string name="common_cancel_download">取消下戴</string>
-  <string name="common_cancel_upload">取消上戴</string>
   <string name="common_cancel">取消</string>
   <string name="common_save_exit">儲存並離開</string>
   <string name="common_error">錯誤</string>

+ 0 - 4
res/values-zh-rTW/strings.xml

@@ -78,7 +78,6 @@
   <string name="filedetails_created">建立:</string>
   <string name="filedetails_modified">修改:</string>
   <string name="filedetails_download">下載</string>
-  <string name="filedetails_sync_file">更新檔案列表</string>
   <string name="filedetails_renamed_in_upload_msg">檔案名稱在上傳時已被更改為 %1$s</string>
   <string name="list_layout">列表版型</string>
   <string name="action_share_file">分享連結</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">是</string>
   <string name="common_no">否</string>
   <string name="common_ok">好</string>
-  <string name="common_cancel_download">取消下載</string>
-  <string name="common_cancel_upload">取消上傳</string>
   <string name="common_cancel">取消</string>
   <string name="common_save_exit">儲存並離開</string>
   <string name="common_error">錯誤</string>
@@ -310,7 +307,6 @@
   <string name="prefs_category_instant_uploading">即時上傳</string>
   <string name="prefs_category_security">安全性</string>
   <string name="prefs_instant_video_upload_path_title">影片上傳路徑</string>
-  <string name="download_folder_failed_content">%1$s 目錄的下載未完成</string>
   <string name="shared_subject_header">以分享的</string>
   <string name="with_you_subject_header">與你</string>
   <string name="subject_token">%1$s 分享了 \"%2$s\" 給您</string>

+ 3 - 4
res/values/strings.xml

@@ -82,7 +82,7 @@
     <string name="filedetails_created">Created:</string>
     <string name="filedetails_modified">Modified:</string>
     <string name="filedetails_download">Download</string>
-    <string name="filedetails_sync_file">Refresh file</string>
+    <string name="filedetails_sync_file">Synchronize</string>
     <string name="filedetails_renamed_in_upload_msg">File was renamed to %1$s during upload</string>
     <string name="list_layout">List Layout</string>
     <string name="action_share_file">Share link</string>
@@ -90,8 +90,7 @@
     <string name="common_yes">Yes</string>
     <string name="common_no">No</string>
     <string name="common_ok">OK</string>
-    <string name="common_cancel_download">Cancel download</string>
-    <string name="common_cancel_upload">Cancel upload</string>
+    <string name="common_cancel_sync">Cancel synchronization</string>
     <string name="common_cancel">Cancel</string>
     <string name="common_save_exit">Save &amp; Exit</string>
     <string name="common_error">Error</string>
@@ -343,7 +342,7 @@
 	<string name="prefs_category_security">Security</string>
 
 	<string name="prefs_instant_video_upload_path_title">Upload Video Path</string>
-    <string name="download_folder_failed_content">Download of %1$s folder could not be completed</string>
+    <string name="sync_folder_failed_content">Synchronization of %1$s folder could not be completed</string>
 
 	<string name="shared_subject_header">shared</string>
 	<string name="with_you_subject_header">with you</string>

+ 144 - 124
src/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -24,8 +24,10 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 import java.util.Vector;
 
 import android.accounts.Account;
@@ -88,18 +90,10 @@ public class FileDataStorageManager {
         return mAccount;
     }
 
-    public void setContentResolver(ContentResolver cr) {
-        mContentResolver = cr;
-    }
-
     public ContentResolver getContentResolver() {
         return mContentResolver;
     }
 
-    public void setContentProviderClient(ContentProviderClient cp) {
-        mContentProviderClient = cp;
-    }
-
     public ContentProviderClient getContentProviderClient() {
         return mContentProviderClient;
     }
@@ -188,7 +182,6 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
         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_PATH, file.getRemotePath());
         if (!file.isFolder())
@@ -204,11 +197,12 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
         cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
         cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
-        
+        cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
+
         boolean sameRemotePath = fileExists(file.getRemotePath());
         if (sameRemotePath ||                fileExists(file.getFileId())) {           // for renamed files; no more delete and create
 
-            OCFile oldFile = null;
+            OCFile oldFile;
             if (sameRemotePath) {
                 oldFile = getFileByPath(file.getRemotePath());
                 file.setFileId(oldFile.getFileId());
@@ -254,12 +248,6 @@ public class FileDataStorageManager {
             }
         }
 
-//        if (file.isFolder()) {
-//            updateFolderSize(file.getFileId());
-//        } else {
-//            updateFolderSize(file.getParentId());
-//        }
-
         return overriden;
     }
 
@@ -313,6 +301,7 @@ public class FileDataStorageManager {
             cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
             cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
             cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
+            cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
 
             boolean existsByPath = fileExists(file.getRemotePath());
             if (existsByPath || fileExists(file.getFileId())) {
@@ -337,7 +326,6 @@ public class FileDataStorageManager {
         for (OCFile file : filesToRemove) {
             if (file.getParentId() == folder.getFileId()) {
                 whereArgs = new String[]{mAccount.name, file.getRemotePath()};
-                //Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
                 if (file.isFolder()) {
                     operations.add(ContentProviderOperation.newDelete(
                             ContentUris.withAppendedId(
@@ -434,43 +422,9 @@ public class FileDataStorageManager {
             }
         }
 
-        //updateFolderSize(folder.getFileId());
-
     }
 
 
-//    /**
-//     * 
-//     * @param id
-//     */
-//    private void updateFolderSize(long id) {
-//        if (id > FileDataStorageManager.ROOT_PARENT_ID) {
-//            Log_OC.d(TAG, "Updating size of " + id);
-//            if (getContentResolver() != null) {
-//                getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR, 
-//                        new ContentValues(),    
-                            // won't be used, but cannot be null; crashes in KLP
-//                        ProviderTableMeta._ID + "=?",
-//                        new String[] { String.valueOf(id) });
-//            } else {
-//                try {
-//                    getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR, 
-//                            new ContentValues(),    
-                                // won't be used, but cannot be null; crashes in KLP
-//                            ProviderTableMeta._ID + "=?",
-//                            new String[] { String.valueOf(id) });
-//                    
-//                } catch (RemoteException e) {
-//                    Log_OC.e(
-//    TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
-//                }
-//            }
-//        } else {
-//            Log_OC.e(TAG,  "not updating size for folder " + id);
-//        }
-//    }
-
-
     public boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) {
         boolean success = true;
         if (file != null) {
@@ -505,6 +459,7 @@ public class FileDataStorageManager {
                         // maybe unnecessary, but should be checked TODO remove if unnecessary
                         file.setStoragePath(null);
                         saveFile(file);
+                        saveConflict(file, null);
                     }
                 }
             }
@@ -942,44 +897,12 @@ public class FileDataStorageManager {
                     c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1 ? true : false);
             file.setDownloading(c.getInt(
                     c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1 ? true : false);
-                    
-        }
-        return file;
-    }
-
-    /**
-     * Returns if the file/folder is shared by link or not
-     *
-     * @param path Path of the file/folder
-     * @return
-     */
-    public boolean isShareByLink(String path) {
-        Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
-        OCFile file = null;
-        if (c.moveToFirst()) {
-            file = createFileInstance(c);
-        }
-        c.close();
-        return file.isShareByLink();
-    }
+            file.setEtagInConflict(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG_IN_CONFLICT)));
 
-    /**
-     * Returns the public link of the file/folder
-     *
-     * @param path Path of the file/folder
-     * @return
-     */
-    public String getPublicLink(String path) {
-        Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
-        OCFile file = null;
-        if (c.moveToFirst()) {
-            file = createFileInstance(c);
         }
-        c.close();
-        return file.getPublicLink();
+        return file;
     }
 
-
     // Methods for Shares
     public boolean saveShare(OCShare share) {
         boolean overriden = false;
@@ -1310,6 +1233,7 @@ public class FileDataStorageManager {
                         ProviderTableMeta.FILE_IS_DOWNLOADING,
                         file.isDownloading() ? 1 : 0
                 );
+                cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
 
                 boolean existsByPath = fileExists(file.getRemotePath());
                 if (existsByPath || fileExists(file.getFileId())) {
@@ -1490,44 +1414,6 @@ public class FileDataStorageManager {
             }
         }
         return preparedOperations;
-        
-        /*
-        if (operations.size() > 0) {
-            try {
-                if (getContentResolver() != null) {
-                    getContentResolver().applyBatch(MainApp.getAuthority(), operations);
-
-                } else {
-                    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());
-            }
-        }            
-        */
-            
-            /*
-            if (getContentResolver() != null) {
-                
-                getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE, 
-                                            where,
-                                            whereArgs);
-            } else {
-                try {
-                    getContentProviderClient().delete(  ProviderTableMeta.CONTENT_URI_SHARE, 
-                                                        where,
-                                                        whereArgs);
-
-                } catch (RemoteException e) {
-                    Log_OC.e(TAG, "Exception deleting shares in a folder " + e.getMessage());
-                }
-            }
-            */
-        //}
     }
 
     public void triggerMediaScan(String path) {
@@ -1578,4 +1464,138 @@ public class FileDataStorageManager {
 
     }
 
+    public void saveConflict(OCFile file, String etagInConflict) {
+        if (!file.isDown()) {
+            etagInConflict = null;
+        }
+        ContentValues cv = new ContentValues();
+        cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, etagInConflict);
+        int updated = 0;
+        if (getContentResolver() != null) {
+            updated = getContentResolver().update(
+                    ProviderTableMeta.CONTENT_URI_FILE,
+                    cv,
+                    ProviderTableMeta._ID + "=?",
+                    new String[] { String.valueOf(file.getFileId())}
+            );
+        } else {
+            try {
+                updated = getContentProviderClient().update(
+                        ProviderTableMeta.CONTENT_URI_FILE,
+                        cv,
+                        ProviderTableMeta._ID + "=?",
+                        new String[]{String.valueOf(file.getFileId())}
+                );
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage());
+            }
+        }
+
+        Log_OC.d(TAG, "Number of files updated with CONFLICT: " + updated);
+
+        if (updated > 0) {
+            if (etagInConflict != null) {
+                /// set conflict in all ancestor folders
+
+                long parentId = file.getParentId();
+                Set<String> ancestorIds = new HashSet<String>();
+                while (parentId != FileDataStorageManager.ROOT_PARENT_ID) {
+                    ancestorIds.add(Long.toString(parentId));
+                    parentId = getFileById(parentId).getParentId();
+                }
+
+                if (ancestorIds.size() > 0) {
+                    StringBuffer whereBuffer = new StringBuffer();
+                    whereBuffer.append(ProviderTableMeta._ID).append(" IN (");
+                    for (int i = 0; i < ancestorIds.size() - 1; i++) {
+                        whereBuffer.append("?,");
+                    }
+                    whereBuffer.append("?");
+                    whereBuffer.append(")");
+
+                    if (getContentResolver() != null) {
+                        updated = getContentResolver().update(
+                                ProviderTableMeta.CONTENT_URI_FILE,
+                                cv,
+                                whereBuffer.toString(),
+                                ancestorIds.toArray(new String[]{})
+                        );
+                    } else {
+                        try {
+                            updated = getContentProviderClient().update(
+                                    ProviderTableMeta.CONTENT_URI_FILE,
+                                    cv,
+                                    whereBuffer.toString(),
+                                    ancestorIds.toArray(new String[]{})
+                            );
+                        } catch (RemoteException e) {
+                            Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage());
+                        }
+                    }
+                } // else file is ROOT folder, no parent to set in conflict
+
+            } else {
+                /// update conflict in ancestor folders
+                // (not directly unset; maybe there are more conflicts below them)
+                String parentPath = file.getRemotePath();
+                if (parentPath.endsWith(OCFile.PATH_SEPARATOR)) {
+                    parentPath = parentPath.substring(0, parentPath.length() - 1);
+                }
+                parentPath = parentPath.substring(0, parentPath.lastIndexOf(OCFile.PATH_SEPARATOR) + 1);
+
+                Log_OC.d(TAG, "checking parents to remove conflict; STARTING with " + parentPath);
+                while (parentPath.length() > 0) {
+
+                    String where =
+                            ProviderTableMeta.FILE_ETAG_IN_CONFLICT + " IS NOT NULL AND " +
+                                    ProviderTableMeta.FILE_CONTENT_TYPE + " != 'DIR' AND " +
+                                    ProviderTableMeta.FILE_ACCOUNT_OWNER + " = ? AND " +
+                                    ProviderTableMeta.FILE_PATH + " LIKE ?";
+                    Cursor descendentsInConflict = getContentResolver().query(
+                            ProviderTableMeta.CONTENT_URI_FILE,
+                            new String[]{ProviderTableMeta._ID},
+                            where,
+                            new String[]{mAccount.name, parentPath + "%"},
+                            null
+                    );
+                    if (descendentsInConflict == null || descendentsInConflict.getCount() == 0) {
+                        Log_OC.d(TAG, "NO MORE conflicts in " + parentPath);
+                        if (getContentResolver() != null) {
+                            updated = getContentResolver().update(
+                                    ProviderTableMeta.CONTENT_URI_FILE,
+                                    cv,
+                                    ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
+                                            ProviderTableMeta.FILE_PATH + "=?",
+                                    new String[]{mAccount.name, parentPath}
+                            );
+                        } else {
+                            try {
+                                updated = getContentProviderClient().update(
+                                        ProviderTableMeta.CONTENT_URI_FILE,
+                                        cv,
+                                        ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
+                                                ProviderTableMeta.FILE_PATH + "=?"
+                                        , new String[]{mAccount.name, parentPath}
+                                );
+                            } catch (RemoteException e) {
+                                Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage());
+                            }
+                        }
+
+                    } else {
+                        Log_OC.d(TAG, "STILL " + descendentsInConflict.getCount() + " in " + parentPath);
+                    }
+
+                    if (descendentsInConflict != null) {
+                        descendentsInConflict.close();
+                    }
+
+                    parentPath = parentPath.substring(0, parentPath.length() - 1);  // trim last /
+                    parentPath = parentPath.substring(0, parentPath.lastIndexOf(OCFile.PATH_SEPARATOR) + 1);
+                    Log_OC.d(TAG, "checking parents to remove conflict; NEXT " + parentPath);
+                }
+            }
+        }
+
+    }
 }

+ 14 - 25
src/com/owncloud/android/datamodel/OCFile.java

@@ -74,6 +74,8 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
 
     private boolean mIsDownloading;
 
+    private String mEtagInConflict;    // Save file etag in the server, when there is a conflict. No conflict =  null
+
 
     /**
      * Create new {@link OCFile} with given path.
@@ -115,8 +117,9 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         mPublicLink = source.readString();
         mPermissions = source.readString();
         mRemoteId = source.readString();
-        mNeedsUpdateThumbnail = source.readInt() == 0;
-        mIsDownloading = source.readInt() == 0;
+        mNeedsUpdateThumbnail = source.readInt() == 1;
+        mIsDownloading = source.readInt() == 1;
+        mEtagInConflict = source.readString();
 
     }
 
@@ -142,6 +145,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         dest.writeString(mRemoteId);
         dest.writeInt(mNeedsUpdateThumbnail ? 1 : 0);
         dest.writeInt(mIsDownloading ? 1 : 0);
+        dest.writeString(mEtagInConflict);
     }
 
     /**
@@ -315,24 +319,6 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         return mMimeType;
     }
 
-    /**
-     * Adds a file to this directory. If this file is not a directory, an
-     * exception gets thrown.
-     *
-     * @param file to add
-     * @throws IllegalStateException if you try to add a something and this is
-     *                               not a directory
-     */
-    public void addFile(OCFile file) throws IllegalStateException {
-        if (isFolder()) {
-            file.mParentId = mId;
-            mNeedsUpdating = true;
-            return;
-        }
-        throw new IllegalStateException(
-                "This is not a directory where you can add stuff to!");
-    }
-
     /**
      * Used internally. Reset all file properties
      */
@@ -357,6 +343,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         mRemoteId = null;
         mNeedsUpdateThumbnail = false;
         mIsDownloading = false;
+        mEtagInConflict = null;
     }
 
     /**
@@ -498,10 +485,9 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
     }
 
     public void setEtag(String etag) {
-        this.mEtag = etag;
+        this.mEtag = (etag != null ? etag : "");
     }
 
-
     public boolean isShareByLink() {
         return mShareByLink;
     }
@@ -598,8 +584,11 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         this.mIsDownloading = isDownloading;
     }
 
-    public boolean isSynchronizing() {
-        // TODO real implementation
-        return false;
+    public String getEtagInConflict() {
+        return mEtagInConflict;
+    }
+
+    public void setEtagInConflict(String etagInConflict) {
+        mEtagInConflict = etagInConflict;
     }
 }

+ 3 - 2
src/com/owncloud/android/db/ProviderMeta.java

@@ -31,7 +31,7 @@ import com.owncloud.android.MainApp;
 public class ProviderMeta {
 
     public static final String DB_NAME = "filelist";
-    public static final int DB_VERSION = 10;
+    public static final int DB_VERSION = 11;
 
     private ProviderMeta() {
     }
@@ -72,6 +72,7 @@ public class ProviderMeta {
         public static final String FILE_REMOTE_ID = "remote_id";
         public static final String FILE_UPDATE_THUMBNAIL = "update_thumbnail";
         public static final String FILE_IS_DOWNLOADING= "is_downloading";
+        public static final String FILE_ETAG_IN_CONFLICT = "etag_in_conflict";
 
         public static final String FILE_DEFAULT_SORT_ORDER = FILE_NAME
                 + " collate nocase asc";
@@ -94,7 +95,7 @@ public class ProviderMeta {
         
         public static final String OCSHARES_DEFAULT_SORT_ORDER = OCSHARES_FILE_SOURCE 
                 + " collate nocase asc";
-        
+
 
     }
 }

+ 25 - 28
src/com/owncloud/android/files/FileMenuFilter.java

@@ -34,7 +34,6 @@ import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
-import com.owncloud.android.services.OperationsService;
 import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
 import com.owncloud.android.ui.activity.ComponentsGetter;
 
@@ -106,21 +105,25 @@ public class FileMenuFilter {
      * @param toHide            List to save the options that must be shown in the menu.
      */
     private void filter(List<Integer> toShow, List <Integer> toHide) {
-        boolean downloading = false;
-        boolean uploading = false;
+        boolean synchronizing = false;
         if (mComponentsGetter != null && mFile != null && mAccount != null) {
-            FileDownloaderBinder downloaderBinder = mComponentsGetter.getFileDownloaderBinder();
-            downloading = (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile));
             OperationsServiceBinder opsBinder = mComponentsGetter.getOperationsServiceBinder();
-            downloading |= (opsBinder != null && opsBinder.isSynchronizing(mAccount, mFile.getRemotePath()));
             FileUploaderBinder uploaderBinder = mComponentsGetter.getFileUploaderBinder();
-            uploading = (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile));
+            FileDownloaderBinder downloaderBinder = mComponentsGetter.getFileDownloaderBinder();
+            synchronizing = (
+                // comparing local and remote
+                (opsBinder != null && opsBinder.isSynchronizing(mAccount, mFile.getRemotePath())) ||
+                // downloading
+                (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) ||
+                // 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) {
+        if (mFile == null || mFile.isDown() || mFile.isFolder() || synchronizing) {
             toHide.add(R.id.action_download_file);
 
         } else {
@@ -128,7 +131,7 @@ public class FileMenuFilter {
         }
 
         // RENAME
-        if (mFile == null || downloading || uploading) {
+        if (mFile == null || synchronizing) {
             toHide.add(R.id.action_rename_file);
 
         } else {
@@ -136,7 +139,7 @@ public class FileMenuFilter {
         }
 
         // MOVE & COPY
-        if (mFile == null || downloading || uploading) {
+        if (mFile == null || synchronizing) {
             toHide.add(R.id.action_move);
             toHide.add(R.id.action_copy);
         } else {
@@ -145,7 +148,7 @@ public class FileMenuFilter {
         }
 
         // REMOVE
-        if (mFile == null || downloading || uploading) {
+        if (mFile == null || synchronizing) {
             toHide.add(R.id.action_remove_file);
 
         } else {
@@ -153,31 +156,25 @@ public class FileMenuFilter {
         }
 
         // OPEN WITH (different to preview!)
-        if (mFile == null || mFile.isFolder() || !mFile.isDown() || downloading || uploading) {
+        if (mFile == null || mFile.isFolder() || !mFile.isDown() || synchronizing) {
             toHide.add(R.id.action_open_file_with);
 
         } else {
             toShow.add(R.id.action_open_file_with);
         }
 
+        // CANCEL SYNCHRONIZATION
+        if (mFile == null || !synchronizing) {
+            toHide.add(R.id.action_cancel_sync);
 
-        // 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);
+            toShow.add(R.id.action_cancel_sync);
         }
 
-        // SYNC FILE CONTENTS
-        if (mFile == null || mFile.isFolder() || !mFile.isDown() || downloading || uploading) {
+        // SYNC CONTENTS (BOTH FILE AND FOLDER)
+        if (mFile == null || (!mFile.isFolder() && !mFile.isDown()) || synchronizing) {
             toHide.add(R.id.action_sync_file);
+
         } else {
             toShow.add(R.id.action_sync_file);
         }
@@ -210,21 +207,21 @@ public class FileMenuFilter {
         // SEND
         boolean sendAllowed = (mContext != null &&
                 mContext.getString(R.string.send_files_to_other_apps).equalsIgnoreCase("on"));
-        if (mFile == null || !sendAllowed || mFile.isFolder() || uploading || downloading) {
+        if (mFile == null || !sendAllowed || mFile.isFolder() || synchronizing) {
             toHide.add(R.id.action_send_file);
         } else {
             toShow.add(R.id.action_send_file);
         }
 
         // FAVORITES
-        if (mFile == null || downloading || uploading || mFile.isFolder() || mFile.isFavorite()) {
+        if (mFile == null || synchronizing || mFile.isFolder() || mFile.isFavorite()) {
             toHide.add(R.id.action_favorite_file);
         } else {
             toShow.add(R.id.action_favorite_file);
         }
 
         // UNFAVORITES
-        if (mFile == null || downloading || uploading || mFile.isFolder() || !mFile.isFavorite()) {
+        if (mFile == null || synchronizing || mFile.isFolder() || !mFile.isFavorite()) {
             toHide.add(R.id.action_unfavorite_file);
         } else {
             toShow.add(R.id.action_unfavorite_file);

+ 9 - 13
src/com/owncloud/android/files/FileOperationsHelper.java

@@ -236,9 +236,12 @@ public class FileOperationsHelper {
         }
     }
 
-
+    /**
+     * Request the synchronization of a file or folder with the OC server, including its contents.
+     *
+     * @param file          The file or folder to synchronize
+     */
     public void syncFile(OCFile file) {
-
         if (!file.isFolder()){
             Intent intent = new Intent(mFileActivity, OperationsService.class);
             intent.setAction(OperationsService.ACTION_SYNC_FILE);
@@ -254,6 +257,7 @@ public class FileOperationsHelper {
             intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
             intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
             mFileActivity.startService(intent);
+
         }
     }
 
@@ -328,19 +332,11 @@ public class FileOperationsHelper {
 
         // for both files and folders
         FileDownloaderBinder downloaderBinder = mFileActivity.getFileDownloaderBinder();
-        FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder();
         if (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) {
             downloaderBinder.cancel(account, file);
-
-            // TODO - review why is this here, and solve in a better way
-            // Remove etag for parent, if file is a favorite
-            if (file.isFavorite()) {
-                OCFile parent = mFileActivity.getStorageManager().getFileById(file.getParentId());
-                parent.setEtag("");
-                mFileActivity.getStorageManager().saveFile(parent);
-            }
-
-        } else if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
+        }
+        FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder();
+        if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
             uploaderBinder.cancel(account, file);
         }
     }

+ 19 - 85
src/com/owncloud/android/files/services/FileDownloader.java

@@ -21,14 +21,12 @@
 package com.owncloud.android.files.services;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.AbstractList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Vector;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.authentication.AuthenticatorActivity;
@@ -54,7 +52,6 @@ import com.owncloud.android.utils.ErrorMessageAdapter;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.accounts.AccountsException;
 import android.accounts.OnAccountsUpdateListener;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -153,7 +150,7 @@ public class FileDownloader extends Service
 
     /**
      * Entry point to add one or several files to the queue of downloads.
-     * <p/>
+     *
      * New downloads 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.
      */
@@ -169,12 +166,6 @@ public class FileDownloader extends Service
         } else {
             final Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
             final OCFile file = intent.getParcelableExtra(EXTRA_FILE);
-
-            /*Log_OC.v(
-                    "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                    "Received request to download file"
-            );*/
-
             AbstractList<String> requestedDownloads = new Vector<String>();
             try {
                 DownloadFileOperation newDownload = new DownloadFileOperation(account, file);
@@ -185,20 +176,6 @@ public class FileDownloader extends Service
                 );
                 String downloadKey = putResult.first;
                 requestedDownloads.add(downloadKey);
-                    /*Log_OC.v(
-                        "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Download on " + file.getRemotePath() + " added to queue"
-                    );*/
-
-                // Store file on db with state 'downloading'
-                    /*
-                    TODO - check if helps with UI responsiveness,
-                    letting only folders use FileDownloaderBinder to check
-                    FileDataStorageManager storageManager =
-                    new FileDataStorageManager(account, getContentResolver());
-                    file.setDownloading(true);
-                    storageManager.saveFile(file);
-                    */
 
                 sendBroadcastNewDownload(newDownload, putResult.second);
 
@@ -275,34 +252,23 @@ public class FileDownloader extends Service
          * @param file    A file in the queue of pending downloads
          */
         public void cancel(Account account, OCFile file) {
-            /*Log_OC.v(
-                    "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                    "Received request to cancel download of " + file.getRemotePath()
-            );
-            Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                    "Removing download of " + file.getRemotePath());*/
-            Pair<DownloadFileOperation, String> removeResult =
-                    mPendingDownloads.remove(account, file.getRemotePath());
+            Pair<DownloadFileOperation, String> removeResult = mPendingDownloads.remove(account, file.getRemotePath());
             DownloadFileOperation download = removeResult.first;
             if (download != null) {
-                /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Canceling returned download of " + file.getRemotePath());*/
                 download.cancel();
             } else {
                 if (mCurrentDownload != null && mCurrentAccount != null &&
                         mCurrentDownload.getRemotePath().startsWith(file.getRemotePath()) &&
                         account.name.equals(mCurrentAccount.name)) {
-                    /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                     "Canceling current sync as descendant: " + mCurrentDownload.getRemotePath());*/
                     mCurrentDownload.cancel();
                 }
             }
         }
 
         /**
-         * Cancels a pending or current upload for an account
+         * Cancels all the downloads for an account
          *
-         * @param account Owncloud accountName where the remote file will be stored.
+         * @param account   ownCloud account.
          */
         public void cancel(Account account) {
             Log_OC.d(TAG, "Account= " + account.name);
@@ -325,7 +291,7 @@ public class FileDownloader extends Service
         /**
          * Returns True when the file described by 'file' in the ownCloud account 'account'
          * is downloading or waiting to download.
-         * <p/>
+         *
          * If 'file' is a directory, returns 'true' if any of its descendant files is downloading or
          * waiting to download.
          *
@@ -349,7 +315,6 @@ public class FileDownloader extends Service
                 OnDatatransferProgressListener listener, Account account, OCFile file
         ) {
             if (account == null || file == null || listener == null) return;
-            //String targetKey = buildKey(account, file.getRemotePath());
             mBoundListeners.put(file.getFileId(), listener);
         }
 
@@ -357,15 +322,14 @@ public class FileDownloader extends Service
         /**
          * Removes a listener interested in the progress of the download for a concrete file.
          *
-         * @param listener Object to notify about progress of transfer.
-         * @param account  ownCloud account holding the file of interest.
-         * @param file     {@link OCFile} of interest for listener.
+         * @param listener      Object to notify about progress of transfer.
+         * @param account       ownCloud account holding the file of interest.
+         * @param file          {@link OCFile} of interest for listener.
          */
         public void removeDatatransferProgressListener(
                 OnDatatransferProgressListener listener, Account account, OCFile file
         ) {
             if (account == null || file == null || listener == null) return;
-            //String targetKey = buildKey(account, file.getRemotePath());
             Long fileId = file.getFileId();
             if (mBoundListeners.get(fileId) == listener) {
                 mBoundListeners.remove(fileId);
@@ -375,8 +339,6 @@ public class FileDownloader extends Service
         @Override
         public void onTransferProgress(long progressRate, long totalTransferredSoFar,
                                        long totalToTransfer, String fileName) {
-            //String key = buildKey(mCurrentDownload.getAccount(),
-            // mCurrentDownload.getFile().getRemotePath());
             OnDatatransferProgressListener boundListener =
                     mBoundListeners.get(mCurrentDownload.getFile().getFileId());
             if (boundListener != null) {
@@ -385,23 +347,12 @@ public class FileDownloader extends Service
             }
         }
 
-        /**
-         * Review downloads and cancel it if its account doesn't exist
-         */
-        public void checkAccountOfCurrentDownload() {
-            if (mCurrentDownload != null &&
-                    !AccountUtils.exists(mCurrentDownload.getAccount(), getApplicationContext())) {
-                mCurrentDownload.cancel();
-            }
-            // The rest of downloads are cancelled when they try to start
-        }
-
     }
 
 
     /**
      * Download worker. Performs the pending downloads in the order they were requested.
-     * <p/>
+
      * Created with the Looper of a new thread, started in {@link FileUploader#onCreate()}.
      */
     private static class ServiceHandler extends Handler {
@@ -440,14 +391,13 @@ public class FileDownloader extends Service
      */
     private void downloadFile(String downloadKey) {
 
-        /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                "Getting download of " + downloadKey);*/
         mCurrentDownload = mPendingDownloads.get(downloadKey);
 
         if (mCurrentDownload != null) {
             // Detect if the account exists
             if (AccountUtils.exists(mCurrentDownload.getAccount(), getApplicationContext())) {
                 Log_OC.d(TAG, "Account " + mCurrentDownload.getAccount().name + " exists");
+
                 notifyDownloadStart(mCurrentDownload);
 
                 RemoteOperationResult downloadResult = null;
@@ -470,26 +420,16 @@ public class FileDownloader extends Service
 
 
                     /// perform the download
-                    /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Executing download of " + mCurrentDownload.getRemotePath());*/
                     downloadResult = mCurrentDownload.execute(mDownloadClient);
                     if (downloadResult.isSuccess()) {
                         saveDownloadedFile();
                     }
 
-                } catch (AccountsException e) {
-                    Log_OC.e(TAG, "Error while trying to get authorization for "
-                            + mCurrentAccount.name, e);
-                    downloadResult = new RemoteOperationResult(e);
-                } catch (IOException e) {
-                    Log_OC.e(TAG, "Error while trying to get authorization for "
-                            + mCurrentAccount.name, e);
+                } catch (Exception e) {
+                    Log_OC.e(TAG, "Error downloading", e);
                     downloadResult = new RemoteOperationResult(e);
 
                 } finally {
-                /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Removing payload " + mCurrentDownload.getRemotePath());*/
-
                     Pair<DownloadFileOperation, String> removeResult =
                             mPendingDownloads.removePayload(mCurrentAccount,
                                     mCurrentDownload.getRemotePath());
@@ -497,9 +437,9 @@ public class FileDownloader extends Service
                     /// notify result
                     notifyDownloadResult(mCurrentDownload, downloadResult);
 
-                    sendBroadcastDownloadFinished(mCurrentDownload, downloadResult,
-                            removeResult.second);
+                    sendBroadcastDownloadFinished(mCurrentDownload, downloadResult, removeResult.second);
                 }
+
             } else {
                 // Cancel the transfer
                 Log_OC.d(TAG, "Account " + mCurrentDownload.getAccount().toString() +
@@ -513,6 +453,8 @@ public class FileDownloader extends Service
 
     /**
      * Updates the OC File after a successful download.
+     *
+     * TODO move to DownloadFileOperation
      */
     private void saveDownloadedFile() {
         OCFile file = mStorageManager.getFileById(mCurrentDownload.getFile().getFileId());
@@ -522,25 +464,16 @@ public class FileDownloader extends Service
         file.setNeedsUpdateThumbnail(true);
         file.setModificationTimestamp(mCurrentDownload.getModificationTimestamp());
         file.setModificationTimestampAtLastSyncForData(mCurrentDownload.getModificationTimestamp());
-        // file.setEtag(mCurrentDownload.getEtag());    // TODO Etag, where available
+        file.setEtag(mCurrentDownload.getEtag());
         file.setMimetype(mCurrentDownload.getMimeType());
         file.setStoragePath(mCurrentDownload.getSavePath());
         file.setFileLength((new File(mCurrentDownload.getSavePath()).length()));
         file.setRemoteId(mCurrentDownload.getFile().getRemoteId());
         mStorageManager.saveFile(file);
         mStorageManager.triggerMediaScan(file.getStoragePath());
+        mStorageManager.saveConflict(file, null);
     }
 
-    /**
-     * Update the OC File after a unsuccessful download
-     */
-    private void updateUnsuccessfulDownloadedFile() {
-        OCFile file = mStorageManager.getFileById(mCurrentDownload.getFile().getFileId());
-        file.setDownloading(false);
-        mStorageManager.saveFile(file);
-    }
-
-
     /**
      * Creates a status notification to show the download progress
      *
@@ -683,6 +616,7 @@ public class FileDownloader extends Service
             DownloadFileOperation download,
             RemoteOperationResult downloadResult,
             String unlinkedFromRemotePath) {
+
         Intent end = new Intent(getDownloadFinishMessage());
         end.putExtra(EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess());
         end.putExtra(ACCOUNT_NAME, download.getAccount().name);

+ 117 - 125
src/com/owncloud/android/files/services/FileUploader.java

@@ -21,18 +21,14 @@
 package com.owncloud.android.files.services;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.AbstractList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Vector;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.accounts.AccountsException;
 import android.accounts.OnAccountsUpdateListener;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -46,6 +42,7 @@ import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
 import android.support.v4.app.NotificationCompat;
+import android.util.Pair;
 import android.webkit.MimeTypeMap;
 
 import com.owncloud.android.R;
@@ -86,6 +83,7 @@ public class FileUploader extends Service
     public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
     public static final String EXTRA_OLD_REMOTE_PATH = "OLD_REMOTE_PATH";
     public static final String EXTRA_OLD_FILE_PATH = "OLD_FILE_PATH";
+    public static final String EXTRA_LINKED_TO_PATH = "LINKED_TO";
     public static final String ACCOUNT_NAME = "ACCOUNT_NAME";
 
     public static final String KEY_FILE = "FILE";
@@ -113,11 +111,10 @@ public class FileUploader extends Service
     private ServiceHandler mServiceHandler;
     private IBinder mBinder;
     private OwnCloudClient mUploadClient = null;
-    private Account mLastAccount = null;
+    private Account mCurrentAccount = null;
     private FileDataStorageManager mStorageManager;
 
-    private ConcurrentMap<String, UploadFileOperation> mPendingUploads =
-            new ConcurrentHashMap<String, UploadFileOperation>();
+    private IndexedForest<UploadFileOperation> mPendingUploads = new IndexedForest<UploadFileOperation>();
     private UploadFileOperation mCurrentUpload = null;
 
     private NotificationManager mNotificationManager;
@@ -132,20 +129,6 @@ public class FileUploader extends Service
         return FileUploader.class.getName() + UPLOAD_FINISH_MESSAGE;
     }
 
-    /**
-     * Builds a key for mPendingUploads from the account and file to upload
-     *
-     * @param account   Account where the file to upload is stored
-     * @param file      File to upload
-     */
-    private String buildRemoteName(Account account, OCFile file) {
-        return account.name + file.getRemotePath();
-    }
-
-    private String buildRemoteName(Account account, String remotePath) {
-        return account.name + remotePath;
-    }
-
     /**
      * Checks if an ownCloud server version should support chunked uploads.
      *
@@ -153,6 +136,8 @@ public class FileUploader extends Service
      *            server.
      * @return 'True' if the ownCloud server with version supports chunked
      *         uploads.
+     *
+     * TODO - move to OCClient
      */
     private static boolean chunkedUploadIsSupported(OwnCloudVersion version) {
         return (version != null && version.compareTo(OwnCloudVersion.owncloud_v4_5) >= 0);
@@ -282,7 +267,7 @@ public class FileUploader extends Service
             files = new OCFile[localPaths.length];
             for (int i = 0; i < localPaths.length; i++) {
                 files[i] = obtainNewOCFileToUpload(remotePaths[i], localPaths[i],
-                        ((mimeTypes != null) ? mimeTypes[i] : null), storageManager);
+                        ((mimeTypes != null) ? mimeTypes[i] : null));
                 if (files[i] == null) {
                     // TODO @andomaex add failure Notification
                     return Service.START_NOT_STICKY;
@@ -298,18 +283,23 @@ public class FileUploader extends Service
         UploadFileOperation newUpload = null;
         try {
             for (int i = 0; i < files.length; i++) {
-                uploadKey = buildRemoteName(account, files[i].getRemotePath());
-                newUpload = new UploadFileOperation(account, files[i], chunked, isInstant,
+                newUpload = new UploadFileOperation(
+                        account,
+                        files[i],
+                        chunked,
+                        isInstant,
                         forceOverwrite, localAction,
-                        getApplicationContext());
+                        getApplicationContext()
+                );
                 if (isInstant) {
                     newUpload.setRemoteFolderToBeCreated();
                 }
-                // Grants that the file only upload once time
-                mPendingUploads.putIfAbsent(uploadKey, newUpload);
-
                 newUpload.addDatatransferProgressListener(this);
-                newUpload.addDatatransferProgressListener((FileUploaderBinder)mBinder);
+                newUpload.addDatatransferProgressListener((FileUploaderBinder) mBinder);
+                Pair<String, String> putResult = mPendingUploads.putIfAbsent(
+                        account, files[i].getRemotePath(), newUpload
+                );
+                uploadKey = putResult.first;
                 requestedUploads.add(uploadKey);
             }
 
@@ -333,7 +323,6 @@ public class FileUploader extends Service
             msg.obj = requestedUploads;
             mServiceHandler.sendMessage(msg);
         }
-        Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
         return Service.START_NOT_STICKY;
     }
 
@@ -386,23 +375,27 @@ public class FileUploader extends Service
         /**
          * Cancels a pending or current upload of a remote file.
          *
-         * @param account Owncloud account where the remote file will be stored.
-         * @param file A file in the queue of pending uploads
+         * @param account   ownCloud account where the remote file will be stored.
+         * @param file      A file in the queue of pending uploads
          */
         public void cancel(Account account, OCFile file) {
-            UploadFileOperation upload;
-            synchronized (mPendingUploads) {
-                upload = mPendingUploads.remove(buildRemoteName(account, file));
-            }
+            Pair<UploadFileOperation, String> removeResult = mPendingUploads.remove(account, file.getRemotePath());
+            UploadFileOperation upload = removeResult.first;
             if (upload != null) {
                 upload.cancel();
+            } else {
+                if (mCurrentUpload != null && mCurrentAccount != null &&
+                        mCurrentUpload.getRemotePath().startsWith(file.getRemotePath()) &&
+                        account.name.equals(mCurrentAccount.name)) {
+                    mCurrentUpload.cancel();
+                }
             }
         }
 
         /**
-         * Cancels a pending or current upload for an account
+         * Cancels all the uploads for an account
          *
-         * @param account Owncloud accountName where the remote file will be stored.
+         * @param account   ownCloud account.
          */
         public void cancel(Account account) {
             Log_OC.d(TAG, "Account= " + account.name);
@@ -414,13 +407,14 @@ public class FileUploader extends Service
                 }
             }
             // Cancel pending uploads
-            cancelUploadForAccount(account.name);
+            cancelUploadsForAccount(account);
         }
 
         public void clearListeners() {
             mBoundListeners.clear();
         }
 
+
         /**
          * Returns True when the file described by 'file' is being uploaded to
          * the ownCloud account 'account' or waiting for it
@@ -432,22 +426,8 @@ public class FileUploader extends Service
          * @param file      A file that could be in the queue of pending uploads
          */
         public boolean isUploading(Account account, OCFile file) {
-            if (account == null || file == null)
-                return false;
-            String targetKey = buildRemoteName(account, file);
-            synchronized (mPendingUploads) {
-                if (file.isFolder()) {
-                    // this can be slow if there are many uploads :(
-                    Iterator<String> it = mPendingUploads.keySet().iterator();
-                    boolean found = false;
-                    while (it.hasNext() && !found) {
-                        found = it.next().startsWith(targetKey);
-                    }
-                    return found;
-                } else {
-                    return (mPendingUploads.containsKey(targetKey));
-                }
-            }
+            if (account == null || file == null) return false;
+            return (mPendingUploads.contains(account, file.getRemotePath()));
         }
 
 
@@ -496,15 +476,19 @@ public class FileUploader extends Service
         }
 
         /**
-         * Review uploads and cancel it if its account doesn't exist
+         * Builds a key for the map of listeners.
+         *
+         * TODO remove and replace key with file.getFileId() after changing current policy (upload file, then
+         * add to local database) to better policy (add to local database, then upload)
+         *
+         * @param account       ownCloud account where the file to upload belongs.
+         * @param file          File to upload
+         * @return              Key
          */
-        public void checkAccountOfCurrentUpload() {
-            if (mCurrentUpload != null &&
-                    !AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) {
-                mCurrentUpload.cancel();
-            }
-            // The rest of uploads are cancelled when they try to start
+        private String buildRemoteName(Account account, OCFile file) {
+            return account.name + file.getRemotePath();
         }
+
     }
 
     /**
@@ -544,17 +528,13 @@ public class FileUploader extends Service
     /**
      * Core upload method: sends the file(s) to upload
      *
-     * @param uploadKey Key to access the upload to perform, contained in
-     *            mPendingUploads
+     * @param uploadKey Key to access the upload to perform, contained in mPendingUploads
      */
     public void uploadFile(String uploadKey) {
 
-        synchronized (mPendingUploads) {
-            mCurrentUpload = mPendingUploads.get(uploadKey);
-        }
+        mCurrentUpload = mPendingUploads.get(uploadKey);
 
         if (mCurrentUpload != null) {
-
             // Detect if the account exists
             if (AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) {
                 Log_OC.d(TAG, "Account " + mCurrentUpload.getAccount().name + " exists");
@@ -564,16 +544,20 @@ public class FileUploader extends Service
                 RemoteOperationResult uploadResult = null, grantResult;
 
                 try {
-                    /// prepare client object to send requests to the ownCloud server
-                    if (mUploadClient == null ||
-                            !mLastAccount.equals(mCurrentUpload.getAccount())) {
-                        mLastAccount = mCurrentUpload.getAccount();
-                        mStorageManager =
-                                new FileDataStorageManager(mLastAccount, getContentResolver());
-                        OwnCloudAccount ocAccount = new OwnCloudAccount(mLastAccount, this);
-                        mUploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().
-                                getClientFor(ocAccount, this);
-                    }
+                    /// prepare client object to send the request to the ownCloud server
+                    if (mCurrentAccount == null || !mCurrentAccount.equals(mCurrentUpload.getAccount())) {
+                        mCurrentAccount = mCurrentUpload.getAccount();
+                        mStorageManager = new FileDataStorageManager(
+                                mCurrentAccount,
+                                getContentResolver()
+                        );
+                    }   // else, reuse storage manager from previous operation
+
+                    // always get client from client manager, to get fresh credentials in case of update
+                    OwnCloudAccount ocAccount = new OwnCloudAccount(mCurrentAccount, this);
+                    mUploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                            getClientFor(ocAccount, this);
+
 
                     /// check the existence of the parent folder for the file to upload
                     String remoteParentPath = new File(mCurrentUpload.getRemotePath()).getParent();
@@ -588,43 +572,44 @@ public class FileUploader extends Service
                         uploadResult = mCurrentUpload.execute(mUploadClient);
                         if (uploadResult.isSuccess()) {
                             saveUploadedFile();
+
+                        } else if (uploadResult.getCode() == ResultCode.SYNC_CONFLICT) {
+                            mStorageManager.saveConflict(mCurrentUpload.getFile(),
+                                    mCurrentUpload.getFile().getEtagInConflict());
                         }
                     } else {
                         uploadResult = grantResult;
                     }
 
-                } catch (AccountsException e) {
-                    Log_OC.e(TAG, "Error while trying to get autorization for " +
-                            mLastAccount.name, e);
-                    uploadResult = new RemoteOperationResult(e);
-
-                } catch (IOException e) {
-                    Log_OC.e(TAG, "Error while trying to get autorization for " +
-                            mLastAccount.name, e);
+                } catch (Exception e) {
+                    Log_OC.e(TAG, "Error uploading", e);
                     uploadResult = new RemoteOperationResult(e);
 
                 } finally {
-                    synchronized (mPendingUploads) {
-                        mPendingUploads.remove(uploadKey);
-                        Log_OC.i(TAG, "Remove CurrentUploadItem from pending upload Item Map.");
-                    }
-                    if (uploadResult != null && uploadResult.isException()) {
-                        // enforce the creation of a new client object for next uploads;
-                        // this grant that a new socket will be created in the future if
-                        // the current exception is due to an abrupt lose of network connection
-                        mUploadClient = null;
+                    Pair<UploadFileOperation, String> removeResult;
+                    if (mCurrentUpload.wasRenamed()) {
+                        removeResult = mPendingUploads.removePayload(
+                                mCurrentAccount,
+                                mCurrentUpload.getOldFile().getRemotePath()
+                        );
+                    } else {
+                        removeResult = mPendingUploads.removePayload(
+                                mCurrentAccount,
+                                mCurrentUpload.getRemotePath()
+                        );
                     }
-                }
 
-                /// notify result
-                notifyUploadResult(uploadResult, mCurrentUpload);
-                sendFinalBroadcast(mCurrentUpload, uploadResult);
+                    /// notify result
+                    notifyUploadResult(mCurrentUpload, uploadResult);
+
+                    sendBroadcastUploadFinished(mCurrentUpload, uploadResult, removeResult.second);
+                }
 
             } else {
                 // Cancel the transfer
                 Log_OC.d(TAG, "Account " + mCurrentUpload.getAccount().toString() +
                         " doesn't exist");
-                cancelUploadForAccount(mCurrentUpload.getAccount().name);
+                cancelUploadsForAccount(mCurrentUpload.getAccount());
 
             }
         }
@@ -691,7 +676,7 @@ public class FileUploader extends Service
      * synchronized with the server, specially the modification time and Etag
      * (where available)
      *
-     * TODO refactor this ugly thing
+     * TODO move into UploadFileOperation
      */
     private void saveUploadedFile() {
         OCFile file = mCurrentUpload.getFile();
@@ -709,6 +694,8 @@ public class FileUploader extends Service
         if (result.isSuccess()) {
             updateOCFile(file, (RemoteFile) result.getData().get(0));
             file.setLastSyncDateForProperties(syncDate);
+        } else {
+            Log_OC.e(TAG, "Error reading properties of file after successful upload; this is gonna hurt...");
         }
 
         // / maybe this would be better as part of UploadFileOperation... or
@@ -718,6 +705,7 @@ public class FileUploader extends Service
             if (oldFile.fileExists()) {
                 oldFile.setStoragePath(null);
                 mStorageManager.saveFile(oldFile);
+                mStorageManager.saveConflict(oldFile, null);
 
             } // else: it was just an automatic renaming due to a name
             // coincidence; nothing else is needed, the storagePath is right
@@ -725,7 +713,10 @@ public class FileUploader extends Service
         }
         file.setNeedsUpdateThumbnail(true);
         mStorageManager.saveFile(file);
+        mStorageManager.saveConflict(file, null);
+        
         mStorageManager.triggerMediaScan(file.getStoragePath());
+
     }
 
     private void updateOCFile(OCFile file, RemoteFile remoteFile) {
@@ -734,12 +725,11 @@ public class FileUploader extends Service
         file.setMimetype(remoteFile.getMimeType());
         file.setModificationTimestamp(remoteFile.getModifiedTimestamp());
         file.setModificationTimestampAtLastSyncForData(remoteFile.getModifiedTimestamp());
-        // file.setEtag(remoteFile.getEtag());    // TODO Etag, where available
+        file.setEtag(remoteFile.getEtag());
         file.setRemoteId(remoteFile.getRemoteId());
     }
 
-    private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType,
-                                           FileDataStorageManager storageManager) {
+    private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType) {
 
         // MIME type
         if (mimeType == null || mimeType.length() <= 0) {
@@ -830,11 +820,11 @@ public class FileUploader extends Service
     /**
      * Updates the status notification with the result of an upload operation.
      *
-     * @param uploadResult Result of the upload operation.
-     * @param upload Finished upload operation
+     * @param uploadResult  Result of the upload operation.
+     * @param upload        Finished upload operation
      */
-    private void notifyUploadResult(
-            RemoteOperationResult uploadResult, UploadFileOperation upload) {
+    private void notifyUploadResult(UploadFileOperation upload,
+                                    RemoteOperationResult uploadResult) {
         Log_OC.d(TAG, "NotifyUploadResult with resultCode: " + uploadResult.getCode());
         // / cancelled operation or success -> silent removal of progress notification
         mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);
@@ -941,10 +931,15 @@ public class FileUploader extends Service
      * Sends a broadcast in order to the interested activities can update their
      * view
      *
-     * @param upload Finished upload operation
-     * @param uploadResult Result of the upload operation
+     * @param upload                    Finished upload operation
+     * @param uploadResult              Result of the upload operation
+     * @param unlinkedFromRemotePath    Path in the uploads tree where the upload was unlinked from
      */
-    private void sendFinalBroadcast(UploadFileOperation upload, RemoteOperationResult uploadResult) {
+    private void sendBroadcastUploadFinished(
+            UploadFileOperation upload,
+            RemoteOperationResult uploadResult,
+            String unlinkedFromRemotePath) {
+
         Intent end = new Intent(getUploadFinishMessage());
         end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote
         // path, after
@@ -957,6 +952,10 @@ public class FileUploader extends Service
         end.putExtra(EXTRA_OLD_FILE_PATH, upload.getOriginalStoragePath());
         end.putExtra(ACCOUNT_NAME, upload.getAccount().name);
         end.putExtra(EXTRA_UPLOAD_RESULT, uploadResult.isSuccess());
+        if (unlinkedFromRemotePath != null) {
+            end.putExtra(EXTRA_LINKED_TO_PATH, unlinkedFromRemotePath);
+        }
+
         sendStickyBroadcast(end);
     }
 
@@ -966,6 +965,8 @@ public class FileUploader extends Service
      * @param localPath         Full path to a file in the local file system.
      * @param mimeType          MIME type of the file.
      * @return true if is needed to add the pdf file extension to the file
+     *
+     * TODO - move to OCFile or Utils class
      */
     private boolean isPdfFileFromContentProviderWithoutExtension(String localPath,
                                                                  String mimeType) {
@@ -976,20 +977,11 @@ public class FileUploader extends Service
 
     /**
      * Remove uploads of an account
-     * @param accountName       Name of an OC account
+     *
+     * @param account       Downloads account to remove
      */
-    private void cancelUploadForAccount(String accountName){
-        // this can be slow if there are many uploads :(
-        Iterator<String> it = mPendingUploads.keySet().iterator();
-        Log_OC.d(TAG, "Number of pending updloads= "  + mPendingUploads.size());
-        while (it.hasNext()) {
-            String key = it.next();
-            Log_OC.d(TAG, "mPendingUploads CANCELLED " + key);
-            if (key.startsWith(accountName)) {
-                synchronized (mPendingUploads) {
-                    mPendingUploads.remove(key);
-                }
-            }
-        }
+    private void cancelUploadsForAccount(Account account){
+        // Cancel pending uploads
+        mPendingUploads.remove(account);
     }
 }

+ 9 - 4
src/com/owncloud/android/operations/DownloadFileOperation.java

@@ -27,7 +27,6 @@ import java.util.Iterator;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
 import com.owncloud.android.lib.common.OwnCloudClient;
@@ -52,6 +51,7 @@ public class DownloadFileOperation extends RemoteOperation {
     private OCFile mFile;
     private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
     private long mModificationTimestamp = 0;
+    private String mEtag = "";
     private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
     
     private DownloadRemoteFileOperation mDownloadOperation;
@@ -127,11 +127,15 @@ public class DownloadFileOperation extends RemoteOperation {
                 mFile.getModificationTimestamp();
     }
 
+    public String getEtag() {
+        return mEtag;
+    }
+
     @Override
     protected RemoteOperationResult run(OwnCloudClient client) {
-        RemoteOperationResult result = null;
-        File newFile = null;
-        boolean moved = true;
+        RemoteOperationResult result;
+        File newFile;
+        boolean moved;
         
         /// download will be performed to a temporal file, then moved to the final location
         File tmpFile = new File(getTmpPath());
@@ -154,6 +158,7 @@ public class DownloadFileOperation extends RemoteOperation {
         
         if (result.isSuccess()) {
             mModificationTimestamp = mDownloadOperation.getModificationTimestamp();
+            mEtag = mDownloadOperation.getEtag();
             newFile = new File(getSavePath());
             newFile.getParentFile().mkdirs();
             moved = tmpFile.renameTo(newFile);

+ 61 - 162
src/com/owncloud/android/operations/RefreshFolderOperation.java

@@ -20,26 +20,17 @@
 
 package com.owncloud.android.operations;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
-import org.apache.http.HttpStatus;
 import android.accounts.Account;
 import android.content.Context;
 import android.content.Intent;
 import android.util.Log;
-//import android.support.v4.content.LocalBroadcastManager;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 
@@ -50,7 +41,6 @@ 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.lib.resources.shares.GetRemoteSharesForFileOperation;
-import com.owncloud.android.lib.resources.files.FileUtils;
 import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation;
 import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
 import com.owncloud.android.lib.resources.files.RemoteFile;
@@ -120,7 +110,10 @@ public class RefreshFolderOperation extends RemoteOperation {
     /** 'True' means that Etag will be ignored */
     private boolean mIgnoreETag;
 
-    
+    private List<SynchronizeFileOperation> mFilesToSyncContents;
+    // this will be used for every file when 'folder synchronization' replaces 'folder download'
+
+
     /**
      * Creates a new instance of {@link RefreshFolderOperation}.
      * 
@@ -154,6 +147,7 @@ public class RefreshFolderOperation extends RemoteOperation {
         mForgottenLocalFiles = new HashMap<String, String>();
         mRemoteFolderChanged = false;
         mIgnoreETag = ignoreETag;
+        mFilesToSyncContents = new Vector<SynchronizeFileOperation>();
     }
     
     
@@ -191,7 +185,7 @@ public class RefreshFolderOperation extends RemoteOperation {
         mConflictsFound = 0;
         mForgottenLocalFiles.clear();
         
-        if (FileUtils.PATH_SEPARATOR.equals(mLocalFolder.getRemotePath()) && !mSyncFullAccount) {
+        if (OCFile.ROOT_PATH.equals(mLocalFolder.getRemotePath()) && !mSyncFullAccount) {
             updateOCVersion(client);
         }
         
@@ -201,9 +195,14 @@ public class RefreshFolderOperation extends RemoteOperation {
             if (mRemoteFolderChanged) {
                 result = fetchAndSyncRemoteFolder(client);
             } else {
-                // TODO Enable when "On Device" is recovered ?
+                fetchFavoritesToSyncFromLocalData();
                 mChildren = mStorageManager.getFolderContent(mLocalFolder/*, false*/);
             }
+
+            if (result.isSuccess()) {
+                // request for the synchronization of KEPT-IN-SYNC file contents
+                startContentSynchronizations(mFilesToSyncContents, client);
+            }
         }
         
         if (!mSyncFullAccount) {            
@@ -239,9 +238,8 @@ public class RefreshFolderOperation extends RemoteOperation {
     private RemoteOperationResult checkForChanges(OwnCloudClient client) {
         mRemoteFolderChanged = true;
         RemoteOperationResult result = null;
-        String remotePath = null;
+        String remotePath = mLocalFolder.getRemotePath();
 
-        remotePath = mLocalFolder.getRemotePath();
         Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath);
         
         // remote request 
@@ -264,7 +262,7 @@ public class RefreshFolderOperation extends RemoteOperation {
 
             result = new RemoteOperationResult(ResultCode.OK);
         
-            Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + 
+            Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " +
                     (mRemoteFolderChanged ? "changed" : "not changed"));
             
         } else {
@@ -337,15 +335,15 @@ public class RefreshFolderOperation extends RemoteOperation {
         mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath());
 
         // parse data from remote folder 
-        OCFile remoteFolder = fillOCFile((RemoteFile)folderAndFiles.get(0));
+        OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) folderAndFiles.get(0));
         remoteFolder.setParentId(mLocalFolder.getParentId());
         remoteFolder.setFileId(mLocalFolder.getFileId());
         
-        Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() 
+        Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath()
                 + " changed - starting update of local data ");
         
         List<OCFile> updatedFiles = new Vector<OCFile>(folderAndFiles.size() - 1);
-        List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
+        mFilesToSyncContents.clear();
 
         // get current data about local contents of the folder to synchronize
         // TODO Enable when "On Device" is recovered ?
@@ -356,54 +354,55 @@ public class RefreshFolderOperation extends RemoteOperation {
         }
         
         // loop to update every child
-        OCFile remoteFile = null, localFile = null;
+        OCFile remoteFile = null, localFile = null, updatedFile = null;
+        RemoteFile r;
         for (int i=1; i<folderAndFiles.size(); i++) {
             /// new OCFile instance with the data from the server
-            remoteFile = fillOCFile((RemoteFile)folderAndFiles.get(i));
-            remoteFile.setParentId(mLocalFolder.getFileId());
+            r = (RemoteFile) folderAndFiles.get(i);
+            remoteFile = FileStorageUtils.fillOCFile(r);
+
+            /// new OCFile instance to merge fresh data from server with local state
+            updatedFile = FileStorageUtils.fillOCFile(r);
+            updatedFile.setParentId(mLocalFolder.getFileId());
 
             /// retrieve local data for the read file 
             //  localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
             localFile = localFilesMap.remove(remoteFile.getRemotePath());
             
-            /// add to the remoteFile (the new one) data about LOCAL STATE (not existing in server)
-            remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
+            /// add to updatedFile data about LOCAL STATE (not existing in server)
+            updatedFile.setLastSyncDateForProperties(mCurrentSyncTime);
             if (localFile != null) {
-                // some properties of local state are kept unmodified
-                remoteFile.setFileId(localFile.getFileId());
-                remoteFile.setFavorite(localFile.isFavorite());
-                remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
-                remoteFile.setModificationTimestampAtLastSyncForData(
+                updatedFile.setFileId(localFile.getFileId());
+                updatedFile.setFavorite(localFile.isFavorite());
+                updatedFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
+                updatedFile.setModificationTimestampAtLastSyncForData(
                         localFile.getModificationTimestampAtLastSyncForData()
                 );
-                remoteFile.setStoragePath(localFile.getStoragePath());
-                // eTag will not be updated unless contents are synchronized 
-                //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
-                remoteFile.setEtag(localFile.getEtag());    
-                if (remoteFile.isFolder()) {
-                    remoteFile.setFileLength(localFile.getFileLength()); 
+                updatedFile.setStoragePath(localFile.getStoragePath());
+                // eTag will not be updated unless file CONTENTS are synchronized
+                updatedFile.setEtag(localFile.getEtag());
+                if (updatedFile.isFolder()) {
+                    updatedFile.setFileLength(localFile.getFileLength());
                         // TODO move operations about size of folders to FileContentProvider
                 } else if (mRemoteFolderChanged && remoteFile.isImage() &&
                         remoteFile.getModificationTimestamp() !=
                                 localFile.getModificationTimestamp()) {
-                    remoteFile.setNeedsUpdateThumbnail(true);
+                    updatedFile.setNeedsUpdateThumbnail(true);
                     Log.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server");
                 }
-                remoteFile.setPublicLink(localFile.getPublicLink());
-                remoteFile.setShareByLink(localFile.isShareByLink());
+                updatedFile.setPublicLink(localFile.getPublicLink());
+                updatedFile.setShareByLink(localFile.isShareByLink());
+                updatedFile.setEtagInConflict(localFile.getEtagInConflict());
             } else {
-                // remote eTag will not be updated unless contents are synchronized 
-                //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
-                remoteFile.setEtag(""); 
+                // remote eTag will not be updated unless file CONTENTS are synchronized
+                updatedFile.setEtag("");
             }
 
             /// check and fix, if needed, local storage path
-            checkAndFixForeignStoragePath(remoteFile);      // policy - local files are COPIED 
-                                                            // into the ownCloud local folder;
-            searchForLocalFileInDefaultPath(remoteFile);    // legacy   
+            FileStorageUtils.searchForLocalFileInDefaultPath(updatedFile, mAccount);
 
             /// prepare content synchronization for kept-in-sync files
-            if (remoteFile.isFavorite()) {
+            if (updatedFile.isFavorite()) {
                 SynchronizeFileOperation operation = new SynchronizeFileOperation(  localFile,        
                                                                                     remoteFile, 
                                                                                     mAccount, 
@@ -411,18 +410,15 @@ public class RefreshFolderOperation extends RemoteOperation {
                                                                                     mContext
                                                                                     );
                 
-                filesToSyncContents.add(operation);
+                mFilesToSyncContents.add(operation);
             }
-            
-            updatedFiles.add(remoteFile);
+
+            updatedFiles.add(updatedFile);
         }
 
         // save updated contents in local database
         mStorageManager.saveFolder(remoteFolder, updatedFiles, localFilesMap.values());
 
-        // request for the synchronization of file contents AFTER saving current remote properties
-        startContentSynchronizations(filesToSyncContents, client);
-
         mChildren = updatedFiles;
     }
 
@@ -460,97 +456,6 @@ public class RefreshFolderOperation extends RemoteOperation {
     }
 
 
-    public boolean isMultiStatus(int status) {
-        return (status == HttpStatus.SC_MULTI_STATUS); 
-    }
-
-    /**
-     * Creates and populates a new {@link OCFile} object with the data read from the server.
-     * 
-     * @param remote    remote file read from the server (remote file or folder).
-     * @return          New OCFile instance representing the remote resource described by we.
-     */
-    private OCFile fillOCFile(RemoteFile remote) {
-        OCFile file = new OCFile(remote.getRemotePath());
-        file.setCreationTimestamp(remote.getCreationTimestamp());
-        file.setFileLength(remote.getLength());
-        file.setMimetype(remote.getMimeType());
-        file.setModificationTimestamp(remote.getModifiedTimestamp());
-        file.setEtag(remote.getEtag());
-        file.setPermissions(remote.getPermissions());
-        file.setRemoteId(remote.getRemoteId());
-        return file;
-    }
-    
-
-    /**
-     * Checks the storage path of the OCFile received as parameter. 
-     * If it's out of the local ownCloud folder, tries to copy the file inside it. 
-     * 
-     * If the copy fails, the link to the local file is nullified. The account of forgotten 
-     * files is kept in {@link #mForgottenLocalFiles}
-     *) 
-     * @param file      File to check and fix.
-     */
-    private void checkAndFixForeignStoragePath(OCFile file) {
-        String storagePath = file.getStoragePath();
-        String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
-        if (storagePath != null && !storagePath.equals(expectedPath)) {
-            /// fix storagePaths out of the local ownCloud folder
-            File originalFile = new File(storagePath);
-            if (FileStorageUtils.getUsableSpace(mAccount.name) < originalFile.length()) {
-                mForgottenLocalFiles.put(file.getRemotePath(), storagePath);
-                file.setStoragePath(null);
-                    
-            } else {
-                InputStream in = null;
-                OutputStream out = null;
-                try {
-                    File expectedFile = new File(expectedPath);
-                    File expectedParent = expectedFile.getParentFile();
-                    expectedParent.mkdirs();
-                    if (!expectedParent.isDirectory()) {
-                        throw new IOException(
-                                "Unexpected error: parent directory could not be created"
-                        );
-                    }
-                    expectedFile.createNewFile();
-                    if (!expectedFile.isFile()) {
-                        throw new IOException("Unexpected error: target file could not be created");
-                    }                    
-                    in = new FileInputStream(originalFile);
-                    out = new FileOutputStream(expectedFile);
-                    byte[] buf = new byte[1024];
-                    int len;
-                    while ((len = in.read(buf)) > 0){
-                        out.write(buf, 0, len);
-                    }
-                    file.setStoragePath(expectedPath);
-                    
-                } catch (Exception e) {
-                    Log_OC.e(TAG, "Exception while copying foreign file " + expectedPath, e);
-                    mForgottenLocalFiles.put(file.getRemotePath(), storagePath);
-                    file.setStoragePath(null);
-                    
-                } finally {
-                    try {
-                        if (in != null) in.close();
-                    } catch (Exception e) {
-                        Log_OC.d(TAG, "Weird exception while closing input stream for " 
-                                + storagePath + " (ignoring)", e);
-                    }
-                    try {
-                        if (out != null) out.close();
-                    } catch (Exception e) {
-                        Log_OC.d(TAG, "Weird exception while closing output stream for " 
-                                + expectedPath + " (ignoring)", e);
-                    }
-                }
-            }
-        }
-    }
-    
-    
     private RemoteOperationResult refreshSharesForFolder(OwnCloudClient client) {
         RemoteOperationResult result = null;
         
@@ -572,24 +477,6 @@ public class RefreshFolderOperation extends RemoteOperation {
     }
     
 
-    /**
-     * Scans the default location for saving local copies of files searching for
-     * a 'lost' file with the same full name as the {@link OCFile} received as 
-     * parameter.
-     *  
-     * @param file      File to associate a possible 'lost' local file.
-     */
-    private void searchForLocalFileInDefaultPath(OCFile file) {
-        if (file.getStoragePath() == null && !file.isFolder()) {
-            File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
-            if (f.exists()) {
-                file.setStoragePath(f.getAbsolutePath());
-                file.setLastSyncDateForData(f.lastModified());
-            }
-        }
-    }
-
-    
     /**
      * Sends a message to any application component interested in the progress 
      * of the synchronization.
@@ -614,8 +501,20 @@ public class RefreshFolderOperation extends RemoteOperation {
     }
 
 
-    public boolean getRemoteFolderChanged() {
-        return mRemoteFolderChanged;
+    private void fetchFavoritesToSyncFromLocalData() {
+        List<OCFile> children = mStorageManager.getFolderContent(mLocalFolder);
+        for (OCFile child : children) {
+            if (!child.isFolder() && child.isFavorite()) {
+                SynchronizeFileOperation operation = new SynchronizeFileOperation(
+                        child,
+                        child,  // cheating with the remote file to get an update to server; to refactor
+                        mAccount,
+                        true,
+                        mContext
+                );
+                mFilesToSyncContents.add(operation);
+            }
+        }
     }
 
 }

+ 14 - 11
src/com/owncloud/android/operations/SynchronizeFileOperation.java

@@ -22,7 +22,6 @@
 
 package com.owncloud.android.operations;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileUploader;
@@ -208,15 +207,13 @@ public class SynchronizeFileOperation extends SyncOperation {
 
                 /// check changes in server and local file
                 boolean serverChanged = false;
-                /* time for eTag is coming, but not yet
-                    if (mServerFile.getEtag() != null) {
-                        serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag()));
-                    } else { */
-                serverChanged = (
-                    mServerFile.getModificationTimestamp() !=
-                            mLocalFile.getModificationTimestampAtLastSyncForData()
-                );
-                //}
+                if (mLocalFile.getEtag() == null || mLocalFile.getEtag().length() == 0) {
+                    // file uploaded (null) or downloaded ("") before upgrade to version 1.8.0; check the old condition
+                    serverChanged = mServerFile.getModificationTimestamp() !=
+                            mLocalFile.getModificationTimestampAtLastSyncForData();
+                } else {
+                    serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag()));
+                }
                 boolean localChanged = (
                     mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData()
                 );
@@ -225,6 +222,7 @@ public class SynchronizeFileOperation extends SyncOperation {
                 //if (!mLocalFile.getEtag().isEmpty() && localChanged && serverChanged) {
                 if (localChanged && serverChanged) {
                     result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
+                    getStorageManager().saveConflict(mLocalFile, mServerFile.getEtag());
 
                 } else if (localChanged) {
                     if (mSyncFileContents && mAllowUploads) {
@@ -254,6 +252,7 @@ public class SynchronizeFileOperation extends SyncOperation {
                         mServerFile.setLastSyncDateForData(mLocalFile.getLastSyncDateForData());
                         mServerFile.setStoragePath(mLocalFile.getStoragePath());
                         mServerFile.setParentId(mLocalFile.getParentId());
+                        mServerFile.setEtag(mLocalFile.getEtag());
                         getStorageManager().saveFile(mServerFile);
 
                     }
@@ -264,7 +263,11 @@ public class SynchronizeFileOperation extends SyncOperation {
                     result = new RemoteOperationResult(ResultCode.OK);
                 }
 
-            } 
+                // safe blanket: sync'ing a not in-conflict file will clean wrong conflict markers in ancestors
+                if (result.getCode() != ResultCode.SYNC_CONFLICT) {
+                    getStorageManager().saveConflict(mLocalFile, null);
+                }
+            }
 
         }
 

+ 52 - 72
src/com/owncloud/android/operations/SynchronizeFolderOperation.java

@@ -60,7 +60,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
  *  Fetches the list and properties of the files contained in the given folder, including their 
  *  properties, and updates the local database with them.
  *  
- *  Does NOT enter in the child folders to synchronize their contents also.
+ *  Does NOT enter in the child folders to synchronize their contents also, BUT requests for a new operation instance
+ *  doing so.
  */
 public class SynchronizeFolderOperation extends SyncOperation {
 
@@ -96,10 +97,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
     private List<OCFile> mFilesForDirectDownload;
         // to avoid extra PROPFINDs when there was no change in the folder
     
-    private List<SyncOperation> mFilesToSyncContentsWithoutUpload;
-        // this will go out when 'folder synchronization' replaces 'folder download'; step by step  
-
-    private List<SyncOperation> mFavouriteFilesToSyncContents;
+    private List<SyncOperation> mFilesToSyncContents;
         // this will be used for every file when 'folder synchronization' replaces 'folder download' 
 
     private final AtomicBoolean mCancellationRequested;
@@ -120,8 +118,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
         mContext = context;
         mRemoteFolderChanged = false;
         mFilesForDirectDownload = new Vector<OCFile>();
-        mFilesToSyncContentsWithoutUpload = new Vector<SyncOperation>();
-        mFavouriteFilesToSyncContents = new Vector<SyncOperation>();
+        mFilesToSyncContents = new Vector<SyncOperation>();
         mCancellationRequested = new AtomicBoolean(false);
     }
 
@@ -281,7 +278,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
         FileDataStorageManager storageManager = getStorageManager();
         
         // parse data from remote folder
-        OCFile remoteFolder = fillOCFile((RemoteFile)folderAndFiles.get(0));
+        OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) folderAndFiles.get(0));
         remoteFolder.setParentId(mLocalFolder.getParentId());
         remoteFolder.setFileId(mLocalFolder.getFileId());
 
@@ -290,8 +287,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
 
         List<OCFile> updatedFiles = new Vector<OCFile>(folderAndFiles.size() - 1);
         mFilesForDirectDownload.clear();
-        mFilesToSyncContentsWithoutUpload.clear();
-        mFavouriteFilesToSyncContents.clear();
+        mFilesToSyncContents.clear();
 
         if (mCancellationRequested.get()) {
             throw new OperationCancelledException();
@@ -306,85 +302,77 @@ public class SynchronizeFolderOperation extends SyncOperation {
         }
 
         // loop to synchronize every child
-        OCFile remoteFile = null, localFile = null;
+        OCFile remoteFile = null, localFile = null, updatedFile = null;
+        RemoteFile r;
         for (int i=1; i<folderAndFiles.size(); i++) {
             /// new OCFile instance with the data from the server
-            remoteFile = fillOCFile((RemoteFile)folderAndFiles.get(i));
-            remoteFile.setParentId(mLocalFolder.getFileId());
+            r = (RemoteFile) folderAndFiles.get(i);
+            remoteFile = FileStorageUtils.fillOCFile(r);
+
+            /// new OCFile instance to merge fresh data from server with local state
+            updatedFile = FileStorageUtils.fillOCFile(r);
+            updatedFile.setParentId(mLocalFolder.getFileId());
 
             /// retrieve local data for the read file
             //  localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
             localFile = localFilesMap.remove(remoteFile.getRemotePath());
 
-            /// add to the remoteFile (the new one) data about LOCAL STATE (not existing in server)
-            remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
+            /// add to updatedFile data about LOCAL STATE (not existing in server)
+            updatedFile.setLastSyncDateForProperties(mCurrentSyncTime);
             if (localFile != null) {
-                // some properties of local state are kept unmodified
-                remoteFile.setFileId(localFile.getFileId());
-                remoteFile.setFavorite(localFile.isFavorite());
-                remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
-                remoteFile.setModificationTimestampAtLastSyncForData(
+                updatedFile.setFileId(localFile.getFileId());
+                updatedFile.setFavorite(localFile.isFavorite());
+                updatedFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
+                updatedFile.setModificationTimestampAtLastSyncForData(
                         localFile.getModificationTimestampAtLastSyncForData()
                 );
-                remoteFile.setStoragePath(localFile.getStoragePath());
-                // eTag will not be updated unless contents are synchronized
-                //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
-                remoteFile.setEtag(localFile.getEtag());
-                if (remoteFile.isFolder()) {
-                    remoteFile.setFileLength(localFile.getFileLength());
+                updatedFile.setStoragePath(localFile.getStoragePath());
+                // eTag will not be updated unless file CONTENTS are synchronized
+                updatedFile.setEtag(localFile.getEtag());
+                if (updatedFile.isFolder()) {
+                    updatedFile.setFileLength(localFile.getFileLength());
                         // TODO move operations about size of folders to FileContentProvider
                 } else if (mRemoteFolderChanged && remoteFile.isImage() &&
                         remoteFile.getModificationTimestamp() !=
                                 localFile.getModificationTimestamp()) {
-                    remoteFile.setNeedsUpdateThumbnail(true);
+                    updatedFile.setNeedsUpdateThumbnail(true);
                     Log.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server");
                 }
-                remoteFile.setPublicLink(localFile.getPublicLink());
-                remoteFile.setShareByLink(localFile.isShareByLink());
+                updatedFile.setPublicLink(localFile.getPublicLink());
+                updatedFile.setShareByLink(localFile.isShareByLink());
+                updatedFile.setEtagInConflict(localFile.getEtagInConflict());
             } else {
-                // remote eTag will not be updated unless contents are synchronized
-                //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
-                remoteFile.setEtag("");
+                // remote eTag will not be updated unless file CONTENTS are synchronized
+                updatedFile.setEtag("");
             }
 
             /// check and fix, if needed, local storage path
-            searchForLocalFileInDefaultPath(remoteFile);
+            searchForLocalFileInDefaultPath(updatedFile);
             
             /// classify file to sync/download contents later
             if (remoteFile.isFolder()) {
                 /// to download children files recursively
-                synchronized(mCancellationRequested) {
+                synchronized (mCancellationRequested) {
                     if (mCancellationRequested.get()) {
                         throw new OperationCancelledException();
                     }
                     startSyncFolderOperation(remoteFile.getRemotePath());
                 }
 
-            } else if (remoteFile.isFavorite()) {
-                /// prepare content synchronization for kept-in-sync files
-                SynchronizeFileOperation operation = new SynchronizeFileOperation(
-                        localFile,
-                        remoteFile,
-                        mAccount,
-                        true,
-                        mContext
-                    );
-                mFavouriteFilesToSyncContents.add(operation);
-                
             } else {
-                /// prepare limited synchronization for regular files
+                /// prepare content synchronization for files (any file, not just favorites)
                 SynchronizeFileOperation operation = new SynchronizeFileOperation(
                         localFile,
                         remoteFile,
                         mAccount,
                         true,
-                        false,
                         mContext
                     );
-                mFilesToSyncContentsWithoutUpload.add(operation);
+                mFilesToSyncContents.add(operation);
+                
             }
 
-            updatedFiles.add(remoteFile);
+            updatedFiles.add(updatedFile);
         }
 
         // save updated contents in local database
@@ -408,10 +396,23 @@ public class SynchronizeFolderOperation extends SyncOperation {
                 }
 
             } else {
-                /// prepare limited synchronization for regular files
+                /// synchronization for regular files
                 if (!child.isDown()) {
                     mFilesForDirectDownload.add(child);
+
+                } else {
+                    /// this should result in direct upload of files that were locally modified
+                    SynchronizeFileOperation operation = new SynchronizeFileOperation(
+                            child,
+                            (child.getEtagInConflict() != null ? child : null),
+                            mAccount,
+                            true,
+                            mContext
+                    );
+                    mFilesToSyncContents.add(operation);
+
                 }
+
             }
         }
     }
@@ -419,8 +420,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
 
     private void syncContents(OwnCloudClient client) throws OperationCancelledException {
         startDirectDownloads();
-        startContentSynchronizations(mFilesToSyncContentsWithoutUpload, client);
-        startContentSynchronizations(mFavouriteFilesToSyncContents, client);
+        startContentSynchronizations(mFilesToSyncContents, client);
     }
 
     
@@ -478,26 +478,6 @@ public class SynchronizeFolderOperation extends SyncOperation {
     }
 
     
-    /**
-     * Creates and populates a new {@link com.owncloud.android.datamodel.OCFile}
-     * object with the data read from the server.
-     *
-     * @param remote    remote file read from the server (remote file or folder).
-     * @return          New OCFile instance representing the remote resource described by we.
-     */
-    private OCFile fillOCFile(RemoteFile remote) {
-        OCFile file = new OCFile(remote.getRemotePath());
-        file.setCreationTimestamp(remote.getCreationTimestamp());
-        file.setFileLength(remote.getLength());
-        file.setMimetype(remote.getMimeType());
-        file.setModificationTimestamp(remote.getModifiedTimestamp());
-        file.setEtag(remote.getEtag());
-        file.setPermissions(remote.getPermissions());
-        file.setRemoteId(remote.getRemoteId());
-        return file;
-    }
-
-
     /**
      * Scans the default location for saving local copies of files searching for
      * a 'lost' file with the same full name as the {@link com.owncloud.android.datamodel.OCFile}

+ 44 - 45
src/com/owncloud/android/operations/UploadFileOperation.java

@@ -31,7 +31,7 @@ import java.util.Iterator;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.HttpStatus;
 import org.apache.commons.httpclient.methods.RequestEntity;
 
 import android.accounts.Account;
@@ -75,7 +75,6 @@ public class UploadFileOperation extends RemoteOperation {
     private boolean mWasRenamed = false;
     private String mOriginalFileName = null;
     private String mOriginalStoragePath = null;
-    PutMethod mPutMethod = null;
     private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
     private AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
     private Context mContext;
@@ -312,61 +311,61 @@ public class UploadFileOperation extends RemoteOperation {
                     (new File(mFile.getStoragePath())).length() >
                             ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) {
                 mUploadOperation = new ChunkedUploadRemoteFileOperation(mFile.getStoragePath(),
-                        mFile.getRemotePath(), mFile.getMimetype());
+                        mFile.getRemotePath(), mFile.getMimetype(), mFile.getEtagInConflict());
             } else {
                 mUploadOperation = new UploadRemoteFileOperation(mFile.getStoragePath(),
-                        mFile.getRemotePath(), mFile.getMimetype());
+                        mFile.getRemotePath(), mFile.getMimetype(), mFile.getEtagInConflict());
             }
             Iterator <OnDatatransferProgressListener> listener = mDataTransferListeners.iterator();
             while (listener.hasNext()) {
                 mUploadOperation.addDatatransferProgressListener(listener.next());
             }
-            if (!mCancellationRequested.get()) {
-                result = mUploadOperation.execute(client);
-
-                /// move local temporal file or original file to its corresponding
-                // location in the ownCloud local folder
-                if (result.isSuccess()) {
-                    if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) {
-                        mFile.setStoragePath(null);
-
-                    } else {
-                        mFile.setStoragePath(expectedPath);
-                        File fileToMove = null;
-                        if (temporalFile != null) { // FileUploader.LOCAL_BEHAVIOUR_COPY
-                            // ; see where temporalFile was
-                            // set
-                            fileToMove = temporalFile;
-                        } else { // FileUploader.LOCAL_BEHAVIOUR_MOVE
-                            fileToMove = originalFile;
-                        }
-                        if (!expectedFile.equals(fileToMove)) {
-                            File expectedFolder = expectedFile.getParentFile();
-                            expectedFolder.mkdirs();
-                            if (!expectedFolder.isDirectory() || !fileToMove.renameTo(expectedFile)) {
-                                mFile.setStoragePath(null); // forget the local file
-                                // by now, treat this as a success; the file was
-                                // uploaded; the user won't like that the local file
-                                // is not linked, but this should be a very rare
-                                // fail;
-                                // the best option could be show a warning message
-                                // (but not a fail)
-                                // result = new
-                                // RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED);
-                                // return result;
-                            }
+            if (mCancellationRequested.get()) {
+                throw new OperationCancelledException();
+            }
+
+            result = mUploadOperation.execute(client);
+
+            /// move local temporal file or original file to its corresponding
+            // location in the ownCloud local folder
+            if (result.isSuccess()) {
+                if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) {
+                    mFile.setStoragePath(null);
+
+                } else {
+                    mFile.setStoragePath(expectedPath);
+                    File fileToMove = null;
+                    if (temporalFile != null) { // FileUploader.LOCAL_BEHAVIOUR_COPY
+                        // ; see where temporalFile was
+                        // set
+                        fileToMove = temporalFile;
+                    } else { // FileUploader.LOCAL_BEHAVIOUR_MOVE
+                        fileToMove = originalFile;
+                    }
+                    if (!expectedFile.equals(fileToMove)) {
+                        File expectedFolder = expectedFile.getParentFile();
+                        expectedFolder.mkdirs();
+                        if (!expectedFolder.isDirectory() || !fileToMove.renameTo(expectedFile)) {
+                            mFile.setStoragePath(null); // forget the local file
+                            // by now, treat this as a success; the file was
+                            // uploaded; the user won't like that the local file
+                            // is not linked, but this should be a very rare
+                            // fail;
+                            // the best option could be show a warning message
+                            // (but not a fail)
+                            // result = new
+                            // RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED);
+                            // return result;
                         }
                     }
                 }
+
+            } else if (result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED ) {
+                result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
             }
 
         } catch (Exception e) {
-            // TODO something cleaner with cancellations
-            if (mCancellationRequested.get()) {
-                result = new RemoteOperationResult(new OperationCancelledException());
-            } else {
-                result = new RemoteOperationResult(e);
-            }
+            result = new RemoteOperationResult(e);
 
         } finally {
             if (temporalFile != null && !originalFile.equals(temporalFile)) {
@@ -406,7 +405,7 @@ public class UploadFileOperation extends RemoteOperation {
         newFile.setModificationTimestamp(mFile.getModificationTimestamp());
         newFile.setModificationTimestampAtLastSyncForData(
                 mFile.getModificationTimestampAtLastSyncForData());
-        // newFile.setEtag(mFile.getEtag())
+        newFile.setEtag(mFile.getEtag());
         newFile.setFavorite(mFile.isFavorite());
         newFile.setLastSyncDateForProperties(mFile.getLastSyncDateForProperties());
         newFile.setLastSyncDateForData(mFile.getLastSyncDateForData());

+ 22 - 55
src/com/owncloud/android/providers/FileContentProvider.java

@@ -23,7 +23,6 @@
 package com.owncloud.android.providers;
 
 import java.io.File;
-import java.security.Provider;
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -107,6 +106,8 @@ public class FileContentProvider extends ContentProvider {
                 ProviderTableMeta.FILE_UPDATE_THUMBNAIL);
         mFileProjectionMap.put(ProviderTableMeta.FILE_IS_DOWNLOADING,
                 ProviderTableMeta.FILE_IS_DOWNLOADING);
+        mFileProjectionMap.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT,
+                ProviderTableMeta.FILE_ETAG_IN_CONFLICT);
     }
 
     private static final int SINGLE_FILE = 1;
@@ -527,59 +528,6 @@ public class FileContentProvider extends ContentProvider {
         }
     }
 
- /*
-    private int updateFolderSize(SQLiteDatabase db, String folderId) {
-        int count = 0;
-        String [] whereArgs = new String[] { folderId };
-
-        // read current size saved for the folder
-        long folderSize = 0;
-        long folderParentId = -1;
-        Uri selectFolderUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, folderId);
-        String[] folderProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH,  ProviderTableMeta.FILE_PARENT};
-        String folderWhere = ProviderTableMeta._ID + "=?";
-        Cursor folderCursor = query(db, selectFolderUri, folderProjection, folderWhere, whereArgs, null);
-        if (folderCursor != null && folderCursor.moveToFirst()) {
-            folderSize = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));;
-            folderParentId = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_PARENT));;
-        }
-        folderCursor.close();
-
-        // read and sum sizes of children
-        long childrenSize = 0;
-        Uri selectChildrenUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, folderId);
-        String[] childrenProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH,  ProviderTableMeta.FILE_PARENT};
-        String childrenWhere = ProviderTableMeta.FILE_PARENT + "=?";
-        Cursor childrenCursor = query(db, selectChildrenUri, childrenProjection, childrenWhere, whereArgs, null);
-        if (childrenCursor != null && childrenCursor.moveToFirst()) {
-            while (!childrenCursor.isAfterLast()) {
-                childrenSize += childrenCursor.getLong(childrenCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));
-                childrenCursor.moveToNext();
-            }
-        }
-        childrenCursor.close();
-
-        // update if needed
-        if (folderSize != childrenSize) {
-            Log_OC.d("FileContentProvider", "Updating " + folderSize + " to " + childrenSize);
-            ContentValues cv = new ContentValues();
-            cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, childrenSize);
-            count = db.update(ProviderTableMeta.FILE_TABLE_NAME, cv, folderWhere, whereArgs);
-
-            // propagate update until root
-            if (folderParentId > FileDataStorageManager.ROOT_PARENT_ID) {
-                Log_OC.d("FileContentProvider", "Propagating update to " + folderParentId);
-                updateFolderSize(db, String.valueOf(folderParentId));
-            } else {
-                Log_OC.d("FileContentProvider", "NOT propagating to " + folderParentId);
-            }
-        } else {
-            Log_OC.d("FileContentProvider", "NOT updating, sizes are " + folderSize + " and " + childrenSize);
-        }
-        return count;
-    }
-*/
-
     @Override
     public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> operations)
             throws OperationApplicationException {
@@ -636,7 +584,8 @@ public class FileContentProvider extends ContentProvider {
                     + ProviderTableMeta.FILE_PERMISSIONS  + " TEXT null,"
                     + ProviderTableMeta.FILE_REMOTE_ID  + " TEXT null,"
                     + ProviderTableMeta.FILE_UPDATE_THUMBNAIL  + " INTEGER," //boolean
-                    + ProviderTableMeta.FILE_IS_DOWNLOADING  + " INTEGER);" //boolean
+                    + ProviderTableMeta.FILE_IS_DOWNLOADING  + " INTEGER," //boolean
+                    + ProviderTableMeta.FILE_ETAG_IN_CONFLICT + " TEXT);"
                     );
 
             // Create table ocshares
@@ -836,6 +785,24 @@ public class FileContentProvider extends ContentProvider {
              if (!upgraded)
                 Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
                         ", newVersion == " + newVersion);
+
+            if (oldVersion < 11 && newVersion >= 11) {
+                Log_OC.i("SQL", "Entering in the #11 ADD in onUpgrade");
+                db.beginTransaction();
+                try {
+                    db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
+                            " ADD COLUMN " + ProviderTableMeta.FILE_ETAG_IN_CONFLICT + " TEXT " +
+                            " DEFAULT NULL");
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            if (!upgraded)
+                Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
+                        ", newVersion == " + newVersion);
+
         }
     }
 

+ 3 - 5
src/com/owncloud/android/services/OperationsService.java

@@ -100,7 +100,7 @@ public class OperationsService extends Service {
     public static final String ACTION_REMOVE = "REMOVE";
     public static final String ACTION_CREATE_FOLDER = "CREATE_FOLDER";
     public static final String ACTION_SYNC_FILE = "SYNC_FILE";
-    public static final String ACTION_SYNC_FOLDER = "SYNC_FOLDER";//for the moment, just to download
+    public static final String ACTION_SYNC_FOLDER = "SYNC_FOLDER";
     public static final String ACTION_MOVE_FILE = "MOVE_FILE";
     public static final String ACTION_COPY_FILE = "COPY_FILE";
 
@@ -234,7 +234,6 @@ public class OperationsService extends Service {
      */
     @Override
     public IBinder onBind(Intent intent) {
-        //Log_OC.wtf(TAG, "onBind" );
         return mOperationsBinder;
     }
 
@@ -615,7 +614,7 @@ public class OperationsService extends Service {
                     );
                     
                 } else if (action.equals(ACTION_SYNC_FOLDER)) {
-                    // Sync file
+                    // Sync folder (all its descendant files are sync'ed)
                     String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
                     operation = new SynchronizeFolderOperation(
                             this,                       // TODO remove this dependency from construction time
@@ -623,7 +622,7 @@ public class OperationsService extends Service {
                             account, 
                             System.currentTimeMillis()  // TODO remove this dependency from construction time
                     );
-                    
+
                 } else if (action.equals(ACTION_MOVE_FILE)) {
                     // Move file/folder
                     String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
@@ -726,7 +725,6 @@ public class OperationsService extends Service {
             }
         }
         if (count == 0) {
-            //mOperationResults.put(operation.hashCode(), result);
             Pair<RemoteOperation, RemoteOperationResult> undispatched =
                     new Pair<RemoteOperation, RemoteOperationResult>(operation, result);
             mUndispatchedFinishedOperations.put(((Runnable) operation).hashCode(), undispatched);

+ 9 - 28
src/com/owncloud/android/syncadapter/FileSyncAdapter.java

@@ -30,7 +30,6 @@ import java.util.Map;
 
 import org.apache.jackrabbit.webdav.DavException;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -59,7 +58,7 @@ import android.support.v4.app.NotificationCompat;
  * Implementation of {@link AbstractThreadedSyncAdapter} responsible for synchronizing 
  * ownCloud files.
  * 
- * Performs a full synchronization of the account recieved in {@link #onPerformSync(Account, Bundle,
+ * Performs a full synchronization of the account received in {@link #onPerformSync(Account, Bundle,
  * String, ContentProviderClient, SyncResult)}.
  */
 public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
@@ -77,9 +76,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             ".EVENT_FULL_SYNC_END";
     public static final String EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED =
             FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED";
-    //public static final String EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED =
-    // FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED";
-    
+
     public static final String EXTRA_ACCOUNT_NAME = FileSyncAdapter.class.getName() +
             ".EXTRA_ACCOUNT_NAME";
     public static final String EXTRA_FOLDER_PATH = FileSyncAdapter.class.getName() +
@@ -268,16 +265,6 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
         if (mFailedResultsCounter > MAX_FAILED_RESULTS || isFinisher(mLastFailedResult))
             return;
         
-        /*
-        OCFile folder, 
-        long currentSyncTime, 
-        boolean updateFolderProperties,
-        boolean syncFullAccount,
-        DataStorageManager dataStorageManager, 
-        Account account, 
-        Context context ) {
-        }
-        */
         // folder synchronization
         RefreshFolderOperation synchFolderOp = new RefreshFolderOperation( folder,
                                                                                    mCurrentSyncTime,
@@ -308,7 +295,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
                 // synchronize children folders 
                 List<OCFile> children = synchFolderOp.getChildren();
                 // beware of the 'hidden' recursion here!
-                fetchChildren(folder, children, synchFolderOp.getRemoteFolderChanged());
+                syncChildren(children);
             }
             
         } else {
@@ -351,25 +338,19 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
 
     /**
      * Triggers the synchronization of any folder contained in the list of received files.
+     *
+     * No consideration of etag here because it MUST walk down anyway, in case that kept-in-sync files
+     * have local changes.
      * 
      * @param files         Files to recursively synchronize.
      */
-    private void fetchChildren(OCFile parent, List<OCFile> files, boolean parentEtagChanged) {
+    private void syncChildren(List<OCFile> files) {
         int i;
-        OCFile newFile = null;
-        //String etag = null;
-        //boolean syncDown = false;
+        OCFile newFile;
         for (i=0; i < files.size() && !mCancellation; i++) {
             newFile = files.get(i);
             if (newFile.isFolder()) {
-                /*
-                etag = newFile.getEtag();
-                syncDown = (parentEtagChanged || etag == null || etag.length() == 0);
-                if(syncDown) { */
-                    synchronizeFolder(newFile);
-                    //sendLocalBroadcast(EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED, parent.getRemotePath(),
-                    // null);
-                //}
+                synchronizeFolder(newFile);
             }
         }
        

+ 17 - 5
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -1043,7 +1043,11 @@ public class FileDisplayActivity extends HookActivity
                         (uploadedRemotePath.startsWith(currentDir.getRemotePath()));
 
                 if (sameAccount && isDescendant) {
-                    refreshListOfFilesFragment();
+                    String linkedToRemotePath =
+                            intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
+                    if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
+                        refreshListOfFilesFragment();
+                    }
                 }
 
                 boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT,
@@ -1096,6 +1100,16 @@ public class FileDisplayActivity extends HookActivity
 
         }
 
+        // TODO refactor this receiver, and maybe DownloadFinishReceiver; this method is duplicated :S
+        private boolean isAscendant(String linkedToRemotePath) {
+            OCFile currentDir = getCurrentDir();
+            return (
+                    currentDir != null &&
+                            currentDir.getRemotePath().startsWith(linkedToRemotePath)
+            );
+        }
+
+
     }
 
 
@@ -1107,11 +1121,10 @@ public class FileDisplayActivity extends HookActivity
      */
     private class DownloadFinishReceiver extends BroadcastReceiver {
 
-        //int refreshCounter = 0;
         @Override
         public void onReceive(Context context, Intent intent) {
             try {
-                boolean sameAccount = isSameAccount(context, intent);
+                boolean sameAccount = isSameAccount(intent);
                 String downloadedRemotePath =
                         intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
                 boolean isDescendant = isDescendant(downloadedRemotePath);
@@ -1120,7 +1133,6 @@ public class FileDisplayActivity extends HookActivity
                     String linkedToRemotePath =
                             intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
                     if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
-                        //Log_OC.v(TAG, "refresh #" + ++refreshCounter);
                         refreshListOfFilesFragment();
                     }
                     refreshSecondFragment(
@@ -1162,7 +1174,7 @@ public class FileDisplayActivity extends HookActivity
             );
         }
 
-        private boolean isSameAccount(Context context, Intent intent) {
+        private boolean isSameAccount(Intent intent) {
             String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
             return (accountName != null && getAccount() != null &&
                     accountName.equals(getAccount().name));

+ 34 - 51
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -252,24 +252,47 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                             mTransferServiceGetter.getFileDownloaderBinder();
                     FileUploaderBinder uploaderBinder =
                             mTransferServiceGetter.getFileUploaderBinder();
-                    boolean downloading = (downloaderBinder != null &&
-                            downloaderBinder.isDownloading(mAccount, file));
                     OperationsServiceBinder opsBinder =
                             mTransferServiceGetter.getOperationsServiceBinder();
-                    downloading |= (opsBinder != null &&
-                            opsBinder.isSynchronizing(mAccount, file.getRemotePath()));
-                    if (downloading) {
-                        localStateView.setImageResource(R.drawable.downloading_file_indicator);
+
+                    localStateView.setVisibility(View.INVISIBLE);   // default first
+
+                    if ( //synchronizing
+                                opsBinder != null &&
+                                opsBinder.isSynchronizing(mAccount, file.getRemotePath())
+                            ) {
+                        localStateView.setImageResource(R.drawable.synchronizing_file_indicator);
+                        localStateView.setVisibility(View.VISIBLE);
+
+                    } else if ( // downloading
+                                downloaderBinder != null &&
+                                downloaderBinder.isDownloading(mAccount, file)
+                            ) {
+                        localStateView.setImageResource(
+                                file.isFolder() ?
+                                        R.drawable.synchronizing_file_indicator :
+                                        R.drawable.downloading_file_indicator
+                        );
                         localStateView.setVisibility(View.VISIBLE);
-                    } else if (uploaderBinder != null &&
-                            uploaderBinder.isUploading(mAccount, file)) {
-                        localStateView.setImageResource(R.drawable.uploading_file_indicator);
+
+                    } else if ( //uploading
+                                uploaderBinder != null &&
+                                uploaderBinder.isUploading(mAccount, file)
+                            ) {
+                        localStateView.setImageResource(
+                                file.isFolder() ?
+                                        R.drawable.synchronizing_file_indicator :
+                                        R.drawable.uploading_file_indicator
+                        );
+                        localStateView.setVisibility(View.VISIBLE);
+
+                    } else if (file.getEtagInConflict() != null) {   // conflict
+                        localStateView.setImageResource(R.drawable.conflict_file_indicator);
                         localStateView.setVisibility(View.VISIBLE);
+
                     } else if (file.isDown()) {
                         localStateView.setImageResource(R.drawable.local_file_indicator);
                         localStateView.setVisibility(View.VISIBLE);
-                    } else {
-                        localStateView.setVisibility(View.INVISIBLE);
                     }
 
                     // share with me icon
@@ -348,46 +371,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         return view;
     }
 
-    /**
-     * Local Folder size in human readable format
-     * 
-     * @param path
-     *            String
-     * @return Size in human readable format
-     */
-    private String getFolderSizeHuman(String path) {
-
-        File dir = new File(path);
-
-        if (dir.exists()) {
-            long bytes = FileStorageUtils.getFolderSize(dir);
-            return DisplayUtils.bytesToHumanReadable(bytes);
-        }
-
-        return "0 B";
-    }
-
-    /**
-     * Local Folder size
-     * @param dir File
-     * @return Size in bytes
-     */
-    private long getFolderSize(File dir) {
-        if (dir.exists()) {
-            long result = 0;
-            File[] fileList = dir.listFiles();
-            for(int i = 0; i < fileList.length; i++) {
-                if(fileList[i].isDirectory()) {
-                    result += getFolderSize(fileList[i]);
-                } else {
-                    result += fileList[i].length();
-                }
-            }
-            return result;
-        }
-        return 0;
-    } 
-
     @Override
     public int getViewTypeCount() {
         return 1;

+ 0 - 29
src/com/owncloud/android/ui/dialog/RemoveFileDialogFragment.java

@@ -25,7 +25,6 @@ package com.owncloud.android.ui.dialog;
  * 
  *  Triggers the removal according to the user response.
  */
-import java.util.Vector;
 
 import android.app.Dialog;
 import android.os.Bundle;
@@ -106,34 +105,6 @@ implements ConfirmationDialogFragmentListener {
     public void onCancel(String callerTag) {
         ComponentsGetter cg = (ComponentsGetter)getActivity();
         cg.getFileOperationsHelper().removeFile(mTargetFile, true);
-        
-        FileDataStorageManager storageManager = cg.getStorageManager();
-        
-        boolean containsFavorite = false;
-        if (mTargetFile.isFolder()) {
-            // TODO Enable when "On Device" is recovered ?
-            Vector<OCFile> files = storageManager.getFolderContent(mTargetFile/*, false*/);
-            for(OCFile file: files) {
-                containsFavorite = file.isFavorite() || containsFavorite;
-
-                if (containsFavorite)
-                    break;
-            }
-        }
-
-        // Remove etag for parent, if file is a favorite
-        // or is a folder and contains favorite
-        if (mTargetFile.isFavorite() || containsFavorite) {
-            OCFile folder = null;
-            if (mTargetFile.isFolder()) {
-                folder = mTargetFile;
-            } else {
-                folder = storageManager.getFileById(mTargetFile.getParentId());
-            }
-            
-           folder.setEtag("");
-           storageManager.saveFile(folder);
-        }
     }
 
     @Override

+ 2 - 4
src/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -248,9 +248,8 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
                 dialog.show(getFragmentManager(), FTAG_RENAME_FILE);
                 return true;
             }
-            case R.id.action_cancel_download:
-            case R.id.action_cancel_upload: {
-                ((FileDisplayActivity) mContainerActivity).cancelTransference(getFile());
+            case R.id.action_cancel_sync: {
+                ((FileDisplayActivity)mContainerActivity).cancelTransference(getFile());
                 return true;
             }
             case R.id.action_download_file:
@@ -300,7 +299,6 @@ 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.
      *

+ 2 - 3
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -368,9 +368,8 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
                 mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile);
                 return true;
             }
-            case R.id.action_cancel_download:
-            case R.id.action_cancel_upload: {
-                ((FileDisplayActivity) mContainerActivity).cancelTransference(mTargetFile);
+            case R.id.action_cancel_sync: {
+                ((FileDisplayActivity)mContainerActivity).cancelTransference(mTargetFile);
                 return true;
             }
             case R.id.action_see_details: {

+ 11 - 14
src/com/owncloud/android/utils/DisplayUtils.java

@@ -200,22 +200,19 @@ public class DisplayUtils {
         else if ((System.currentTimeMillis() - time) < 60 * 1000) {
             return c.getString(R.string.file_list_seconds_ago);
         } else {
-            // Workaround 2.x bug (see https://github.com/owncloud/android/issues/716)
-            if (    Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB && 
-                    (System.currentTimeMillis() - time) > 24 * 60 * 60 * 1000   ) {
-                Date date = new Date(time);
-                date.setHours(0);
-                date.setMinutes(0);
-                date.setSeconds(0);
-                dateString = DateUtils.getRelativeDateTimeString(
-                        c, date.getTime(), minResolution, transitionResolution, flags
-                );
-            } else {
-                dateString = DateUtils.getRelativeDateTimeString(c, time, minResolution, transitionResolution, flags);
+            dateString = DateUtils.getRelativeDateTimeString(c, time, minResolution, transitionResolution, flags);
+        }
+
+        String[] parts = dateString.toString().split(",");
+        if (parts.length == 2) {
+            if (parts[1].contains(":") && !parts[0].contains(":")) {
+                return parts[0];
+            } else if (parts[0].contains(":") && !parts[1].contains(":")) {
+                return parts[1];
             }
         }
-        
-        return dateString.toString().split(",")[0];
+        //dateString contains unexpected format. fallback: use relative date time string from android api as is.
+        return dateString.toString();
     }
 
     /**

+ 1 - 1
src/com/owncloud/android/utils/ErrorMessageAdapter.java

@@ -238,7 +238,7 @@ public class ErrorMessageAdapter {
 
                 } else {    // Generic error
                     // Show a Message, operation finished without success
-                    message = String.format(res.getString(R.string.download_folder_failed_content),
+                    message = String.format(res.getString(R.string.sync_folder_failed_content),
                             folderPathName);
                 }
             }

+ 31 - 4
src/com/owncloud/android/utils/FileStorageUtils.java

@@ -32,6 +32,7 @@ import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.resources.files.RemoteFile;
 
+import android.accounts.Account;
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -53,8 +54,6 @@ public class FileStorageUtils {
     public static Boolean mSortAscending = true;
 
     
-    //private static final String LOG_TAG = "FileStorageUtils";
-
     public static final String getSavePath(String accountName) {
         File sdCard = Environment.getExternalStorageDirectory();
         return sdCard.getAbsolutePath() + "/" + MainApp.getDataFolder() + "/" + Uri.encode(accountName, "@");
@@ -120,7 +119,7 @@ public class FileStorageUtils {
      * Creates and populates a new {@link OCFile} object with the data read from the server.
      * 
      * @param remote    remote file read from the server (remote file or folder).
-     * @return          New OCFile instance representing the remote resource described by we.
+     * @return          New OCFile instance representing the remote resource described by remote.
      */
     public static OCFile fillOCFile(RemoteFile remote) {
         OCFile file = new OCFile(remote.getRemotePath());
@@ -302,5 +301,33 @@ public class FileStorageUtils {
         String result = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
         return (result != null) ? result : "";
     }
-  
+
+    /**
+     * Scans the default location for saving local copies of files searching for
+     * a 'lost' file with the same full name as the {@link OCFile} received as
+     * parameter.
+     *
+     * This method helps to keep linked local copies of the files when the app is uninstalled, and then
+     * reinstalled in the device. OR after the cache of the app was deleted in system settings.
+     *
+     * The method is assuming that all the local changes in the file where synchronized in the past. This is dangerous,
+     * but assuming the contrary could lead to massive unnecessary synchronizations of downloaded file after deleting
+     * the app cache.
+     *
+     * This should be changed in the near future to avoid any chance of data loss, but we need to add some options
+     * to limit hard automatic synchronizations to wifi, unless the user wants otherwise.
+     *
+     * @param file      File to associate a possible 'lost' local file.
+     * @param account   Account holding file.
+     */
+    public static void searchForLocalFileInDefaultPath(OCFile file, Account account) {
+        if (file.getStoragePath() == null && !file.isFolder()) {
+            File f = new File(FileStorageUtils.getDefaultSavePathFor(account.name, file));
+            if (f.exists()) {
+                file.setStoragePath(f.getAbsolutePath());
+                file.setLastSyncDateForData(f.lastModified());
+            }
+        }
+    }
+
 }