Browse Source

Merge branch 'master' into develop

David A. Velasco 10 năm trước cách đây
mục cha
commit
ec6b9d7c70
55 tập tin đã thay đổi với 526 bổ sung415 xóa
  1. 3 5
      AndroidManifest.xml
  2. 2 2
      oc_jb_workaround/AndroidManifest.xml
  3. 1 1
      owncloud-android-library
  4. 22 5
      res/layout/list_fragment.xml
  5. 0 1
      res/values-ar/strings.xml
  6. 0 1
      res/values-az/strings.xml
  7. 0 1
      res/values-bn-rBD/strings.xml
  8. 0 1
      res/values-ca/strings.xml
  9. 0 3
      res/values-cs-rCZ/strings.xml
  10. 0 3
      res/values-da/strings.xml
  11. 0 3
      res/values-de-rDE/strings.xml
  12. 0 3
      res/values-de/strings.xml
  13. 0 3
      res/values-el/strings.xml
  14. 0 3
      res/values-en-rGB/strings.xml
  15. 0 1
      res/values-eo/strings.xml
  16. 0 1
      res/values-es-rAR/strings.xml
  17. 0 1
      res/values-es-rMX/strings.xml
  18. 0 1
      res/values-et-rEE/strings.xml
  19. 0 1
      res/values-fa/strings.xml
  20. 0 2
      res/values-fi-rFI/strings.xml
  21. 0 1
      res/values-hu-rHU/strings.xml
  22. 0 1
      res/values-id/strings.xml
  23. 0 3
      res/values-it/strings.xml
  24. 0 3
      res/values-ja-rJP/strings.xml
  25. 0 3
      res/values-ko/strings.xml
  26. 0 1
      res/values-lt-rLT/strings.xml
  27. 0 1
      res/values-mk/strings.xml
  28. 1 3
      res/values-nl/strings.xml
  29. 0 3
      res/values-pt-rBR/strings.xml
  30. 0 3
      res/values-ru/strings.xml
  31. 0 3
      res/values-sk-rSK/strings.xml
  32. 0 1
      res/values-sq/strings.xml
  33. 0 3
      res/values-sv/strings.xml
  34. 1 3
      res/values-tr/strings.xml
  35. 0 1
      res/values-ug/strings.xml
  36. 0 1
      res/values-zh-rCN/strings.xml
  37. 1 3
      res/values/strings.xml
  38. 1 2
      src/com/owncloud/android/authentication/AuthenticatorActivity.java
  39. 3 43
      src/com/owncloud/android/authentication/SsoWebViewClient.java
  40. 21 4
      src/com/owncloud/android/files/services/FileDownloader.java
  41. 19 1
      src/com/owncloud/android/files/services/FileUploader.java
  42. 1 2
      src/com/owncloud/android/operations/CreateShareOperation.java
  43. 2 1
      src/com/owncloud/android/operations/SynchronizeFolderOperation.java
  44. 16 15
      src/com/owncloud/android/services/OperationsService.java
  45. 1 18
      src/com/owncloud/android/services/SyncFolderHandler.java
  46. 79 0
      src/com/owncloud/android/ui/ExtendedListView.java
  47. 9 9
      src/com/owncloud/android/ui/activity/FileDisplayActivity.java
  48. 11 5
      src/com/owncloud/android/ui/adapter/FileListListAdapter.java
  49. 1 1
      src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java
  50. 19 22
      src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java
  51. 179 99
      src/com/owncloud/android/ui/fragment/ExtendedListFragment.java
  52. 9 9
      src/com/owncloud/android/ui/fragment/LocalFileListFragment.java
  53. 51 58
      src/com/owncloud/android/ui/fragment/OCFileListFragment.java
  54. 0 28
      src/com/owncloud/android/utils/DisplayUtils.java
  55. 73 19
      src/third_parties/in/srain/cube/GridViewWithHeaderAndFooter.java

+ 3 - 5
AndroidManifest.xml

@@ -18,8 +18,8 @@
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  -->
 <manifest package="com.owncloud.android"
-    android:versionCode="10600200"
-    android:versionName="1.6.2" xmlns:android="http://schemas.android.com/apk/res/android">
+    android:versionCode="10700000"
+    android:versionName="1.7.0" xmlns:android="http://schemas.android.com/apk/res/android">
 
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
@@ -86,9 +86,7 @@
             android:name=".ui.activity.Preferences"
             android:theme="@style/Theme.ownCloud" >
         </activity>
-        <activity android:name=".ui.activity.PreferencesNewSessionewSession" >
-        </activity>
-        
+
         <activity	
             android:name=".ui.preview.PreviewImageActivity" 
             />

+ 2 - 2
oc_jb_workaround/AndroidManifest.xml

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.owncloud.android.workaround.accounts"
-    android:versionCode="0100020"
-    android:versionName="1.0.20" >
+    android:versionCode="0100021"
+    android:versionName="1.0.21" >
 
     <uses-sdk
         android:minSdkVersion="16"

+ 1 - 1
owncloud-android-library

@@ -1 +1 @@
-Subproject commit e87f5f25ad91950d47ec9b6fa01401360cd7ec8d
+Subproject commit 2f178c9c34e3dab507c46e718705913ed44db3c5

+ 22 - 5
res/layout/list_fragment.xml

@@ -24,16 +24,33 @@
     android:layout_weight="1" >
 
     <android.support.v4.widget.SwipeRefreshLayout
-        android:id="@+id/swipe_refresh_files"
+        android:id="@+id/swipe_containing_list"
         android:layout_width="match_parent"
         android:layout_height="match_parent" 
         android:layout_weight="1"
-        android:footerDividersEnabled="false" > 
+        android:footerDividersEnabled="false"
+        android:visibility="visible" >
         
-        <third_parties.in.srain.cube.GridViewWithHeaderAndFooter
+        <com.owncloud.android.ui.ExtendedListView
             android:id="@+id/list_root"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:visibility="visible" />
+
+    </android.support.v4.widget.SwipeRefreshLayout>
+
+    <android.support.v4.widget.SwipeRefreshLayout
+        android:id="@+id/swipe_containing_grid"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:footerDividersEnabled="false"
+        android:visibility="gone" >
+
+        <third_parties.in.srain.cube.GridViewWithHeaderAndFooter
+            android:id="@+id/grid_root"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
             android:columnWidth="100dp"
             android:gravity="center"
             android:horizontalSpacing="2dp"
@@ -42,9 +59,9 @@
             android:visibility="visible" />
 
     </android.support.v4.widget.SwipeRefreshLayout>
-    	
+
     <android.support.v4.widget.SwipeRefreshLayout
-        android:id="@+id/swipe_refresh_files_emptyView"
+        android:id="@+id/swipe_containing_empty"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:visibility="gone" >

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

@@ -258,5 +258,4 @@
   <string name="saml_authentication_wrong_pass">كلمة مرور خاطئة</string>
   <string name="folder_picker_choose_button_text">اختيار</string>
   <string name="prefs_category_security">الأمان</string>
-  <string name="shared_subject_header">مُشارك</string>
 </resources>

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

@@ -277,5 +277,4 @@ inzibatçınızla əlaqə saxlayasınız.</string>
   <string name="prefs_category_accounts">Hesablar</string>
   <string name="prefs_add_account">Hesab əlavə et</string>
   <string name="saml_authentication_wrong_pass">Yalnış şifrə</string>
-  <string name="shared_subject_header">yayımlanmış</string>
 </resources>

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

@@ -268,5 +268,4 @@
   <string name="folder_picker_choose_button_text">বেছে নিন</string>
   <string name="move_file_not_found">সরাতে ব্যার্থ হলো। ফাইলটি রয়েছে কিনা দেখুন।</string>
   <string name="prefs_category_security">নিরাপত্তা</string>
-  <string name="shared_subject_header">ভাগাভাগিকৃত</string>
 </resources>

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

@@ -274,5 +274,4 @@
   <string name="saml_authentication_wrong_pass">Contrasenya incorrecta</string>
   <string name="folder_picker_choose_button_text">Escull</string>
   <string name="prefs_category_security">Seguretat</string>
-  <string name="shared_subject_header">compartit</string>
 </resources>

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

@@ -298,7 +298,4 @@ správce systému.</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="shared_subject_header">sdílené</string>
-  <string name="with_you_subject_header">s vámi</string>
-  <string name="subject_token">%1$s %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -297,7 +297,4 @@
   <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 %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -299,7 +299,4 @@
   <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 %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -299,7 +299,4 @@
   <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 %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -299,7 +299,4 @@
   <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 &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -299,7 +299,4 @@
   <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="shared_subject_header">shared</string>
-  <string name="with_you_subject_header">with you</string>
-  <string name="subject_token">%1$s %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -194,5 +194,4 @@
   <string name="saml_authentication_wrong_pass">Malĝusta pasvorto</string>
   <string name="folder_picker_choose_button_text">Elekti</string>
   <string name="prefs_category_security">Sekuro</string>
-  <string name="shared_subject_header">kunhavigita</string>
 </resources>

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

@@ -249,5 +249,4 @@
   <string name="saml_authentication_wrong_pass">Clave incorrecta</string>
   <string name="folder_picker_choose_button_text">Elegir</string>
   <string name="prefs_category_security">Seguridad</string>
-  <string name="shared_subject_header">compartido</string>
 </resources>

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

@@ -219,5 +219,4 @@
   <string name="saml_authentication_wrong_pass">Contraseña incorrecta</string>
   <string name="folder_picker_choose_button_text">Seleccionar</string>
   <string name="prefs_category_security">Seguridad</string>
-  <string name="shared_subject_header">compartido</string>
 </resources>

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

@@ -298,5 +298,4 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi
   <string name="forbidden_permissions_move">selle faili liigutamiseks</string>
   <string name="prefs_category_instant_uploading">Kohesed üleslaadimised</string>
   <string name="prefs_category_security">Turvalisus</string>
-  <string name="shared_subject_header">jagatud</string>
 </resources>

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

@@ -240,5 +240,4 @@
   <string name="saml_authentication_wrong_pass">رمز عبور اشتباه است</string>
   <string name="folder_picker_choose_button_text">انتخاب کردن</string>
   <string name="prefs_category_security">امنیت</string>
-  <string name="shared_subject_header">اشتراک گذاشته شده</string>
 </resources>

+ 0 - 2
res/values-fi-rFI/strings.xml

@@ -276,6 +276,4 @@
   <string name="move_file_error">Tämän tiedoston tai kansion siirtoa yrittäessä 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="shared_subject_header">jaettu</string>
-  <string name="with_you_subject_header">kanssasi</string>
 </resources>

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

@@ -253,5 +253,4 @@
   <string name="actionbar_move">Mozgatás</string>
   <string name="folder_picker_choose_button_text">Válasszon</string>
   <string name="prefs_category_security">Biztonság</string>
-  <string name="shared_subject_header">Megosztott</string>
 </resources>

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

@@ -294,5 +294,4 @@
   <string name="forbidden_permissions_move">untuk memindahkan berkas ini</string>
   <string name="prefs_category_instant_uploading">Unggah Cepat</string>
   <string name="prefs_category_security">Keamanan</string>
-  <string name="shared_subject_header">dibagikan</string>
 </resources>

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

@@ -299,7 +299,4 @@
   <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="shared_subject_header">condiviso</string>
-  <string name="with_you_subject_header">con te</string>
-  <string name="subject_token">%1$s %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -300,7 +300,4 @@
   <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 &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -298,7 +298,4 @@
   <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 &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -250,5 +250,4 @@
   <string name="saml_authentication_wrong_pass">Neteisingas slaptažodis</string>
   <string name="folder_picker_choose_button_text">Pasirinkite</string>
   <string name="prefs_category_security">Saugumas</string>
-  <string name="shared_subject_header">bendrinamas</string>
 </resources>

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

@@ -130,5 +130,4 @@
   <string name="saml_authentication_wrong_pass">Погрешна лозинка</string>
   <string name="folder_picker_choose_button_text">Избери</string>
   <string name="prefs_category_security">Безбедност</string>
-  <string name="shared_subject_header">споделен</string>
 </resources>

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

@@ -302,7 +302,5 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar
   <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="shared_subject_header">gedeeld</string>
-  <string name="with_you_subject_header">met u</string>
-  <string name="subject_token">%1$s %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
+  <string name="subject_token">%1$s deelde \"%2$s\" met u</string>
 </resources>

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

@@ -299,7 +299,4 @@
   <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="shared_subject_header">compartilhado</string>
-  <string name="with_you_subject_header">com você</string>
-  <string name="subject_token">%1$s %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -300,7 +300,4 @@
   <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 &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -299,7 +299,4 @@
   <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 %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

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

@@ -77,5 +77,4 @@
   <string name="saml_authentication_wrong_pass">Fjalëkalim i gabuar</string>
   <string name="folder_picker_choose_button_text">Zgjidh</string>
   <string name="prefs_category_security">Siguria</string>
-  <string name="shared_subject_header">Ndarë</string>
 </resources>

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

@@ -298,7 +298,4 @@
   <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="shared_subject_header">delad</string>
-  <string name="with_you_subject_header">med dig</string>
-  <string name="subject_token">%1$s %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

+ 1 - 3
res/values-tr/strings.xml

@@ -299,7 +299,5 @@
   <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">paylaşılan</string>
-  <string name="with_you_subject_header">sizinle</string>
-  <string name="subject_token">%1$s %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
+  <string name="subject_token">%1$s sizinle \"%2$s\" paylaştı</string>
 </resources>

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

@@ -44,5 +44,4 @@
   <string name="empty"></string>
   <string name="prefs_category_accounts">ھېساباتلار</string>
   <string name="prefs_category_security">بىخەتەرلىك</string>
-  <string name="shared_subject_header">ھەمبەھىرلەنگەن</string>
 </resources>

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

@@ -298,5 +298,4 @@
   <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>
 </resources>

+ 1 - 3
res/values/strings.xml

@@ -326,8 +326,6 @@
 	<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="shared_subject_header">shared</string>
-	<string name="with_you_subject_header">with you</string>
-	<string name="subject_token">%1$s %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
+	<string name="subject_token">%1$s shared \"%2$s\" with you</string>
 
 </resources>

+ 1 - 2
src/com/owncloud/android/authentication/AuthenticatorActivity.java

@@ -1020,12 +1020,11 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         dismissDialog(WAIT_DIALOG_TAG);
 
         if (result.isIdPRedirection()) {
-            String url = result.getRedirectedLocation();
             String targetUrl = mServerInfo.mBaseUrl 
                     + AccountUtils.getWebdavPath(mServerInfo.mVersion, mAuthTokenType);
 
             // Show dialog
-            SamlWebViewDialog dialog = SamlWebViewDialog.newInstance(url, targetUrl);            
+            SamlWebViewDialog dialog = SamlWebViewDialog.newInstance(targetUrl, targetUrl);            
             dialog.show(getSupportFragmentManager(), SAML_DIALOG_TAG);
 
             mAuthStatusIcon = 0;

+ 3 - 43
src/com/owncloud/android/authentication/SsoWebViewClient.java

@@ -1,5 +1,5 @@
 /* ownCloud Android client application
- *   Copyright (C) 2012-2013 ownCloud Inc.
+ *   Copyright (C) 2012-2015 ownCloud Inc.
  *
  *   This program is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
@@ -124,7 +124,7 @@ public class SsoWebViewClient extends WebViewClient {
             view.setVisibility(View.GONE);
             CookieManager cookieManager = CookieManager.getInstance();
             final String cookies = cookieManager.getCookie(url);
-            Log_OC.d(TAG, "Cookies: " + cookies);
+            //Log_OC.d(TAG, "Cookies: " + cookies);
             if (mListenerHandler != null && mListenerRef != null) {
                 // this is good idea because onPageFinished is not running in the UI thread
                 mListenerHandler.post(new Runnable() {
@@ -141,22 +141,14 @@ public class SsoWebViewClient extends WebViewClient {
         } 
     }
     
-    
-    @Override
-    public void doUpdateVisitedHistory (WebView view, String url, boolean isReload) {
-        Log_OC.d(TAG, "doUpdateVisitedHistory : " + url);
-    }
-    
     @Override
     public void onReceivedSslError (final WebView view, final SslErrorHandler handler, SslError error) {
-        Log_OC.d(TAG, "onReceivedSslError : " + error);
+        Log_OC.e(TAG, "onReceivedSslError : " + error);
         // Test 1
         X509Certificate x509Certificate = getX509CertificateFromError(error);
         boolean isKnownServer = false;
         
         if (x509Certificate != null) {
-            Log_OC.d(TAG, "------>>>>> x509Certificate " + x509Certificate.toString());
-            
             try {
                 isKnownServer = NetworkUtils.isCertInKnownServersStore((Certificate) x509Certificate, mContext);
             } catch (Exception e) {
@@ -201,36 +193,4 @@ public class SsoWebViewClient extends WebViewClient {
         ((AuthenticatorActivity)mContext).createAuthenticationDialog(view, handler);
     }
 
-    @Override
-    public WebResourceResponse shouldInterceptRequest (WebView view, String url) {
-        Log_OC.d(TAG, "shouldInterceptRequest : " + url);
-        return null;
-    }
-    
-    @Override
-    public void onLoadResource (WebView view, String url) {
-        Log_OC.d(TAG, "onLoadResource : " + url);   
-    }
-    
-    @Override
-    public void onReceivedLoginRequest (WebView view, String realm, String account, String args) {
-        Log_OC.d(TAG, "onReceivedLoginRequest : " + realm + ", " + account + ", " + args);
-    }
-    
-    @Override
-    public void onScaleChanged (WebView view, float oldScale, float newScale) {
-        Log_OC.d(TAG, "onScaleChanged : " + oldScale + " -> " + newScale);
-        super.onScaleChanged(view, oldScale, newScale);
-    }
-
-    @Override
-    public void onUnhandledKeyEvent (WebView view, KeyEvent event) {
-        Log_OC.d(TAG, "onUnhandledKeyEvent : " + event);
-    }
-    
-    @Override
-    public boolean shouldOverrideKeyEvent (WebView view, KeyEvent event) {
-        Log_OC.d(TAG, "shouldOverrideKeyEvent : " + event);
-        return false;
-    }
 }

+ 21 - 4
src/com/owncloud/android/files/services/FileDownloader.java

@@ -109,15 +109,31 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
     @Override
     public void onCreate() {
         super.onCreate();
+        Log_OC.d(TAG, "Creating service");
         mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-        HandlerThread thread = new HandlerThread("FileDownloaderThread",
-                Process.THREAD_PRIORITY_BACKGROUND);
+        HandlerThread thread = new HandlerThread("FileDownloaderThread", Process.THREAD_PRIORITY_BACKGROUND);
         thread.start();
         mServiceLooper = thread.getLooper();
         mServiceHandler = new ServiceHandler(mServiceLooper, this);
         mBinder = new FileDownloaderBinder();
     }
 
+
+    /**
+     * Service clean up
+     */
+    @Override
+    public void onDestroy() {
+        Log_OC.v(TAG, "Destroying service" );
+        mBinder = null;
+        mServiceHandler = null;
+        mServiceLooper.quit();
+        mServiceLooper = null;
+        mNotificationManager = null;
+        super.onDestroy();
+    }
+
+
     /**
      * Entry point to add one or several files to the queue of downloads.
      *
@@ -126,6 +142,8 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
      */
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
+        Log_OC.d(TAG, "Starting command with id " + startId);
+
         if (    !intent.hasExtra(EXTRA_ACCOUNT) ||
                 !intent.hasExtra(EXTRA_FILE)
            ) {
@@ -342,11 +360,10 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
                 Iterator<String> it = requestedDownloads.iterator();
                 while (it.hasNext()) {
                     String next = it.next();
-                    /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                            "Handling download file " + next);*/
                     mService.downloadFile(next);
                 }
             }
+            Log_OC.d(TAG, "Stopping after command with id " + msg.arg1);
             mService.stopSelf(msg.arg1);
         }
     }

+ 19 - 1
src/com/owncloud/android/files/services/FileUploader.java

@@ -161,7 +161,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
     @Override
     public void onCreate() {
         super.onCreate();
-        Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
+        Log_OC.d(TAG, "Creating service");
         mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
         HandlerThread thread = new HandlerThread("FileUploaderThread", Process.THREAD_PRIORITY_BACKGROUND);
         thread.start();
@@ -170,6 +170,21 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
         mBinder = new FileUploaderBinder();
     }
 
+    /**
+     * Service clean up
+     */
+    @Override
+    public void onDestroy() {
+        Log_OC.v(TAG, "Destroying service" );
+        mBinder = null;
+        mServiceHandler = null;
+        mServiceLooper.quit();
+        mServiceLooper = null;
+        mNotificationManager = null;
+        super.onDestroy();
+    }
+
+
     /**
      * Entry point to add one or several files to the queue of uploads.
      * 
@@ -179,6 +194,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
      */
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
+        Log_OC.d(TAG, "Starting command with id " + startId);
+
         if (!intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_UPLOAD_TYPE)
                 || !(intent.hasExtra(KEY_LOCAL_FILE) || intent.hasExtra(KEY_FILE))) {
             Log_OC.e(TAG, "Not enough information provided in intent");
@@ -467,6 +484,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
                     mService.uploadFile(it.next());
                 }
             }
+            Log_OC.d(TAG, "Stopping command after id " + msg.arg1);
             mService.stopSelf(msg.arg1);
         }
     }

+ 1 - 2
src/com/owncloud/android/operations/CreateShareOperation.java

@@ -134,8 +134,7 @@ public class CreateShareOperation extends SyncOperation {
         if (file!=null) {
             mSendIntent.putExtra(Intent.EXTRA_TEXT, share.getShareLink());
             mSendIntent.putExtra(Intent.EXTRA_SUBJECT, String.format(mContext.getString(R.string.subject_token),
-                    getClient().getCredentials().getUsername(), mContext.getString(R.string.shared_subject_header),
-                    file.getFileName(), mContext.getString(R.string.with_you_subject_header)));
+                    getClient().getCredentials().getUsername(), file.getFileName()));
             file.setPublicLink(share.getShareLink());
             file.setShareByLink(true);
             getStorageManager().saveFile(file);

+ 2 - 1
src/com/owncloud/android/operations/SynchronizeFolderOperation.java

@@ -440,7 +440,8 @@ public class SynchronizeFolderOperation extends SyncOperation {
      */
     private void startContentSynchronizations(List<SyncOperation> filesToSyncContents, OwnCloudClient client) 
             throws OperationCancelledException {
-        
+
+        Log_OC.v(TAG, "Starting content synchronization... ");
         RemoteOperationResult contentsResult = null;
         for (SyncOperation op: filesToSyncContents) {
             if (mCancellationRequested.get()) {

+ 16 - 15
src/com/owncloud/android/services/OperationsService.java

@@ -144,6 +144,8 @@ public class OperationsService extends Service {
     @Override
     public void onCreate() {
         super.onCreate();
+        Log_OC.d(TAG, "Creating service");
+
         /// First worker thread for most of operations 
         HandlerThread thread = new HandlerThread("Operations thread", Process.THREAD_PRIORITY_BACKGROUND);
         thread.start();
@@ -165,12 +167,12 @@ public class OperationsService extends Service {
      */
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
-        // WIP: for the moment, only SYNC_FOLDER and CANCEL_SYNC_FOLDER is expected here;
+        Log_OC.d(TAG, "Starting command with id " + startId);
+
+        // WIP: for the moment, only SYNC_FOLDER is expected here;
         // the rest of the operations are requested through the Binder
         if (ACTION_SYNC_FOLDER.equals(intent.getAction())) {
 
-            /*Log_OC.v("NOW " + TAG + ", thread " + Thread.currentThread().getName(), "Received request to sync folder");*/
-
             if (!intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_REMOTE_PATH)) {
                 Log_OC.e(TAG, "Not enough information provided in intent");
                 return START_NOT_STICKY;
@@ -186,10 +188,6 @@ public class OperationsService extends Service {
                 Message msg = mSyncFolderHandler.obtainMessage();
                 msg.arg1 = startId;
                 msg.obj = itemSyncKey;
-                /*Log_OC.v(
-                        "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Sync folder " + remotePath + " added to queue"
-                );*/
                 mSyncFolderHandler.sendMessage(msg);
             }
 
@@ -204,7 +202,7 @@ public class OperationsService extends Service {
 
     @Override
     public void onDestroy() {
-        //Log_OC.wtf(TAG, "onDestroy init" );
+        Log_OC.v(TAG, "Destroying service" );
         // Saving cookies
         try {
             OwnCloudClientManagerFactory.getDefaultSingleton().
@@ -221,10 +219,16 @@ public class OperationsService extends Service {
             e.printStackTrace();
         }
         
-        //Log_OC.wtf(TAG, "Clear mUndispatchedFinishedOperations" );
         mUndispatchedFinishedOperations.clear();
-        
-        //Log_OC.wtf(TAG, "onDestroy end" );
+
+        mOperationsBinder = null;
+
+        mOperationsHandler.getLooper().quit();
+        mOperationsHandler = null;
+
+        mSyncFolderHandler.getLooper().quit();
+        mSyncFolderHandler = null;
+
         super.onDestroy();
     }
 
@@ -276,10 +280,6 @@ public class OperationsService extends Service {
          * @param file          A folder in the queue of pending synchronizations
          */
         public void cancel(Account account, OCFile file) {
-            /*Log_OC.v(
-                    "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                    "Received request to cancel folder " + file.getRemotePath()
-            );*/
             mSyncFolderHandler.cancel(account, file);
         }
 
@@ -413,6 +413,7 @@ public class OperationsService extends Service {
         @Override
         public void handleMessage(Message msg) {
             nextOperation();
+            Log_OC.d(TAG, "Stopping after command with id " + msg.arg1);
             mService.stopSelf(msg.arg1);
         }
         

+ 1 - 18
src/com/owncloud/android/services/SyncFolderHandler.java

@@ -86,9 +86,8 @@ class SyncFolderHandler extends Handler {
     @Override
     public void handleMessage(Message msg) {
         Pair<Account, String> itemSyncKey = (Pair<Account, String>) msg.obj;
-        /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                    "Handling sync folder " + itemSyncKey.second);*/
         doOperation(itemSyncKey.first, itemSyncKey.second);
+        Log_OC.d(TAG, "Stopping after command with id " + msg.arg1);
         mService.stopSelf(msg.arg1);
     }
 
@@ -98,8 +97,6 @@ class SyncFolderHandler extends Handler {
      */
     private void doOperation(Account account, String remotePath) {
 
-        /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                "Getting sync folder " + remotePath);*/
         mCurrentSyncOperation = mPendingOperations.get(account, remotePath);
 
         if (mCurrentSyncOperation != null) {
@@ -120,8 +117,6 @@ class SyncFolderHandler extends Handler {
                 mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
                         getClientFor(ocAccount, mService);
 
-                /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Executing sync folder " + remotePath);*/
                 result = mCurrentSyncOperation.execute(mOwnCloudClient, mStorageManager);
 
             } catch (AccountsException e) {
@@ -129,9 +124,6 @@ class SyncFolderHandler extends Handler {
             } catch (IOException e) {
                 Log_OC.e(TAG, "Error while trying to get authorization", e);
             } finally {
-                /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Removing payload " + remotePath);*/
-
                 mPendingOperations.removePayload(account, remotePath);
 
                 mService.dispatchResultToOperationListeners(null, mCurrentSyncOperation, result);
@@ -158,26 +150,17 @@ class SyncFolderHandler extends Handler {
             Log_OC.e(TAG, "Cannot cancel with NULL parameters");
             return;
         }
-        /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                "Removing sync folder " + file.getRemotePath());*/
         Pair<SynchronizeFolderOperation, String> removeResult =
                 mPendingOperations.remove(account, file.getRemotePath());
         SynchronizeFolderOperation synchronization = removeResult.first;
         if (synchronization != null) {
-            /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                    "Canceling returned sync of " + file.getRemotePath());*/
             synchronization.cancel();
         } else {
             // TODO synchronize?
             if (mCurrentSyncOperation != null && mCurrentAccount != null &&
                     mCurrentSyncOperation.getRemotePath().startsWith(file.getRemotePath()) &&
                     account.name.equals(mCurrentAccount.name)) {
-                /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Canceling current sync as descendant: " + mCurrentSyncOperation.getRemotePath());*/
                 mCurrentSyncOperation.cancel();
-            } else {
-                /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Nothing else in cancelation of " + file.getRemotePath());*/
             }
         }
 

+ 79 - 0
src/com/owncloud/android/ui/ExtendedListView.java

@@ -0,0 +1,79 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012 Bartek Przybylski
+ *   Copyright (C) 2012-2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.widget.ListView;
+
+import com.owncloud.android.lib.common.utils.Log_OC;
+
+/**
+ * ListView allowing to specify the position of an item that should be centered in the visible area, if possible.
+ *
+ * The cleanest way I found to overcome the problem due to getHeight() returns 0 until the view is really drawn. 
+ *
+ * @author David A. Velasco
+ */
+public class ExtendedListView extends ListView {
+
+    private static final String TAG = ExtendedListView.class.getSimpleName();
+
+    private int mPositionToSetAndCenter = 0;
+
+    public ExtendedListView(Context context) {
+        super(context);
+    }
+
+    public ExtendedListView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ExtendedListView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     *
+     */
+    @Override
+    protected void onDraw (Canvas canvas) {
+        super.onDraw(canvas);
+        if (mPositionToSetAndCenter > 0) {
+            Log_OC.v(TAG, "Centering around position " + mPositionToSetAndCenter);
+            this.setSelectionFromTop(mPositionToSetAndCenter, getHeight() / 2);
+            mPositionToSetAndCenter = 0;
+        }
+    }
+
+    /**
+     * Public method to set the position of the item that should be centered in the visible area of the view.
+     *
+     * The position is saved here and checked in onDraw().
+     *
+     * @param position         Position (in the list of items) of the item to center in the visible area.     
+     */
+    public void setAndCenterSelection(int position) {
+        mPositionToSetAndCenter = position;
+    }
+
+}

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

@@ -256,7 +256,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
             setNavigationListWithFolder(file);
             
             if (!stateWasRecovered) {
-                Log_OC.e(TAG, "Initializing Fragments in onAccountChanged..");
+                Log_OC.d(TAG, "Initializing Fragments in onAccountChanged..");
                 initFragmentsWithFile();
                 if (file.isFolder()) {
                     startSyncFolderOperation(file, false);
@@ -555,19 +555,19 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
     }
 
     private void startSynchronization() {
-        Log_OC.e(TAG, "Got to start sync");
+        Log_OC.d(TAG, "Got to start sync");
         if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
-            Log_OC.e(TAG, "Canceling all syncs for " + MainApp.getAuthority());
+            Log_OC.d(TAG, "Canceling all syncs for " + MainApp.getAuthority());
             ContentResolver.cancelSync(null, MainApp.getAuthority());   // cancel the current synchronizations of any ownCloud account
             Bundle bundle = new Bundle();
             bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
             bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
-            Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority());
+            Log_OC.d(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority());
             ContentResolver.requestSync(
                     getAccount(),
                     MainApp.getAuthority(), bundle);
         } else {
-            Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority() + " with new API");
+            Log_OC.d(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority() + " with new API");
             SyncRequest.Builder builder = new SyncRequest.Builder();
             builder.setSyncAdapter(getAccount(), MainApp.getAuthority());
             builder.setExpedited(true);
@@ -699,7 +699,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
 
         } finally {
             if (filepath == null) {
-                Log_OC.e(TAG, "Couldnt resolve path to file");
+                Log_OC.e(TAG, "Couldn't resolve path to file");
                 Toast t = Toast.makeText(this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG);
                 t.show();
                 return;
@@ -786,7 +786,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
     @Override
     protected void onSaveInstanceState(Bundle outState) {
         // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved
-        Log_OC.e(TAG, "onSaveInstanceState() start");
+        Log_OC.d(TAG, "onSaveInstanceState() start");
         super.onSaveInstanceState(outState);
         outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
         outState.putBoolean(FileDisplayActivity.KEY_SYNC_IN_PROGRESS, mSyncInProgress);
@@ -801,7 +801,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
     @Override
     protected void onResume() {
         super.onResume();
-        Log_OC.e(TAG, "onResume() start");
+        Log_OC.d(TAG, "onResume() start");
         
         // refresh list of files
         refreshListOfFilesFragment();
@@ -833,7 +833,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
 
     @Override
     protected void onPause() {
-        Log_OC.e(TAG, "onPause() start");
+        Log_OC.d(TAG, "onPause() start");
         if (mSyncBroadcastReceiver != null) {
             unregisterReceiver(mSyncBroadcastReceiver);
             //LocalBroadcastManager.getInstance(this).unregisterReceiver(mSyncBroadcastReceiver);

+ 11 - 5
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -30,6 +30,7 @@ import android.text.format.DateUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AbsListView;
 import android.widget.BaseAdapter;
 import android.widget.GridView;
 import android.widget.ImageView;
@@ -69,6 +70,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private FileDataStorageManager mStorageManager;
     private Account mAccount;
     private ComponentsGetter mTransferServiceGetter;
+    private boolean mGridMode;
 
     private enum ViewType {LIST_ITEM, GRID_IMAGE, GRID_ITEM };
 
@@ -95,6 +97,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         
         // initialise thumbnails cache on background thread
         new ThumbnailsCacheManager.InitDiskCacheTask().execute();
+
+        mGridMode = false;
     }
     
     @Override
@@ -134,8 +138,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
 
-        boolean fileView = DisplayUtils.decideViewLayout(mFiles);
-
         View view = convertView;
         OCFile file = null;
         LayoutInflater inflator = (LayoutInflater) mContext
@@ -147,7 +149,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
 
         // Find out which layout should be displayed
         ViewType viewType;
-        if (!fileView){
+        if (!mGridMode){
             viewType = ViewType.LIST_ITEM;
         } else if (file.isImage()){
             viewType = ViewType.GRID_IMAGE;
@@ -192,8 +194,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                     fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));
 
                     if (!file.isFolder()) {
-                        GridView parentList = (GridView)parent;
-                        if (parentList.getChoiceMode() == GridView.CHOICE_MODE_NONE) {
+                        AbsListView parentList = (AbsListView)parent;
+                        if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {
                             checkBoxV.setVisibility(View.GONE);
                         } else {
                             if (parentList.isItemChecked(position)) {
@@ -456,4 +458,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         return DisplayUtils.getRelativeDateTimeString(mContext, file.getModificationTimestamp(),
                 DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);
     }
+
+    public void setGridMode(boolean gridMode) {
+        mGridMode = gridMode;
+    }
 }

+ 1 - 1
src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java

@@ -121,7 +121,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
 
                 lastModV.setVisibility(View.VISIBLE);
                 lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.lastModified()));
-                GridViewWithHeaderAndFooter parentList = (GridViewWithHeaderAndFooter)parent;
+                ListView parentList = (ListView) parent;
                 if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) { 
                     checkBoxV.setVisibility(View.GONE);
                 } else {

+ 19 - 22
src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java

@@ -76,7 +76,6 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
      * @return              New dialog instance, ready to show.
      */
     public static SamlWebViewDialog newInstance(String url, String targetUrl) {
-        Log_OC.d(TAG, "New instance");
         SamlWebViewDialog fragment = new SamlWebViewDialog();
         Bundle args = new Bundle();
         args.putString(ARG_INITIAL_URL, url);
@@ -88,13 +87,12 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
     
     public SamlWebViewDialog() {
         super();
-        Log_OC.d(TAG, "constructor");
     }
     
     
     @Override
     public void onAttach(Activity activity) {
-        Log_OC.d(TAG, "onAttach");
+        Log_OC.v(TAG, "onAttach");
         super.onAttach(activity);
         try {
             mSsoWebViewClientListener = (SsoWebViewClientListener) activity;
@@ -110,7 +108,7 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
     @SuppressLint("SetJavaScriptEnabled")
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        Log_OC.d(TAG, "onCreate, savedInstanceState is " + savedInstanceState);
+        Log_OC.v(TAG, "onCreate, savedInstanceState is " + savedInstanceState);
         super.onCreate(savedInstanceState);
         
         setRetainInstance(true);
@@ -132,7 +130,7 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
     @SuppressLint("SetJavaScriptEnabled")
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-        Log_OC.d(TAG, "onCreateView, savedInsanceState is " + savedInstanceState);
+        Log_OC.v(TAG, "onCreateView, savedInsanceState is " + savedInstanceState);
         
         // Inflate layout of the dialog  
         RelativeLayout ssoRootView = (RelativeLayout) inflater.inflate(R.layout.sso_dialog, container, false);  // null parent view because it will go in the dialog layout
@@ -144,11 +142,6 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
             mSsoWebView.setFocusableInTouchMode(true);
             mSsoWebView.setClickable(true);
             
-            CookieManager cookieManager = CookieManager.getInstance();
-            cookieManager.setAcceptCookie(true);
-            cookieManager.removeAllCookie();
-            mSsoWebView.loadUrl(mInitialUrl);
-          
             WebSettings webSettings = mSsoWebView.getSettings();
             webSettings.setJavaScriptEnabled(true);
             webSettings.setBuiltInZoomControls(false);
@@ -156,6 +149,12 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
             webSettings.setSavePassword(false);
             webSettings.setUserAgentString(OwnCloudClient.USER_AGENT);
             webSettings.setSaveFormData(false);
+            
+            CookieManager cookieManager = CookieManager.getInstance();
+            cookieManager.setAcceptCookie(true);
+            cookieManager.removeAllCookie();
+            
+            mSsoWebView.loadUrl(mInitialUrl);
         }
         
         mWebViewClient.setTargetUrl(mTargetUrl);
@@ -174,7 +173,7 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
 
     @Override
     public void onSaveInstanceState(Bundle outState) {
-        Log_OC.d(TAG, "onSaveInstanceState being CALLED");
+        Log_OC.v(TAG, "onSaveInstanceState being CALLED");
         super.onSaveInstanceState(outState);
         
         // save URLs
@@ -184,7 +183,7 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
 
     @Override
     public void onDestroyView() {
-        Log_OC.d(TAG, "onDestroyView");
+        Log_OC.v(TAG, "onDestroyView");
         
         if ((ViewGroup)mSsoWebView.getParent() != null) {
             ((ViewGroup)mSsoWebView.getParent()).removeView(mSsoWebView);
@@ -196,8 +195,6 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
         Dialog dialog = getDialog();
         if ((dialog != null)) {
             dialog.setOnDismissListener(null);
-            //dialog.dismiss();
-            //dialog.setDismissMessage(null);
         }
         
         super.onDestroyView();
@@ -205,13 +202,13 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
     
     @Override
     public void onDestroy() {
-        Log_OC.d(TAG, "onDestroy");
+        Log_OC.v(TAG, "onDestroy");
         super.onDestroy();
     }
 
     @Override
     public void onDetach() {
-        Log_OC.d(TAG, "onDetach");
+        Log_OC.v(TAG, "onDetach");
         mSsoWebViewClientListener = null;
         mWebViewClient = null;
         super.onDetach();
@@ -231,39 +228,39 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
     
     @Override
     public void onStart() {
-        Log_OC.d(TAG, "onStart");
+        Log_OC.v(TAG, "onStart");
         super.onStart();
     }
 
     @Override
     public void onStop() {
-        Log_OC.d(TAG, "onStop");
+        Log_OC.v(TAG, "onStop");
         super.onStop();
     }
 
     @Override
     public void onResume() {
-        Log_OC.d(TAG, "onResume");
+        Log_OC.v(TAG, "onResume");
         super.onResume();
         mSsoWebView.onResume();
     }
 
     @Override
     public void onPause() {
-        Log_OC.d(TAG, "onPause");
+        Log_OC.v(TAG, "onPause");
         mSsoWebView.onPause();
         super.onPause();
     }
     
     @Override
     public int show (FragmentTransaction transaction, String tag) {
-        Log_OC.d(TAG, "show (transaction)");
+        Log_OC.v(TAG, "show (transaction)");
         return super.show(transaction, tag);
     }
 
     @Override
     public void show (FragmentManager manager, String tag) {
-        Log_OC.d(TAG, "show (manager)");
+        Log_OC.v(TAG, "show (manager)");
         super.show(manager, tag);
     }
     

+ 179 - 99
src/com/owncloud/android/ui/fragment/ExtendedListFragment.java

@@ -1,6 +1,6 @@
 /* ownCloud Android client application
  *   Copyright (C) 2012 Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
+ *   Copyright (C) 2012-2015 ownCloud Inc.
  *
  *   This program is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
@@ -20,11 +20,13 @@ package com.owncloud.android.ui.fragment;
 
 import java.util.ArrayList;
 
+import android.content.Context;
 import android.os.Bundle;
 import android.support.v4.widget.SwipeRefreshLayout;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.GridView;
@@ -34,8 +36,11 @@ import android.widget.TextView;
 import com.actionbarsherlock.app.SherlockFragment;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.common.utils.Log_OC;
-import third_parties.in.srain.cube.GridViewWithHeaderAndFooter;
+import com.owncloud.android.ui.ExtendedListView;
 import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
+import com.owncloud.android.ui.adapter.FileListListAdapter;
+
+import third_parties.in.srain.cube.GridViewWithHeaderAndFooter;
 
 /**
  * TODO extending SherlockListFragment instead of SherlockFragment
@@ -52,7 +57,8 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
     private static final String KEY_HEIGHT_CELL = "HEIGHT_CELL";
     private static final String KEY_EMPTY_LIST_MESSAGE = "EMPTY_LIST_MESSAGE";
 
-    private SwipeRefreshLayout mRefreshLayout;
+    private SwipeRefreshLayout mRefreshListLayout;
+    private SwipeRefreshLayout mRefreshGridLayout;
     private SwipeRefreshLayout mRefreshEmptyLayout;
     private TextView mEmptyListMessage;
     
@@ -64,67 +70,99 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
 
     private OnEnforceableRefreshListener mOnRefreshListener = null;
     
-    protected GridViewWithHeaderAndFooter imageView;
-       
-    public void setListAdapter(ListAdapter listAdapter) {
-        imageView.setAdapter(listAdapter);
-        imageView.invalidate();
-    }
+    protected AbsListView mCurrentListView;
+    private ExtendedListView mListView;
+    private View mListFooterView;
+    private GridViewWithHeaderAndFooter mGridView;
+    private View mGridFooterView;
 
-    public GridView getGridView() {
-        return imageView;
-    }
+    private ListAdapter mAdapter;
 
-    public void setFooterView(View footer) {
-        imageView.addFooterView(footer, null, false);
-        imageView.invalidate();
-    }
 
-    public void removeFooterView(View footer) {
-        imageView.removeFooterView(footer);
-        imageView.invalidate();
+    protected void setListAdapter(ListAdapter listAdapter) {
+        mAdapter = listAdapter;
+        mCurrentListView.setAdapter(listAdapter);
+        mCurrentListView.invalidate();
     }
 
-    public int getFooterViewCount() {
-        return imageView.getFooterViewCount();
+    protected AbsListView getListView() {
+        return mCurrentListView;
     }
-    
-    protected void switchImageView(){
-       imageView.setNumColumns(GridView.AUTO_FIT);
-       imageView.invalidateRowHeight();  // Force to recalculate mRowHeight of imageView
-       imageView.invalidate();
+
+
+    protected void switchToGridView() {
+        if ((mCurrentListView == mListView)) {
+
+            mListView.setAdapter(null);
+            mRefreshListLayout.setVisibility(View.GONE);
+
+            if (mAdapter instanceof FileListListAdapter) {
+                ((FileListListAdapter) mAdapter).setGridMode(true);
+            }
+            mGridView.setAdapter(mAdapter);
+            mRefreshGridLayout.setVisibility(View.VISIBLE);
+
+            mCurrentListView = mGridView;
+        }
     }
     
-    protected void switchFileView(){
-       imageView.setNumColumns(1);
-       imageView.invalidate();
+    protected void switchToListView() {
+        if (mCurrentListView == mGridView) {
+            mGridView.setAdapter(null);
+            mRefreshGridLayout.setVisibility(View.GONE);
+
+            if (mAdapter instanceof FileListListAdapter) {
+                ((FileListListAdapter) mAdapter).setGridMode(false);
+            }
+            mListView.setAdapter(mAdapter);
+            mRefreshListLayout.setVisibility(View.VISIBLE);
+
+            mCurrentListView = mListView;
+        }
     }
     
     
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-        Log_OC.e(TAG, "onCreateView");
+        Log_OC.d(TAG, "onCreateView");
 
         View v = inflater.inflate(R.layout.list_fragment, null);
-        
-        imageView = (GridViewWithHeaderAndFooter)(v.findViewById(R.id.list_root));
-        imageView.setOnItemClickListener(this);
+
+        mListView = (ExtendedListView)(v.findViewById(R.id.list_root));
+        mListView.setOnItemClickListener(this);
+        mListFooterView = inflater.inflate(R.layout.list_footer, null, false);
+
+        mGridView = (GridViewWithHeaderAndFooter) (v.findViewById(R.id.grid_root));
+        mGridView.setNumColumns(GridView.AUTO_FIT);
+        mGridView.setOnItemClickListener(this);
+        mGridFooterView = inflater.inflate(R.layout.list_footer, null, false);
 
         if (savedInstanceState != null) {
             int referencePosition = savedInstanceState.getInt(KEY_SAVED_LIST_POSITION);
-            setReferencePosition(referencePosition);
+            if (mCurrentListView == mListView) {
+                Log_OC.v(TAG, "Setting and centering around list position " + referencePosition);
+                mListView.setAndCenterSelection(referencePosition);
+            } else {
+                Log_OC.v(TAG, "Setting grid position " + referencePosition);
+                mGridView.setSelection(referencePosition);
+            }
         }
 
-        // Pull down refresh
-        mRefreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_refresh_files);
-        mRefreshEmptyLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_refresh_files_emptyView);
+        // Pull-down to refresh layout
+        mRefreshListLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_list);
+        mRefreshGridLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_grid);
+        mRefreshEmptyLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_empty);
         mEmptyListMessage = (TextView) v.findViewById(R.id.empty_list_view);
         
-        onCreateSwipeToRefresh(mRefreshLayout);
+        onCreateSwipeToRefresh(mRefreshListLayout);
+        onCreateSwipeToRefresh(mRefreshGridLayout);
         onCreateSwipeToRefresh(mRefreshEmptyLayout);
 
-        imageView.setEmptyView(mRefreshEmptyLayout);
-        
+        mListView.setEmptyView(mRefreshEmptyLayout);
+        mGridView.setEmptyView(mRefreshEmptyLayout);
+
+        mCurrentListView = mListView;   // list as default
+
         return v;
     }
 
@@ -154,7 +192,7 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
     @Override
     public void onSaveInstanceState(Bundle savedInstanceState) {
         super.onSaveInstanceState(savedInstanceState);
-        Log_OC.e(TAG, "onSaveInstanceState()");
+        Log_OC.d(TAG, "onSaveInstanceState()");
         savedInstanceState.putInt(KEY_SAVED_LIST_POSITION, getReferencePosition());
         savedInstanceState.putIntegerArrayList(KEY_INDEXES, mIndexes);
         savedInstanceState.putIntegerArrayList(KEY_FIRST_POSITIONS, mFirstPositions);
@@ -168,32 +206,20 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
      * reposition the visible items in the list when the device is turned to
      * other position.
      * 
-     * THe current policy is take as a reference the visible item in the center
+     * The current policy is take as a reference the visible item in the center
      * of the screen.
      * 
      * @return The position in the list of the visible item in the center of the
      *         screen.
      */
     protected int getReferencePosition() {
-        if (imageView != null) {
-            return (imageView.getFirstVisiblePosition() + imageView.getLastVisiblePosition()) / 2;
+        if (mCurrentListView != null) {
+            return (mCurrentListView.getFirstVisiblePosition() + mCurrentListView.getLastVisiblePosition()) / 2;
         } else {
             return 0;
         }
     }
 
-    /**
-     * Sets the visible part of the list from the reference position.
-     * 
-     * @param position Reference position previously returned by
-     *            {@link LocalFileListFragment#getReferencePosition()}
-     */
-    protected void setReferencePosition(int position) {
-        if (imageView != null) {
-            imageView.setSelection(position);
-        }
-    }
-
 
     /*
      * Restore index and position
@@ -203,20 +229,28 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
             // needs to be checked; not every browse-up had a browse-down before 
             
             int index = mIndexes.remove(mIndexes.size() - 1);
-            
-            int firstPosition = mFirstPositions.remove(mFirstPositions.size() -1);
-            
+            final int firstPosition = mFirstPositions.remove(mFirstPositions.size() -1);
             int top = mTops.remove(mTops.size() - 1);
-            
-            imageView.smoothScrollToPosition(firstPosition);
-            
-            // Move the scroll if the selection is not visible
-            int indexPosition = mHeightCell*index;
-            int height = imageView.getHeight();
-            
-            if (indexPosition > height) {
-                imageView.smoothScrollToPosition(index);
+
+            Log_OC.v(TAG, "Setting selection to position: " + firstPosition + "; top: " + top + "; index: " + index);
+
+            if (mCurrentListView == mListView) {
+                if (mHeightCell*index <= mListView.getHeight()) {
+                    mListView.setSelectionFromTop(firstPosition, top);
+                } else {
+                    mListView.setSelectionFromTop(index, 0);
+                }
+
+            } else {
+                if (mHeightCell*index <= mGridView.getHeight()) {
+                    mGridView.setSelection(firstPosition);
+                    //mGridView.smoothScrollToPosition(firstPosition);
+                } else {
+                    mGridView.setSelection(index);
+                    //mGridView.smoothScrollToPosition(index);
+                }
             }
+
         }
     }
     
@@ -227,10 +261,10 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
         
         mIndexes.add(index);
         
-        int firstPosition = imageView.getFirstVisiblePosition();
+        int firstPosition = mCurrentListView.getFirstVisiblePosition();
         mFirstPositions.add(firstPosition);
         
-        View view = imageView.getChildAt(0);
+        View view = mCurrentListView.getChildAt(0);
         int top = (view == null) ? 0 : view.getTop() ;
 
         mTops.add(top);
@@ -247,10 +281,10 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
 
     @Override
     public void onRefresh() {
-        // to be @overriden
-        mRefreshLayout.setRefreshing(false);
+        mRefreshListLayout.setRefreshing(false);
+        mRefreshGridLayout.setRefreshing(false);
         mRefreshEmptyLayout.setRefreshing(false);
-        
+
         if (mOnRefreshListener != null) {
             mOnRefreshListener.onRefresh();
         }
@@ -261,32 +295,18 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
     
 
     /**
-     * Enables swipe gesture
+     * Disables swipe gesture.
+     *
+     * Sets the 'enabled' state of the refresh layouts contained in the fragment.
+     *
+     * When 'false' is set, prevents user gestures but keeps the option to refresh programatically,
+     *
+     * @param   enabled     Desired state for capturing swipe gesture.
      */
-    public void enableSwipe() {
-        mRefreshLayout.setEnabled(true);
-    }
- 
-    /**
-     * Disables swipe gesture. It prevents manual gestures but keeps the option you show
-     * refreshing programmatically.
-     */
-    public void disableSwipe() {
-        mRefreshLayout.setEnabled(false);
-    }
-    
-    /**
-     * It shows the SwipeRefreshLayout progress
-     */
-    public void showSwipeProgress() {
-        mRefreshLayout.setRefreshing(true);
-    }
- 
-    /**
-     * It shows the SwipeRefreshLayout progress
-     */
-    public void hideSwipeProgress() {
-        mRefreshLayout.setRefreshing(false);
+    public void setSwipeEnabled(boolean enabled) {
+        mRefreshListLayout.setEnabled(enabled);
+        mRefreshGridLayout.setEnabled(enabled);
+        mRefreshEmptyLayout.setEnabled(enabled);
     }
 
     /**
@@ -317,11 +337,71 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
 
     @Override
     public void onRefresh(boolean ignoreETag) {
-        mRefreshLayout.setRefreshing(false);
+        mRefreshListLayout.setRefreshing(false);
+        mRefreshGridLayout.setRefreshing(false);
         mRefreshEmptyLayout.setRefreshing(false);
 
         if (mOnRefreshListener != null) {
             mOnRefreshListener.onRefresh(ignoreETag);
         }
     }
+
+
+    protected void setChoiceMode(int choiceMode) {
+        mListView.setChoiceMode(choiceMode);
+        mGridView.setChoiceMode(choiceMode);
+    }
+
+    protected void registerForContextMenu() {
+        registerForContextMenu(mListView);
+        registerForContextMenu(mGridView);
+        mListView.setOnCreateContextMenuListener(this);
+        mGridView.setOnCreateContextMenuListener(this);
+    }
+
+    /**
+     * TODO doc
+     * To be called before setAdapter, or GridViewWithHeaderAndFooter will throw an exception
+     *
+     * @param enabled
+     */
+    protected void setFooterEnabled(boolean enabled) {
+        if (enabled) {
+            if (mGridView.getFooterViewCount() == 0) {
+                if (mGridFooterView.getParent() != null ) {
+                    ((ViewGroup) mGridFooterView.getParent()).removeView(mGridFooterView);
+                }
+                mGridView.addFooterView(mGridFooterView, null, false);
+            }
+            mGridFooterView.invalidate();
+
+            if (mListView.getFooterViewsCount() == 0) {
+                if (mListFooterView.getParent() != null ) {
+                    ((ViewGroup) mListFooterView.getParent()).removeView(mListFooterView);
+                }
+                mListView.addFooterView(mListFooterView, null, false);
+            }
+            mListFooterView.invalidate();
+
+        } else {
+            mGridView.removeFooterView(mGridFooterView);
+            mListView.removeFooterView(mListFooterView);
+        }
+    }
+
+    /**
+     * TODO doc
+     * @param text
+     */
+    protected void setFooterText(String text) {
+        if (text != null && text.length() > 0) {
+            ((TextView)mListFooterView.findViewById(R.id.footerText)).setText(text);
+            ((TextView)mGridFooterView.findViewById(R.id.footerText)).setText(text);
+            setFooterEnabled(true);
+
+        } else {
+            setFooterEnabled(false);
+        }
+    }
+
 }

+ 9 - 9
src/com/owncloud/android/ui/fragment/LocalFileListFragment.java

@@ -76,12 +76,12 @@ public class LocalFileListFragment extends ExtendedListFragment {
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         Log_OC.i(TAG, "onCreateView() start");
         View v = super.onCreateView(inflater, container, savedInstanceState);
-        getGridView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
-        disableSwipe(); // Disable pull refresh
+        setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+        setSwipeEnabled(false); // Disable pull-to-refresh
         setMessageForEmptyList(getString(R.string.local_file_list_empty));
         Log_OC.i(TAG, "onCreateView() end");
         return v;
-    }    
+    }
 
 
     /**
@@ -117,7 +117,7 @@ public class LocalFileListFragment extends ExtendedListFragment {
             } else {    /// Click on a file
                 ImageView checkBoxV = (ImageView) v.findViewById(R.id.custom_checkbox);
                 if (checkBoxV != null) {
-                    if (getGridView().isItemChecked(position)) {
+                    if (getListView().isItemChecked(position)) {
                         checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);
                     } else {
                         checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);
@@ -194,10 +194,10 @@ public class LocalFileListFragment extends ExtendedListFragment {
             directory = directory.getParentFile();
         }
 
-        imageView.clearChoices();   // by now, only files in the same directory will be kept as selected
+        mCurrentListView.clearChoices();   // by now, only files in the same directory will be kept as selected
         mAdapter.swapDirectory(directory);
         if (mDirectory == null || !mDirectory.equals(directory)) {
-            imageView.setSelection(0);
+            mCurrentListView.setSelection(0);
         }
         mDirectory = directory;
     }
@@ -210,11 +210,11 @@ public class LocalFileListFragment extends ExtendedListFragment {
      */
     public String[] getCheckedFilePaths() {
         ArrayList<String> result = new ArrayList<String>();
-        SparseBooleanArray positions = imageView.getCheckedItemPositions();
+        SparseBooleanArray positions = mCurrentListView.getCheckedItemPositions();
         if (positions.size() > 0) {
             for (int i = 0; i < positions.size(); i++) {
                 if (positions.get(positions.keyAt(i)) == true) {
-                    result.add(((File) imageView.getItemAtPosition(positions.keyAt(i))).getAbsolutePath());
+                    result.add(((File) mCurrentListView.getItemAtPosition(positions.keyAt(i))).getAbsolutePath());
                 }
             }
 
@@ -234,7 +234,7 @@ public class LocalFileListFragment extends ExtendedListFragment {
         /**
          * Callback method invoked when a directory is clicked by the user on the files list
          *  
-         * @param file
+         * @param directory
          */
         public void onDirectoryClick(File directory);
         

+ 51 - 58
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -18,10 +18,8 @@
 package com.owncloud.android.ui.fragment;
 
 import java.io.File;
-import java.util.Vector;
 
 import android.app.Activity;
-import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.v4.widget.SwipeRefreshLayout;
@@ -29,11 +27,8 @@ import android.view.ContextMenu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.AdapterView.AdapterContextMenuInfo;
-import android.widget.TextView;
-import android.view.LayoutInflater;
 
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -49,7 +44,6 @@ import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
 import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
-import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.FileStorageUtils;
 
 /**
@@ -73,11 +67,13 @@ public class OCFileListFragment extends ExtendedListFragment {
             
     private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE";
 
+    private final static Double THUMBNAIL_THRESHOLD = 0.5;
+
     private FileFragment.ContainerActivity mContainerActivity;
    
     private OCFile mFile = null;
     private FileListListAdapter mAdapter;
-    private View mFooterView;
+    private boolean mJustFolders;
     
     private OCFile mTargetFile;
 
@@ -125,23 +121,24 @@ public class OCFileListFragment extends ExtendedListFragment {
             mFile = savedInstanceState.getParcelable(KEY_FILE);
         }
 
-        mFooterView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
-                        R.layout.list_footer, null, false);
-        setFooterView(mFooterView);
+        if (mJustFolders) {
+            setFooterEnabled(false);
+        } else {
+            setFooterEnabled(true);
+        }
 
         Bundle args = getArguments();
-        boolean justFolders = (args == null) ? false : args.getBoolean(ARG_JUST_FOLDERS, false); 
+        mJustFolders = (args == null) ? false : args.getBoolean(ARG_JUST_FOLDERS, false);
         mAdapter = new FileListListAdapter(
-                justFolders,
+                mJustFolders,
                 getSherlockActivity(),
                 mContainerActivity
                 );
         setListAdapter(mAdapter);
-        
-        registerForContextMenu(getGridView());
-        getGridView().setOnCreateContextMenuListener(this);
+
+        registerForContextMenu();
   }
-    
+
     /**
      * Saves the current listed folder.
      */
@@ -391,69 +388,65 @@ public class OCFileListFragment extends ExtendedListFragment {
 
             mAdapter.swapDirectory(directory, storageManager);
             if (mFile == null || !mFile.equals(directory)) {
-                imageView.setSelection(0);
+                mCurrentListView.setSelection(0);
             }
             mFile = directory;
 
-            Vector<OCFile> files = storageManager.getFolderContent(directory);
-            // Update Footer
-            TextView footerText = (TextView) mFooterView.findViewById(R.id.footerText);
-            footerText.setText(generateFooterText(directory));
-            if (DisplayUtils.decideViewLayout(files)){
-                switchImageView();
-            } else {
-                switchFileView();
-            }
+            updateLayout();
+
         }
     }
-    
-    private String generateFooterText(OCFile directory) {
-        Integer files = 0;
-        Integer folders = 0;
 
-        FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
-        Vector<OCFile> mFiles = storageManager.getFolderContent(mFile);
+    private void updateLayout() {
+        if (!mJustFolders) {
+            int filesCount = 0, foldersCount = 0, imagesCount = 0;
+            int count = mAdapter.getCount();
+            OCFile file;
+            for (int i=0; i < count ; i++) {
+                file = (OCFile) mAdapter.getItem(i);
+                if (file.isFolder()) {
+                    foldersCount++;
+                } else {
+                    filesCount++;
+                    if (file.isImage()){
+                        imagesCount++;
+                    }
+                }
+            }
+            // set footer text
+            setFooterText(generateFooterText(filesCount, foldersCount));
 
-        for (OCFile ocFile : mFiles) {
-            if (ocFile.isFolder()) {
-                folders++;
+            // decide grid vs list view
+            if (((double)imagesCount / (double)filesCount) >= THUMBNAIL_THRESHOLD) {
+                switchToGridView();
             } else {
-                files++;
+                switchToListView();
             }
         }
+    }
 
+    private String generateFooterText(int filesCount, int foldersCount) {
         String output = "";
-       
-        if (files > 0){
-            if (files == 1) {
-                output = output + files.toString() + " " + getResources().getString(R.string.file_list_file);
+        if (filesCount > 0){
+            if (filesCount == 1) {
+                output = output + filesCount + " " + getResources().getString(R.string.file_list_file);
             } else {
-                output = output + files.toString() + " " + getResources().getString(R.string.file_list_files);
+                output = output + filesCount + " " + getResources().getString(R.string.file_list_files);
             }
         }
-        if (folders > 0 && files > 0){
+        if (foldersCount > 0 && filesCount > 0){
             output = output + ", ";
         }
-        if (folders == 1) {
-            output = output + folders.toString() + " " + getResources().getString(R.string.file_list_folder);
-        } else if (folders > 1) {
-            output = output + folders.toString() + " " + getResources().getString(R.string.file_list_folders);
+        if (foldersCount == 1) {
+            output = output + foldersCount + " " + getResources().getString(R.string.file_list_folder);
+        } else if (foldersCount > 1) {
+            output = output + foldersCount + " " + getResources().getString(R.string.file_list_folders);
         }
 
-        // Fix for showing or not to show the footerView
-        if (folders == 0 && files == 0) {   // If no files or folders, remove footerView for allowing
-                                            // to show the emptyList message
-            removeFooterView(mFooterView);
-        } else { // set a new footerView if there is not one for showing the number or files/folders
-            if (getFooterViewCount()== 0) {
-                ((ViewGroup)mFooterView.getParent()).removeView(mFooterView);
-                setFooterView(mFooterView);
-            }
-        }
-        
         return output;
     }
-    
+
+
     public void sortByName(boolean descending) {
         mAdapter.setSortOrder(FileStorageUtils.SORT_NAME, descending);
     }

+ 0 - 28
src/com/owncloud/android/utils/DisplayUtils.java

@@ -52,8 +52,6 @@ public class DisplayUtils {
     
     private static final String[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
 
-    private final static Double THUMBNAIL_THRESHOLD = 0.5;
-
     private static HashMap<String, String> mimeType2HUmanReadable;
     static {
         mimeType2HUmanReadable = new HashMap<String, String>();
@@ -344,30 +342,4 @@ public class DisplayUtils {
         return path;
     }
 
-    /**
-     *
-     * @param mFiles
-     * @return true: imageView, false: listView
-     */
-    public static boolean decideViewLayout(Vector<OCFile> mFiles){
-        // decide image vs. file view
-        double countImages = 0;
-        double countFiles = 0;
-
-        for (OCFile file : mFiles){
-            if (!file.isFolder()){
-                countFiles++;
-
-                if (file.isImage()){
-                    countImages++;
-                }
-            }
-        }
-
-        if ((countImages / countFiles) >= THUMBNAIL_THRESHOLD){
-            return true;
-        } else {
-            return false;
-        }
-    }
 }

+ 73 - 19
src/third_parties/in/srain/cube/GridViewWithHeaderAndFooter.java

@@ -17,22 +17,28 @@
 package third_parties.in.srain.cube;
 
 
-        import android.annotation.TargetApi;
-        import android.content.Context;
-        import android.database.DataSetObservable;
-        import android.database.DataSetObserver;
-        import android.os.Build;
-        import android.util.AttributeSet;
-        import android.util.Log;
-        import android.view.View;
-        import android.view.ViewGroup;
-        import android.widget.*;
-
-        import java.lang.reflect.Field;
-        import java.util.ArrayList;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.database.DataSetObservable;
+import android.database.DataSetObserver;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.Filter;
+import android.widget.Filterable;
+import android.widget.FrameLayout;
+import android.widget.GridView;
+import android.widget.ListAdapter;
+import android.widget.WrapperListAdapter;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
 
 /**
- * A {@link GridView} that supports adding header rows in a
+ * A {@link android.widget.GridView} that supports adding header rows in a
  * very similar way to {@link android.widget.ListView}.
  * See {@link GridViewWithHeaderAndFooter#addHeaderView(View, Object, boolean)}
  * See {@link GridViewWithHeaderAndFooter#addFooterView(View, Object, boolean)}
@@ -52,7 +58,7 @@ public class GridViewWithHeaderAndFooter extends GridView {
         public View view;
         public ViewGroup viewContainer;
         /**
-         * The data backing the view. This is returned from {@link ListAdapter#getItem(int)}.
+         * The data backing the view. This is returned from {@link android.widget.ListAdapter#getItem(int)}.
          */
         public Object data;
         /**
@@ -151,7 +157,7 @@ public class GridViewWithHeaderAndFooter extends GridView {
 
         if (lyp != null) {
             v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));
-            fl.setLayoutParams(new AbsListView.LayoutParams(lyp.width, lyp.height));
+            fl.setLayoutParams(new LayoutParams(lyp.width, lyp.height));
         }
         fl.addView(v);
         info.view = v;
@@ -184,7 +190,7 @@ public class GridViewWithHeaderAndFooter extends GridView {
 
         if (lyp != null) {
             v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));
-            fl.setLayoutParams(new AbsListView.LayoutParams(lyp.width, lyp.height));
+            fl.setLayoutParams(new LayoutParams(lyp.width, lyp.height));
         }
         fl.addView(v);
         info.view = v;
@@ -315,9 +321,9 @@ public class GridViewWithHeaderAndFooter extends GridView {
         }
         int mColumnWidth = getColumnWidthCompatible();
         View view = getAdapter().getView(numColumns * mHeaderViewInfos.size(), mViewForMeasureRowHeight, this);
-        AbsListView.LayoutParams p = (AbsListView.LayoutParams) view.getLayoutParams();
+        LayoutParams p = (LayoutParams) view.getLayoutParams();
         if (p == null) {
-            p = new AbsListView.LayoutParams(-1, -2, 0);
+            p = new LayoutParams(-1, -2, 0);
             view.setLayoutParams(p);
         }
         int childHeightSpec = getChildMeasureSpec(
@@ -784,4 +790,52 @@ public class GridViewWithHeaderAndFooter extends GridView {
             mDataSetObservable.notifyChanged();
         }
     }
+
+
+    /**
+     * Sets the selected item and positions the selection y pixels from the top edge of the ListView.
+     * (If in touch mode, the item will not be selected but it will still be positioned appropriately.)
+     *
+     * @param position     Index (starting at 0) of the data item to be selected.
+     * @param y            The distance from the top edge of the ListView (plus padding)
+     *                     that the item will be positioned.
+     *
+     * @see <a href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/widget/ListView.java#ListView.setSelectionFromTop%28int%2Cint%29">Original code</a>
+     */
+    public void setSelectionFromTop(int position, int y) {
+        if (getAdapter() == null) {
+            return;
+        }
+
+        setSelection(position);
+        //setSelectionInt(position);
+
+        /*if (!isInTouchMode()) {
+            position = super.lookForSelectablePosition(position, true);
+            if (position >= 0) {
+                setNextSelectedPositionInt(position);
+            }
+        } else {
+            mResurrectToPosition = position;
+        }*/
+
+        /*
+        if (position >= 0) {
+            mLayoutMode = LAYOUT_SPECIFIC;
+            mSpecificTop = mListPadding.top + y;
+
+            if (mNeedSync) {
+                mSyncPosition = position;
+                mSyncRowId = getAdapter().getItemId(position);
+            }
+
+            if (mPositionScroller != null) {
+                mPositionScroller.stop();
+            }
+
+            requestLayout();
+        }
+        */
+    }
+
 }