Browse Source

Merge branch 'develop' into download_folder

jabarros 10 years ago
parent
commit
e98fc8b141

+ 1 - 1
build.gradle

@@ -3,7 +3,7 @@ buildscript {
         mavenCentral()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:0.14.0'
+        classpath 'com.android.tools.build:gradle:1.0.0'
     }
 }
 

+ 2 - 2
gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
-#Wed Oct 15 10:45:44 CEST 2014
+#Mon Jan 19 09:42:11 CET 2015
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

+ 1 - 1
owncloud-android-library

@@ -1 +1 @@
-Subproject commit 8261865ff24c1bfc05be19ae9364a66dac8f26c3
+Subproject commit e87f5f25ad91950d47ec9b6fa01401360cd7ec8d

+ 12 - 11
res/values-el/strings.xml

@@ -14,7 +14,7 @@
   <string name="actionbar_sort">Ταξινόμηση</string>
   <string name="actionbar_sort_title">Ταξινόμηση κατά</string>
   <string-array name="actionbar_sortby">
-    <item>A-Z</item>
+    <item>A-Ω</item>
     <item>Νεότερο - Παλαιότερο</item>
   </string-array>
   <!--TODO re-enable when server-side folder size calculation is available   
@@ -60,8 +60,8 @@
   <string name="uploader_error_forbidden_content">Ο %1$s δεν επιτρέπεται να έχει πρόσβαση στο κοινόχρηστο περιεχόμενο</string>
   <string name="uploader_info_uploading">Μεταφόρτωση</string>
   <string name="file_list_seconds_ago">δευτερόλεπτα πριν</string>
-  <string name="file_list_empty">Δεν υπάρχει τίποτα εδώ. Ανεβάστε κάτι!</string>
-  <string name="file_list_loading">Φόρτωση ...</string>
+  <string name="file_list_empty">Δεν υπάρχει τίποτα εδώ. Μεταφορτώστε κάτι!</string>
+  <string name="file_list_loading">Φόρτωση...</string>
   <string name="local_file_list_empty">Δεν υπάρχουν αρχεία σε αυτό τον φάκελο.</string>
   <string name="file_list_folder">φάκελος</string>
   <string name="file_list_folders">φάκελοι</string>
@@ -258,7 +258,7 @@
 		διαχειριστή σας.</string>
   <string name="share_link_file_no_exist">Αδύνατη η κοινή χρήση. Παρακαλώ ελέγξτε αν ο φάκελος υπάρχει</string>
   <string name="share_link_file_error">Ένα σφάλμα προέκυψε κατά την προσπάθεια διαμοιρασμού αυτού του αρχείου ή φακέλου</string>
-  <string name="unshare_link_file_no_exist">Αδύνατη η διακοπή κοινής χρήσης.  Παρακαλώ ελέγξτε αν ο φάκελος υπάρχει</string>
+  <string name="unshare_link_file_no_exist">Αδύνατη η διακοπή κοινής χρήσης.  Παρακαλώ ελέγξτε αν το αρχείο υπάρχει</string>
   <string name="unshare_link_file_error">Ένα σφάλμα προέκυψε κατά τη διάρκεια ακύρωσης διαμοιρασμού αυτού του αρχείου ή φακέλου</string>
   <string name="activity_chooser_send_file_title">Αποστολή</string>
   <string name="copy_link">Αντιγραφή συνδέσμου</string>
@@ -273,24 +273,24 @@
   <string name="forbidden_permissions_rename">για να μετονομάσετε αυτό το αρχείο</string>
   <string name="forbidden_permissions_delete">για να διαγράψετε αυτό το αρχείο</string>
   <string name="share_link_forbidden_permissions">για να μοιραστείτε αυτό το αρχείο</string>
-  <string name="unshare_link_forbidden_permissions">για να μη μοιραστείτε αυτό το αρχείο</string>
+  <string name="unshare_link_forbidden_permissions">για να διακόψετε το διαμοιρασμό αυτού του αρχείου</string>
   <string name="forbidden_permissions_create">για να δημιουργήσετε το αρχείο</string>
-  <string name="uploader_upload_forbidden_permissions">για να μεταφορτώσετε σε αυτό τον κατάλογο</string>
+  <string name="uploader_upload_forbidden_permissions">για να μεταφορτώσετε σε αυτό το φάκελο</string>
   <string name="downloader_download_file_not_found">Αυτό το αρχείο δεν είναι πια διαθέσιμο στο διακομιστή</string>
   <string name="prefs_category_accounts">Λογαριασμοί</string>
   <string name="prefs_add_account">Προσθήκη λογαριασμού</string>
   <string name="auth_redirect_non_secure_connection_title">Ασφαλής σύνδεση ανακατευθύνεται σε μια μη ασφαλή διαδρομή.</string>
   <string name="actionbar_logger">Αρχεία καταγραφών</string>
-  <string name="log_send_history_button">Αποστολή ιστορικού</string>
-  <string name="log_send_no_mail_app">Δεν εντοπίστηκε εφαρμογή αποστολής αναφορών συστήματος. Εγκαταστήστε το mail app!</string>
-  <string name="log_send_mail_subject">%1$s αναφορές του Android app</string>
+  <string name="log_send_history_button">Αποστολή Ιστορικού</string>
+  <string name="log_send_no_mail_app">Δεν εντοπίστηκε εφαρμογή αποστολής αναφορών συστήματος. Εγκαταστήστε την εφαρμογή Ηλ. Ταχυδρομείου!!</string>
+  <string name="log_send_mail_subject">%1$s αναφορές της εφαρμογής Android</string>
   <string name="log_progress_dialog_text">Φόρτωση δεδομένων....</string>
   <string name="saml_authentication_required_text">Απαιτείται πιστοποίηση</string>
-  <string name="saml_authentication_wrong_pass">Εσφαλμένο συνθηματικό</string>
+  <string name="saml_authentication_wrong_pass">Εσφαλμένος κωδικός πρόσβασης</string>
   <string name="actionbar_move">Μετακίνηση</string>
   <string name="file_list_empty_moving">Δεν υπάρχει τίποτα εδώ. Μπορείτε να προσθέσετε ένα φάκελο!</string>
   <string name="folder_picker_choose_button_text">Επιλέξτε</string>
-  <string name="move_file_not_found">Αδύνατη η μετακίνηση. Παρακαλώ ελέγξτε αν ο φάκελος υπάρχει</string>
+  <string name="move_file_not_found">Αδύνατη η μετακίνηση. Παρακαλώ ελέγξτε αν το αρχείο υπάρχει</string>
   <string name="move_file_invalid_into_descendent">Δεν είναι δυνατό να μετακινηθεί ο φάκελος σε έναν απογονικό</string>
   <string name="move_file_invalid_overwrite">Το αρχείο υπάρχει ήδη στο φάκελο προορισμού</string>
   <string name="move_file_error">Ένα σφάλμα προέκυψε κατά την προσπάθεια μετακίνησης αυτού του αρχείου ή φακέλου</string>
@@ -299,5 +299,6 @@
   <string name="prefs_category_security">Ασφάλεια</string>
   <string name="prefs_instant_video_upload_path_title">Διαδρομή Μεταφόρτωσης Βίντεο</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>

+ 2 - 2
res/values-es/strings.xml

@@ -215,7 +215,7 @@
   <string name="ssl_validator_header">La identidad del sitio no puede ser verificada</string>
   <string name="ssl_validator_reason_cert_not_trusted">- El certificado del servidor no es de confianza</string>
   <string name="ssl_validator_reason_cert_expired">- El certificado del servidor expiró</string>
-  <string name="ssl_validator_reason_cert_not_yet_valid">- El certificado del servidor es de una fecha que aún no llega</string>
+  <string name="ssl_validator_reason_cert_not_yet_valid">- El certificado del servidor es de una fecha que aún no ha llegado</string>
   <string name="ssl_validator_reason_hostname_not_verified">- La URL no coincide con el nombre de dominio del certificado</string>
   <string name="ssl_validator_question">¿Confías de todas formas en este certificado?</string>
   <string name="ssl_validator_not_saved">El certificado no pudo ser guardado</string>
@@ -280,7 +280,7 @@
   <string name="prefs_category_accounts">Cuentas</string>
   <string name="prefs_add_account">Agregar cuenta</string>
   <string name="auth_redirect_non_secure_connection_title">La conexión segura está siendo desviada por una ruta insegura.</string>
-  <string name="actionbar_logger">Logs</string>
+  <string name="actionbar_logger">Registros</string>
   <string name="log_send_history_button">Enviar historial</string>
   <string name="log_send_no_mail_app">No se ha encontrado una app para enviar logs. Instale la app mail!</string>
   <string name="log_send_mail_subject">Se han encontrado %1$s logs de la app Android</string>

+ 1 - 1
res/values-fr/strings.xml

@@ -22,7 +22,7 @@
   <string name="prefs_category_general">Général</string>
   <string name="prefs_category_more">Plus</string>
   <string name="prefs_accounts">Comptes</string>
-  <string name="prefs_manage_accounts">Gestion des comptes utilisateur</string>
+  <string name="prefs_manage_accounts">Gestion des comptes</string>
   <string name="prefs_pincode">Code de sécurité</string>
   <string name="prefs_pincode_summary">Protéger l\'accès à l\'application</string>
   <string name="prefs_instant_upload">Envoi instantané des photos</string>

+ 5 - 5
res/values-ja-rJP/strings.xml

@@ -64,8 +64,8 @@
   <string name="file_list_empty">ここには何もありません。何かアップロードしてください。</string>
   <string name="file_list_loading">読込中 ...</string>
   <string name="local_file_list_empty">このフォルダーにはファイルがありません。</string>
-  <string name="file_list_folder">フォルダ</string>
-  <string name="file_list_folders">フォルダ</string>
+  <string name="file_list_folder">フォルダ</string>
+  <string name="file_list_folders">フォルダ</string>
   <string name="file_list_file">ファイル</string>
   <string name="file_list_files">ファイル</string>
   <string name="filedetails_select_file">ファイルをタップすると追加情報が表示されます。</string>
@@ -289,11 +289,11 @@
   <string name="saml_authentication_required_text">認証を必要とする</string>
   <string name="saml_authentication_wrong_pass">無効なパスワード</string>
   <string name="actionbar_move">移動</string>
-  <string name="file_list_empty_moving">ファイルが有りません。フォルダを追加してください。</string>
+  <string name="file_list_empty_moving">何もありません。フォルダーを追加してください。</string>
   <string name="folder_picker_choose_button_text">選択</string>
   <string name="move_file_not_found">移動できません。ファイルがあるか確認してください。</string>
-  <string name="move_file_invalid_into_descendent">フォルダを子フォルダへ移動することはできません。</string>
-  <string name="move_file_invalid_overwrite">そのファイルは、宛先フォルダに既に存在しています。</string>
+  <string name="move_file_invalid_into_descendent">フォルダを子フォルダへ移動することはできません。</string>
+  <string name="move_file_invalid_overwrite">そのファイルは宛先フォルダーにすでに存在します。</string>
   <string name="move_file_error">このファイルまたはフォルダーを移動する際にエラーが発生しました</string>
   <string name="forbidden_permissions_move">このファイルを移動</string>
   <string name="prefs_category_instant_uploading">自動アップロード</string>

+ 132 - 58
res/values-ko/strings.xml

@@ -6,29 +6,42 @@
   <string name="actionbar_upload">업로드</string>
   <string name="actionbar_upload_from_apps">다른 앱의 콘텐츠</string>
   <string name="actionbar_upload_files">파일</string>
-  <string name="actionbar_open_with">로 열기</string>
+  <string name="actionbar_open_with">다음으로 열기</string>
   <string name="actionbar_mkdir">새 폴더</string>
   <string name="actionbar_settings">설정</string>
-  <string name="actionbar_see_details">세부내용</string>
+  <string name="actionbar_see_details">자세한 정보</string>
   <string name="actionbar_send_file">보내기</string>
+  <string name="actionbar_sort">정렬</string>
+  <string name="actionbar_sort_title">정렬 순서</string>
+  <string-array name="actionbar_sortby">
+    <item>가나다</item>
+    <item>최신 - 이전</item>
+  </string-array>
   <!--TODO re-enable when server-side folder size calculation is available   
     	<item>Biggest - Smallest</item>-->
   <string name="prefs_category_general">일반</string>
-  <string name="prefs_category_more">더 중요함</string>
+  <string name="prefs_category_more">더 보기</string>
   <string name="prefs_accounts">계정</string>
   <string name="prefs_manage_accounts">계정 관리</string>
   <string name="prefs_pincode">앱 암호</string>
   <string name="prefs_pincode_summary">내 클라이언트 보호</string>
-  <string name="prefs_log_title">로깅 허용</string>
-  <string name="prefs_log_summary">이건 로그 문제에 사용됩니다</string>
+  <string name="prefs_instant_upload">사진 즉시 업로드</string>
+  <string name="prefs_instant_upload_summary">카메라로 찍은 사진 즉시 업로드</string>
+  <string name="prefs_instant_video_upload">동영상 즉시 업로드</string>
+  <string name="prefs_instant_video_upload_summary">카메라로 찍은 동영상 즉시 업로드</string>
+  <string name="prefs_log_title">로그 기록 사용</string>
+  <string name="prefs_log_summary">문제점을 기록하는 데 사용됩니다</string>
   <string name="prefs_log_title_history">로그 기록</string>
   <string name="prefs_log_summary_history">여기서 기록된 로그를 보여줍니다</string>
-  <string name="prefs_log_delete_history_button">역사 삭제하기</string>
+  <string name="prefs_log_delete_history_button">과거 기록 삭제</string>
   <string name="prefs_help">도움말</string>
-  <string name="prefs_recommend">친구들에게 권하기</string>
+  <string name="prefs_recommend">친구에게 추천하기</string>
   <string name="prefs_feedback">피드백</string>
-  <string name="prefs_imprint">임프린트</string>
-  <string name="recommend_subject">%1$s 을 스마트폰에서 사용해보세요!</string>
+  <string name="prefs_imprint">법적 고지</string>
+  <string name="prefs_remember_last_share_location">공유 위치 기억하기</string>
+  <string name="prefs_remember_last_upload_location_summary">마지막 공유 업로드 위치 기억하기</string>
+  <string name="recommend_subject">%1$s을(를) 스마트폰에서 사용해 보세요!</string>
+  <string name="recommend_text">%1$s을(를) 스마트폰에서 사용해 보는 것을 추천합니다!\n다운로드 링크: %2$s</string>
   <string name="auth_check_server">서버 확인</string>
   <string name="auth_host_url">서버 주소 https://…</string>
   <string name="auth_username">사용자 이름</string>
@@ -37,6 +50,7 @@
   <string name="sync_string_files">파일</string>
   <string name="setup_btn_connect">접속</string>
   <string name="uploader_btn_upload_text">업로드</string>
+  <string name="uploader_top_message">업로드 폴더 선택:</string>
   <string name="uploader_wrn_no_account_title">계정 없음</string>
   <string name="uploader_wrn_no_account_text">이 장치에 %1$s 계정이 없습니다. 먼저 계정을 설정하십시오.</string>
   <string name="uploader_wrn_no_account_setup_btn_text">설정</string>
@@ -45,8 +59,10 @@
   <string name="uploader_wrn_no_content_text">받은 콘텐츠가 없습니다. 업로드할 항목이 없습니다.</string>
   <string name="uploader_error_forbidden_content">%1$s에서 공유된 콘텐츠에 접근할 수 없습니다</string>
   <string name="uploader_info_uploading">업로드 중</string>
-  <string name="file_list_seconds_ago">초 </string>
+  <string name="file_list_seconds_ago">초 지남</string>
   <string name="file_list_empty">내용이 없습니다. 업로드할 수 있습니다!</string>
+  <string name="file_list_loading">불러오는 중...</string>
+  <string name="local_file_list_empty">이 폴더에 파일이 없습니다.</string>
   <string name="file_list_folder">폴더</string>
   <string name="file_list_folders">폴더</string>
   <string name="file_list_file">파일</string>
@@ -57,9 +73,10 @@
   <string name="filedetails_created">만든 날짜:</string>
   <string name="filedetails_modified">수정한 날짜:</string>
   <string name="filedetails_download">다운로드</string>
-  <string name="filedetails_sync_file">파일 새로고침</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>
@@ -69,7 +86,7 @@
   <string name="common_save_exit">저장하고 끝내기</string>
   <string name="common_error">오류</string>
   <string name="common_loading">불러오는 중...</string>
-  <string name="common_error_unknown">알수없는 오류</string>
+  <string name="common_error_unknown">알  없는 오류</string>
   <string name="about_title">정보</string>
   <string name="change_password">암호 변경</string>
   <string name="delete_account">계정 삭제</string>
@@ -81,29 +98,35 @@
   <string name="uploader_upload_succeeded_ticker">업로드 성공</string>
   <string name="uploader_upload_succeeded_content_single">%1$s을(를) 업로드하였습니다</string>
   <string name="uploader_upload_failed_ticker">업로드 실패</string>
-  <string name="uploader_upload_failed_content_single">%1$s을(를) 업로드할 수 없었습니다</string>
+  <string name="uploader_upload_failed_content_single">%1$s을(를) 업로드할 수 없습니다</string>
+  <string name="uploader_upload_failed_credentials_error">업로드가 실패하였습니다. 다시 로그인하십시오</string>
   <string name="downloader_download_in_progress_ticker">다운로드 중...</string>
   <string name="downloader_download_in_progress_content">%1$d%% %2$s 다운로드 중</string>
   <string name="downloader_download_succeeded_ticker">다운로드 성공</string>
   <string name="downloader_download_succeeded_content">%1$s을(를) 다운로드하였습니다</string>
   <string name="downloader_download_failed_ticker">다운로드 실패</string>
-  <string name="downloader_download_failed_content">%1$s을(를) 다운로드할 수 없습니다</string>
+  <string name="downloader_download_failed_content">%1$s을(를) 다운로드할 수 없습니다</string>
   <string name="downloader_not_downloaded_yet">아직 다운로드 되지 않았습니다</string>
+  <string name="downloader_download_failed_credentials_error">다운로드가 실패하였습니다. 다시 로그인하십시오</string>
   <string name="common_choose_account">계정 선택</string>
   <string name="sync_fail_ticker">동기화 실패</string>
+  <string name="sync_fail_ticker_unauthorized">동기화가 실패하였습니다. 다시 로그인하십시오</string>
   <string name="sync_fail_content">%1$s와(과) 동기화할 수 없었습니다</string>
-  <string name="sync_fail_content_unauthorized">%1$s에 대한 비밀번호가 틀립니다</string>
+  <string name="sync_fail_content_unauthorized">%1$s의 암호가 올바르지 않습니다</string>
   <string name="sync_conflicts_in_favourites_ticker">충돌하는 항목 발견됨</string>
-  <string name="sync_conflicts_in_favourites_content">동기화된 파일 중 %1$d개를 동기화할 수 없습니다</string>
+  <string name="sync_conflicts_in_favourites_content">동기화된 파일 중 %1$d개를 동기화할 수 없습니다</string>
   <string name="sync_fail_in_favourites_ticker">파일을 동기화할 수 없었습니다</string>
-  <string name="sync_fail_in_favourites_content">파일 %1$d개의 내용을 동기화할 수 없었습니다 (충돌 %2$d개)</string>
-  <string name="sync_foreign_files_forgotten_ticker">몇몇 로컬 파일이 사라졌습니다.</string>
-  <string name="sync_current_folder_was_removed">%1$s 폴더가 존재하지 않습니다.</string>
-  <string name="foreign_files_move">모두 옮김</string>
-  <string name="foreign_files_success">모든 파일 옮김</string>
-  <string name="foreign_files_fail">몇몇 파일을 옮기지 못했습니다.</string>
+  <string name="sync_fail_in_favourites_content">파일 %1$d개의 내용을 동기화할 수 없습니다 (충돌 %2$d개)</string>
+  <string name="sync_foreign_files_forgotten_ticker">일부 로컬 파일이 사라졌습니다.</string>
+  <string name="sync_foreign_files_forgotten_content">폴더 %2$s의 파일 중 %1$d개를 복사할 수 없습니다</string>
+  <string name="sync_foreign_files_forgotten_explanation">버전 1.3.16부터는 하나의 파일이 여러 계정과 동기화될 때 데이터 손실을 막기 위해서 이 장치에서 업로드된 파일은 로컬 폴더 %1$s(으)로 복사됩니다.\n\n이 변경 사항 때문에 이 앱의 이전 버전에서 업로드된 모든 파일은 폴더 %2$s(으)로 복사되었습니다. 계정 동기화 중 오류가 발생하여 이 작업이 중단되었습니다. 파일을 그대로 둔 다음 %3$s(으)로 향한 링크를 삭제하거나, 파일을 직접 폴더 %1$s(으)로 이동한 다음 %4$s(으)로 향한 링크를 그대로 두십시오.\n\n아래 목록은 로컬 파일과 링크가 걸려 있는 %5$s에 있는 원격 파일입니다.</string>
+  <string name="sync_current_folder_was_removed">폴더 %1$s이(가) 더 이상 존재하지 않습니다.</string>
+  <string name="foreign_files_move">모두 이동</string>
+  <string name="foreign_files_success">모든 파일 이동됨</string>
+  <string name="foreign_files_fail">몇몇 파일을 이동할 수 없음</string>
   <string name="foreign_files_local_text">로컬: %1$s</string>
   <string name="foreign_files_remote_text">원격: %1$s</string>
+  <string name="upload_query_move_foreign_files">선택한 파일을 폴더 %1$s(으)로 복사할 공간이 부족합니다. 파일을 이동하시겠습니까?</string>
   <string name="pincode_enter_pin_code">앱 암호를 입력하십시오</string>
   <string name="pincode_configure_your_pin">앱 암호를 입력하십시오</string>
   <string name="pincode_configure_your_pin_explanation">앱을 시작할 때마다 암호를 물어봅니다</string>
@@ -114,79 +137,88 @@
   <string name="pincode_removed">앱 암호가 삭제되었습니다</string>
   <string name="pincode_stored">앱 암호가 저장되었습니다</string>
   <string name="media_notif_ticker">%1$s 음악 재생기</string>
-  <string name="media_state_playing">%1$s (재생중)</string>
+  <string name="media_state_playing">%1$s (재생 중)</string>
   <string name="media_state_loading">%1$s (불러오는 중)</string>
   <string name="media_event_done">%1$s 재생 완료됨</string>
-  <string name="media_err_nothing_to_play">미디어 파일을 찾을수 없습니다</string>
+  <string name="media_err_nothing_to_play">미디어 파일을 찾을 수 음</string>
   <string name="media_err_no_account">준비된 계정이 없습니다</string>
   <string name="media_err_not_in_owncloud">유효한 계정의 파일이 아닙니다</string>
   <string name="media_err_unsupported">지원하지 않는 미디어 코덱</string>
-  <string name="media_err_io">미디어 파일을 읽을수 </string>
+  <string name="media_err_io">미디어 파일을 읽을 없음</string>
   <string name="media_err_malformed">미디어 파일이 제대로 인코드 되지 않았습니다</string>
   <string name="media_err_timeout">재생 시도 중 시간이 초과됨</string>
-  <string name="media_err_invalid_progressive_playback">미디어 파일을 스트리밍 할수 없습니다</string>
-  <string name="media_err_unknown">내장된 미디어 플레이어에서는 이 미디어 파일을 재생할수 없습니다</string>
-  <string name="media_err_security_ex">%1$s 를 재생하는 중에 보안오류가 발생함</string>
-  <string name="media_err_io_ex">%1$s 를 재생하는 중에 입력 에러가 발생함</string>
-  <string name="media_err_unexpected">%1$s 를 재생하던 중에 알수 없는 오류가 발생함</string>
-  <string name="media_rewind_description">되감기 버튼</string>
-  <string name="media_play_pause_description">재생 혹은 일시정지 버튼</string>
-  <string name="media_forward_description">빨리감기 버튼</string>
-  <string name="auth_trying_to_login">로그인 중...</string>
+  <string name="media_err_invalid_progressive_playback">미디어 파일을 스트리밍 할 수 없습니다</string>
+  <string name="media_err_unknown">내장된 미디어 플레이어에서 이 미디어 파일을 재생할 수 없습니다</string>
+  <string name="media_err_security_ex">%1$s을(를) 재생하는 중 보안 오류가 발생함</string>
+  <string name="media_err_io_ex">%1$s을(를) 재생하는 중 입력 오류가 발생함</string>
+  <string name="media_err_unexpected">%1$s을(를) 재생하는 중 알 수 없는 오류가 발생함</string>
+  <string name="media_rewind_description">되감기 단추</string>
+  <string name="media_play_pause_description">재생 혹은 일시 정지 단추</string>
+  <string name="media_forward_description">빨리감기 단추</string>
+  <string name="auth_getting_authorization">인증 정보 가져오는 중...</string>
+  <string name="auth_trying_to_login">로그인 시도 중...</string>
   <string name="auth_no_net_conn_title">네트워크에 연결할 수 없습니다</string>
   <string name="auth_nossl_plain_ok_title">암호화된 연결을 사용할 수 없습니다.</string>
   <string name="auth_connection_established">연결됨</string>
   <string name="auth_testing_connection">연결 테스트 중...</string>
   <string name="auth_not_configured_title">서버 설정이 잘못됨</string>
   <string name="auth_account_not_new">같은 사용자와 서버에 대한 계정이 이미 존재합니다</string>
-  <string name="auth_account_not_the_same">입력된 사용자가 이 계정의 사용자와 일치하지 않</string>
+  <string name="auth_account_not_the_same">입력된 사용자가 이 계정의 사용자와 일치하지 않습니다</string>
   <string name="auth_unknown_error_title">알 수 없는 오류가 발생하였습니다!</string>
   <string name="auth_unknown_host_title">호스트를 찾을 수 없음</string>
   <string name="auth_incorrect_path_title">서버 인스턴스를 찾을 수 없음</string>
-  <string name="auth_timeout_title">서버 응답 시간이 초과되었습니다</string>
+  <string name="auth_timeout_title">서버 응답 시간이 초과</string>
   <string name="auth_incorrect_address_title">잘못된 URL</string>
   <string name="auth_ssl_general_error_title">SSL 초기화 오류</string>
   <string name="auth_ssl_unverified_server_title">SSL 서버의 신원을 확인할수 없습니다</string>
   <string name="auth_bad_oc_version_title">확인할 수 없는 서버 버전</string>
   <string name="auth_wrong_connection_title">연결을 수립할 수 없음</string>
   <string name="auth_secure_connection">암호화된 연결 사용 중</string>
-  <string name="auth_unauthorized">잘못된 로그인/암호</string>
-  <string name="auth_oauth_error">권한부여가 성공적으로 이뤄지지 않았습니다</string>
-  <string name="auth_oauth_error_access_denied">권한 서버로 부터 접근이 거부되었습니다</string>
-  <string name="auth_wtf_reenter_URL">뜻밖의 상태; 다시 서버 주소를 입력해주십시오</string>
-  <string name="auth_expired_oauth_token_toast">인증이 만료되었습니다. 다시 인증해주세요</string>
-  <string name="auth_expired_basic_auth_toast">현재 암호를 </string>
-  <string name="auth_expired_saml_sso_token_toast">세션이 만료되었습니다. 다시 접속해주세요</string>
-  <string name="auth_connecting_auth_server">인증 서버에 접속하는 중...</string>
+  <string name="auth_unauthorized">잘못된 사용자 이름 및 암호</string>
+  <string name="auth_oauth_error">인증 실패</string>
+  <string name="auth_oauth_error_access_denied">인증 서버 접근 거부됨</string>
+  <string name="auth_wtf_reenter_URL">예상하지 못한 상태입니다. 서버 URL을 다시 입력해 주십시오</string>
+  <string name="auth_expired_oauth_token_toast">인증이 만료되었습니다. 다시 인증해 주십시오</string>
+  <string name="auth_expired_basic_auth_toast">현재 암호를 입력해 주십시오</string>
+  <string name="auth_expired_saml_sso_token_toast">세션이 만료되었습니다. 다시 접속해 주십시오</string>
+  <string name="auth_connecting_auth_server">인증 서버에 연결하는 중...</string>
   <string name="auth_unsupported_auth_method">서버에서 이 인증 방법을 지원하지 않습니다.</string>
-  <string name="auth_unsupported_multiaccount">%1$s 에서는 다중 계정을 지원하지 않습니다</string>
+  <string name="auth_unsupported_multiaccount">%1$s에서 다중 계정을 지원하지 않습니다</string>
+  <string name="auth_fail_get_user_name">서버에서 올바른 사용자 ID를 반환하지 않았습니다. 관리자에게 연락하십시오
+	</string>
+  <string name="auth_can_not_auth_against_server">이 서버에 인증할 수 없음</string>
   <string name="fd_keep_in_sync">파일을 최신 정보로 유지</string>
   <string name="common_rename">이름 바꾸기</string>
   <string name="common_remove">삭제</string>
+  <string name="confirmation_remove_alert">%1$s을(를) 삭제하시겠습니까?</string>
+  <string name="confirmation_remove_folder_alert">%1$s 및 포함된 내용을 삭제하시겠습니까?</string>
   <string name="confirmation_remove_local">로컬만</string>
   <string name="confirmation_remove_folder_local">로컬 콘텐츠만</string>
   <string name="confirmation_remove_remote">서버에서 삭제</string>
   <string name="confirmation_remove_remote_and_local">서버와 로컬 모두</string>
-  <string name="remove_success_msg">성공적으로 삭제하였습니다</string>
-  <string name="remove_fail_msg">삭제할 수 없었습니다</string>
+  <string name="remove_success_msg">성공적으로 삭제</string>
+  <string name="remove_fail_msg">삭제할 수 없</string>
   <string name="rename_dialog_title">새 이름 입력</string>
   <string name="rename_local_fail_msg">로컬 파일의 이름을 변경할 수 없습니다. 다른 이름을 입력하십시오</string>
-  <string name="rename_server_fail_msg">이름을 변경할 수 없었습니다</string>
-  <string name="sync_file_fail_msg">원격 파일을 확인할 수 없었습니다</string>
-  <string name="sync_file_nothing_to_do_msg">파일 내용이 이미 동기화되었습니다</string>
-  <string name="filename_forbidden_characters">사용할수 없는 문자들: / \\ &lt; &gt; : \" | ? *</string>
+  <string name="rename_server_fail_msg">이름을 변경할 수 없음</string>
+  <string name="sync_file_fail_msg">원격 파일을 확인할 수 없음</string>
+  <string name="sync_file_nothing_to_do_msg">파일 내용이 이미 동기화됨</string>
+  <string name="create_dir_fail_msg">폴더를 만들 수 없음</string>
+  <string name="filename_forbidden_characters">사용할 수 없는 문자: / \\ &lt; &gt; : \" | ? *</string>
+  <string name="filename_empty">파일 이름이 비어 있을 수 없음</string>
   <string name="wait_a_moment">잠시 기다려 주십시오</string>
   <string name="filedisplay_unexpected_bad_get_content">예상하지 못한 오류입니다. 다른 앱에서 파일을 선택하십시오</string>
   <string name="filedisplay_no_file_selected">선택한 파일 없음</string>
+  <string name="activity_chooser_title">다음으로 링크 보내기...</string>
   <string name="oauth_check_onoff">oAuth2로 로그인하기</string>
-  <string name="oauth_login_connection">oAuth2 서버에 연결중...</string>
-  <string name="ssl_validator_header">사이트 인증서를 확인할 수 없습니다</string>
+  <string name="oauth_login_connection">oAuth2 서버에 연결 중...</string>
+  <string name="ssl_validator_header">사이트 인증서를 확인할 수 없습니다</string>
   <string name="ssl_validator_reason_cert_not_trusted">- 서버 인증서를 신뢰할 수 없습니다</string>
   <string name="ssl_validator_reason_cert_expired">- 서버 인증서가 만료되었습니다</string>
   <string name="ssl_validator_reason_cert_not_yet_valid">- 서버 인증서의 유효 기간이 시작되지 않았습니다</string>
   <string name="ssl_validator_reason_hostname_not_verified">- 인증서의 URL과 입력한 URL이 일치하지 않습니다</string>
   <string name="ssl_validator_question">이 인증서를 신뢰하시겠습니까?</string>
-  <string name="ssl_validator_not_saved">인증서를 저장할 수 없습니다</string>
+  <string name="ssl_validator_not_saved">인증서를 저장할 수 없습니다</string>
   <string name="ssl_validator_btn_details_see">자세히</string>
   <string name="ssl_validator_btn_details_hide">숨기기</string>
   <string name="ssl_validator_label_subject">발급 대상:</string>
@@ -202,28 +234,70 @@
   <string name="ssl_validator_label_validity_to">끝:</string>
   <string name="ssl_validator_label_signature">서명:</string>
   <string name="ssl_validator_label_signature_algorithm">알고리즘:</string>
-  <string name="placeholder_sentence">이것은 플레이스홀더입니다</string>
+  <string name="ssl_validator_null_cert">인증서를 표시할 수 없습니다.</string>
+  <string name="ssl_validator_no_info_about_error">- 오류에 대한 정보가 없습니다</string>
+  <string name="placeholder_sentence">이것은 자리 비움자입니다</string>
   <string name="placeholder_filename">placeholder.txt</string>
   <string name="placeholder_filetype">PNG 그림</string>
   <string name="placeholder_filesize">389 KB</string>
   <string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
   <string name="placeholder_media_time">12:23:45</string>
-  <string name="instant_upload_on_wifi">WiFi 사용 중일때만 사진 업로드</string>
+  <string name="instant_upload_on_wifi">Wi-Fi 사용 중일때만 사진 업로드</string>
+  <string name="instant_video_upload_on_wifi">Wi-Fi 사용 중일때만 동영상 업로드</string>
   <string name="instant_upload_path">/InstantUpload</string>
   <string name="conflict_title">업데이트 충돌</string>
   <string name="conflict_message">원격 파일 %s이(가) 로컬 파일과 동기화되지 않았습니다. 계속 진행하면 서버에 있는 파일을 덮어씁니다.</string>
   <string name="conflict_keep_both">모두 저장</string>
   <string name="conflict_overwrite">덮어쓰기</string>
   <string name="conflict_dont_upload">업로드하지 않음</string>
-  <string name="preview_image_description">그림 미리보기</string>
+  <string name="preview_image_description">사진 미리 보기</string>
+  <string name="preview_image_error_unknown_format">이 사진을 미리 볼 수 없습니다</string>
+  <string name="error__upload__local_file_not_copied">%1$s을(를) 로컬 폴더 %2$s(으)로 복사할 수 없습니다</string>
+  <string name="prefs_instant_upload_path_title">업로드 경로</string>
+  <string name="share_link_no_support_share_api">서버에서 공유가 비활성화되어 있습니다. 관리자에게 연락하십시오.</string>
+  <string name="share_link_file_no_exist">공유할 수 없습니다. 파일이 있는지 확인하십시오</string>
+  <string name="share_link_file_error">이 파일이나 폴더를 공유하는 중 오류 발생</string>
+  <string name="unshare_link_file_no_exist">공유를 해제할 수 없습니다. 파일이 있는지 확인하십시오</string>
+  <string name="unshare_link_file_error">이 파일이나 폴더의 공유를 해제하는 중 오류 발생</string>
   <string name="activity_chooser_send_file_title">보내기</string>
-  <string name="copy_link">링크 복사</string>
+  <string name="copy_link">링크 주소 복사</string>
   <string name="clipboard_text_copied">클립보드로 복사됨</string>
+  <string name="error_cant_bind_to_operations_service">치명적 오류: 작업을 진행할 수 없음</string>
+  <string name="network_error_socket_exception">서버에 연결하는 중 오류가 발생하였습니다.</string>
+  <string name="network_error_socket_timeout_exception">서버를 기다리는 중 오류가 발생하였습니다. 작업이 진행되지 않았을 수도 있습니다</string>
+  <string name="network_error_connect_timeout_exception">서버를 기다리는 중 오류가 발생하였습니다. 작업이 진행되지 않았을 수도 있습니다</string>
+  <string name="network_host_not_available">서버를 사용할 수 없어서 작업을 진행할 수 없습니다</string>
   <string name="empty"></string>
+  <string name="forbidden_permissions">%s 권한이 없습니다</string>
+  <string name="forbidden_permissions_rename">이 파일의 이름을 바꿀</string>
+  <string name="forbidden_permissions_delete">이 파일을 삭제할</string>
+  <string name="share_link_forbidden_permissions">이 파일을 공유할</string>
+  <string name="unshare_link_forbidden_permissions">이 파일의 공유를 해제할</string>
+  <string name="forbidden_permissions_create">파일을 생성할</string>
+  <string name="uploader_upload_forbidden_permissions">이 폴더에 업로드할</string>
+  <string name="downloader_download_file_not_found">이 파일을 서버에서 더 이상 사용할 수 없습니다</string>
   <string name="prefs_category_accounts">계정</string>
+  <string name="prefs_add_account">계정 추가</string>
+  <string name="auth_redirect_non_secure_connection_title">보안 연결이 안전하지 않은 경로로 넘어갑니다.</string>
+  <string name="actionbar_logger">로그</string>
+  <string name="log_send_history_button">과거 기록 보내기</string>
+  <string name="log_send_no_mail_app">로그를 보낼 앱이 없습니다. 메일 앱을 설치하십시오!</string>
+  <string name="log_send_mail_subject">%1$s Android 앱 로그</string>
+  <string name="log_progress_dialog_text">데이터 불러오는 중...</string>
   <string name="saml_authentication_required_text">인증 필요함</string>
   <string name="saml_authentication_wrong_pass">잘못된 암호</string>
+  <string name="actionbar_move">이동</string>
+  <string name="file_list_empty_moving">항목이 없습니다. 폴더를 추가할 수 있습니다!</string>
   <string name="folder_picker_choose_button_text">선택</string>
+  <string name="move_file_not_found">이동할 수 없습니다. 파일이 존재하는 지 확인하십시오</string>
+  <string name="move_file_invalid_into_descendent">폴더를 하위 폴더 아래로 이동할 수 없습니다</string>
+  <string name="move_file_invalid_overwrite">파일이 이미 대상 폴더에 존재합니다</string>
+  <string name="move_file_error">이 파일이나 폴더를 이동하는 중 오류가 발생하였습니다</string>
+  <string name="forbidden_permissions_move">이 파일을 이동할</string>
+  <string name="prefs_category_instant_uploading">즉시 업로드</string>
   <string name="prefs_category_security">보안</string>
+  <string name="prefs_instant_video_upload_path_title">동영상 업로드 경로</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>

+ 25 - 23
res/values-pt-rPT/strings.xml

@@ -41,7 +41,7 @@
   <string name="prefs_remember_last_share_location">Lembrar localização de partilha</string>
   <string name="prefs_remember_last_upload_location_summary">Lembrar da última localização de envio de partilha</string>
   <string name="recommend_subject">Test %1$s no seu smartphone!</string>
-  <string name="recommend_text">Quero convidar-te a usares %1$s no teu smartphone!\nFaz download aqui: %2$s</string>
+  <string name="recommend_text">Eu quero convidar-te para usares %1$s no teu smartphone!\nTransfere  aqui: %2$s</string>
   <string name="auth_check_server">Verificar Servidor</string>
   <string name="auth_host_url">Endereço do servidor https://..</string>
   <string name="auth_username">Nome de Utilizador</string>
@@ -52,7 +52,7 @@
   <string name="uploader_btn_upload_text">Enviar</string>
   <string name="uploader_top_message">Escolha a pasta de envio:</string>
   <string name="uploader_wrn_no_account_title">A conta não foi encontrada</string>
-  <string name="uploader_wrn_no_account_text">Não tem nenhuma conta  %1$s no seu dispositivo. Por favor, configure primeiro uma conta.</string>
+  <string name="uploader_wrn_no_account_text">Não existe nenhuma conta %1$s no seu dispositivo. Por favor, configure primeiro uma conta.</string>
   <string name="uploader_wrn_no_account_setup_btn_text">Configurar</string>
   <string name="uploader_wrn_no_account_quit_btn_text">Sair</string>
   <string name="uploader_wrn_no_content_title">Sem conteúdo para enviar</string>
@@ -76,7 +76,7 @@
   <string name="filedetails_sync_file">Atualizar ficheiro</string>
   <string name="filedetails_renamed_in_upload_msg">O ficheiro foi renomeado para %1$s durante o envio.</string>
   <string name="action_share_file">Partilhar a hiperligação</string>
-  <string name="action_unshare_file">Deixar de partilhar a ligação</string>
+  <string name="action_unshare_file">Deixar de partilhar a hiperligação</string>
   <string name="common_yes">Sim</string>
   <string name="common_no">Não</string>
   <string name="common_ok">ACEITAR</string>
@@ -98,14 +98,14 @@
   <string name="uploader_upload_succeeded_ticker">Envio bem sucedido</string>
   <string name="uploader_upload_succeeded_content_single">%1$s foi enviado com sucesso</string>
   <string name="uploader_upload_failed_ticker">Não foi possível enviar</string>
-  <string name="uploader_upload_failed_content_single">O envio do ficheiro %1$s não foi concluído.</string>
+  <string name="uploader_upload_failed_content_single">Não foi possível concluir o envio de %1$s.</string>
   <string name="uploader_upload_failed_credentials_error">Falha no carregamento, é necessário fazer novo login</string>
-  <string name="downloader_download_in_progress_ticker">A transferir ...</string>
+  <string name="downloader_download_in_progress_ticker">A transferir...</string>
   <string name="downloader_download_in_progress_content">%1$d%% A transferir %2$s</string>
   <string name="downloader_download_succeeded_ticker">Transferência bem sucedida</string>
-  <string name="downloader_download_succeeded_content">%1$s foi descarregado com sucesso</string>
-  <string name="downloader_download_failed_ticker">Descarga falhou</string>
-  <string name="downloader_download_failed_content">O descarregamento %1$s não foi possível descarregar</string>
+  <string name="downloader_download_succeeded_content">%1$s foi transferido com sucesso</string>
+  <string name="downloader_download_failed_ticker">Transferência falhada</string>
+  <string name="downloader_download_failed_content">Não foi possível concluir a transferência de %1$s</string>
   <string name="downloader_not_downloaded_yet">Ainda não foi transferido</string>
   <string name="downloader_download_failed_credentials_error">Não foi possível transferir, tem de iniciar a sessão novamente</string>
   <string name="common_choose_account">Escolha a conta</string>
@@ -132,10 +132,10 @@
   <string name="pincode_configure_your_pin_explanation">O PIN será pedido sempre que a app seja iniciada.</string>
   <string name="pincode_reenter_your_pincode">Por favor, reinsira o PIN da App</string>
   <string name="pincode_remove_your_pincode">Remover o seu PIN da App</string>
-  <string name="pincode_mismatch">Os códigos PIN introduzidos não são iguais.</string>
-  <string name="pincode_wrong">Código PIN Incorrecto.</string>
-  <string name="pincode_removed">PIN da aplicação removido</string>
-  <string name="pincode_stored">PIN da aplicação guardado</string>
+  <string name="pincode_mismatch">Os CÓDIGOS da APP não são iguais</string>
+  <string name="pincode_wrong">CÓDIGO da App Incorreto</string>
+  <string name="pincode_removed">CÓDIGOS da App removido</string>
+  <string name="pincode_stored">CÓDIGO da App guardado</string>
   <string name="media_notif_ticker">%1$s leitor de música</string>
   <string name="media_state_playing">%1$s (a reproduzir)</string>
   <string name="media_state_loading">%1$s (a carregar)</string>
@@ -143,8 +143,8 @@
   <string name="media_err_nothing_to_play">Não foi encontrado nenhum ficheiro de média</string>
   <string name="media_err_no_account">Não foi fornecida conta</string>
   <string name="media_err_not_in_owncloud">O ficheiro não está numa conta válida</string>
-  <string name="media_err_unsupported">Codec de média não suportado</string>
-  <string name="media_err_io">Não foi possível reproduzir o ficheiro</string>
+  <string name="media_err_unsupported">Codec de multimédia não suportado</string>
+  <string name="media_err_io">Não foi possível ler o ficheiro de multimédia</string>
   <string name="media_err_malformed">Ficheiro erradamente codificado (codec)</string>
   <string name="media_err_timeout">O tempo de espera para jogar expirou</string>
   <string name="media_err_invalid_progressive_playback">O ficheiro não pode ser reproduzido (streaming)</string>
@@ -152,25 +152,25 @@
   <string name="media_err_security_ex">Erro de segurança a tentar reproduzir o ficheiro %1$s</string>
   <string name="media_err_io_ex">Erro de input a tentar reproduzir %1$s</string>
   <string name="media_err_unexpected">Erro inesperado a tentar reproduzir %1$s</string>
-  <string name="media_rewind_description">Botão de rebobinar</string>
-  <string name="media_play_pause_description">Botão Tocar/Pausa</string>
+  <string name="media_rewind_description">Botão de Retroceder</string>
+  <string name="media_play_pause_description">Botão de Reproduzir/Pausar</string>
   <string name="media_forward_description">Botão de avanço rápido</string>
   <string name="auth_getting_authorization">A obter autorização...</string>
-  <string name="auth_trying_to_login">A tentar entrar...</string>
+  <string name="auth_trying_to_login">A tentar iniciar a sessão...</string>
   <string name="auth_no_net_conn_title">Sem ligação à rede</string>
-  <string name="auth_nossl_plain_ok_title">Ligação segura indisponível</string>
+  <string name="auth_nossl_plain_ok_title">Ligação segura indisponível.</string>
   <string name="auth_connection_established">Ligação estabelecida</string>
   <string name="auth_testing_connection">A testar a ligação...</string>
   <string name="auth_not_configured_title">Configuração do servidor incorrecta.</string>
   <string name="auth_account_not_new">Uma conta para este utilizador e servidor já existe no dispositivo</string>
   <string name="auth_account_not_the_same">O utilizador que escreveu não coincide com o nome de utilizador desta conta</string>
   <string name="auth_unknown_error_title">Ocorreu um erro desconhecido!</string>
-  <string name="auth_unknown_host_title">Não é possível encontrar o servidor</string>
-  <string name="auth_incorrect_path_title">Instância servidor não encontrada</string>
-  <string name="auth_timeout_title">O servidor levou demasiado tempo a responder</string>
+  <string name="auth_unknown_host_title">Não foi possível encontrar o anfitrião</string>
+  <string name="auth_incorrect_path_title">Instância do servidor não encontrada</string>
+  <string name="auth_timeout_title">O servidor demorou muito tempo a responder</string>
   <string name="auth_incorrect_address_title">URL errado</string>
   <string name="auth_ssl_general_error_title">Inicialização de SSL falhou</string>
-  <string name="auth_ssl_unverified_server_title">Não foi possível verificar a identidade SSL do servidor</string>
+  <string name="auth_ssl_unverified_server_title">Não foi possível verificar a identidade do servidor SSL</string>
   <string name="auth_bad_oc_version_title">Versão do servidor não reconhecida</string>
   <string name="auth_wrong_connection_title">Não consegue estabelecer ligação</string>
   <string name="auth_secure_connection">Ligação segura estabelecida</string>
@@ -179,7 +179,7 @@
   <string name="auth_oauth_error_access_denied">Acesso negado pelo servidor</string>
   <string name="auth_wtf_reenter_URL">Estado inesperado, por favor, digite a URL do servidor novamente</string>
   <string name="auth_expired_oauth_token_toast">O prazo da sua autorização expirou. Por favor renove-a</string>
-  <string name="auth_expired_basic_auth_toast">Por favor, introduza a password actual</string>
+  <string name="auth_expired_basic_auth_toast">Por favor, insira a palavra-passe atual</string>
   <string name="auth_expired_saml_sso_token_toast">A sua sessão expirou. Por favor autentique-se de novo</string>
   <string name="auth_connecting_auth_server">A verificar a sua autenticação no servidor...</string>
   <string name="auth_unsupported_auth_method">O servidor não suporta este método de autenticação</string>
@@ -297,4 +297,6 @@
   <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="shared_subject_header">partilhado</string>
+  <string name="with_you_subject_header">consigo</string>
+  <string name="subject_token">%1$s %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
 </resources>

+ 48 - 48
res/values-ru/strings.xml

@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <resources>
-  <string name="about_android">%1$s Приложение для Андроид</string>
-  <string name="about_version">Версия %1$s</string>
+  <string name="about_android">%1$s для Android</string>
+  <string name="about_version">версия %1$s</string>
   <string name="actionbar_sync">Обновить учетную запись</string>
   <string name="actionbar_upload">Загрузить</string>
   <string name="actionbar_upload_from_apps">Содержимое из других приложений</string>
@@ -15,7 +15,7 @@
   <string name="actionbar_sort_title">Упорядочить по</string>
   <string-array name="actionbar_sortby">
     <item>А-Я</item>
-    <item>По новизне</item>
+    <item>Новое - Старое</item>
   </string-array>
   <!--TODO re-enable when server-side folder size calculation is available   
     	<item>Biggest - Smallest</item>-->
@@ -23,7 +23,7 @@
   <string name="prefs_category_more">Больше</string>
   <string name="prefs_accounts">Учётные записи</string>
   <string name="prefs_manage_accounts">Управление учётными записями</string>
-  <string name="prefs_pincode">App PIN</string>
+  <string name="prefs_pincode">PIN приложения</string>
   <string name="prefs_pincode_summary">Защитить ваш клиент</string>
   <string name="prefs_instant_upload">Мгновенная загрузка фотографий</string>
   <string name="prefs_instant_upload_summary">Немедленно загружать фотографии сделанные камерой</string>
@@ -51,16 +51,16 @@
   <string name="sync_string_files">Файлы</string>
   <string name="setup_btn_connect">Подключиться</string>
   <string name="uploader_btn_upload_text">Загрузить</string>
-  <string name="uploader_top_message">Выберете каталог для загрузки</string>
+  <string name="uploader_top_message">Выберите каталог для загрузки</string>
   <string name="uploader_wrn_no_account_title">Учётная запись не найдена</string>
-  <string name="uploader_wrn_no_account_text">На вашем устройстве нет учётных записей %1$s. Сначала, необходимо настроить учётную запись.</string>
-  <string name="uploader_wrn_no_account_setup_btn_text">Установка</string>
+  <string name="uploader_wrn_no_account_text">На вашем устройстве нет учётных записей %1$s. Пожалуйста настройте учётную запись.</string>
+  <string name="uploader_wrn_no_account_setup_btn_text">Настройка</string>
   <string name="uploader_wrn_no_account_quit_btn_text">Выход</string>
   <string name="uploader_wrn_no_content_title">Нет содержимого для загрузки</string>
   <string name="uploader_wrn_no_content_text">Содержимое не получено. Нечего загружать.</string>
   <string name="uploader_error_forbidden_content">Доступ к общему ресурсу для %1$s запрещен</string>
   <string name="uploader_info_uploading">Загрузка</string>
-  <string name="file_list_seconds_ago">менее минуты</string>
+  <string name="file_list_seconds_ago">пару секунд назад</string>
   <string name="file_list_empty">Здесь ничего нет. Загрузите что-нибудь!</string>
   <string name="file_list_loading">Загрузка...</string>
   <string name="local_file_list_empty">В этом каталоге нет файлов.</string>
@@ -86,32 +86,32 @@
   <string name="common_cancel">Отмена</string>
   <string name="common_save_exit">Сохранить и выйти</string>
   <string name="common_error">Ошибка</string>
-  <string name="common_loading">Идёт загрузка...</string>
+  <string name="common_loading">Загрузка ...</string>
   <string name="common_error_unknown">Неизвестная ошибка</string>
   <string name="about_title">О программе</string>
   <string name="change_password">Сменить пароль</string>
   <string name="delete_account">Удалить учётную запись</string>
   <string name="create_account">Создать учётную запись</string>
-  <string name="upload_chooser_title">Загрузить из...</string>
+  <string name="upload_chooser_title">Загрузить из ...</string>
   <string name="uploader_info_dirname">Имя каталога</string>
-  <string name="uploader_upload_in_progress_ticker">Загрузка...</string>
-  <string name="uploader_upload_in_progress_content">%1$d%% загрузки %2$s</string>
+  <string name="uploader_upload_in_progress_ticker">Загрузка ...</string>
+  <string name="uploader_upload_in_progress_content">%1$d%% Загружается %2$s</string>
   <string name="uploader_upload_succeeded_ticker">Загрузка завершена</string>
   <string name="uploader_upload_succeeded_content_single">%1$s был успешно загружен</string>
   <string name="uploader_upload_failed_ticker">Ошибка загрузки</string>
   <string name="uploader_upload_failed_content_single">Загрузка %1$s не может быть завершена</string>
-  <string name="uploader_upload_failed_credentials_error">Загрузка не удалась, необходимо переподключиться</string>
-  <string name="downloader_download_in_progress_ticker">Скачивание...</string>
-  <string name="downloader_download_in_progress_content">%1$d%% скачивания %2$s</string>
+  <string name="uploader_upload_failed_credentials_error">Загрузка не удалась, нужно заново войти в свою учетную запись</string>
+  <string name="downloader_download_in_progress_ticker">Скачивание ...</string>
+  <string name="downloader_download_in_progress_content">%1$d%% Скачивается %2$s</string>
   <string name="downloader_download_succeeded_ticker">Скачивание завершено</string>
   <string name="downloader_download_succeeded_content">%1$s успешно скачан</string>
   <string name="downloader_download_failed_ticker">Скачивание не удалось</string>
   <string name="downloader_download_failed_content">Скачивание %1$s не может быть завершено</string>
   <string name="downloader_not_downloaded_yet">Ещё не скачано</string>
-  <string name="downloader_download_failed_credentials_error">Скачивание не удалось, необходимо переподключиться</string>
+  <string name="downloader_download_failed_credentials_error">Скачивание не удалось, нужно заново войти в свою учетную запись</string>
   <string name="common_choose_account">Выберите учётную запись</string>
   <string name="sync_fail_ticker">Синхронизация прошла неудачно</string>
-  <string name="sync_fail_ticker_unauthorized">Синхронизация не удалась, необходимо переподключиться</string>
+  <string name="sync_fail_ticker_unauthorized">Синхронизация не удалась, нужно заново войти в свою учетную запись</string>
   <string name="sync_fail_content">Синхронизация %1$s не может быть завершена</string>
   <string name="sync_fail_content_unauthorized">Неверный пароль для %1$s</string>
   <string name="sync_conflicts_in_favourites_ticker">Обнаружены конфликты</string>
@@ -125,18 +125,18 @@
   <string name="foreign_files_move">Переместить всё</string>
   <string name="foreign_files_success">Все файлы были перемещены</string>
   <string name="foreign_files_fail">Некоторые файлы не могут быть перемещены</string>
-  <string name="foreign_files_local_text">Локально: %1$s</string>
-  <string name="foreign_files_remote_text">Удаленно: %1$s</string>
+  <string name="foreign_files_local_text">Локальные: %1$s</string>
+  <string name="foreign_files_remote_text">Удаленные: %1$s</string>
   <string name="upload_query_move_foreign_files">Для копирования выбранных файлов в каталог %1$s недостаточно свободного места. Скопировать в другое место?</string>
-  <string name="pincode_enter_pin_code">Укажите App PIN</string>
-  <string name="pincode_configure_your_pin">Введите App PIN</string>
-  <string name="pincode_configure_your_pin_explanation">PIN-код будет запрашиваться при каждом запуске приложения.</string>
-  <string name="pincode_reenter_your_pincode">Повторите ввод App PIN</string>
-  <string name="pincode_remove_your_pincode">Удалить App PIN</string>
-  <string name="pincode_mismatch">Введённые App PIN не совпадают</string>
-  <string name="pincode_wrong">Неверный App PIN</string>
-  <string name="pincode_removed">App PIN удалён</string>
-  <string name="pincode_stored">App PIN сохранён</string>
+  <string name="pincode_enter_pin_code">Укажите PIN приложения</string>
+  <string name="pincode_configure_your_pin">Введите PIN приложения</string>
+  <string name="pincode_configure_your_pin_explanation">PIN будет запрашиваться при каждом запуске приложения.</string>
+  <string name="pincode_reenter_your_pincode">Повторите ввод PIN приложения</string>
+  <string name="pincode_remove_your_pincode">Удалить PIN приложения</string>
+  <string name="pincode_mismatch">Введённые PIN не совпадают</string>
+  <string name="pincode_wrong">Неверный PIN приложения</string>
+  <string name="pincode_removed">PIN приложения удалён</string>
+  <string name="pincode_stored">PIN приложения сохранён</string>
   <string name="media_notif_ticker">%1$s аудиоплеер</string>
   <string name="media_state_playing">%1$s (проигрывается)</string>
   <string name="media_state_loading">%1$s (загружается)</string>
@@ -147,7 +147,7 @@
   <string name="media_err_unsupported">Неподдерживаемый кодек</string>
   <string name="media_err_io">Медиафайл не может быть прочитан</string>
   <string name="media_err_malformed">Медиафайл некорректно закодирован</string>
-  <string name="media_err_timeout">Время попыток воспроизведения вышло</string>
+  <string name="media_err_timeout">Истекло время попытки воспроизведения</string>
   <string name="media_err_invalid_progressive_playback">Невозможно организовать потоковую передачу медиафайла</string>
   <string name="media_err_unknown">Медиафайл не может быть проигран стандартным плеером</string>
   <string name="media_err_security_ex">Ошибка безопасности при воспроизведении %1$s</string>
@@ -156,7 +156,7 @@
   <string name="media_rewind_description">Перемотка назад</string>
   <string name="media_play_pause_description">Воспроизведение или пауза</string>
   <string name="media_forward_description">Перемотка вперед</string>
-  <string name="auth_getting_authorization">Происходит авторизация.....</string>
+  <string name="auth_getting_authorization">Выполняется авторизация...</string>
   <string name="auth_trying_to_login">Попытка входа...</string>
   <string name="auth_no_net_conn_title">Нет подключения к сети</string>
   <string name="auth_nossl_plain_ok_title">Защищённое соединение недоступно.</string>
@@ -173,7 +173,7 @@
   <string name="auth_ssl_general_error_title">Ошибка инициализации SSL</string>
   <string name="auth_ssl_unverified_server_title">Невозможно проверить SSL-сертификат сервера</string>
   <string name="auth_bad_oc_version_title">Неизвестная версия сервера</string>
-  <string name="auth_wrong_connection_title">Невозможно установить соединение</string>
+  <string name="auth_wrong_connection_title">Не удается установить соединение</string>
   <string name="auth_secure_connection">Защищённое соединение установлено</string>
   <string name="auth_unauthorized">Неверное имя пользователя или пароль</string>
   <string name="auth_oauth_error">Ошибка авторизации</string>
@@ -210,7 +210,7 @@
   <string name="wait_a_moment">Подождите немного</string>
   <string name="filedisplay_unexpected_bad_get_content">Неизвестная ошибка; выберите этот файл из другого приложения</string>
   <string name="filedisplay_no_file_selected">Файлы не выбраны</string>
-  <string name="activity_chooser_title">Отправить ссылку...</string>
+  <string name="activity_chooser_title">Отправить ссылку ...</string>
   <string name="oauth_check_onoff">Войти через oAuth2</string>
   <string name="oauth_login_connection">Подключение к серверу oAuth2...</string>
   <string name="ssl_validator_header">Подлинность сайта не может быть проверена</string>
@@ -218,21 +218,21 @@
   <string name="ssl_validator_reason_cert_expired">- Срок действия сертификата сервера истёк</string>
   <string name="ssl_validator_reason_cert_not_yet_valid">- Срок действия сертификата сервера ещё не начался</string>
   <string name="ssl_validator_reason_hostname_not_verified">- URL не совпадает с именем сервера в сертификате</string>
-  <string name="ssl_validator_question">Вы хотите доверять данному сертификату в любом случае?</string>
+  <string name="ssl_validator_question">Доверять этому сертификату в любом случае?</string>
   <string name="ssl_validator_not_saved">Сертификат не может быть сохранён</string>
   <string name="ssl_validator_btn_details_see">Подробно</string>
   <string name="ssl_validator_btn_details_hide">Скрыть</string>
-  <string name="ssl_validator_label_subject">Кому выдано:</string>
-  <string name="ssl_validator_label_issuer">Кем выдано:</string>
+  <string name="ssl_validator_label_subject">Кому выдан:</string>
+  <string name="ssl_validator_label_issuer">Кем выдан:</string>
   <string name="ssl_validator_label_CN">Имя:</string>
   <string name="ssl_validator_label_O">Организация:</string>
-  <string name="ssl_validator_label_OU">Организационное подразделение:</string>
+  <string name="ssl_validator_label_OU">Подразделение:</string>
   <string name="ssl_validator_label_C">Страна:</string>
   <string name="ssl_validator_label_ST">Штат:</string>
   <string name="ssl_validator_label_L">Местонахождение:</string>
   <string name="ssl_validator_label_validity">Срок действия:</string>
-  <string name="ssl_validator_label_validity_from">Из:</string>
-  <string name="ssl_validator_label_validity_to">В:</string>
+  <string name="ssl_validator_label_validity_from">С:</string>
+  <string name="ssl_validator_label_validity_to">По:</string>
   <string name="ssl_validator_label_signature">Подпись:</string>
   <string name="ssl_validator_label_signature_algorithm">Алгоритм:</string>
   <string name="ssl_validator_null_cert">Сертификат не может быть показан.</string>
@@ -270,13 +270,13 @@
   <string name="network_error_connect_timeout_exception">Во время ожидания сервера произошла ошибка, действие не может быть выполнено</string>
   <string name="network_host_not_available">Действие не может быть выполнено, сервер недоступен</string>
   <string name="empty"></string>
-  <string name="forbidden_permissions">Недостаточно прав в %s</string>
-  <string name="forbidden_permissions_rename">что-бы переименовать этот файл</string>
-  <string name="forbidden_permissions_delete">что-бы удалить этот файл</string>
-  <string name="share_link_forbidden_permissions">что-бы поделиться этим файлом</string>
-  <string name="unshare_link_forbidden_permissions">что-бы закрыть доступ к этому файлу</string>
-  <string name="forbidden_permissions_create">что-бы создать файл</string>
-  <string name="uploader_upload_forbidden_permissions">что-бы загрузить в этот каталог</string>
+  <string name="forbidden_permissions">У вас нет прав %s</string>
+  <string name="forbidden_permissions_rename">для переименования этого файла</string>
+  <string name="forbidden_permissions_delete">для удаления этого файла</string>
+  <string name="share_link_forbidden_permissions">для открытия доступа к этому файлу</string>
+  <string name="unshare_link_forbidden_permissions">для закрытия доступа к этому файлу</string>
+  <string name="forbidden_permissions_create">для создания файла</string>
+  <string name="uploader_upload_forbidden_permissions">для загрузки в этот каталог</string>
   <string name="downloader_download_file_not_found">Этот файл больше недоступен на сервере</string>
   <string name="prefs_category_accounts">Учётные записи</string>
   <string name="prefs_add_account">Добавить учетную запись</string>
@@ -284,7 +284,7 @@
   <string name="actionbar_logger">Журналы</string>
   <string name="log_send_history_button">История Отправлений</string>
   <string name="log_send_no_mail_app">Приложение для отправки журнала не найдено. Установите почтовое приложение!</string>
-  <string name="log_send_mail_subject">Журналы приложения %1$s для Android</string>
+  <string name="log_send_mail_subject">Журналы %1$s для Android</string>
   <string name="log_progress_dialog_text">Загрузка данных…</string>
   <string name="saml_authentication_required_text">Требуется аутентификация </string>
   <string name="saml_authentication_wrong_pass">Неправильный пароль</string>
@@ -295,11 +295,11 @@
   <string name="move_file_invalid_into_descendent">Невозможно переместить каталог в его подкаталог</string>
   <string name="move_file_invalid_overwrite">Файл уже существует в каталоге назначения</string>
   <string name="move_file_error">Произошла ошибка при попытке перемещения этого файла или каталога</string>
-  <string name="forbidden_permissions_move">переместить этот файл</string>
+  <string name="forbidden_permissions_move">для перемещения этого файла</string>
   <string name="prefs_category_instant_uploading">Мгновенные загрузки</string>
   <string name="prefs_category_security">Безопасность</string>
   <string name="prefs_instant_video_upload_path_title">Путь для загрузки Видео</string>
-  <string name="shared_subject_header">Общие</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>

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

@@ -2,6 +2,7 @@
 <resources>
   <string name="actionbar_upload">Pošalji</string>
   <string name="actionbar_upload_files">Fajlovi</string>
+  <string name="actionbar_mkdir">Novi direktorijum</string>
   <string name="actionbar_settings">Podešavanja</string>
   <string name="actionbar_see_details">Detaljnije</string>
   <string name="actionbar_send_file">Pošalji</string>
@@ -26,8 +27,10 @@
   <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>
   <string name="change_password">Izmeni lozinku</string>
   <string name="delete_account">Ukloni nalog</string>
   <string name="create_account">Novi nalog</string>

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

@@ -282,9 +282,9 @@
   <string name="auth_redirect_non_secure_connection_title">Güvenli bağlantı, güvenli olmayan bir rotaya yönlendirildi.</string>
   <string name="actionbar_logger">Günlükler</string>
   <string name="log_send_history_button">Geçmişi Gönder</string>
-  <string name="log_send_no_mail_app">Günlükleri göndermek için uygulama bulunamadı. E-posta uygulamasını yükleyin!</string>
+  <string name="log_send_no_mail_app">Kayıtları göndermek için uygulama bulunamadı. E-posta uygulamasını yükleyin!</string>
   <string name="log_send_mail_subject">%1$s Android uygulama kayıtları</string>
-  <string name="log_progress_dialog_text">Yükleniyor...</string>
+  <string name="log_progress_dialog_text">Veri yükleniyor...</string>
   <string name="saml_authentication_required_text">Kimlik doğrulama gerekli</string>
   <string name="saml_authentication_wrong_pass">Hatalı parola</string>
   <string name="actionbar_move">Taşı</string>
@@ -299,4 +299,6 @@
   <string name="prefs_category_security">Güvenlik</string>
   <string name="prefs_instant_video_upload_path_title">Video Yükleme Yolu</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>
 </resources>

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

@@ -38,6 +38,8 @@
   <string name="prefs_recommend">Порадити товаришу</string>
   <string name="prefs_feedback">Зворотній зв\'язок</string>
   <string name="prefs_imprint">Відбиток</string>
+  <string name="prefs_remember_last_share_location">Запам\'ятати позицію</string>
+  <string name="prefs_remember_last_upload_location_summary">Запам\'ятати останній опублікований шлях завантаження</string>
   <string name="recommend_subject">Спробуйте %1$s на своєму смартфоні!</string>
   <string name="recommend_text">Пропоную вам користуватися %1$s на вашому смартфоні!\nЗавантажити можна за посиланням: %2$s</string>
   <string name="auth_check_server">Перевірити сервер</string>
@@ -279,6 +281,9 @@
   <string name="auth_redirect_non_secure_connection_title">Безпечне підключення перенаправляється через незабезпечений маршрут.</string>
   <string name="actionbar_logger">Журнали</string>
   <string name="log_send_history_button">Надіслати історію</string>
+  <string name="log_send_no_mail_app">Немає додатку для відправки журналів. Встановіть поштовий додаток!</string>
+  <string name="log_send_mail_subject">%1$s Android лог додатку</string>
+  <string name="log_progress_dialog_text">Завантаження даних...</string>
   <string name="saml_authentication_required_text">Потрібна аутентифікація</string>
   <string name="saml_authentication_wrong_pass">Невірний пароль</string>
   <string name="actionbar_move">Перемістити</string>
@@ -291,5 +296,8 @@
   <string name="forbidden_permissions_move">перемістити цей файл</string>
   <string name="prefs_category_instant_uploading">Миттєво завантаження</string>
   <string name="prefs_category_security">Безпека</string>
+  <string name="prefs_instant_video_upload_path_title">Шлях завантаження відео</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>

+ 6 - 0
res/values-yo/strings.xml

@@ -0,0 +1,6 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources>
+  <!--TODO re-enable when server-side folder size calculation is available   
+    	<item>Biggest - Smallest</item>-->
+  <string name="empty"></string>
+</resources>

+ 189 - 133
src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java

@@ -29,10 +29,8 @@ import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.CompressFormat;
 import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-import android.media.ExifInterface;
 import android.media.ThumbnailUtils;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -76,7 +74,7 @@ public class ThumbnailsCacheManager {
     public static Bitmap mDefaultImg = 
             BitmapFactory.decodeResource(
                     MainApp.getAppContext().getResources(), 
-                    DisplayUtils.getResourceId("image/png", "default.png")
+                    DisplayUtils.getFileTypeIconId("image/png", "default.png")
             );
 
     
@@ -139,44 +137,15 @@ public class ThumbnailsCacheManager {
         return null;
     }
 
-    
-    public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {
-        final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
-
-        if (bitmapWorkerTask != null) {
-            final OCFile bitmapData = bitmapWorkerTask.mFile;
-            // If bitmapData is not yet set or it differs from the new data
-            if (bitmapData == null || bitmapData != file) {
-                // Cancel previous task
-                bitmapWorkerTask.cancel(true);
-            } else {
-                // The same work is already in progress
-                return false;
-            }
-        }
-        // No task associated with the ImageView, or an existing task was cancelled
-        return true;
-    }
-    
-    public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
-        if (imageView != null) {
-            final Drawable drawable = imageView.getDrawable();
-            if (drawable instanceof AsyncDrawable) {
-                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
-                return asyncDrawable.getBitmapWorkerTask();
-            }
-         }
-         return null;
-     }
-
-    public static class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
+    public static class ThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> {
         private final WeakReference<ImageView> mImageViewReference;
         private static Account mAccount;
-        private OCFile mFile;
+        private Object mFile;
         private FileDataStorageManager mStorageManager;
-        
+
+
         public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account) {
-         // Use a WeakReference to ensure the ImageView can be garbage collected
+            // Use a WeakReference to ensure the ImageView can be garbage collected
             mImageViewReference = new WeakReference<ImageView>(imageView);
             if (storageManager == null)
                 throw new IllegalArgumentException("storageManager must not be NULL");
@@ -184,95 +153,46 @@ public class ThumbnailsCacheManager {
             mAccount = account;
         }
 
-        // Decode image in background.
+        public ThumbnailGenerationTask(ImageView imageView) {
+            // Use a WeakReference to ensure the ImageView can be garbage collected
+            mImageViewReference = new WeakReference<ImageView>(imageView);
+        }
+
         @Override
-        protected Bitmap doInBackground(OCFile... params) {
+        protected Bitmap doInBackground(Object... params) {
             Bitmap thumbnail = null;
-            
+
             try {
                 if (mAccount != null) {
                     AccountManager accountMgr = AccountManager.get(MainApp.getAppContext());
-                    
+
                     mServerVersion = accountMgr.getUserData(mAccount, Constants.KEY_OC_VERSION);
                     OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, MainApp.getAppContext());
                     mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
                             getClientFor(ocAccount, MainApp.getAppContext());
                 }
-                
+
                 mFile = params[0];
-                final String imageKey = String.valueOf(mFile.getRemoteId());
-    
-                // Check disk cache in background thread
-                thumbnail = getBitmapFromDiskCache(imageKey);
-    
-                // Not found in disk cache
-                if (thumbnail == null || mFile.needsUpdateThumbnail()) { 
-                    // Converts dp to pixel
-                    Resources r = MainApp.getAppContext().getResources();
-                    
-                    int px = (int) Math.round(r.getDimension(R.dimen.file_icon_size));
-                    
-                    if (mFile.isDown()){
-                        Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
-                                mFile.getStoragePath(), px, px);
-                        
-                        if (bitmap != null) {
-                            thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
-                            
-                            // Rotate image, obeying exif tag
-                            thumbnail = BitmapUtils.rotateImage(thumbnail, mFile.getStoragePath());
-    
-                            // Add thumbnail to cache
-                            addBitmapToCache(imageKey, thumbnail);
 
-                            mFile.setNeedsUpdateThumbnail(false);
-                            mStorageManager.saveFile(mFile);
-                        }
-    
-                    } else {
-                        // Download thumbnail from server
-                        if (mClient != null && mServerVersion != null) {
-                            OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion);
-                            if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) {
-                                try {
-                                    int status = -1;
-
-                                    String uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + 
-                                            px + "/" + px + Uri.encode(mFile.getRemotePath(), "/");
-                                    Log_OC.d("Thumbnail", "URI: " + uri);
-                                    GetMethod get = new GetMethod(uri);
-                                    status = mClient.executeMethod(get);
-                                    if (status == HttpStatus.SC_OK) {
-                                        byte[] bytes = get.getResponseBody();
-                                        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
-                                        thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
-
-                                        // Add thumbnail to cache
-                                        if (thumbnail != null) {
-                                            addBitmapToCache(imageKey, thumbnail);
-                                        }
-                                    }
-                                } catch (Exception e) {
-                                    e.printStackTrace();
-                                }
-                            } else {
-                                Log_OC.d(TAG, "Server too old");
-                            }
-                        }
-                    }
+                if (mFile instanceof OCFile) {
+                    thumbnail = doOCFileInBackground();
+                }  else if (mFile instanceof File) {
+                    thumbnail = doFileInBackground();
+                } else {
+                    // do nothing
                 }
-                
-            } catch (Throwable t) {
-                // the app should never break due to a problem with thumbnails
-                Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
-                if (t instanceof OutOfMemoryError) {
-                    System.gc();
+
+                }catch(Throwable t){
+                    // the app should never break due to a problem with thumbnails
+                    Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
+                    if (t instanceof OutOfMemoryError) {
+                        System.gc();
+                    }
                 }
-            }
-            
+
             return thumbnail;
         }
-        
+
         protected void onPostExecute(Bitmap bitmap){
             if (isCancelled()) {
                 bitmap = null;
@@ -280,47 +200,183 @@ public class ThumbnailsCacheManager {
 
             if (mImageViewReference != null && bitmap != null) {
                 final ImageView imageView = mImageViewReference.get();
-                final ThumbnailGenerationTask bitmapWorkerTask =
-                        getBitmapWorkerTask(imageView);
+                final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
                 if (this == bitmapWorkerTask && imageView != null) {
-                    if (imageView.getTag().equals(mFile.getFileId())) {
+                    String tagId = "";
+                    if (mFile instanceof OCFile){
+                        tagId = String.valueOf(((OCFile)mFile).getFileId());
+                    } else if (mFile instanceof File){
+                        tagId = String.valueOf(((File)mFile).hashCode());
+                    }
+                    if (String.valueOf(imageView.getTag()).equals(tagId)) {
                         imageView.setImageBitmap(bitmap);
                     }
                 }
             }
         }
+
+        /**
+         * Add thumbnail to cache
+         * @param imageKey: thumb key
+         * @param bitmap:   image for extracting thumbnail
+         * @param path:     image path
+         * @param px:       thumbnail dp
+         * @return Bitmap
+         */
+        private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){
+
+            Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
+
+            // Rotate image, obeying exif tag
+            thumbnail = BitmapUtils.rotateImage(thumbnail,path);
+
+            // Add thumbnail to cache
+            addBitmapToCache(imageKey, thumbnail);
+
+            return thumbnail;
+        }
+
+        /**
+         * Converts size of file icon from dp to pixel
+         * @return int
+         */
+        private int getThumbnailDimension(){
+            // Converts dp to pixel
+            Resources r = MainApp.getAppContext().getResources();
+            return (int) Math.round(r.getDimension(R.dimen.file_icon_size));
+        }
+
+        private Bitmap doOCFileInBackground() {
+            Bitmap thumbnail = null;
+            OCFile file = (OCFile)mFile;
+
+            final String imageKey = String.valueOf(file.getRemoteId());
+
+            // Check disk cache in background thread
+            thumbnail = getBitmapFromDiskCache(imageKey);
+
+            // Not found in disk cache
+            if (thumbnail == null || file.needsUpdateThumbnail()) {
+
+                int px = getThumbnailDimension();
+
+                if (file.isDown()) {
+                    Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
+                            file.getStoragePath(), px, px);
+
+                    if (bitmap != null) {
+                        thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px);
+
+                        file.setNeedsUpdateThumbnail(false);
+                        mStorageManager.saveFile(file);
+                    }
+
+                } else {
+                    // Download thumbnail from server
+                    if (mClient != null && mServerVersion != null) {
+                        OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion);
+                        if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) {
+                            try {
+                                int status = -1;
+
+                                String uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" +
+                                        px + "/" + px + Uri.encode(file.getRemotePath(), "/");
+                                Log_OC.d("Thumbnail", "URI: " + uri);
+                                GetMethod get = new GetMethod(uri);
+                                status = mClient.executeMethod(get);
+                                if (status == HttpStatus.SC_OK) {
+                                    byte[] bytes = get.getResponseBody();
+                                    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
+                                    thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
+
+                                    // Add thumbnail to cache
+                                    if (thumbnail != null) {
+                                        addBitmapToCache(imageKey, thumbnail);
+                                    }
+                                }
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        } else {
+                            Log_OC.d(TAG, "Server too old");
+                        }
+                    }
+                }
+            }
+
+            return thumbnail;
+
+        }
+
+        private Bitmap doFileInBackground() {
+            Bitmap thumbnail = null;
+            File file = (File)mFile;
+
+            final String imageKey = String.valueOf(file.hashCode());
+
+            // Check disk cache in background thread
+            thumbnail = getBitmapFromDiskCache(imageKey);
+
+            // Not found in disk cache
+            if (thumbnail == null) {
+
+                int px = getThumbnailDimension();
+
+                Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
+                        file.getAbsolutePath(), px, px);
+
+                if (bitmap != null) {
+                    thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px);
+                }
+            }
+            return thumbnail;
+        }
+
     }
-  
-    
+
+    public static boolean cancelPotentialWork(Object file, ImageView imageView) {
+        final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+
+        if (bitmapWorkerTask != null) {
+            final Object bitmapData = bitmapWorkerTask.mFile;
+            // If bitmapData is not yet set or it differs from the new data
+            if (bitmapData == null || bitmapData != file) {
+                // Cancel previous task
+                bitmapWorkerTask.cancel(true);
+            } else {
+                // The same work is already in progress
+                return false;
+            }
+        }
+        // No task associated with the ImageView, or an existing task was cancelled
+        return true;
+    }
+
+    public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
+        if (imageView != null) {
+            final Drawable drawable = imageView.getDrawable();
+            if (drawable instanceof AsyncDrawable) {
+                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
+                return asyncDrawable.getBitmapWorkerTask();
+            }
+        }
+        return null;
+    }
+
     public static class AsyncDrawable extends BitmapDrawable {
         private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
 
         public AsyncDrawable(
                 Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask
-            ) {
-            
+        ) {
+
             super(res, bitmap);
             bitmapWorkerTaskReference =
-                new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
+                    new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
         }
 
         public ThumbnailGenerationTask getBitmapWorkerTask() {
             return bitmapWorkerTaskReference.get();
         }
     }
-
-    
-    /**
-     * Remove from cache the remoteId passed
-     * @param fileRemoteId: remote id of mFile passed
-     */
-    public static void removeFileFromCache(String fileRemoteId){
-        synchronized (mThumbnailsDiskCacheLock) {
-            if (mThumbnailCache != null) {
-                mThumbnailCache.removeKey(fileRemoteId);
-            }
-            mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
-        }
-    }
-    
 }

+ 1 - 1
src/com/owncloud/android/operations/RenameFileOperation.java

@@ -158,7 +158,7 @@ public class RenameFileOperation extends SyncOperation {
      */
     private boolean isValidNewName() throws IOException {
         // check tricky names
-        if (mNewName == null || mNewName.length() <= 0 || mNewName.contains(File.separator) || mNewName.contains("%")) { 
+        if (mNewName == null || mNewName.length() <= 0 || mNewName.contains(File.separator)) {
             return false;
         }
         // create a test file

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

@@ -109,6 +109,7 @@ import com.owncloud.android.ui.preview.PreviewMediaFragment;
 import com.owncloud.android.ui.preview.PreviewVideoActivity;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ErrorMessageAdapter;
+import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.UriUtils;
 
 
@@ -519,7 +520,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener {
             
             // Read sorting order, default to sort by name ascending
             Integer sortOrder = appPreferences
-                    .getInt("sortOrder", FileListListAdapter.SORT_NAME);
+                    .getInt("sortOrder", FileStorageUtils.SORT_NAME);
             
             AlertDialog.Builder builder = new AlertDialog.Builder(this);
             builder.setTitle(R.string.actionbar_sort_title)

+ 33 - 143
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -17,7 +17,7 @@
  */
 package com.owncloud.android.ui.adapter;
 
-
+
 import java.io.File;
 import java.util.Collections;
 import java.util.Comparator;
@@ -44,14 +44,13 @@ import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncDrawable;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
 import com.owncloud.android.ui.activity.ComponentsGetter;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.FileStorageUtils;
-
+
 
 /**
  * This Adapter populates a ListView with all files and folders in an ownCloud
@@ -61,7 +60,7 @@ import com.owncloud.android.utils.FileStorageUtils;
  * @author Tobias Kaminsky
  * @author David A. Velasco
  */
-public class FileListListAdapter extends BaseAdapter implements ListAdapter {
+public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private final static String PERMISSION_SHARED_WITH_ME = "S";
     
     private Context mContext;
@@ -69,14 +68,10 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private Vector<OCFile> mFiles = null;
     private boolean mJustFolders;
 
-    private FileDataStorageManager mStorageManager;
-    private Account mAccount;
+    private FileDataStorageManager mStorageManager;
+    private Account mAccount;
     private ComponentsGetter mTransferServiceGetter;
-    private Integer mSortOrder;
-    public static final Integer SORT_NAME = 0;
-    public static final Integer SORT_DATE = 1;
-    public static final Integer SORT_SIZE = 2;
-    private Boolean mSortAscending;
+    
     private SharedPreferences mAppPreferences;
     
     public FileListListAdapter(
@@ -88,22 +83,22 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         mJustFolders = justFolders;
         mContext = context;
         mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
-
-        mTransferServiceGetter = transferServiceGetter;
+
+        mTransferServiceGetter = transferServiceGetter;
         
         mAppPreferences = PreferenceManager
                 .getDefaultSharedPreferences(mContext);
         
         // Read sorting order, default to sort by name ascending
-        mSortOrder = mAppPreferences
-                .getInt("sortOrder", 0);
-        mSortAscending = mAppPreferences.getBoolean("sortAscending", true);
+        FileStorageUtils.mSortOrder = mAppPreferences.getInt("sortOrder", 0);
+        FileStorageUtils.mSortAscending = mAppPreferences.getBoolean("sortAscending", true);
+
         
         // initialise thumbnails cache on background thread
         new ThumbnailsCacheManager.InitDiskCacheTask().execute();
 
     }
-    
+    
     @Override
     public boolean areAllItemsEnabled() {
         return true;
@@ -217,16 +212,18 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                     if (thumbnail != null && !file.needsUpdateThumbnail()){
                         fileIcon.setImageBitmap(thumbnail);
                     } else {
+
                         // generate new Thumbnail
                         if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
-                            final ThumbnailsCacheManager.ThumbnailGenerationTask task = 
+                            final ThumbnailsCacheManager.ThumbnailGenerationTask task =
                                     new ThumbnailsCacheManager.ThumbnailGenerationTask(
                                             fileIcon, mStorageManager, mAccount
                                     );
                             if (thumbnail == null) {
                                 thumbnail = ThumbnailsCacheManager.mDefaultImg;
                             }
-                            final AsyncDrawable asyncDrawable = new AsyncDrawable(
+                            final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =
+                                    new ThumbnailsCacheManager.AsyncDrawable(
                                     mContext.getResources(), 
                                     thumbnail, 
                                     task
@@ -236,11 +233,9 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                         }
                     }
                 } else {
-                    fileIcon.setImageResource(
-                            DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())
-                    );
+                    fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName()));
                 }
-
+
                 if (checkIfFileIsSharedWithMe(file)) {
                     sharedWithMeIconV.setVisibility(View.VISIBLE);
                 }
@@ -253,7 +248,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
 //                } else {
                     fileSizeV.setVisibility(View.INVISIBLE);
 //                }
-
+
                 lastModV.setVisibility(View.VISIBLE);
                 lastModV.setText(showRelativeTimestamp(file));
                 checkBoxV.setVisibility(View.GONE);
@@ -264,7 +259,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                     sharedWithMeIconV.setVisibility(View.VISIBLE);
                 } else {
                     fileIcon.setImageResource(
-                            DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())
+                            DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName())
                     );
                 }
 
@@ -284,7 +279,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
 
         return view;
     }
-
+
     /**
      * Local Folder size in human readable format
      * 
@@ -297,7 +292,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         File dir = new File(path);
 
         if (dir.exists()) {
-            long bytes = getFolderSize(dir);
+            long bytes = FileStorageUtils.getFolderSize(dir);
             return DisplayUtils.bytesToHumanReadable(bytes);
         }
 
@@ -323,8 +318,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
             return result;
         }
         return 0;
-    } 
-
+    } 
+
     @Override
     public int getViewTypeCount() {
         return 1;
@@ -362,29 +357,11 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
             mFiles = null;
         }
 
-        sortDirectory();
-    }
-    
-    /**
-     * Sorts all filenames, regarding last user decision 
-     */
-    private void sortDirectory(){
-        switch (mSortOrder){
-        case 0:
-            sortByName(mSortAscending);
-            break;
-        case 1:
-            sortByDate(mSortAscending);
-            break;
-        case 2: 
-            sortBySize(mSortAscending);
-            break;
-        }
-        
+        mFiles = FileStorageUtils.sortFolder(mFiles);
         notifyDataSetChanged();
     }
     
-    
+
     /**
      * Filter for getting only the folders
      * @param files
@@ -417,110 +394,23 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                 && file.getPermissions().contains(PERMISSION_SHARED_WITH_ME));
     }
 
-    /**
-     * Sorts list by Date
-     * @param sortAscending true: ascending, false: descending
-     */
-    private void sortByDate(boolean sortAscending){
-        final Integer val;
-        if (sortAscending){
-            val = 1;
-        } else {
-            val = -1;
-        }
-        
-        Collections.sort(mFiles, new Comparator<OCFile>() {
-            public int compare(OCFile o1, OCFile o2) {
-                if (o1.isFolder() && o2.isFolder()) {
-                    Long obj1 = o1.getModificationTimestamp();
-                    return val * obj1.compareTo(o2.getModificationTimestamp());
-                }
-                else if (o1.isFolder()) {
-                    return -1;
-                } else if (o2.isFolder()) {
-                    return 1;
-                } else if (o1.getModificationTimestamp() == 0 || o2.getModificationTimestamp() == 0){
-                    return 0;
-                } else {
-                    Long obj1 = o1.getModificationTimestamp();
-                    return val * obj1.compareTo(o2.getModificationTimestamp());
-                }
-            }
-        });
-    }
-
-    /**
-     * Sorts list by Size
-     * @param sortAscending true: ascending, false: descending
-     */
-    private void sortBySize(boolean sortAscending){
-        final Integer val;
-        if (sortAscending){
-            val = 1;
-        } else {
-            val = -1;
-        }
-        
-        Collections.sort(mFiles, new Comparator<OCFile>() {
-            public int compare(OCFile o1, OCFile o2) {
-                if (o1.isFolder() && o2.isFolder()) {
-                    Long obj1 = getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o1)));
-                    return val * obj1.compareTo(getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o2))));
-                }
-                else if (o1.isFolder()) {
-                    return -1;
-                } else if (o2.isFolder()) {
-                    return 1;
-                } else if (o1.getFileLength() == 0 || o2.getFileLength() == 0){
-                    return 0;
-                } else {
-                    Long obj1 = o1.getFileLength();
-                    return val * obj1.compareTo(o2.getFileLength());
-                }
-            }
-        });
-    }
-
-    /**
-     * Sorts list by Name
-     * @param sortAscending true: ascending, false: descending
-     */
-    private void sortByName(boolean sortAscending){
-        final Integer val;
-        if (sortAscending){
-            val = 1;
-        } else {
-            val = -1;
-        }
-
-        Collections.sort(mFiles, new Comparator<OCFile>() {
-            public int compare(OCFile o1, OCFile o2) {
-                if (o1.isFolder() && o2.isFolder()) {
-                    return val * o1.getRemotePath().toLowerCase().compareTo(o2.getRemotePath().toLowerCase());
-                } else if (o1.isFolder()) {
-                    return -1;
-                } else if (o2.isFolder()) {
-                    return 1;
-                }
-                return val * new AlphanumComparator().compare(o1, o2);
-            }
-        });
-    }
-
     public void setSortOrder(Integer order, boolean ascending) {
         SharedPreferences.Editor editor = mAppPreferences.edit();
         editor.putInt("sortOrder", order);
         editor.putBoolean("sortAscending", ascending);
         editor.commit();
         
-        mSortOrder = order;
-        mSortAscending = ascending;
+        FileStorageUtils.mSortOrder = order;
+        FileStorageUtils.mSortAscending = ascending;
         
-        sortDirectory();
+
+        mFiles = FileStorageUtils.sortFolder(mFiles);
+        notifyDataSetChanged();
+
     }    
     
     private CharSequence showRelativeTimestamp(OCFile file){
         return DisplayUtils.getRelativeDateTimeString(mContext, file.getModificationTimestamp(),
                 DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);
-    }
+    }
 }

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

@@ -22,6 +22,7 @@ import java.util.Arrays;
 import java.util.Comparator;
 
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -32,6 +33,8 @@ import android.widget.ListView;
 import android.widget.TextView;
 
 import com.owncloud.android.R;
+import com.owncloud.android.datamodel.ThumbnailsCacheManager;
+import com.owncloud.android.utils.BitmapUtils;
 import com.owncloud.android.utils.DisplayUtils;
 
 /**
@@ -46,7 +49,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
     private Context mContext;
     private File mDirectory;
     private File[] mFiles = null;
-
+    
     public LocalFileListAdapter(File directory, Context context) {
         mContext = context;
         swapDirectory(directory);
@@ -105,6 +108,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
             } else {
                 fileIcon.setImageResource(R.drawable.ic_menu_archive);
             }
+            fileIcon.setTag(file.hashCode());
 
             TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);
             TextView lastModV = (TextView) view.findViewById(R.id.last_mod);
@@ -125,6 +129,37 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
                     }
                     checkBoxV.setVisibility(View.VISIBLE);
                 }
+                
+             // get Thumbnail if file is image
+                if (BitmapUtils.isImage(file)){
+                // Thumbnail in Cache?
+                    Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
+                            String.valueOf(file.hashCode())
+                    );
+                    if (thumbnail != null){
+                        fileIcon.setImageBitmap(thumbnail);
+                    } else {
+
+                        // generate new Thumbnail
+                        if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
+                            final ThumbnailsCacheManager.ThumbnailGenerationTask task =
+                                    new ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon);
+                            if (thumbnail == null) {
+                                thumbnail = ThumbnailsCacheManager.mDefaultImg;
+                            }
+                            final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =
+                        		new ThumbnailsCacheManager.AsyncDrawable(
+                                    mContext.getResources(), 
+                                    thumbnail, 
+                                    task
+                		        );
+                            fileIcon.setImageDrawable(asyncDrawable);
+                            task.execute(file);
+                        }
+                    }
+                } else {
+                    fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(null, file.getName()));
+                }  
 
             } else {
                 fileSizeV.setVisibility(View.GONE);
@@ -132,7 +167,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
                 checkBoxV.setVisibility(View.GONE);
             }
             
-            view.findViewById(R.id.imageView2).setVisibility(View.INVISIBLE);   // not GONE; the alignment changes; ugly way to keep it
+            view.findViewById(R.id.imageView2).setVisibility(View.INVISIBLE);   // not GONE; the alignment would change
             view.findViewById(R.id.imageView3).setVisibility(View.GONE);
             
             view.findViewById(R.id.sharedIcon).setVisibility(View.GONE);

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

@@ -396,7 +396,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
         }
         ImageView iv = (ImageView) getView().findViewById(R.id.fdIcon);
         if (iv != null) {
-            iv.setImageResource(DisplayUtils.getResourceId(mimetype, filename));
+            iv.setImageResource(DisplayUtils.getFileTypeIconId(mimetype, filename));
         }
     }
 

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

@@ -48,6 +48,7 @@ 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.FileStorageUtils;
 
 /**
  * A Fragment that lists all files and folders in a given path.
@@ -437,15 +438,15 @@ public class OCFileListFragment extends ExtendedListFragment {
     }
     
     public void sortByName(boolean descending) {
-        mAdapter.setSortOrder(FileListListAdapter.SORT_NAME, descending);
+        mAdapter.setSortOrder(FileStorageUtils.SORT_NAME, descending);
     }
 
     public void sortByDate(boolean descending) {
-        mAdapter.setSortOrder(FileListListAdapter.SORT_DATE, descending);
+        mAdapter.setSortOrder(FileStorageUtils.SORT_DATE, descending);
     }
 
     public void sortBySize(boolean descending) {
-        mAdapter.setSortOrder(FileListListAdapter.SORT_SIZE, descending);
+        mAdapter.setSortOrder(FileStorageUtils.SORT_SIZE, descending);
     }  
 
 }

+ 7 - 1
src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java

@@ -16,6 +16,8 @@
  */
 package com.owncloud.android.ui.preview;
 
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -31,7 +33,9 @@ import android.view.ViewGroup;
 
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.ui.adapter.FileListListAdapter;
 import com.owncloud.android.ui.fragment.FileFragment;
+import com.owncloud.android.utils.FileStorageUtils;
 
 /**
  * Adapter class that provides Fragment instances  
@@ -73,13 +77,15 @@ public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
         mAccount = account;
         mStorageManager = storageManager;
         mImageFiles = mStorageManager.getFolderImages(parentFolder); 
+        
+        mImageFiles = FileStorageUtils.sortFolder(mImageFiles);
+        
         mObsoleteFragments = new HashSet<Object>();
         mObsoletePositions = new HashSet<Integer>();
         mDownloadErrors = new HashSet<Integer>();
         //mFragmentManager = fragmentManager;
         mCachedFragments = new HashMap<Integer, FileFragment>();
     }
-
     
     /**
      * Returns the image files handled by the adapter.

+ 17 - 1
src/com/owncloud/android/utils/BitmapUtils.java

@@ -23,6 +23,10 @@ import android.graphics.BitmapFactory;
 import android.graphics.Matrix;
 import android.graphics.BitmapFactory.Options;
 import android.media.ExifInterface;
+import android.net.Uri;
+import android.webkit.MimeTypeMap;
+
+import java.io.File;
 
 /**
  * Utility class with methods for decoding Bitmaps.
@@ -169,6 +173,18 @@ public class BitmapUtils {
         }
         return resultBitmap;
     }
-    
+
+    /**
+     * Checks if file passed is an image
+     * @param file
+     * @return true/false
+     */
+    public static boolean isImage(File file) {
+        Uri selectedUri = Uri.fromFile(file);
+        String fileExtension = MimeTypeMap.getFileExtensionFromUrl(selectedUri.toString().toLowerCase());
+        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
+
+        return (mimeType != null && mimeType.startsWith("image/"));
+    }
     
 }

+ 61 - 54
src/com/owncloud/android/utils/DisplayUtils.java

@@ -19,6 +19,7 @@
 package com.owncloud.android.utils;
 
 import java.net.IDN;
+import java.text.DateFormat;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
@@ -30,6 +31,7 @@ import android.annotation.TargetApi;
 import android.content.Context;
 import android.os.Build;
 import android.text.format.DateUtils;
+import android.webkit.MimeTypeMap;
 
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
@@ -73,21 +75,28 @@ public class DisplayUtils {
     private static final String TYPE_VIDEO = "video";
     
     private static final String SUBTYPE_PDF = "pdf";
-    private static final String[] SUBTYPES_DOCUMENT = { "msword",
-                                                        "vnd.openxmlformats-officedocument.wordprocessingml.document",
-                                                        "vnd.oasis.opendocument.text",
-                                                        "rtf"
-                                                        };
+    private static final String SUBTYPE_XML = "xml";
+    private static final String[] SUBTYPES_DOCUMENT = { 
+        "msword",
+        "vnd.openxmlformats-officedocument.wordprocessingml.document",
+        "vnd.oasis.opendocument.text",
+        "rtf",
+        "javascript"
+    };
     private static Set<String> SUBTYPES_DOCUMENT_SET = new HashSet<String>(Arrays.asList(SUBTYPES_DOCUMENT));
-    private static final String[] SUBTYPES_SPREADSHEET = { "msexcel",
-                                                           "vnd.openxmlformats-officedocument.spreadsheetml.sheet",
-                                                           "vnd.oasis.opendocument.spreadsheet"
-                                                           };
+    private static final String[] SUBTYPES_SPREADSHEET = {
+        "msexcel",
+        "vnd.ms-excel",
+        "vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+        "vnd.oasis.opendocument.spreadsheet"
+    };
     private static Set<String> SUBTYPES_SPREADSHEET_SET = new HashSet<String>(Arrays.asList(SUBTYPES_SPREADSHEET));
-    private static final String[] SUBTYPES_PRESENTATION = { "mspowerpoint",
-                                                            "vnd.openxmlformats-officedocument.presentationml.presentation",
-                                                            "vnd.oasis.opendocument.presentation"
-                                                            };
+    private static final String[] SUBTYPES_PRESENTATION = { 
+        "mspowerpoint",
+        "vnd.ms-powerpoint",
+        "vnd.openxmlformats-officedocument.presentationml.presentation",
+        "vnd.oasis.opendocument.presentation"
+    };
     private static Set<String> SUBTYPES_PRESENTATION_SET = new HashSet<String>(Arrays.asList(SUBTYPES_PRESENTATION));
     private static final String[] SUBTYPES_COMPRESSED = {"x-tar", "x-gzip", "zip"};
     private static final Set<String> SUBTYPES_COMPRESSED_SET = new HashSet<String>(Arrays.asList(SUBTYPES_COMPRESSED));
@@ -95,6 +104,8 @@ public class DisplayUtils {
     private static final String EXTENSION_RAR = "rar";
     private static final String EXTENSION_RTF = "rtf";
     private static final String EXTENSION_3GP = "3gp";
+    private static final String EXTENSION_PY = "py";
+    private static final String EXTENSION_JS = "js";
     
     /**
      * Converts the file size in bytes to human readable output.
@@ -113,30 +124,6 @@ public class DisplayUtils {
         return result + " " + sizeSuffixes[attachedsuff];
     }
 
-    /**
-     * Removes special HTML entities from a string
-     * 
-     * @param s Input string
-     * @return A cleaned version of the string
-     */
-    public static String HtmlDecode(String s) {
-        /*
-         * TODO: Perhaps we should use something more proven like:
-         * http://commons.apache.org/lang/api-2.6/org/apache/commons/lang/StringEscapeUtils.html#unescapeHtml%28java.lang.String%29
-         */
-
-        String ret = "";
-        for (int i = 0; i < s.length(); ++i) {
-            if (s.charAt(i) == '%') {
-                ret += (char) Integer.parseInt(s.substring(i + 1, i + 3), 16);
-                i += 2;
-            } else {
-                ret += s.charAt(i);
-            }
-        }
-        return ret;
-    }
-
     /**
      * Converts MIME types like "image/jpg" to more end user friendly output
      * like "JPG image".
@@ -155,18 +142,25 @@ public class DisplayUtils {
     
     
     /**
-     * Returns the resource identifier of an image resource to use as icon associated to a 
-     * known MIME type.
+     * Returns the resource identifier of an image to use as icon associated to a known MIME type.
      * 
-     * @param mimetype      MIME type string.
-     * @param filename      name, with extension
-     * @return              Resource identifier of an image resource.
+     * @param mimetype      MIME type string; if NULL, the method tries to guess it from the extension in filename
+     * @param filename      Name, with extension.
+     * @return              Identifier of an image resource.
      */
-    public static int getResourceId(String mimetype, String filename) {
+    public static int getFileTypeIconId(String mimetype, String filename) {
 
-        if (mimetype == null || "DIR".equals(mimetype)) {
-            return R.drawable.ic_menu_archive;
+        if (mimetype == null) {
+            String fileExtension = getExtension(filename);
+            mimetype = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
+            if (mimetype == null) {
+                mimetype = TYPE_APPLICATION + "/" + SUBTYPE_OCTET_STREAM;
+            }
+        } 
             
+        if ("DIR".equals(mimetype)) {
+            return R.drawable.ic_menu_archive;
+
         } else {
             String [] parts = mimetype.split("/");
             String type = parts[0];
@@ -189,6 +183,9 @@ public class DisplayUtils {
                 if (SUBTYPE_PDF.equals(subtype)) {
                     return R.drawable.file_pdf;
                     
+                } else if (SUBTYPE_XML.equals(subtype)) {
+                    return R.drawable.file_doc;
+
                 } else if (SUBTYPES_DOCUMENT_SET.contains(subtype)) {
                     return R.drawable.file_doc;
 
@@ -200,7 +197,7 @@ public class DisplayUtils {
 
                 } else if (SUBTYPES_COMPRESSED_SET.contains(subtype)) {
                     return R.drawable.file_zip;
-                    
+
                 } else if (SUBTYPE_OCTET_STREAM.equals(subtype) ) {
                     if (getExtension(filename).equalsIgnoreCase(EXTENSION_RAR)) {
                         return R.drawable.file_zip;
@@ -210,7 +207,10 @@ public class DisplayUtils {
                         
                     } else if (getExtension(filename).equalsIgnoreCase(EXTENSION_3GP)) {
                         return R.drawable.file_movie;
-                        
+                     
+                    } else if ( getExtension(filename).equalsIgnoreCase(EXTENSION_PY) ||
+                                getExtension(filename).equalsIgnoreCase(EXTENSION_JS)) {
+                        return R.drawable.file_doc;
                     } 
                 } 
             }
@@ -222,8 +222,7 @@ public class DisplayUtils {
 
     
     private static String getExtension(String filename) {
-        String extension = filename.substring(filename.lastIndexOf(".") + 1);
-        
+        String extension = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
         return extension;
     }
     
@@ -234,7 +233,8 @@ public class DisplayUtils {
      */
     public static String unixTimeToHumanReadable(long milliseconds) {
         Date date = new Date(milliseconds);
-        return date.toLocaleString();
+        DateFormat df = DateFormat.getDateTimeInstance();
+        return df.format(date);
     }
     
     
@@ -295,7 +295,11 @@ public class DisplayUtils {
         return fileExtension;
     }
 
-    public static CharSequence getRelativeDateTimeString(Context c, long time, long minResolution, long transitionResolution, int flags){
+    @SuppressWarnings("deprecation")
+    public static CharSequence getRelativeDateTimeString (
+            Context c, long time, long minResolution, long transitionResolution, int flags
+            ){
+        
         CharSequence dateString = "";
         
         // in Future
@@ -307,18 +311,21 @@ public class DisplayUtils {
             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){
+            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);
+                dateString = DateUtils.getRelativeDateTimeString(
+                        c, date.getTime(), minResolution, transitionResolution, flags
+                );
             } else {
                 dateString = DateUtils.getRelativeDateTimeString(c, time, minResolution, transitionResolution, flags);
             }
         }
         
-        return dateString.toString().split(",")[0];
+        return dateString.toString().split(",")[0];
     }
 
     /**

+ 148 - 0
src/com/owncloud/android/utils/FileStorageUtils.java

@@ -18,6 +18,11 @@
 package com.owncloud.android.utils;
 
 import java.io.File;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Vector;
+
+import third_parties.daveKoeller.AlphanumComparator;
 
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
@@ -39,6 +44,13 @@ import android.os.StatFs;
  * @author David A. Velasco
  */
 public class FileStorageUtils {
+    public static Integer mSortOrder;
+    public static Boolean mSortAscending;
+    public static final Integer SORT_NAME = 0;
+    public static final Integer SORT_DATE = 1;
+    public static final Integer SORT_SIZE = 2;
+  
+    
     //private static final String LOG_TAG = "FileStorageUtils";
 
     public static final String getSavePath(String accountName) {
@@ -137,5 +149,141 @@ public class FileStorageUtils {
         file.setRemoteId(ocFile.getRemoteId());
         return file;
     }
+    
+    /**
+     * Sorts all filenames, regarding last user decision 
+     */
+    public static Vector<OCFile> sortFolder(Vector<OCFile> files){
+        switch (mSortOrder){
+        case 0:
+            files = FileStorageUtils.sortByName(files);
+            break;
+        case 1:
+            files = FileStorageUtils.sortByDate(files);
+            break;
+        case 2: 
+           // mFiles = FileStorageUtils.sortBySize(mSortAscending);
+            break;
+        }
+       
+        return files;
+    }
+    
+    /**
+     * Sorts list by Date
+     * @param sortAscending true: ascending, false: descending
+     */
+    public static Vector<OCFile> sortByDate(Vector<OCFile> files){
+        final Integer val;
+        if (mSortAscending){
+            val = 1;
+        } else {
+            val = -1;
+        }
+        
+        Collections.sort(files, new Comparator<OCFile>() {
+            public int compare(OCFile o1, OCFile o2) {
+                if (o1.isFolder() && o2.isFolder()) {
+                    Long obj1 = o1.getModificationTimestamp();
+                    return val * obj1.compareTo(o2.getModificationTimestamp());
+                }
+                else if (o1.isFolder()) {
+                    return -1;
+                } else if (o2.isFolder()) {
+                    return 1;
+                } else if (o1.getModificationTimestamp() == 0 || o2.getModificationTimestamp() == 0){
+                    return 0;
+                } else {
+                    Long obj1 = o1.getModificationTimestamp();
+                    return val * obj1.compareTo(o2.getModificationTimestamp());
+                }
+            }
+        });
+        
+        return files;
+    }
+
+//    /**
+//     * Sorts list by Size
+//     * @param sortAscending true: ascending, false: descending
+//     */
+//    public static Vector<OCFile> sortBySize(Vector<OCFile> files){
+//        final Integer val;
+//        if (mSortAscending){
+//            val = 1;
+//        } else {
+//            val = -1;
+//        }
+//        
+//        Collections.sort(files, new Comparator<OCFile>() {
+//            public int compare(OCFile o1, OCFile o2) {
+//                if (o1.isFolder() && o2.isFolder()) {
+//                    Long obj1 = getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o1)));
+//                    return val * obj1.compareTo(getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o2))));
+//                }
+//                else if (o1.isFolder()) {
+//                    return -1;
+//                } else if (o2.isFolder()) {
+//                    return 1;
+//                } else if (o1.getFileLength() == 0 || o2.getFileLength() == 0){
+//                    return 0;
+//                } else {
+//                    Long obj1 = o1.getFileLength();
+//                    return val * obj1.compareTo(o2.getFileLength());
+//                }
+//            }
+//        });
+//        
+//        return files;
+//    }
+
+    /**
+     * Sorts list by Name
+     * @param sortAscending true: ascending, false: descending
+     */
+    public static Vector<OCFile> sortByName(Vector<OCFile> files){
+        final Integer val;
+        if (mSortAscending){
+            val = 1;
+        } else {
+            val = -1;
+        }
+
+        Collections.sort(files, new Comparator<OCFile>() {
+            public int compare(OCFile o1, OCFile o2) {
+                if (o1.isFolder() && o2.isFolder()) {
+                    return val * o1.getRemotePath().toLowerCase().compareTo(o2.getRemotePath().toLowerCase());
+                } else if (o1.isFolder()) {
+                    return -1;
+                } else if (o2.isFolder()) {
+                    return 1;
+                }
+                return val * new AlphanumComparator().compare(o1, o2);
+            }
+        });
+        
+        return files;
+    }
+    
+    /**
+     * Local Folder size
+     * @param dir File
+     * @return Size in bytes
+     */
+    public static 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;
+    } 
   
 }