From: jabarros Date: Mon, 19 Jan 2015 11:49:28 +0000 (+0100) Subject: Merge branch 'develop' into download_folder X-Git-Tag: oc-android-1.7.0_signed~23^2~11 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/e98fc8b141fed66cbdd265aaebd2cfa3affb68ac?hp=2275f2eca4a223618194bf4f6b5b41f50d4b1d36 Merge branch 'develop' into download_folder --- diff --git a/build.gradle b/build.gradle index 46308aca..57ec86e5 100644 --- a/build.gradle +++ b/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' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8d63f892..ae8d5b24 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/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 diff --git a/owncloud-android-library b/owncloud-android-library index 8261865f..e87f5f25 160000 --- a/owncloud-android-library +++ b/owncloud-android-library @@ -1 +1 @@ -Subproject commit 8261865ff24c1bfc05be19ae9364a66dac8f26c3 +Subproject commit e87f5f25ad91950d47ec9b6fa01401360cd7ec8d diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index c365dff9..0a1006de 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -14,7 +14,7 @@ Ταξινόμηση Ταξινόμηση κατά - A-Z + A-Ω Νεότερο - Παλαιότερο 일반 - 더 중요함 + 더 보기 계정 계정 관리 앱 암호 내 클라이언트 보호 - 로깅 허용 - 이건 로그 문제에 사용됩니다 + 사진 즉시 업로드 + 카메라로 찍은 사진 즉시 업로드 + 동영상 즉시 업로드 + 카메라로 찍은 동영상 즉시 업로드 + 로그 기록 사용 + 문제점을 기록하는 데 사용됩니다 로그 기록 여기서 기록된 로그를 보여줍니다 - 역사 삭제하기 + 과거 기록 삭제 도움말 - 친구들에게 권하기 + 친구에게 추천하기 피드백 - 임프린트 - %1$s 을 스마트폰에서 사용해보세요! + 법적 고지 + 공유 위치 기억하기 + 마지막 공유 업로드 위치 기억하기 + %1$s을(를) 스마트폰에서 사용해 보세요! + %1$s을(를) 스마트폰에서 사용해 보는 것을 추천합니다!\n다운로드 링크: %2$s 서버 확인 서버 주소 https://… 사용자 이름 @@ -37,6 +50,7 @@ 파일 접속 업로드 + 업로드 폴더 선택: 계정 없음 이 장치에 %1$s 계정이 없습니다. 먼저 계정을 설정하십시오. 설정 @@ -45,8 +59,10 @@ 받은 콘텐츠가 없습니다. 업로드할 항목이 없습니다. %1$s에서 공유된 콘텐츠에 접근할 수 없습니다 업로드 중 - 초 전 + 초 지남 내용이 없습니다. 업로드할 수 있습니다! + 불러오는 중... + 이 폴더에 파일이 없습니다. 폴더 폴더 파일 @@ -57,9 +73,10 @@ 만든 날짜: 수정한 날짜: 다운로드 - 파일 새로고침 + 파일 새로 고침 업로드 중 파일 이름을 %1$s(으)로 변경하였습니다 링크 공유 + 링크 공유 해제 예 아니요 확인 @@ -69,7 +86,7 @@ 저장하고 끝내기 오류 불러오는 중... - 알수없는 오류 + 알 수 없는 오류 정보 암호 변경 계정 삭제 @@ -81,29 +98,35 @@ 업로드 성공 %1$s을(를) 업로드하였습니다 업로드 실패 - %1$s을(를) 업로드할 수 없었습니다 + %1$s을(를) 업로드할 수 없습니다 + 업로드가 실패하였습니다. 다시 로그인하십시오 다운로드 중... %1$d%% %2$s 다운로드 중 다운로드 성공 %1$s을(를) 다운로드하였습니다 다운로드 실패 - %1$s을(를) 다운로드할 수 없었습니다 + %1$s을(를) 다운로드할 수 없습니다 아직 다운로드 되지 않았습니다 + 다운로드가 실패하였습니다. 다시 로그인하십시오 계정 선택 동기화 실패 + 동기화가 실패하였습니다. 다시 로그인하십시오 %1$s와(과) 동기화할 수 없었습니다 - %1$s에 대한 비밀번호가 틀립니다 + %1$s의 암호가 올바르지 않습니다 충돌하는 항목 발견됨 - 동기화된 파일 중 %1$d개를 동기화할 수 없었습니다 + 동기화된 파일 중 %1$d개를 동기화할 수 없습니다 파일을 동기화할 수 없었습니다 - 파일 %1$d개의 내용을 동기화할 수 없었습니다 (충돌 %2$d개) - 몇몇 로컬 파일이 사라졌습니다. - %1$s 폴더가 존재하지 않습니다. - 모두 옮김 - 모든 파일 옮김 - 몇몇 파일을 옮기지 못했습니다. + 파일 %1$d개의 내용을 동기화할 수 없습니다 (충돌 %2$d개) + 일부 로컬 파일이 사라졌습니다. + 폴더 %2$s의 파일 중 %1$d개를 복사할 수 없습니다 + 버전 1.3.16부터는 하나의 파일이 여러 계정과 동기화될 때 데이터 손실을 막기 위해서 이 장치에서 업로드된 파일은 로컬 폴더 %1$s(으)로 복사됩니다.\n\n이 변경 사항 때문에 이 앱의 이전 버전에서 업로드된 모든 파일은 폴더 %2$s(으)로 복사되었습니다. 계정 동기화 중 오류가 발생하여 이 작업이 중단되었습니다. 파일을 그대로 둔 다음 %3$s(으)로 향한 링크를 삭제하거나, 파일을 직접 폴더 %1$s(으)로 이동한 다음 %4$s(으)로 향한 링크를 그대로 두십시오.\n\n아래 목록은 로컬 파일과 링크가 걸려 있는 %5$s에 있는 원격 파일입니다. + 폴더 %1$s이(가) 더 이상 존재하지 않습니다. + 모두 이동 + 모든 파일 이동됨 + 몇몇 파일을 이동할 수 없음 로컬: %1$s 원격: %1$s + 선택한 파일을 폴더 %1$s(으)로 복사할 공간이 부족합니다. 파일을 이동하시겠습니까? 앱 암호를 입력하십시오 앱 암호를 입력하십시오 앱을 시작할 때마다 암호를 물어봅니다 @@ -114,79 +137,88 @@ 앱 암호가 삭제되었습니다 앱 암호가 저장되었습니다 %1$s 음악 재생기 - %1$s (재생중) + %1$s (재생 중) %1$s (불러오는 중) %1$s 재생 완료됨 - 미디어 파일을 찾을수 없습니다 + 미디어 파일을 찾을 수 음 준비된 계정이 없습니다 유효한 계정의 파일이 아닙니다 지원하지 않는 미디어 코덱 - 미디어 파일을 읽을수 + 미디어 파일을 읽을 수 없음 미디어 파일이 제대로 인코드 되지 않았습니다 재생 시도 중 시간이 초과됨 - 미디어 파일을 스트리밍 할수 없습니다 - 내장된 미디어 플레이어에서는 이 미디어 파일을 재생할수 없습니다 - %1$s 를 재생하는 중에 보안오류가 발생함 - %1$s 를 재생하는 중에 입력 에러가 발생함 - %1$s 를 재생하던 중에 알수 없는 오류가 발생함 - 되감기 버튼 - 재생 혹은 일시정지 버튼 - 빨리감기 버튼 - 로그인 중... + 미디어 파일을 스트리밍 할 수 없습니다 + 내장된 미디어 플레이어에서 이 미디어 파일을 재생할 수 없습니다 + %1$s을(를) 재생하는 중 보안 오류가 발생함 + %1$s을(를) 재생하는 중 입력 오류가 발생함 + %1$s을(를) 재생하는 중 알 수 없는 오류가 발생함 + 되감기 단추 + 재생 혹은 일시 정지 단추 + 빨리감기 단추 + 인증 정보 가져오는 중... + 로그인 시도 중... 네트워크에 연결할 수 없습니다 암호화된 연결을 사용할 수 없습니다. 연결됨 연결 테스트 중... 서버 설정이 잘못됨 같은 사용자와 서버에 대한 계정이 이미 존재합니다 - 입력된 사용자가 이 계정의 사용자와 일치하지 않음 + 입력된 사용자가 이 계정의 사용자와 일치하지 않습니다 알 수 없는 오류가 발생하였습니다! 호스트를 찾을 수 없음 서버 인스턴스를 찾을 수 없음 - 서버 응답 시간이 초과되었습니다 + 서버 응답 시간이 초과됨 잘못된 URL SSL 초기화 오류 SSL 서버의 신원을 확인할수 없습니다 확인할 수 없는 서버 버전 연결을 수립할 수 없음 암호화된 연결 사용 중 - 잘못된 로그인/암호 - 권한부여가 성공적으로 이뤄지지 않았습니다 - 권한 서버로 부터 접근이 거부되었습니다 - 뜻밖의 상태; 다시 서버 주소를 입력해주십시오 - 인증이 만료되었습니다. 다시 인증해주세요 - 현재 암호를 - 세션이 만료되었습니다. 다시 접속해주세요 - 인증 서버에 접속하는 중... + 잘못된 사용자 이름 및 암호 + 인증 실패 + 인증 서버 접근 거부됨 + 예상하지 못한 상태입니다. 서버 URL을 다시 입력해 주십시오 + 인증이 만료되었습니다. 다시 인증해 주십시오 + 현재 암호를 입력해 주십시오 + 세션이 만료되었습니다. 다시 접속해 주십시오 + 인증 서버에 연결하는 중... 서버에서 이 인증 방법을 지원하지 않습니다. - %1$s 에서는 다중 계정을 지원하지 않습니다 + %1$s에서 다중 계정을 지원하지 않습니다 + 서버에서 올바른 사용자 ID를 반환하지 않았습니다. 관리자에게 연락하십시오 + + 이 서버에 인증할 수 없음 파일을 최신 정보로 유지 이름 바꾸기 삭제 + %1$s을(를) 삭제하시겠습니까? + %1$s 및 포함된 내용을 삭제하시겠습니까? 로컬만 로컬 콘텐츠만 서버에서 삭제 서버와 로컬 모두 - 성공적으로 삭제하였습니다 - 삭제할 수 없었습니다 + 성공적으로 삭제함 + 삭제할 수 없음 새 이름 입력 로컬 파일의 이름을 변경할 수 없습니다. 다른 이름을 입력하십시오 - 이름을 변경할 수 없었습니다 - 원격 파일을 확인할 수 없었습니다 - 파일 내용이 이미 동기화되었습니다 - 사용할수 없는 문자들: / \\ < > : \" | ? * + 이름을 변경할 수 없음 + 원격 파일을 확인할 수 없음 + 파일 내용이 이미 동기화됨 + 폴더를 만들 수 없음 + 사용할 수 없는 문자: / \\ < > : \" | ? * + 파일 이름이 비어 있을 수 없음 잠시 기다려 주십시오 예상하지 못한 오류입니다. 다른 앱에서 파일을 선택하십시오 선택한 파일 없음 + 다음으로 링크 보내기... oAuth2로 로그인하기 - oAuth2 서버에 연결중... - 사이트 인증서를 확인할 수 없었습니다 + oAuth2 서버에 연결 중... + 사이트 인증서를 확인할 수 없습니다 - 서버 인증서를 신뢰할 수 없습니다 - 서버 인증서가 만료되었습니다 - 서버 인증서의 유효 기간이 시작되지 않았습니다 - 인증서의 URL과 입력한 URL이 일치하지 않습니다 이 인증서를 신뢰하시겠습니까? - 인증서를 저장할 수 없었습니다 + 인증서를 저장할 수 없습니다 자세히 숨기기 발급 대상: @@ -202,28 +234,70 @@ 끝: 서명: 알고리즘: - 이것은 플레이스홀더입니다 + 인증서를 표시할 수 없습니다. + - 오류에 대한 정보가 없습니다 + 이것은 자리 비움자입니다 placeholder.txt PNG 그림 389 KB 2012/05/18 12:23 PM 12:23:45 - WiFi 사용 중일때만 사진 업로드 + Wi-Fi 사용 중일때만 사진 업로드 + Wi-Fi 사용 중일때만 동영상 업로드 /InstantUpload 업데이트 충돌 원격 파일 %s이(가) 로컬 파일과 동기화되지 않았습니다. 계속 진행하면 서버에 있는 파일을 덮어씁니다. 모두 저장 덮어쓰기 업로드하지 않음 - 그림 미리보기 + 사진 미리 보기 + 이 사진을 미리 볼 수 없습니다 + %1$s을(를) 로컬 폴더 %2$s(으)로 복사할 수 없습니다 + 업로드 경로 + 서버에서 공유가 비활성화되어 있습니다. 관리자에게 연락하십시오. + 공유할 수 없습니다. 파일이 있는지 확인하십시오 + 이 파일이나 폴더를 공유하는 중 오류 발생 + 공유를 해제할 수 없습니다. 파일이 있는지 확인하십시오 + 이 파일이나 폴더의 공유를 해제하는 중 오류 발생 보내기 - 링크 복사 + 링크 주소 복사 클립보드로 복사됨 + 치명적 오류: 작업을 진행할 수 없음 + 서버에 연결하는 중 오류가 발생하였습니다. + 서버를 기다리는 중 오류가 발생하였습니다. 작업이 진행되지 않았을 수도 있습니다 + 서버를 기다리는 중 오류가 발생하였습니다. 작업이 진행되지 않았을 수도 있습니다 + 서버를 사용할 수 없어서 작업을 진행할 수 없습니다 + %s 권한이 없습니다 + 이 파일의 이름을 바꿀 + 이 파일을 삭제할 + 이 파일을 공유할 + 이 파일의 공유를 해제할 + 파일을 생성할 + 이 폴더에 업로드할 + 이 파일을 서버에서 더 이상 사용할 수 없습니다 계정 + 계정 추가 + 보안 연결이 안전하지 않은 경로로 넘어갑니다. + 로그 + 과거 기록 보내기 + 로그를 보낼 앱이 없습니다. 메일 앱을 설치하십시오! + %1$s Android 앱 로그 + 데이터 불러오는 중... 인증 필요함 잘못된 암호 + 이동 + 항목이 없습니다. 폴더를 추가할 수 있습니다! 선택 + 이동할 수 없습니다. 파일이 존재하는 지 확인하십시오 + 폴더를 하위 폴더 아래로 이동할 수 없습니다 + 파일이 이미 대상 폴더에 존재합니다 + 이 파일이나 폴더를 이동하는 중 오류가 발생하였습니다 + 이 파일을 이동할 + 즉시 업로드 보안 + 동영상 업로드 경로 공유됨 + 나와 + %1$s %2$s >>%3$s<< %4$s diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 9a37c42f..efadb601 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -41,7 +41,7 @@ Lembrar localização de partilha Lembrar da última localização de envio de partilha Test %1$s no seu smartphone! - Quero convidar-te a usares %1$s no teu smartphone!\nFaz download aqui: %2$s + Eu quero convidar-te para usares %1$s no teu smartphone!\nTransfere aqui: %2$s Verificar Servidor Endereço do servidor https://.. Nome de Utilizador @@ -52,7 +52,7 @@ Enviar Escolha a pasta de envio: A conta não foi encontrada - Não tem nenhuma conta %1$s no seu dispositivo. Por favor, configure primeiro uma conta. + Não existe nenhuma conta %1$s no seu dispositivo. Por favor, configure primeiro uma conta. Configurar Sair Sem conteúdo para enviar @@ -76,7 +76,7 @@ Atualizar ficheiro O ficheiro foi renomeado para %1$s durante o envio. Partilhar a hiperligação - Deixar de partilhar a ligação + Deixar de partilhar a hiperligação Sim Não ACEITAR @@ -98,14 +98,14 @@ Envio bem sucedido %1$s foi enviado com sucesso Não foi possível enviar - O envio do ficheiro %1$s não foi concluído. + Não foi possível concluir o envio de %1$s. Falha no carregamento, é necessário fazer novo login - A transferir ... + A transferir... %1$d%% A transferir %2$s Transferência bem sucedida - %1$s foi descarregado com sucesso - Descarga falhou - O descarregamento %1$s não foi possível descarregar + %1$s foi transferido com sucesso + Transferência falhada + Não foi possível concluir a transferência de %1$s Ainda não foi transferido Não foi possível transferir, tem de iniciar a sessão novamente Escolha a conta @@ -132,10 +132,10 @@ O PIN será pedido sempre que a app seja iniciada. Por favor, reinsira o PIN da App Remover o seu PIN da App - Os códigos PIN introduzidos não são iguais. - Código PIN Incorrecto. - PIN da aplicação removido - PIN da aplicação guardado + Os CÓDIGOS da APP não são iguais + CÓDIGO da App Incorreto + CÓDIGOS da App removido + CÓDIGO da App guardado %1$s leitor de música %1$s (a reproduzir) %1$s (a carregar) @@ -143,8 +143,8 @@ Não foi encontrado nenhum ficheiro de média Não foi fornecida conta O ficheiro não está numa conta válida - Codec de média não suportado - Não foi possível reproduzir o ficheiro + Codec de multimédia não suportado + Não foi possível ler o ficheiro de multimédia Ficheiro erradamente codificado (codec) O tempo de espera para jogar expirou O ficheiro não pode ser reproduzido (streaming) @@ -152,25 +152,25 @@ Erro de segurança a tentar reproduzir o ficheiro %1$s Erro de input a tentar reproduzir %1$s Erro inesperado a tentar reproduzir %1$s - Botão de rebobinar - Botão Tocar/Pausa + Botão de Retroceder + Botão de Reproduzir/Pausar Botão de avanço rápido A obter autorização... - A tentar entrar... + A tentar iniciar a sessão... Sem ligação à rede - Ligação segura indisponível + Ligação segura indisponível. Ligação estabelecida A testar a ligação... Configuração do servidor incorrecta. Uma conta para este utilizador e servidor já existe no dispositivo O utilizador que escreveu não coincide com o nome de utilizador desta conta Ocorreu um erro desconhecido! - Não é possível encontrar o servidor - Instância servidor não encontrada - O servidor levou demasiado tempo a responder + Não foi possível encontrar o anfitrião + Instância do servidor não encontrada + O servidor demorou muito tempo a responder URL errado Inicialização de SSL falhou - Não foi possível verificar a identidade SSL do servidor + Não foi possível verificar a identidade do servidor SSL Versão do servidor não reconhecida Não consegue estabelecer ligação Ligação segura estabelecida @@ -179,7 +179,7 @@ Acesso negado pelo servidor Estado inesperado, por favor, digite a URL do servidor novamente O prazo da sua autorização expirou. Por favor renove-a - Por favor, introduza a password actual + Por favor, insira a palavra-passe atual A sua sessão expirou. Por favor autentique-se de novo A verificar a sua autenticação no servidor... O servidor não suporta este método de autenticação @@ -297,4 +297,6 @@ Segurança Envio do Caminho do Vídeo partilhado + consigo + %1$s %2$s >>%3$s<< %4$s diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index bf3c9757..d79ca6f6 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -1,7 +1,7 @@ - %1$s Приложение для Андроид - Версия %1$s + %1$s для Android + версия %1$s Обновить учетную запись Загрузить Содержимое из других приложений @@ -15,7 +15,7 @@ Упорядочить по А-Я - По новизне + Новое - Старое @@ -23,7 +23,7 @@ Больше Учётные записи Управление учётными записями - App PIN + PIN приложения Защитить ваш клиент Мгновенная загрузка фотографий Немедленно загружать фотографии сделанные камерой @@ -51,16 +51,16 @@ Файлы Подключиться Загрузить - Выберете каталог для загрузки + Выберите каталог для загрузки Учётная запись не найдена - На вашем устройстве нет учётных записей %1$s. Сначала, необходимо настроить учётную запись. - Установка + На вашем устройстве нет учётных записей %1$s. Пожалуйста настройте учётную запись. + Настройка Выход Нет содержимого для загрузки Содержимое не получено. Нечего загружать. Доступ к общему ресурсу для %1$s запрещен Загрузка - менее минуты + пару секунд назад Здесь ничего нет. Загрузите что-нибудь! Загрузка... В этом каталоге нет файлов. @@ -86,32 +86,32 @@ Отмена Сохранить и выйти Ошибка - Идёт загрузка... + Загрузка ... Неизвестная ошибка О программе Сменить пароль Удалить учётную запись Создать учётную запись - Загрузить из... + Загрузить из ... Имя каталога - Загрузка... - %1$d%% загрузки %2$s + Загрузка ... + %1$d%% Загружается %2$s Загрузка завершена %1$s был успешно загружен Ошибка загрузки Загрузка %1$s не может быть завершена - Загрузка не удалась, необходимо переподключиться - Скачивание... - %1$d%% скачивания %2$s + Загрузка не удалась, нужно заново войти в свою учетную запись + Скачивание ... + %1$d%% Скачивается %2$s Скачивание завершено %1$s успешно скачан Скачивание не удалось Скачивание %1$s не может быть завершено Ещё не скачано - Скачивание не удалось, необходимо переподключиться + Скачивание не удалось, нужно заново войти в свою учетную запись Выберите учётную запись Синхронизация прошла неудачно - Синхронизация не удалась, необходимо переподключиться + Синхронизация не удалась, нужно заново войти в свою учетную запись Синхронизация %1$s не может быть завершена Неверный пароль для %1$s Обнаружены конфликты @@ -125,18 +125,18 @@ Переместить всё Все файлы были перемещены Некоторые файлы не могут быть перемещены - Локально: %1$s - Удаленно: %1$s + Локальные: %1$s + Удаленные: %1$s Для копирования выбранных файлов в каталог %1$s недостаточно свободного места. Скопировать в другое место? - Укажите App PIN - Введите App PIN - PIN-код будет запрашиваться при каждом запуске приложения. - Повторите ввод App PIN - Удалить App PIN - Введённые App PIN не совпадают - Неверный App PIN - App PIN удалён - App PIN сохранён + Укажите PIN приложения + Введите PIN приложения + PIN будет запрашиваться при каждом запуске приложения. + Повторите ввод PIN приложения + Удалить PIN приложения + Введённые PIN не совпадают + Неверный PIN приложения + PIN приложения удалён + PIN приложения сохранён %1$s аудиоплеер %1$s (проигрывается) %1$s (загружается) @@ -147,7 +147,7 @@ Неподдерживаемый кодек Медиафайл не может быть прочитан Медиафайл некорректно закодирован - Время попыток воспроизведения вышло + Истекло время попытки воспроизведения Невозможно организовать потоковую передачу медиафайла Медиафайл не может быть проигран стандартным плеером Ошибка безопасности при воспроизведении %1$s @@ -156,7 +156,7 @@ Перемотка назад Воспроизведение или пауза Перемотка вперед - Происходит авторизация..... + Выполняется авторизация... Попытка входа... Нет подключения к сети Защищённое соединение недоступно. @@ -173,7 +173,7 @@ Ошибка инициализации SSL Невозможно проверить SSL-сертификат сервера Неизвестная версия сервера - Невозможно установить соединение + Не удается установить соединение Защищённое соединение установлено Неверное имя пользователя или пароль Ошибка авторизации @@ -210,7 +210,7 @@ Подождите немного Неизвестная ошибка; выберите этот файл из другого приложения Файлы не выбраны - Отправить ссылку... + Отправить ссылку ... Войти через oAuth2 Подключение к серверу oAuth2... Подлинность сайта не может быть проверена @@ -218,21 +218,21 @@ - Срок действия сертификата сервера истёк - Срок действия сертификата сервера ещё не начался - URL не совпадает с именем сервера в сертификате - Вы хотите доверять данному сертификату в любом случае? + Доверять этому сертификату в любом случае? Сертификат не может быть сохранён Подробно Скрыть - Кому выдано: - Кем выдано: + Кому выдан: + Кем выдан: Имя: Организация: - Организационное подразделение: + Подразделение: Страна: Штат: Местонахождение: Срок действия: - Из: - В: + С: + По: Подпись: Алгоритм: Сертификат не может быть показан. @@ -270,13 +270,13 @@ Во время ожидания сервера произошла ошибка, действие не может быть выполнено Действие не может быть выполнено, сервер недоступен - Недостаточно прав в %s - что-бы переименовать этот файл - что-бы удалить этот файл - что-бы поделиться этим файлом - что-бы закрыть доступ к этому файлу - что-бы создать файл - что-бы загрузить в этот каталог + У вас нет прав %s + для переименования этого файла + для удаления этого файла + для открытия доступа к этому файлу + для закрытия доступа к этому файлу + для создания файла + для загрузки в этот каталог Этот файл больше недоступен на сервере Учётные записи Добавить учетную запись @@ -284,7 +284,7 @@ Журналы История Отправлений Приложение для отправки журнала не найдено. Установите почтовое приложение! - Журналы приложения %1$s для Android + Журналы %1$s для Android Загрузка данных… Требуется аутентификация Неправильный пароль @@ -295,11 +295,11 @@ Невозможно переместить каталог в его подкаталог Файл уже существует в каталоге назначения Произошла ошибка при попытке перемещения этого файла или каталога - переместить этот файл + для перемещения этого файла Мгновенные загрузки Безопасность Путь для загрузки Видео - Общие + общие с вами %1$s %2$s >>%3$s<< %4$s diff --git a/res/values-sr-rSP/strings.xml b/res/values-sr-rSP/strings.xml index ada7c59e..41e12381 100644 --- a/res/values-sr-rSP/strings.xml +++ b/res/values-sr-rSP/strings.xml @@ -2,6 +2,7 @@ Pošalji Fajlovi + Novi direktorijum Podešavanja Detaljnije Pošalji @@ -26,8 +27,10 @@ Da Ne Ok + Otkaži otpremanje Otkaži Greška + Nepoznata greška Izmeni lozinku Ukloni nalog Novi nalog diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 56ec0389..a24876d4 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -282,9 +282,9 @@ Güvenli bağlantı, güvenli olmayan bir rotaya yönlendirildi. Günlükler Geçmişi Gönder - Günlükleri göndermek için uygulama bulunamadı. E-posta uygulamasını yükleyin! + Kayıtları göndermek için uygulama bulunamadı. E-posta uygulamasını yükleyin! %1$s Android uygulama kayıtları - Yükleniyor... + Veri yükleniyor... Kimlik doğrulama gerekli Hatalı parola Taşı @@ -299,4 +299,6 @@ Güvenlik Video Yükleme Yolu paylaşılan + sizinle + %1$s %2$s >>%3$s<< %4$s diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 8af7792f..e57daeaa 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -38,6 +38,8 @@ Порадити товаришу Зворотній зв\'язок Відбиток + Запам\'ятати позицію + Запам\'ятати останній опублікований шлях завантаження Спробуйте %1$s на своєму смартфоні! Пропоную вам користуватися %1$s на вашому смартфоні!\nЗавантажити можна за посиланням: %2$s Перевірити сервер @@ -279,6 +281,9 @@ Безпечне підключення перенаправляється через незабезпечений маршрут. Журнали Надіслати історію + Немає додатку для відправки журналів. Встановіть поштовий додаток! + %1$s Android лог додатку + Завантаження даних... Потрібна аутентифікація Невірний пароль Перемістити @@ -291,5 +296,8 @@ перемістити цей файл Миттєво завантаження Безпека + Шлях завантаження відео спільне + з тобою + %1$s %2$s >>%3$s<< %4$s diff --git a/res/values-yo/strings.xml b/res/values-yo/strings.xml new file mode 100644 index 00000000..69623e19 --- /dev/null +++ b/res/values-yo/strings.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index ce53c444..edab29d4 100644 --- a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/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 { + public static class ThumbnailGenerationTask extends AsyncTask { private final WeakReference 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); 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); + } + @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 bitmapWorkerTaskReference; public AsyncDrawable( Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask - ) { - + ) { + super(res, bitmap); bitmapWorkerTaskReference = - new WeakReference(bitmapWorkerTask); + new WeakReference(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 - } - } - } diff --git a/src/com/owncloud/android/operations/RenameFileOperation.java b/src/com/owncloud/android/operations/RenameFileOperation.java index bd60e1fb..2fdc8f18 100644 --- a/src/com/owncloud/android/operations/RenameFileOperation.java +++ b/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 diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index 059cb2b4..398a833d 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/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) diff --git a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java index 850d03b8..0e3e0377 100644 --- a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java +++ b/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 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() { - 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() { - 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() { - 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); - } + } } diff --git a/src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java b/src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java index 6190ebee..996851e1 100644 --- a/src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java +++ b/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); diff --git a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java index 2ff29250..1e0e7ee3 100644 --- a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java +++ b/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)); } } diff --git a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java index 73ae5dc2..9c85dd98 100644 --- a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/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); } } diff --git a/src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java b/src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java index f2a9a9b2..3c15de71 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java +++ b/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(); mObsoletePositions = new HashSet(); mDownloadErrors = new HashSet(); //mFragmentManager = fragmentManager; mCachedFragments = new HashMap(); } - /** * Returns the image files handled by the adapter. diff --git a/src/com/owncloud/android/utils/BitmapUtils.java b/src/com/owncloud/android/utils/BitmapUtils.java index 70367278..92824f44 100644 --- a/src/com/owncloud/android/utils/BitmapUtils.java +++ b/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/")); + } } diff --git a/src/com/owncloud/android/utils/DisplayUtils.java b/src/com/owncloud/android/utils/DisplayUtils.java index a1afb894..32d90173 100644 --- a/src/com/owncloud/android/utils/DisplayUtils.java +++ b/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 SUBTYPES_DOCUMENT_SET = new HashSet(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 SUBTYPES_SPREADSHEET_SET = new HashSet(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 SUBTYPES_PRESENTATION_SET = new HashSet(Arrays.asList(SUBTYPES_PRESENTATION)); private static final String[] SUBTYPES_COMPRESSED = {"x-tar", "x-gzip", "zip"}; private static final Set SUBTYPES_COMPRESSED_SET = new HashSet(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. @@ -114,30 +125,6 @@ public class DisplayUtils { } /** - * 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]; } /** diff --git a/src/com/owncloud/android/utils/FileStorageUtils.java b/src/com/owncloud/android/utils/FileStorageUtils.java index 892a1ca8..b462cd95 100644 --- a/src/com/owncloud/android/utils/FileStorageUtils.java +++ b/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 sortFolder(Vector 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 sortByDate(Vector files){ + final Integer val; + if (mSortAscending){ + val = 1; + } else { + val = -1; + } + + Collections.sort(files, new Comparator() { + 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 sortBySize(Vector files){ +// final Integer val; +// if (mSortAscending){ +// val = 1; +// } else { +// val = -1; +// } +// +// Collections.sort(files, new Comparator() { +// 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 sortByName(Vector files){ + final Integer val; + if (mSortAscending){ + val = 1; + } else { + val = -1; + } + + Collections.sort(files, new Comparator() { + 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; + } }