diff --git a/.gitignore b/.gitignore index ac460002d..023b57957 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,12 @@ -local.properties -build.properties +/local.properties +/build.properties .classpath /bin/ /gen/ /build /.gradle -proguard.cfg -build.xml +/proguard.cfg +/build.xml *~ .idea *.iml diff --git a/AndroidManifest.xml b/AndroidManifest.xml index e11b9835e..72bc34282 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2,11 +2,11 @@ - - - diff --git a/build.gradle b/build.gradle index 3cb2a0234..164057946 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:0.6.+' + classpath 'com.android.tools.build:gradle:0.7.+' } } @@ -15,7 +15,7 @@ dependencies { android { compileSdkVersion 19 - buildToolsVersion "19.0.0" + buildToolsVersion "19.0.1" sourceSets { main { diff --git a/extern/Universal-Image-Loader b/extern/Universal-Image-Loader index 2a8a184d4..75ea56004 160000 --- a/extern/Universal-Image-Loader +++ b/extern/Universal-Image-Loader @@ -1 +1 @@ -Subproject commit 2a8a184d40b16756fd80edc342550bb2335d6461 +Subproject commit 75ea560049c9a256ca4fba0a70de1971aa852612 diff --git a/res/drawable/ic_cab_done_holo_dark.png b/res/drawable/ic_cab_done_holo_dark.png deleted file mode 100644 index 2e06dd01b..000000000 Binary files a/res/drawable/ic_cab_done_holo_dark.png and /dev/null differ diff --git a/res/layout-land/appdetails.xml b/res/layout-land/appdetails.xml index 5441f258d..592971970 100644 --- a/res/layout-land/appdetails.xml +++ b/res/layout-land/appdetails.xml @@ -14,8 +14,8 @@ android:id="@+id/landleft" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="5dp" - android:paddingRight="6dp" + android:padding="5dp" + android:layout_marginRight="4dp" android:orientation="vertical" > + android:textSize="13sp" /> + android:textSize="13sp" /> diff --git a/res/layout/appdetails.xml b/res/layout/appdetails.xml index 7bd9e3059..ac8c5e846 100644 --- a/res/layout/appdetails.xml +++ b/res/layout/appdetails.xml @@ -1,57 +1,71 @@ + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:padding="5dp" + android:baselineAligned="false" + android:orientation="vertical" > - - - - + android:paddingTop="2sp" + android:paddingBottom="2sp" + android:layout_marginLeft="8dp" + android:textSize="13sp" /> + + + + + + diff --git a/res/layout/appinfo.xml b/res/layout/appinfo.xml index 6b7428ad7..546d06bed 100644 --- a/res/layout/appinfo.xml +++ b/res/layout/appinfo.xml @@ -2,10 +2,7 @@ @@ -13,14 +10,13 @@ android:id="@+id/summary" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:textSize="14sp" android:textStyle="bold" /> + android:textSize="13sp" /> @@ -50,7 +45,6 @@ android:layout_height="wrap_content" android:layout_marginTop="8sp" android:singleLine="true" - android:textSize="14sp" android:textStyle="bold" /> + + + + + - + - + - + - + - - - - - - - - - + diff --git a/res/layout/fdroid.xml b/res/layout/fdroid.xml index 9880ed10e..fe0687322 100644 --- a/res/layout/fdroid.xml +++ b/res/layout/fdroid.xml @@ -3,8 +3,6 @@ android:id="@+id/fdroid_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:paddingLeft="2dp" - android:paddingRight="2dp" android:baselineAligned="false" android:orientation="vertical"> diff --git a/res/layout/searchresults.xml b/res/layout/searchresults.xml index 417bdb240..b7ddbba70 100644 --- a/res/layout/searchresults.xml +++ b/res/layout/searchresults.xml @@ -9,7 +9,6 @@ niemals Automatische Paketaktualisierung Anwendungsliste automatisch aus den Paketquellen aktualisieren - Nur bei WLAN - Anwendungsliste nur bei WLAN automatisch aktualisieren + Nur über WLAN + Anwendungsliste nur über WLAN automatisch aktualisieren Benachrichtigen - Bei verfügbaren Aktualisierungen benachrichtigen + Benachrichtigen, wenn neue Aktualisierungen verfügbar sind Aktualisierungsverlauf Zeitraum in Tagen, für den neue bzw. aktualisierte Anwendungen angezeigt werden. Suchergebnisse @@ -93,8 +93,8 @@ Sollen diese aktualisiert werden? Experte Expertenmodus einschalten Anwendungen suchen - Art der Datenbanksynchronisation - SQLite Synchronisationsmodus setzen + Datenbanksynchronisierungsart + SQLite-Synchronisationsmodus einstellen Kompatibilität der Anwendung Inkompatible Versionen Anwendungsversionen anzeigen, welche mit dem Gerät inkompatibel sind diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index 9adb9ffef..a68ac09e5 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -1,34 +1,34 @@ - Atopáronse %1$d aplicacións que cadran con \'%2$s\': - Atopouse unha aplicación que cadra con \'%s\': - Non se atoparon aplicacións que cadren con \'%s\' - A nova versión está asinada cunha chave diferente da antiga. Para instalar a nova versión, antes débese desinstalar a anterior. Por favor, fai esto e téntao de novo. (Decátate que ó desinstalar borrarase calquera dato interno gardado pola aplicación) + Atopáronse %1$d aplicativos que cadran con \'%2$s\': + Atopouse un aplicativo que cadra con \'%s\': + Non se atoparon aplicativos que cadren con \'%s\' + A nova versión está asinada cunha clave diferente da antiga. Para instalar a nova versión, antes débese desinstalar a anterior. Por favor, fágao e téntao de novo. (Ao desinstalar borrarase calquera dato interno gardado pola aplicación) Parece que este paquete non é compatíbel co seu dispositivo. Quere facer a proba e instalalo aínda así? - Estás tentando de instalar unha versión anterior. Esto pode acarrexar un mal funcionamento ou pérdida de datos. ¿Queres tentalo aínda así? + Está tentando instalar unha versión anterior. Isto pode supoñer un mal funcionamento ou perda de datos. Quere tentalo de todas maneiras? Versión - %d versións dispoñíbles - %d versión dispoñíbles - Caché de aplicacións descargadas + %d versións dispoñíbeis + %d versión dispoñíbeis + Memorizar as aps descargadas Gardar os ficheiros apk descargados na tarxeta SD Actualizacións Outro Último escaneado do repositorio: %s nunca Escaneado automático dos repositorios - Actualizar automáticamente a lista de aplicacións do repositorio + Actualizar automaticamente a lista de aps do repositorio Soamente no wifi Actualizar as listas de aps automaticamente soamente cando hai wifi Notificar - Avisarme cando estean dispoñíbles novas actualizacións + Avisarme cando estean dispoñíbeis novas actualizacións Histórico de actualizacións - Días para mostrar aplicacións novas/actualizadas + Días para amosar aps novas/actualizadas Resultados da busca Detalles da ap Non se atopa tal ap Sobre F-Droid Baseado en Aptoide. -Publicado con licencia GNU GPLv3. +Publicado con licenza GNU GPLv3. Sitio web: Correo: Versión: @@ -43,8 +43,8 @@ Un enderezo a un repositorio sería algo como isto: https://f-droid.org/repo Instalada - Non instalado - Engadido en %s + Non instalada + Engadida a %s Aceptar Si Non @@ -54,17 +54,17 @@ Un enderezo a un repositorio sería algo Escoller o repositorio que retirar Actualizar repositorios Instalado - Dispoñíble + Dispoñíbel Actualizacións - 1 Actualización dispoñíble - %d actualizacións dispoñíbles - Actualizacións de F-Droid dispoñíbles + 1 Actualización dispoñíbel + %d actualizacións dispoñíbeis + Actualizacións de F-Droid dispoñíbeis Agarde por favor - Actualizando a lista de aplicacións... - Obtendo a aplicación desde + Actualizando a lista de aplicativos... + Obtención do aplicativo desde Enderezo do repositorio Cambiou a lista de repositorios usados. -¿Queres actualizalos? +Quere actualizalos? Actualizar repositorios Xestionar repositorios Preferencias @@ -85,7 +85,7 @@ Un enderezo a un repositorio sería algo Doar Instalada a versión %s Non instalada - O ficheiro descargado está corrompido + O ficheiro descargado está corrupto Descarga cancelada Esta ap contén publicidade Esta ap rexistra e informa da súa actividade @@ -95,35 +95,35 @@ Un enderezo a un repositorio sería algo Amosar Experto Activar o modo experto - Buscar aplicacións + Buscar aplicativos Modo de sincronización da base de datos - Estabelece o valor da bandeira de sincronización de SQLite - Compatibilidade de aplicacións + Estabelece o valor da marca de sincronización de SQLite + Compatibilidade de aplicativos Versións incompatíbeis Amosar versións de aps que son incompatíbeis co dispositivo Root - Amosar aplicacións que requiren privilexios de root + Amosar aplicativos que requiren privilexios de root Ignorar a pantalla táctil - Incluír sempre as aplicacións que requiren pantalla táctil + Incluír sempre as aps que requiren pantalla táctil Todos Qué novidades hai Actualizado recentemente Descargando %2$s / %3$s (%4$d%%) desde %1$s - Procesando a aplicación + Procesando o aplicativo %2$d de %3$d desde %1$s Conectándose con %1$s - Comprobando a compatibilidade das aplicacións con teu aparato + Comprobando a compatibilidade das aps con seu aparello Non se usan permisos Permisos para a versión %s Amosar permisos - Amosar unha lista dos permisos que precisa unha aplicación + Presentar a lista dos permisos que precisa unha ap Non ten ningunha ap dispoñíbel que poida manexar %s Deseño compacto - Amosar únicamente os nomes das aplicacións e resumos na lista + Amosar unicamente os nomes das aps e resumos na lista Tema Escolla un tema diff --git a/res/values-ko/array.xml b/res/values-ko/array.xml new file mode 100644 index 000000000..2bf47cb19 --- /dev/null +++ b/res/values-ko/array.xml @@ -0,0 +1,19 @@ + + + + + 매시간마다 + 4시간마다 + 12시간마다 + 매일 + + + 어두운 + 밝은 + + + 해제 (안전하지 않음) + 보통 + 전체 + + diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml new file mode 100644 index 000000000..b4657fd03 --- /dev/null +++ b/res/values-ko/strings.xml @@ -0,0 +1,107 @@ + + + \'%2$s\' 검색결과 (%1$d개) + \'%s\' 검색결과: + \'%s\' 와 일치하는 응용프로그램을 찾을 수 없습니다. + 이 응용 프로그램의 다운그레이드 하려고 합니다. 이전 버전을 설치할 경우, 응용 프로그램에 데이터가 손상되거나 오작동이 발생할 수 있습니다. 정말로 다운그레이드하시겠습니까? + 버전 + %d개의 버전을 사용할 수 있습니다. + %d개의 버전을 사용할 수 있습니다. + 다운로드된 설치파일 저장 + SD카드에 다운로드된 설치파일을 보관 + 업데이트 + 기타 + 마지막 저장소 검색: %s + 자동으로 저장소 검색 + 자동으로 저장소의 앱 목록을 갱신합니다. + Wi-Fi 연결 시에만 + Wi-Fi에 연결되어 있을 때만 자동으로 앱 목록을 갱신합니다. + 알림 + 새로운 업데이트가 가능할 때 알림 + 이력 업데이트 + 검색 결과 + 앱 상세정보 + F-Droid 대하여 + 웹사이트: + 이메일: + 버전: + 웹사이트 + 저장소가 구성되지 않았습니다! +저장소는 응용프로그램의 소스입니다. +추가하려면, 메뉴에 \"새 저장소\" 버튼을 누르고 URL 입력해주세요. +저장소 URL 예: https://f-droid.org/repo + 설치됨 + 설치되지 않음 + %s에 추가됨 + 확인 + + 아니오 + 새로운 저장소 추가 + 추가 + 취소 + 제거할 저장소 선택 + 저장소 업데이트 + 설치됨 + 업데이트 + 1개의 업데이트를 사용할 수 있습니다. + %d개의 업데이트를 사용할 수 있습니다. + F-Droid 업데이트를 사용할 수 있습니다. + 잠시만 기다려주세요 + 응용 프로그램 목록 업데이트중... + 에서 응용프로그램 가져오기 + 저장소 주소 + 사용된 저장소의 목록이 변경되었습니다. +업데이트 하시겠습니까? + 저장소 업데이트 + 저장소 관리 + 설정 + 대하여 + 검색 + 새로운 저장소 + 저장소 제거 + 실행 + 공유 + 설치 + 제거 + 모든 업데이트 무시 + 이 업데이트 무시 + 웹사이트 + 이슈 + 소스코드 + 업그레이드 + 기부 + 설치되지 않음 + 다운로드된 파일이 손상되었습니다. + 다운로드 취소됨 + 이 응용프로그램은 광고가 포함되어 있습니다. + 이 응용프로그램은 활동을 추적하여 리포트를 보고합니다. + 표시 + 전문가 + 전문가 모드 사용 + 응용 프로그램 검색 + 데이터베이스 동기화 모드 + 응용 프로그램 호환성 + 호환되지 않는 버전 + Root 권한이 필요한 앱을 보여줍니다. + 터치스크린 무시 + 터치스크린을 요구하는 앱을 포함합니다 + 전체 + 새로운 기능 + 최근 업데이트 + %1$s 에서 다운로드 중입니다. +%2$s / %3$s (%4$d%%) + 응용 프로그램 처리중 +%1$s +%2$d / %3$d + %1$s에 접속중 + 장치와 응용프로그램의 호환성 확인중… + 사용된 권한이 없습니다. + %s 버전에 대한 권한 + 권한 표시 + 응용 프로그램이 필요한 권한의 목록을 표시 + %s을(를) 처리할 수 있는 응용프로그램이 없습니다. + 컴팩트 레이아웃 + 목록에 웹이름과 요약정보만 표시합니다. + 테마 + 사용할 테마를 선택하세요. + diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 9c7949482..3bb122e70 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -3,7 +3,7 @@ %1$d applicaties gevonden die voldoen aan \'%2$s\': Één applicatie gevonden die voldoet aan \'%s\': Geen applicaties gevonden die voldoen aan \'%s\' - De nieuwe versie is gesigned met een andere sleutel als de oude. Om de nieuwe versie te installeren moet eerst de oude verwijderd worden. Probeer het daarna nogmaals. (Let op dat het verwijderen de data van de applicatie verwijderd wordt) + De nieuwe versie is gesigneerd met een andere sleutel als de oude. Om de nieuwe versie te installeren moet eerst de oude verwijderd worden. Probeer het daarna nogmaals. (Let op dat bij het verwijderen de data van de applicatie ook verwijderd wordt) Dit pakket is niet verenigbaar met uw apparaat. Wilt u het alsnog proberen te installeren? U probeert deze applicatie te degraderen naar een oudere versie. Als u dit doet uw data kan corrupt of verloren raken. Wilt u dit alsnog uitvoeren? Versie @@ -15,12 +15,12 @@ Andere Laatste bronnen scan: %s nooit - Automatische bronnen-scan + Scan bronnen automatisch app-lijst automatisch bijwerken Allen op wifi Vernieuw app-lijst alleen op wifi automatisch Verwittigen - Verwittigen bij nieuwe beschikbare updates + Verwittigen wanneer nieuwe updates beschikbaar zijn Vernieuw historie Dagen om nieuwe/verbeterde apps te laten zien Zoekresultaten @@ -59,11 +59,11 @@ Een bron-adres ziet er ongeveer %d vernieuwingen zijn beschikbaar F-Droid Vernieuwingen Beschikbaar Even geduld aub - Applicatie-lijst vernieuwen + Applicatie-lijst vernieuwen... downloaden applicatie van Bron-adres De lijst van gebruikte bronnen is veranderd. -Wil je ze vernieuwen? +Wilt u ze vernieuwen? Vernieuw Bronnen Beheer bronnen Voorkeuren @@ -82,8 +82,8 @@ Wil je ze vernieuwen? Broncode Verbeteren Doneer - Versie %s geinstalleerd - Niet geinstalleerd + Versie %s geïnstalleerd + Niet geïnstalleerd Gedownloade bestand is corrupt Download geannuleerd Deze app bevat advertenties @@ -94,9 +94,9 @@ Wil je ze vernieuwen? Laat zien Expert Ga in expert-modus - Zoek-applicaties + Zoek applicaties Database sync-modus - Zet de SQLite\'s synchronisatie-vlag + Zet de waarde van SQLite\'s synchronisatie-vlag Applicatie verenigbaarheid Onverenigbare versies Laat versies van apps die onverenigbaar zijn met het apparaat diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 45ee6a7a3..52b0c1d9e 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -10,12 +10,18 @@ Buforuj pobrane aplikacje Przechowuj pobrane pliki apk na karcie SD Aktualizacje + Inne Ostatnie uaktualnienie listy aplikacji: %s nigdy Automatycznie skanuj repozytoria Automatycznie uaktualnij listę aplikacji z repozytorium + Tylko przez wifi + Aktualizuj automatycznie tylko przez wifi Powiadom Powiadamiaj, gdy dostępne będą nowe aktualizacje + Historia aktualizacji + Wyniki wyszukiwania + Nie znaleziono takiej aplikacji O F-Droid Strona internetowa: Email: @@ -23,6 +29,7 @@ Strona internetowa Zainstalowano Niezainstalowane + Dodano %s OK Tak Nie @@ -48,8 +55,11 @@ Czy chcesz je zaktualizować? Nowe repozytorium Usuń repozytorium Uruchom - Instaluj + Udostępnij + Zainstaluj Odinstaluj + Ignoruj wszystkie aktualizacje + Ignoruj tę aktualizację Strona internetowa Problemy Kod żródłowy @@ -67,6 +77,9 @@ Czy chcesz je zaktualizować? Root Pokaż aplikacje wymagające uprawnień root Wszystkie - Ostatnio dodane + Co nowego Ostatnio zaktualizowane + Trwa łączenie z +%1$s + Wyświetl uprawnienia diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index d5aa6f31f..b9411288d 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -4,7 +4,7 @@ Ett program matchade \'%s\': Inga program matchade \'%s\' Den nya versionen är signerad med en annan nyckel än den gamla. Den gamla versionen måste först avinstalleras. Försök sedan igen. (Observera att data som tillhör programmet kommer att raderas när det avinstalleras.) - Det verkar som om detta programmet inte är kompatibelt med enheten. Vill ni försöka installera det ändå? + Det verkar som att detta program inte är kompatibelt med enheten. Vill ni försöka installera det ändå? Du försöker nedgradera detta program. Detta kan få det att fungera felaktigt eller orsaka förlust av dina data. Vill du ändå försöka nedgradera? Version %d versioner tillgängliga @@ -18,7 +18,7 @@ Automatisk förrådsavsökning Uppdatera applistan från förråd automatiskt Endast via WiFi - Uppdatera applikasjonslista automatiskt endast över wifi + Uppdatera applistor automatiskt endast över wifi Avisering Meddela mig när nya uppdateringar finns Uppdateringshistorik @@ -58,7 +58,7 @@ En förrådsadress ser ut så här: https://f-droid.org/repo Var vänlig vänta Uppdaterar programlistan... Hämtar program från - Förrådadress + Förrådsadress Listan över förråd har ändrats. Vill du uppdatera dem? Uppdatera förråd @@ -72,8 +72,8 @@ Vill du uppdatera dem? Dela Installera Avinstallera - Ignorer alla uppdateringar - Ignorer denna uppdateringen + Ignorera alla uppdateringar + Ignorera denna uppdatering Webbplats Buggar Källkod @@ -85,9 +85,9 @@ Vill du uppdatera dem? Nerladdning avbruten Denna app innehåller reklam Denna app övervakar dina aktiviteter - Denna app promoterar ufria tillägg - Denna app promoterar ufria nätverkstjänster - Denna app avhenger av andra ufria apps + Denna app främjar ofria tillägg + Denna app främjar ofria nätverkstjänster + Denna app beror på andra ofria appar Visning Expert Aktivera expertläge @@ -96,7 +96,7 @@ Vill du uppdatera dem? Ställ in värdet på synchronous-flaggan i SQLite Programkompatibilitet Inkompatibla versioner - Visa versioner av apps som är ukompatibla med ditt apparat + Visa versioner av appar som är inkompatibla med enheten Root Visa appar som kräver root-rättigheter Ignorera touchscreen @@ -116,8 +116,8 @@ Vill du uppdatera dem? Inga behörigheter används. Behörigheter för version %s Visa behörigheter - Visa en lista av behörigheter en app behöver - Ni har inte något app tilgängligt för behandling av %s + Visa en lista över behörigheter en app behöver + Du har inte någon app tillgänglig för hantering av %s Kompakt layout Visa endast appnamn och sammanfattningar i listan Tema diff --git a/res/values/dimen.xml b/res/values/dimen.xml index 6fe5117c7..2ba4e3cd3 100644 --- a/res/values/dimen.xml +++ b/res/values/dimen.xml @@ -1,4 +1,7 @@ - 3dp + + 64dp + + 48dp diff --git a/res/values/no_trans.xml b/res/values/no_trans.xml index 78e182e7d..918d10fb4 100644 --- a/res/values/no_trans.xml +++ b/res/values/no_trans.xml @@ -2,13 +2,14 @@ F-Droid - 0.55 + 0.56-test https://f-droid.org team@f-droid.org Bitcoin Litecoin + Dogecoin Flattr diff --git a/res/values/strings.xml b/res/values/strings.xml index 5ea16fd1b..325556670 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7,25 +7,26 @@ It seems like this package is not compatible with your device. Do you want to try and install it anyway? You are trying to downgrade this application. Doing so might get it to malfunction and even lose your data. Do you want to try and downgrade it anyway? Version - %d versions available - %d version available Edit Delete - Cache downloaded apps - Keep downloaded apk files on SD card + App cache + Keep downloaded apk files on SD card + Do not keep any apk files Updates Other Last repo scan: %s never - Automatic repo scan - Update app list from repositories automatically + Automatic update interval + No automatic app list updates Only on wifi - Update app lists automatically only on wifi + Update app lists automatically only on wifi + Always update app lists automatically Notify - Notify when new updates are available + Notify when updates are available + Do not notify of any updates Update history - Days to show new/updated apps + Days to consider apps new or recent: %s Search Results App Details @@ -64,7 +65,6 @@ Choose repository to remove Update repositories - Installed Available Updates 1 update is available. @@ -121,20 +121,23 @@ Display Expert - Enable expert mode + Show extra info and enable extra settings + Hide extras for experienced users Search applications Database sync mode - Set the value of SQLite\'s "synchronous" flag Application compatibility Incompatible versions - Show versions of apps that are incompatible with the device + Show app versions incompatible with the device + Hide app versions incompatible with the device Root - Show apps that require root privileges + Do not grey out apps requiring root privileges + Grey out apps requiring root privileges Ignore Touchscreen - Always include apps that require touchscreen + Always include apps that require touchscreen + Filter apps normally All What\'s New @@ -154,12 +157,13 @@ No permissions are used. Permissions for version %s Show permissions - Display a list of permissions an app needs + Display a list of permissions an app requires + Don\'t show permissions before downloading You don\'t have any available app that can handle %s Compact Layout - Only show app names and summaries in list + Show icons at a smaller size + Show icons at regular size Theme - Choose a theme to use Unsigned URL # of apps diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index 3c75c506c..1fa61df42 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -1,57 +1,56 @@ - diff --git a/src/org/fdroid/fdroid/AppDetails.java b/src/org/fdroid/fdroid/AppDetails.java index e682bc8a5..f5a056e7e 100644 --- a/src/org/fdroid/fdroid/AppDetails.java +++ b/src/org/fdroid/fdroid/AppDetails.java @@ -62,6 +62,7 @@ import android.view.SubMenu; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import android.graphics.Bitmap; import android.support.v4.app.NavUtils; import android.support.v4.view.MenuItemCompat; @@ -71,7 +72,10 @@ import org.fdroid.fdroid.compat.ActionBarCompat; import org.fdroid.fdroid.compat.MenuManager; import org.fdroid.fdroid.DB.CommaSeparatedList; +import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; +import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; +import com.nostra13.universalimageloader.core.assist.ImageScaleType; public class AppDetails extends ListActivity { @@ -83,11 +87,18 @@ public class AppDetails extends ListActivity { private List items; public ApkListAdapter(Context context, List items) { - this.items = (items != null ? items : new ArrayList()); + this.items = new ArrayList(); + if (items != null) { + for (DB.Apk apk : items) { + this.addItem(apk); + } + } } public void addItem(DB.Apk apk) { - items.add(apk); + if (apk.compatible || pref_incompatibleVersions) { + items.add(apk); + } } public List getItems() { @@ -124,7 +135,7 @@ public class AppDetails extends ListActivity { TextView tv = (TextView) v.findViewById(R.id.version); tv.setText(getString(R.string.version) + " " + apk.version - + (apk == app.curApk ? " *" : "")); + + (apk == app.curApk ? " ☆" : "")); tv.setEnabled(apk.compatible); tv = (TextView) v.findViewById(R.id.status); @@ -182,8 +193,9 @@ public class AppDetails extends ListActivity { private static final int DONATE = Menu.FIRST + 9; private static final int BITCOIN = Menu.FIRST + 10; private static final int LITECOIN = Menu.FIRST + 11; - private static final int FLATTR = Menu.FIRST + 12; - private static final int DONATE_URL = Menu.FIRST + 13; + private static final int DOGECOIN = Menu.FIRST + 12; + private static final int FLATTR = Menu.FIRST + 13; + private static final int DONATE_URL = Menu.FIRST + 14; private DB.App app; private String appid; @@ -197,7 +209,8 @@ public class AppDetails extends ListActivity { LinearLayout headerView; View infoView; - private Context mctx = this; + private final Context mctx = this; + private DisplayImageOptions displayImageOptions; @Override protected void onCreate(Bundle savedInstanceState) { @@ -205,6 +218,16 @@ public class AppDetails extends ListActivity { ((FDroidApp) getApplication()).applyTheme(this); super.onCreate(savedInstanceState); + + displayImageOptions = new DisplayImageOptions.Builder() + .cacheInMemory(true) + .cacheOnDisc(true) + .imageScaleType(ImageScaleType.NONE) + .showImageOnLoading(R.drawable.ic_repo_app_default) + .showImageForEmptyUri(R.drawable.ic_repo_app_default) + .bitmapConfig(Bitmap.Config.RGB_565) + .build(); + ActionBarCompat abCompat = ActionBarCompat.create(this); abCompat.setDisplayHomeAsUpEnabled(true); @@ -214,13 +237,13 @@ public class AppDetails extends ListActivity { Uri data = i.getData(); if (data != null) { if (data.isHierarchical()) { - if (data.getHost().equals("details")) { + if (data.getHost() != null && data.getHost().equals("details")) { // market://details?id=app.id appid = data.getQueryParameter("id"); } else { // https://f-droid.org/app/app.id appid = data.getLastPathSegment(); - if (appid.equals("app")) appid = null; + if (appid != null && appid.equals("app")) appid = null; } } else { // fdroid.app:app.id @@ -234,6 +257,10 @@ public class AppDetails extends ListActivity { appid = i.getStringExtra("appid"); } + if (i.hasExtra("from")) { + setTitle(i.getStringExtra("from")); + } + mPm = getPackageManager(); // Get the preferences we're going to use in this Activity... AppDetails old = (AppDetails) getLastNonConfigurationInstance(); @@ -258,6 +285,8 @@ public class AppDetails extends ListActivity { .getDefaultSharedPreferences(getBaseContext()); pref_expert = prefs.getBoolean("expert", false); pref_permissions = prefs.getBoolean("showPermissions", false); + pref_incompatibleVersions = prefs.getBoolean( + "incompatibleVersions", false); startViews(); @@ -265,6 +294,7 @@ public class AppDetails extends ListActivity { private boolean pref_expert; private boolean pref_permissions; + private boolean pref_incompatibleVersions; private boolean resetRequired; // The signature of the installed version. @@ -308,11 +338,6 @@ public class AppDetails extends ListActivity { super.onPause(); } - @Override - protected void onStop() { - super.onStop(); - } - @Override public Object onRetainNonConfigurationInstance() { stateRetained = true; @@ -418,14 +443,17 @@ public class AppDetails extends ListActivity { // Set the icon... ImageView iv = (ImageView) findViewById(R.id.icon); - ImageLoader.getInstance().displayImage(app.iconUrl, iv); + ImageLoader.getInstance().displayImage(app.iconUrl, iv, + displayImageOptions); // Set the title and other header details... TextView tv = (TextView) findViewById(R.id.title); tv.setText(app.name); tv = (TextView) findViewById(R.id.license); tv.setText(app.license); - tv = (TextView) findViewById(R.id.status); + + tv = (TextView) findViewById(R.id.categories); + tv.setText(app.categories.toString().replaceAll(",",", ")); tv = (TextView) infoView.findViewById(R.id.description); @@ -474,8 +502,7 @@ public class AppDetails extends ListActivity { if (listNum == -1) { output.append("\t• "); } else { - output.append("\t" + Integer.toString(listNum) - + ". "); + output.append("\t").append(Integer.toString(listNum)).append(". "); listNum++; } } else { @@ -510,7 +537,7 @@ public class AppDetails extends ListActivity { String permissionName = permissions.next(); try { Permission permission = new Permission(this, permissionName); - sb.append("\t• " + permission.getName() + '\n'); + sb.append("\t• ").append(permission.getName()).append('\n'); } catch (NameNotFoundException e) { if (permissionName.equals("ACCESS_SUPERUSER")) { sb.append("\t• Full permissions to all device features and storage\n"); @@ -537,7 +564,7 @@ public class AppDetails extends ListActivity { for (String af : app.antiFeatures) { String afdesc = descAntiFeature(af); if (afdesc != null) { - sb.append("\t• " + afdesc + "\n"); + sb.append("\t• ").append(afdesc).append("\n"); } } if (sb.length() > 0) { @@ -611,7 +638,6 @@ public class AppDetails extends ListActivity { @Override public void onClick(DialogInterface dialog, int whichButton) { - return; } }); AlertDialog alert = ask_alrt.create(); @@ -687,6 +713,7 @@ public class AppDetails extends ListActivity { } if (app.detail_bitcoinAddr != null || app.detail_litecoinAddr != null || + app.detail_dogecoinAddr != null || app.detail_flattrID != null || app.detail_donateURL != null) { SubMenu donate = menu.addSubMenu(Menu.NONE, DONATE, 7, R.string.menu_donate).setIcon( @@ -695,6 +722,8 @@ public class AppDetails extends ListActivity { donate.add(Menu.NONE, BITCOIN, 8, R.string.menu_bitcoin); if (app.detail_litecoinAddr != null) donate.add(Menu.NONE, LITECOIN, 8, R.string.menu_litecoin); + if (app.detail_dogecoinAddr != null) + donate.add(Menu.NONE, DOGECOIN, 8, R.string.menu_dogecoin); if (app.detail_flattrID != null) donate.add(Menu.NONE, FLATTR, 9, R.string.menu_flattr); if (app.detail_donateURL != null) @@ -776,6 +805,10 @@ public class AppDetails extends ListActivity { tryOpenUri("litecoin:" + app.detail_litecoinAddr); return true; + case DOGECOIN: + tryOpenUri("dogecoin:" + app.detail_dogecoinAddr); + return true; + case FLATTR: tryOpenUri("https://flattr.com/thing/" + app.detail_flattrID); return true; @@ -824,7 +857,6 @@ public class AppDetails extends ListActivity { @Override public void onClick(DialogInterface dialog, int whichButton) { - return; } }); AlertDialog alert = ask_alrt.create(); diff --git a/src/org/fdroid/fdroid/AppListManager.java b/src/org/fdroid/fdroid/AppListManager.java index 508114c1e..8e30ee7c1 100644 --- a/src/org/fdroid/fdroid/AppListManager.java +++ b/src/org/fdroid/fdroid/AppListManager.java @@ -204,8 +204,9 @@ public class AppListManager { } if (app.installedVersion != null) { installedApps.addItem(app); - if (app.toUpdate) + if (app.toUpdate) { canUpgradeApps.addItem(app); + } } } @@ -215,8 +216,7 @@ public class AppListManager { Collections.sort(availApps, new RecentlyUpdatedComparator()); } - for (DB.App app : availApps) - availableApps.addItem(app); + availableApps.addItems(availApps); return true; } @@ -228,6 +228,10 @@ public class AppListManager { } } + public String getCurrentCategory() { + return this.currentCategory; + } + static class WhatsNewComparator implements Comparator { @Override public int compare(DB.App lhs, DB.App rhs) { diff --git a/src/org/fdroid/fdroid/DB.java b/src/org/fdroid/fdroid/DB.java index 462d18634..ed39f71e9 100644 --- a/src/org/fdroid/fdroid/DB.java +++ b/src/org/fdroid/fdroid/DB.java @@ -58,7 +58,7 @@ import org.fdroid.fdroid.compat.ContextCompat; public class DB { private static Semaphore dbSync = new Semaphore(1, true); - static DB dbInstance = null; + private static DB dbInstance = null; // Initialise the database. Called once when the application starts up. static void initDB(Context ctx) { @@ -102,12 +102,13 @@ public class DB { + "curVersion text," + "curVercode integer," + "antiFeatures string," + "donateURL string," + "bitcoinAddr string," + "litecoinAddr string," + + "dogecoinAddr string," + "flattrID string," + "requirements string," + "categories string," + "added string," + "lastUpdated string," + "compatible int not null," + "ignoreAllUpdates int not null," + "ignoreThisUpdate int not null," - + "primary key(id));"; + + "provides string," + "primary key(id));"; public static class App implements Comparable { @@ -122,8 +123,10 @@ public class DB { detail_donateURL = null; detail_bitcoinAddr = null; detail_litecoinAddr = null; + detail_dogecoinAddr = null; detail_webURL = null; categories = null; + provides = null; antiFeatures = null; requirements = null; hasUpdates = false; @@ -177,6 +180,10 @@ public class DB { // Null when !detail_Populated public String detail_litecoinAddr; + // Dogecoin donate address, or null + // Null when !detail_Populated + public String detail_dogecoinAddr; + // Flattr donate ID, or null // Null when !detail_Populated public String detail_flattrID; @@ -194,6 +201,9 @@ public class DB { public int installedVerCode; public boolean userInstalled; + // List of app IDs that this app provides or null if there aren't any. + public CommaSeparatedList provides; + // List of categories (as defined in the metadata // documentation) or null if there aren't any. public CommaSeparatedList categories; @@ -246,7 +256,8 @@ public class DB { int latestcode = -1; Apk latestapk = null; for (Apk apk : apks) { - if (apk.compatible && apk.vercode <= curVercode + if ((!this.compatible || apk.compatible) + && apk.vercode <= curVercode && apk.vercode > latestcode) { latestapk = apk; latestcode = apk.vercode; @@ -260,7 +271,8 @@ public class DB { int latestcode = -1; Apk latestapk = null; for (Apk apk : apks) { - if (apk.compatible && apk.vercode > latestcode) { + if ((!this.compatible || apk.compatible) + && apk.vercode > latestcode) { latestapk = apk; latestcode = apk.vercode; } @@ -339,38 +351,14 @@ public class DB { // Call isCompatible(apk) on an instance of this class to // check if an APK is compatible with the user's device. - public static abstract class CompatibilityChecker extends Compatibility { - - public abstract boolean isCompatible(Apk apk); - - public static CompatibilityChecker getChecker(Context ctx) { - CompatibilityChecker checker; - if (hasApi(5)) - checker = new EclairChecker(ctx); - else - checker = new BasicChecker(); - Log.d("FDroid", "Compatibility checker for API level " - + getApi() + ": " + checker.getClass().getName()); - return checker; - } - } - - private static class BasicChecker extends CompatibilityChecker { - @Override - public boolean isCompatible(Apk apk) { - return hasApi(apk.minSdkVersion); - } - } - - @TargetApi(5) - private static class EclairChecker extends CompatibilityChecker { + private static class CompatibilityChecker extends Compatibility { private HashSet features; private List cpuAbis; private boolean ignoreTouchscreen; - @SuppressLint("NewApi") - public EclairChecker(Context ctx) { + //@SuppressLint("NewApi") + public CompatibilityChecker(Context ctx) { SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(ctx); @@ -381,10 +369,12 @@ public class DB { StringBuilder logMsg = new StringBuilder(); logMsg.append("Available device features:"); features = new HashSet(); - for (FeatureInfo fi : pm.getSystemAvailableFeatures()) { - features.add(fi.name); - logMsg.append('\n'); - logMsg.append(fi.name); + if (pm != null) { + for (FeatureInfo fi : pm.getSystemAvailableFeatures()) { + features.add(fi.name); + logMsg.append('\n'); + logMsg.append(fi.name); + } } cpuAbis = new ArrayList(); @@ -405,7 +395,6 @@ public class DB { return false; } - @Override public boolean isCompatible(Apk apk) { if (!hasApi(apk.minSdkVersion)) return false; @@ -541,13 +530,13 @@ public class DB { } } - private final int DBVersion = 31; + private final int DBVersion = 33; - private int countAppsForRepo(int id) { + private int countAppsForRepo(int id) { String[] selection = { "COUNT(distinct id)" }; String[] selectionArgs = { Integer.toString(id) }; Cursor result = db.query( - TABLE_APK, selection, "repo = ?", selectionArgs, "repo", null, null); + TABLE_APK, selection, "repo = ?", selectionArgs, "repo", null, null); if (result.getCount() > 0) { result.moveToFirst(); return result.getInt(0); @@ -731,7 +720,7 @@ public class DB { db.execSQL("alter table " + TABLE_REPO + " add column maxage integer not null default 0"); } - if (oldVersion < 31) { + if (oldVersion < 33) { if (!columnExists(db, TABLE_REPO, "lastUpdated")) db.execSQL("Alter table " + TABLE_REPO + " add column lastUpdated string"); } @@ -832,7 +821,7 @@ public class DB { private static final String[] POPULATE_APP_COLS = new String[] { "description", "webURL", "trackerURL", "sourceURL", - "donateURL", "bitcoinAddr", "flattrID", "litecoinAddr" }; + "donateURL", "bitcoinAddr", "flattrID", "litecoinAddr", "dogecoinAddr" }; private void populateAppDetails(App app) { Cursor cursor = null; @@ -848,6 +837,7 @@ public class DB { app.detail_bitcoinAddr = cursor.getString(5); app.detail_flattrID = cursor.getString(6); app.detail_litecoinAddr = cursor.getString(7); + app.detail_dogecoinAddr = cursor.getString(8); app.detail_Populated = true; } catch (Exception e) { Log.d("FDroid", "Error populating app details " + app.id ); @@ -942,7 +932,8 @@ public class DB { String cols[] = new String[] { "antiFeatures", "requirements", "categories", "id", "name", "summary", "icon", "license", "curVersion", "curVercode", "added", "lastUpdated", - "compatible", "ignoreAllUpdates", "ignoreThisUpdate" }; + "compatible", "ignoreAllUpdates", "ignoreThisUpdate", + "provides" }; c = db.query(TABLE_APP, cols, null, null, null, null, null); c.moveToFirst(); while (!c.isAfterLast()) { @@ -968,6 +959,7 @@ public class DB { app.compatible = c.getInt(12) == 1; app.ignoreAllUpdates = c.getInt(13) == 1; app.ignoreThisUpdate = c.getInt(14); + app.provides = DB.CommaSeparatedList.make(c.getString(15)); app.hasUpdates = false; if (getinstalledinfo && systemApks.containsKey(app.id)) { @@ -976,8 +968,10 @@ public class DB { if (app.installedVersion == null) app.installedVersion = "null"; app.installedVerCode = sysapk.versionCode; - app.userInstalled = ((sysapk.applicationInfo.flags - & ApplicationInfo.FLAG_SYSTEM) != 1); + if (sysapk.applicationInfo != null) { + app.userInstalled = ((sysapk.applicationInfo.flags + & ApplicationInfo.FLAG_SYSTEM) != 1); + } } else { app.installedVersion = null; app.installedVerCode = 0; @@ -985,6 +979,11 @@ public class DB { } apps.put(app.id, app); + if (app.provides != null) { + for (String id : app.provides) { + apps.put(id, app); + } + } c.moveToNext(); } @@ -997,8 +996,6 @@ public class DB { List repos = getRepos(); SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(mContext); - boolean incompatibleVersions = prefs - .getBoolean("incompatibleVersions", false); cols = new String[] { "id", "version", "vercode", "sig", "srcname", "apkName", "minSdkVersion", "added", "features", "nativecode", "compatible", "repo" }; @@ -1014,24 +1011,22 @@ public class DB { } boolean compatible = c.getInt(10) == 1; int repoid = c.getInt(11); - if (compatible || incompatibleVersions) { - Apk apk = new Apk(); - apk.id = id; - apk.version = c.getString(1); - apk.vercode = c.getInt(2); - apk.sig = c.getString(3); - apk.srcname = c.getString(4); - apk.apkName = c.getString(5); - apk.minSdkVersion = c.getInt(6); - String sApkAdded = c.getString(7); - apk.added = (sApkAdded == null || sApkAdded.length() == 0) ? null - : mDateFormat.parse(sApkAdded); - apk.features = CommaSeparatedList.make(c.getString(8)); - apk.nativecode = CommaSeparatedList.make(c.getString(9)); - apk.compatible = compatible; - apk.repo = repoid; - app.apks.add(apk); - } + Apk apk = new Apk(); + apk.id = id; + apk.version = c.getString(1); + apk.vercode = c.getInt(2); + apk.sig = c.getString(3); + apk.srcname = c.getString(4); + apk.apkName = c.getString(5); + apk.minSdkVersion = c.getInt(6); + String sApkAdded = c.getString(7); + apk.added = (sApkAdded == null || sApkAdded.length() == 0) ? null + : mDateFormat.parse(sApkAdded); + apk.features = CommaSeparatedList.make(c.getString(8)); + apk.nativecode = CommaSeparatedList.make(c.getString(9)); + apk.compatible = compatible; + apk.repo = repoid; + app.apks.add(apk); if (app.iconUrl == null && app.icon != null) { for (DB.Repo repo : repos) { if (repo.id == repoid) { @@ -1146,7 +1141,7 @@ public class DB { try { String filter = "%" + query + "%"; c = db.query(TABLE_APP, new String[] { "id" }, - "id like ? or name like ? or summary like ? or description like ?", + "id like ? or provides like ? or name like ? or summary like ? or description like ?", new String[] { filter, filter, filter, filter }, null, null, null); c.moveToFirst(); while (!c.isAfterLast()) { @@ -1191,9 +1186,8 @@ public class DB { } public boolean contains(String v) { - Iterator it = iterator(); - while (it.hasNext()) { - if (it.next().equals(v)) + for (String s : this) { + if (s.equals(v)) return true; } return false; @@ -1252,7 +1246,6 @@ public class DB { Log.d("FDroid", "AppUpdate: " + updateApps.size() + " apps on completion."); updateApps = null; - return; } // Called instead of endUpdate if the update failed. @@ -1273,8 +1266,9 @@ public class DB { } // Lazy initialise this... - if (compatChecker == null) - compatChecker = Apk.CompatibilityChecker.getChecker(mContext); + if (compatChecker == null) { + compatChecker = new Apk.CompatibilityChecker(mContext); + } // See if it's compatible (by which we mean if it has at least one // compatible apk) @@ -1346,6 +1340,7 @@ public class DB { values.put("donateURL", upapp.detail_donateURL); values.put("bitcoinAddr", upapp.detail_bitcoinAddr); values.put("litecoinAddr", upapp.detail_litecoinAddr); + values.put("dogecoinAddr", upapp.detail_dogecoinAddr); values.put("flattrID", upapp.detail_flattrID); values.put("added", upapp.added == null ? "" : mDateFormat.format(upapp.added)); diff --git a/src/org/fdroid/fdroid/FDroid.java b/src/org/fdroid/fdroid/FDroid.java index 8f07ef0aa..30a629925 100644 --- a/src/org/fdroid/fdroid/FDroid.java +++ b/src/org/fdroid/fdroid/FDroid.java @@ -28,7 +28,6 @@ import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.NotificationManager; import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -59,7 +58,6 @@ public class FDroid extends FragmentActivity { private static final int SEARCH = Menu.FIRST + 4; private ViewPager viewPager; - private AppListFragmentPageAdapter viewPageAdapter; private AppListManager manager = null; @@ -248,7 +246,7 @@ public class FDroid extends FragmentActivity { @Override public void onClick(DialogInterface dialog, int whichButton) { - // do nothing + // do nothing } }); AlertDialog alert = ask_alrt.create(); @@ -283,7 +281,7 @@ public class FDroid extends FragmentActivity { private void createViews() { viewPager = (ViewPager)findViewById(R.id.main_pager); - viewPageAdapter = new AppListFragmentPageAdapter(this); + AppListFragmentPageAdapter viewPageAdapter = new AppListFragmentPageAdapter(this); viewPager.setAdapter(viewPageAdapter); viewPager.setOnPageChangeListener( new ViewPager.SimpleOnPageChangeListener() { @Override @@ -342,7 +340,7 @@ public class FDroid extends FragmentActivity { public void removeNotification(int id) { NotificationManager nMgr = (NotificationManager) getBaseContext() .getSystemService(Context.NOTIFICATION_SERVICE); - nMgr.cancel(1); + nMgr.cancel(id); } } diff --git a/src/org/fdroid/fdroid/FDroidApp.java b/src/org/fdroid/fdroid/FDroidApp.java index a9cb64ab0..f2949ae88 100644 --- a/src/org/fdroid/fdroid/FDroidApp.java +++ b/src/org/fdroid/fdroid/FDroidApp.java @@ -24,21 +24,16 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.Semaphore; -import android.os.Build; import android.app.Application; import android.app.Activity; import android.preference.PreferenceManager; import android.util.Log; import android.content.Context; import android.content.SharedPreferences; -import android.graphics.Bitmap; import com.nostra13.universalimageloader.utils.StorageUtils; -import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache; +import com.nostra13.universalimageloader.cache.disc.impl.LimitedAgeDiscCache; import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator; -import com.nostra13.universalimageloader.core.assist.ImageScaleType; -import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; -import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; @@ -104,31 +99,24 @@ public class FDroidApp extends Application { DB.initDB(ctx); UpdateService.schedule(ctx); - DisplayImageOptions options = new DisplayImageOptions.Builder() - .cacheInMemory(true) - .cacheOnDisc(true) - .showImageOnLoading(R.drawable.ic_repo_app_default) - .showImageForEmptyUri(R.drawable.ic_repo_app_default) - .displayer(new FadeInBitmapDisplayer(200, true, true, false)) - .bitmapConfig(Bitmap.Config.RGB_565) - .build(); - ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx) - .discCache(new UnlimitedDiscCache( + .discCache(new LimitedAgeDiscCache( new File(StorageUtils.getCacheDirectory(ctx), "icons"), new FileNameGenerator() { @Override public String generate(String imageUri) { return imageUri.substring( imageUri.lastIndexOf('/') + 1); - } } )) - .defaultDisplayImageOptions(options) + } }, + // 30 days in secs: 30*24*60*60 = 2592000 + 2592000) + ) .threadPoolSize(Runtime.getRuntime().availableProcessors() * 2) .build(); ImageLoader.getInstance().init(config); } - Context ctx; + private Context ctx; // Global list of all known applications. private List apps; diff --git a/src/org/fdroid/fdroid/ManageRepo.java b/src/org/fdroid/fdroid/ManageRepo.java index 63412360a..c0e2c2c77 100644 --- a/src/org/fdroid/fdroid/ManageRepo.java +++ b/src/org/fdroid/fdroid/ManageRepo.java @@ -313,9 +313,8 @@ public class ManageRepo extends ListActivity { @Override public void onClick(DialogInterface dialog, int which) { setResult(Activity.RESULT_CANCELED); - if (isImportingRepo) { - finish(); - } + finish(); + return; } }); alrt.show(); @@ -420,8 +419,54 @@ public class ManageRepo extends ListActivity { if (item.getItemId() == ADD_REPO) { showAddRepo(); return true; - } else if (item.getItemId() == UPDATE_REPOS) { - updateRepos(); + + case REM_REPO: + final List rem_lst = new ArrayList(); + CharSequence[] b = new CharSequence[repos.size()]; + for (int i = 0; i < repos.size(); i++) { + b[i] = repos.get(i).address; + } + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(getString(R.string.repo_delete_title)); + builder.setIcon(android.R.drawable.ic_menu_close_clear_cancel); + builder.setMultiChoiceItems(b, null, + new DialogInterface.OnMultiChoiceClickListener() { + @Override + public void onClick(DialogInterface dialog, + int whichButton, boolean isChecked) { + if (isChecked) { + rem_lst.add(repos.get(whichButton).address); + } else { + rem_lst.remove(repos.get(whichButton).address); + } + } + }); + builder.setPositiveButton(getString(R.string.ok), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int whichButton) { + try { + DB db = DB.getDB(); + removeRepos(rem_lst); + } finally { + DB.releaseDB(); + } + changed = true; + redraw(); + } + }); + builder.setNegativeButton(getString(R.string.cancel), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int whichButton) { + return; + } + }); + AlertDialog alert = builder.create(); + alert.show(); return true; } diff --git a/src/org/fdroid/fdroid/Preferences.java b/src/org/fdroid/fdroid/Preferences.java index 891955b02..d90b46de3 100644 --- a/src/org/fdroid/fdroid/Preferences.java +++ b/src/org/fdroid/fdroid/Preferences.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.prefs.PreferenceChangeListener; import android.content.Context; import android.content.SharedPreferences; @@ -27,7 +26,20 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi preferences.registerOnSharedPreferenceChangeListener(this); } - private static final String PREF_COMPACT_LAYOUT = "compactlayout"; + public static final String PREF_UPD_INTERVAL = "updateInterval"; + public static final String PREF_UPD_WIFI_ONLY = "updateOnWifiOnly"; + public static final String PREF_UPD_NOTIFY = "updateNotify"; + public static final String PREF_UPD_HISTORY = "updateHistoryDays"; + public static final String PREF_ROOTED = "rooted"; + public static final String PREF_INCOMP_VER = "incompatibleVersions"; + public static final String PREF_THEME = "theme"; + public static final String PREF_PERMISSIONS = "showPermissions"; + public static final String PREF_COMPACT_LAYOUT = "compactlayout"; + public static final String PREF_IGN_TOUCH = "ignoreTouchscreen"; + public static final String PREF_CACHE_APK = "cacheDownloaded"; + public static final String PREF_EXPERT = "expert"; + public static final String PREF_DB_SYNC = "dbSyncMode"; + private static final boolean DEFAULT_COMPACT_LAYOUT = false; private boolean compactLayout = DEFAULT_COMPACT_LAYOUT; diff --git a/src/org/fdroid/fdroid/PreferencesActivity.java b/src/org/fdroid/fdroid/PreferencesActivity.java index 1303e9f09..5491ce26c 100644 --- a/src/org/fdroid/fdroid/PreferencesActivity.java +++ b/src/org/fdroid/fdroid/PreferencesActivity.java @@ -21,41 +21,157 @@ package org.fdroid.fdroid; import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceActivity; -import android.preference.Preference.OnPreferenceChangeListener; -import android.preference.ListPreference; import android.preference.CheckBoxPreference; +import android.preference.EditTextPreference; +import android.preference.ListPreference; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.view.MenuItem; import android.support.v4.app.NavUtils; +import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.compat.ActionBarCompat; public class PreferencesActivity extends PreferenceActivity implements - OnPreferenceChangeListener { + OnSharedPreferenceChangeListener { public static final int RESULT_RELOAD = 1; public static final int RESULT_REFILTER = 2; public static final int RESULT_RESTART = 4; private int result = 0; + private static String[] summariesToUpdate = { + Preferences.PREF_UPD_INTERVAL, + Preferences.PREF_UPD_WIFI_ONLY, + Preferences.PREF_UPD_NOTIFY, + Preferences.PREF_UPD_HISTORY, + Preferences.PREF_ROOTED, + Preferences.PREF_INCOMP_VER, + Preferences.PREF_THEME, + Preferences.PREF_PERMISSIONS, + Preferences.PREF_COMPACT_LAYOUT, + Preferences.PREF_IGN_TOUCH, + Preferences.PREF_CACHE_APK, + Preferences.PREF_EXPERT, + Preferences.PREF_DB_SYNC + }; + @Override protected void onCreate(Bundle savedInstanceState) { - ((FDroidApp) getApplication()).applyTheme(this); - super.onCreate(savedInstanceState); ActionBarCompat.create(this).setDisplayHomeAsUpEnabled(true); addPreferencesFromResource(R.xml.preferences); - for (String prefkey : new String[] { - "updateInterval", "rooted", "incompatibleVersions", - "theme" }) { - findPreference(prefkey).setOnPreferenceChangeListener(this); + } + + protected void onoffSummary(String key, int on, int off) { + CheckBoxPreference pref = (CheckBoxPreference)findPreference(key); + if (pref.isChecked()) { + pref.setSummary(on); + } else { + pref.setSummary(off); } - CheckBoxPreference onlyOnWifi = (CheckBoxPreference) - findPreference("updateOnWifiOnly"); - onlyOnWifi.setEnabled(Integer.parseInt( - ((ListPreference)findPreference("updateInterval")) - .getValue()) > 0); + } + + protected void entrySummary(String key) { + ListPreference pref = (ListPreference)findPreference(key); + pref.setSummary(pref.getEntry()); + } + + protected void textSummary(String key) { + EditTextPreference pref = (EditTextPreference)findPreference(key); + pref.setSummary(getString(R.string.update_history_summ, + pref.getText())); + } + + + protected void updateSummary(String key) { + + if (key.equals(Preferences.PREF_UPD_INTERVAL)) { + ListPreference pref = (ListPreference)findPreference( + Preferences.PREF_UPD_INTERVAL); + int interval = Integer.parseInt(pref.getValue().toString()); + Preference onlyOnWifi = findPreference( + Preferences.PREF_UPD_WIFI_ONLY); + onlyOnWifi.setEnabled(interval > 0); + if (interval == 0) { + pref.setSummary(R.string.update_interval_zero); + } else { + pref.setSummary(pref.getEntry()); + } + + } else if (key.equals(Preferences.PREF_UPD_WIFI_ONLY)) { + onoffSummary(key, R.string.automatic_scan_wifi_on, + R.string.automatic_scan_wifi_off); + + } else if (key.equals(Preferences.PREF_UPD_NOTIFY)) { + onoffSummary(key, R.string.notify_on, + R.string.notify_off); + + } else if (key.equals(Preferences.PREF_UPD_HISTORY)) { + textSummary(key); + + } else if (key.equals(Preferences.PREF_PERMISSIONS)) { + onoffSummary(key, R.string.showPermissions_on, + R.string.showPermissions_off); + + } else if (key.equals(Preferences.PREF_COMPACT_LAYOUT)) { + onoffSummary(key, R.string.compactlayout_on, + R.string.compactlayout_off); + + } else if (key.equals(Preferences.PREF_THEME)) { + entrySummary(key); + result |= RESULT_RESTART; + setResult(result); + + } else if (key.equals(Preferences.PREF_INCOMP_VER)) { + onoffSummary(key, R.string.show_incompat_versions_on, + R.string.show_incompat_versions_off); + result ^= RESULT_RELOAD; + setResult(result); + + } else if (key.equals(Preferences.PREF_ROOTED)) { + onoffSummary(key, R.string.rooted_on, + R.string.rooted_off); + result ^= RESULT_REFILTER; + setResult(result); + + } else if (key.equals(Preferences.PREF_IGN_TOUCH)) { + onoffSummary(key, R.string.ignoreTouch_on, + R.string.ignoreTouch_off); + + } else if (key.equals(Preferences.PREF_CACHE_APK)) { + onoffSummary(key, R.string.cache_downloaded_on, + R.string.cache_downloaded_off); + + } else if (key.equals(Preferences.PREF_EXPERT)) { + onoffSummary(key, R.string.expert_on, + R.string.expert_off); + + } else if (key.equals(Preferences.PREF_DB_SYNC)) { + entrySummary(key); + } + } + + @Override + protected void onResume() { + + super.onResume(); + getPreferenceScreen().getSharedPreferences() + .registerOnSharedPreferenceChangeListener( + (OnSharedPreferenceChangeListener)this); + + for (String key : summariesToUpdate) { + updateSummary(key); + } + } + + @Override + protected void onPause() { + super.onPause(); + getPreferenceScreen().getSharedPreferences() + .unregisterOnSharedPreferenceChangeListener(this); } @Override @@ -69,31 +185,10 @@ public class PreferencesActivity extends PreferenceActivity implements } @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - String key = preference.getKey(); - if (key.equals("updateInterval")) { - int interval = Integer.parseInt(newValue.toString()); - CheckBoxPreference onlyOnWifi = (CheckBoxPreference) - findPreference("updateOnWifiOnly"); - onlyOnWifi.setEnabled(interval > 0); - return true; - } - if (key.equals("incompatibleVersions")) { - result ^= RESULT_RELOAD; - setResult(result); - return true; - } - if (key.equals("rooted")) { - result ^= RESULT_REFILTER; - setResult(result); - return true; - } - if (key.equals("theme")) { - result |= RESULT_RESTART; - setResult(result); - return true; - } - return false; + public void onSharedPreferenceChanged( + SharedPreferences sharedPreferences, String key) { + + updateSummary(key); } } diff --git a/src/org/fdroid/fdroid/RepoXMLHandler.java b/src/org/fdroid/fdroid/RepoXMLHandler.java index 1cb4b1b33..bbd3b523e 100644 --- a/src/org/fdroid/fdroid/RepoXMLHandler.java +++ b/src/org/fdroid/fdroid/RepoXMLHandler.java @@ -34,6 +34,8 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.HashMap; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -55,7 +57,8 @@ public class RepoXMLHandler extends DefaultHandler { // The repo we're processing. private DB.Repo repo; - private List apps; + private Map apps; + private List appsList; private DB.App curapp = null; private DB.Apk curapk = null; @@ -89,9 +92,11 @@ public class RepoXMLHandler extends DefaultHandler { private int totalAppCount; - public RepoXMLHandler(DB.Repo repo, List apps, ProgressListener listener) { + public RepoXMLHandler(DB.Repo repo, List appsList, ProgressListener listener) { this.repo = repo; - this.apps = apps; + this.apps = new HashMap(); + for (DB.App app : appsList) this.apps.put(app.id, app); + this.appsList = appsList; pubkey = null; name = null; description = null; @@ -118,18 +123,13 @@ public class RepoXMLHandler extends DefaultHandler { // If we already have this application (must be from scanning a // different repo) then just merge in the apks. - // TODO: Scanning the whole app list like this every time is - // going to be stupid if the list gets very big! - boolean merged = false; - for (DB.App app : apps) { - if (app.id.equals(curapp.id)) { - app.apks.addAll(curapp.apks); - merged = true; - break; - } + DB.App app = apps.get(curapp.id); + if (app != null) { + app.apks.addAll(curapp.apks); + } else { + appsList.add(curapp); + apps.put(curapp.id, curapp); } - if (!merged) - apps.add(curapp); curapp = null; @@ -212,6 +212,8 @@ public class RepoXMLHandler extends DefaultHandler { curapp.detail_bitcoinAddr = str; } else if (curel.equals("litecoin")) { curapp.detail_litecoinAddr = str; + } else if (curel.equals("dogecoin")) { + curapp.detail_dogecoinAddr = str; } else if (curel.equals("flattr")) { curapp.detail_flattrID = str; } else if (curel.equals("web")) { @@ -240,6 +242,8 @@ public class RepoXMLHandler extends DefaultHandler { } catch (NumberFormatException ex) { curapp.curVercode = -1; } + } else if (curel.equals("provides")) { + curapp.provides = DB.CommaSeparatedList.make(str); } else if (curel.equals("categories")) { curapp.categories = DB.CommaSeparatedList.make(str); } else if (curel.equals("antifeatures")) { @@ -358,7 +362,7 @@ public class RepoXMLHandler extends DefaultHandler { // value for the index that was successfully processed, or it may contain // null if none was available. public static String doUpdate(Context ctx, DB.Repo repo, - List apps, StringBuilder newetag, List keeprepos, + List appsList, StringBuilder newetag, List keeprepos, ProgressListener progressListener) { try { @@ -443,7 +447,7 @@ public class RepoXMLHandler extends DefaultHandler { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); - RepoXMLHandler handler = new RepoXMLHandler(repo, apps, progressListener); + RepoXMLHandler handler = new RepoXMLHandler(repo, appsList, progressListener); xr.setContentHandler(handler); File tempIndex = new File(ctx.getFilesDir() + "/tempindex.xml"); diff --git a/src/org/fdroid/fdroid/SearchResults.java b/src/org/fdroid/fdroid/SearchResults.java index e8afcb002..1a3ac216b 100644 --- a/src/org/fdroid/fdroid/SearchResults.java +++ b/src/org/fdroid/fdroid/SearchResults.java @@ -92,11 +92,6 @@ public class SearchResults extends ListActivity { updateView(); } - @Override - protected void onResume() { - super.onResume(); - } - private void updateView() { List matchingids = new ArrayList(); @@ -110,24 +105,20 @@ public class SearchResults extends ListActivity { } List apps = new ArrayList(); - List tapps = ((FDroidApp) getApplication()).getApps(); - for (DB.App tapp : tapps) { + List allApps = ((FDroidApp) getApplication()).getApps(); + for (DB.App app : allApps) { boolean include = false; - for (String tid : matchingids) { - if (tid.equals(tapp.id)) { - include = true; + for (String id : matchingids) { + if (id.equals(app.id)) { + apps.add(app); break; } } - if (include) - apps.add(tapp); - } TextView tv = (TextView) findViewById(R.id.description); String headertext; - try - { + try { if (apps.size() == 0) headertext = String.format(getString(R.string.searchres_noapps), mQuery); diff --git a/src/org/fdroid/fdroid/compat/ActionBarCompat.java b/src/org/fdroid/fdroid/compat/ActionBarCompat.java index 11a3fb6a0..e1c0f2cf1 100644 --- a/src/org/fdroid/fdroid/compat/ActionBarCompat.java +++ b/src/org/fdroid/fdroid/compat/ActionBarCompat.java @@ -1,5 +1,6 @@ package org.fdroid.fdroid.compat; +import android.annotation.TargetApi; import android.app.ActionBar; import android.app.Activity; @@ -35,6 +36,7 @@ class OldActionBarCompatImpl extends ActionBarCompat { } } +@TargetApi(11) class HoneycombActionBarCompatImpl extends ActionBarCompat { private final ActionBar actionBar; diff --git a/src/org/fdroid/fdroid/compat/Compatibility.java b/src/org/fdroid/fdroid/compat/Compatibility.java index 946faf483..5fe507bba 100644 --- a/src/org/fdroid/fdroid/compat/Compatibility.java +++ b/src/org/fdroid/fdroid/compat/Compatibility.java @@ -2,8 +2,6 @@ package org.fdroid.fdroid.compat; import android.os.Build; -import org.fdroid.fdroid.Utils; - public abstract class Compatibility { protected static boolean hasApi(int apiLevel) { diff --git a/src/org/fdroid/fdroid/compat/ContextCompat.java b/src/org/fdroid/fdroid/compat/ContextCompat.java index 668b94b5d..dde5c5ca3 100644 --- a/src/org/fdroid/fdroid/compat/ContextCompat.java +++ b/src/org/fdroid/fdroid/compat/ContextCompat.java @@ -2,6 +2,7 @@ package org.fdroid.fdroid.compat; import java.io.File; +import android.annotation.TargetApi; import android.content.Context; import android.os.Environment; @@ -45,6 +46,7 @@ class OldContextCompatImpl extends ContextCompat { } +@TargetApi(8) class FroyoContextCompatImpl extends ContextCompat { public FroyoContextCompatImpl(Context context) { diff --git a/src/org/fdroid/fdroid/compat/LayoutCompat.java b/src/org/fdroid/fdroid/compat/LayoutCompat.java index ab02d8443..6a57ad033 100644 --- a/src/org/fdroid/fdroid/compat/LayoutCompat.java +++ b/src/org/fdroid/fdroid/compat/LayoutCompat.java @@ -1,6 +1,6 @@ package org.fdroid.fdroid.compat; -import android.widget.RelativeLayout; +import android.annotation.TargetApi; public abstract class LayoutCompat extends Compatibility { @@ -30,6 +30,7 @@ class OldLayoutCompatImpl extends LayoutCompat { } } +@TargetApi(17) class JellyBeanMr1LayoutCompatImpl extends LayoutCompat { @Override diff --git a/src/org/fdroid/fdroid/compat/MenuManager.java b/src/org/fdroid/fdroid/compat/MenuManager.java index ddf760c47..08e2341b2 100644 --- a/src/org/fdroid/fdroid/compat/MenuManager.java +++ b/src/org/fdroid/fdroid/compat/MenuManager.java @@ -1,5 +1,6 @@ package org.fdroid.fdroid.compat; +import android.annotation.TargetApi; import android.app.Activity; abstract public class MenuManager extends Compatibility { @@ -34,6 +35,7 @@ class OldMenuManagerImpl extends MenuManager { } +@TargetApi(11) class HoneycombMenuManagerImpl extends MenuManager { protected HoneycombMenuManagerImpl(Activity activity) { diff --git a/src/org/fdroid/fdroid/compat/PackageManagerCompat.java b/src/org/fdroid/fdroid/compat/PackageManagerCompat.java index 2c5c5d81a..714c5b144 100644 --- a/src/org/fdroid/fdroid/compat/PackageManagerCompat.java +++ b/src/org/fdroid/fdroid/compat/PackageManagerCompat.java @@ -2,11 +2,13 @@ package org.fdroid.fdroid.compat; import java.lang.Exception; +import android.annotation.TargetApi; import android.content.pm.PackageManager; import android.util.Log; public class PackageManagerCompat extends Compatibility { + @TargetApi(11) public static void setInstaller(PackageManager mPm, String app_id) { if (!hasApi(11)) return; try { diff --git a/src/org/fdroid/fdroid/compat/TabManager.java b/src/org/fdroid/fdroid/compat/TabManager.java index e5a7e0a66..e3edeb6da 100644 --- a/src/org/fdroid/fdroid/compat/TabManager.java +++ b/src/org/fdroid/fdroid/compat/TabManager.java @@ -3,6 +3,7 @@ package org.fdroid.fdroid.compat; import java.util.ArrayList; import java.util.List; +import android.annotation.TargetApi; import android.app.ActionBar; import android.app.FragmentTransaction; import android.content.res.Configuration; @@ -98,7 +99,7 @@ class OldTabManagerImpl extends TabManager { TabHost.TabSpec installedTabSpec = tabHost.newTabSpec("installed") .setIndicator( - parent.getString(R.string.tab_installed), + parent.getString(R.string.inst), parent.getResources().getDrawable(android.R.drawable.star_off)) .setContent(factory); @@ -150,6 +151,7 @@ class OldTabManagerImpl extends TabManager { } +@TargetApi(11) class HoneycombTabManagerImpl extends TabManager { protected final ActionBar actionBar; @@ -220,7 +222,6 @@ class HoneycombTabManagerImpl extends TabManager { private Spinner getActionBarSpinner() { if (actionBarSpinner == null && dirtyConfig) { dirtyConfig = false; - long time = System.currentTimeMillis(); actionBarSpinner = findActionBarSpinner(); } return actionBarSpinner; diff --git a/src/org/fdroid/fdroid/views/AppListAdapter.java b/src/org/fdroid/fdroid/views/AppListAdapter.java index 1edb46ed9..78d60e8f7 100644 --- a/src/org/fdroid/fdroid/views/AppListAdapter.java +++ b/src/org/fdroid/fdroid/views/AppListAdapter.java @@ -4,25 +4,45 @@ import java.util.ArrayList; import java.util.List; import android.content.Context; +import android.graphics.Typeface; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; +import android.text.SpannableString; +import android.text.style.StyleSpan; +import android.graphics.Bitmap; import org.fdroid.fdroid.DB; import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.R; import org.fdroid.fdroid.compat.LayoutCompat; +import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; +import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; +import com.nostra13.universalimageloader.core.assist.ImageScaleType; abstract public class AppListAdapter extends BaseAdapter { private List items = new ArrayList(); private Context mContext; + private DisplayImageOptions displayImageOptions; public AppListAdapter(Context context) { mContext = context; + + displayImageOptions = new DisplayImageOptions.Builder() + .cacheInMemory(true) + .cacheOnDisc(true) + .imageScaleType(ImageScaleType.NONE) + .resetViewBeforeLoading(true) + .showImageOnLoading(R.drawable.ic_repo_app_default) + .showImageForEmptyUri(R.drawable.ic_repo_app_default) + .displayer(new FadeInBitmapDisplayer(200, true, true, false)) + .bitmapConfig(Bitmap.Config.RGB_565) + .build(); + } abstract protected boolean showStatusUpdate(); @@ -33,6 +53,10 @@ abstract public class AppListAdapter extends BaseAdapter { items.add(app); } + public void addItems(List apps) { + items.addAll(apps); + } + public void clear() { items.clear(); } @@ -75,37 +99,12 @@ abstract public class AppListAdapter extends BaseAdapter { int visibleOnCompact = compact ? View.VISIBLE : View.GONE; int notVisibleOnCompact = compact ? View.GONE : View.VISIBLE; - LinearLayout iconContainer = (LinearLayout)convertView.findViewById(R.id.status_icons); + layoutIcon(icon, compact); + ImageLoader.getInstance().displayImage(app.iconUrl, icon, + displayImageOptions); - iconContainer.setVisibility(visibleOnCompact); - status.setVisibility(notVisibleOnCompact); - license.setVisibility(notVisibleOnCompact); - layoutSummary(summary); - - ImageLoader.getInstance().displayImage(app.iconUrl, icon); - - if (!compact) { - status.setText(getVersionInfo(app)); - license.setText(app.license); - } else { - ImageView iconInstalled = (ImageView) convertView.findViewById(R.id.icon_status_installed); - ImageView iconUpdates = (ImageView) convertView.findViewById(R.id.icon_status_has_updates); - - iconInstalled.setImageResource(R.drawable.ic_cab_done_holo_dark); - iconUpdates.setImageResource(R.drawable.ic_menu_refresh); - - if (app.toUpdate && showStatusUpdate()) { - iconUpdates.setVisibility(View.VISIBLE); - } else { - iconUpdates.setVisibility(View.GONE); - } - - if (app.installedVerCode > 0 && showStatusInstalled()) { - iconInstalled.setVisibility(View.VISIBLE); - } else { - iconInstalled.setVisibility(View.GONE); - } - } + status.setText(getVersionInfo(app)); + license.setText(app.license); // Disable it all if it isn't compatible... View[] views = { convertView, status, summary, license, name }; @@ -116,51 +115,47 @@ abstract public class AppListAdapter extends BaseAdapter { return convertView; } - /** - * In compact view, the summary sites next to the icon, below the name. - * In non-compact view, it sits under the icon, with some padding pushing - * it away from the left margin. - */ - private void layoutSummary(TextView summaryView) { - - if (Preferences.get().hasCompactLayout()) { - - RelativeLayout.LayoutParams summaryLayout = - new RelativeLayout.LayoutParams( - RelativeLayout.LayoutParams.WRAP_CONTENT, - RelativeLayout.LayoutParams.WRAP_CONTENT); - summaryLayout.addRule(RelativeLayout.BELOW, R.id.name); - summaryLayout.addRule(LayoutCompat.RelativeLayout.END_OF, R.id.icon); - summaryView.setLayoutParams(summaryLayout); - summaryView.setPadding(0,0,0,0); - - } else { - - RelativeLayout.LayoutParams summaryLayout = - new RelativeLayout.LayoutParams( - RelativeLayout.LayoutParams.MATCH_PARENT, - RelativeLayout.LayoutParams.WRAP_CONTENT); - summaryLayout.addRule(RelativeLayout.BELOW, R.id.icon); - summaryView.setLayoutParams(summaryLayout); - float padding = mContext.getResources().getDimension(R.dimen.applist_summary_padding); - summaryView.setPadding((int)padding, 0, 0, 0); - + private String ellipsize(String input, int maxLength) { + if (input == null || input.length() < maxLength+1) { + return input; } + return input.substring(0, maxLength) + "…"; } private String getVersionInfo(DB.App app) { - if (app.installedVersion != null) { - if (app.toUpdate) { - return app.installedVersion + " -> " + app.curApk.version; - } - return app.installedVersion; - } else { - int numav = app.apks.size(); - if (numav == 1) { - return mContext.getString(R.string.n_version_available, numav); - } - return mContext.getString(R.string.n_versions_available, numav); + + if (app.curApk == null) { + return null; } + + if (app.installedVersion == null) { + return ellipsize(app.curApk.version, 12); + } + + if (app.toUpdate && showStatusUpdate()) { + return ellipsize(app.installedVersion, 8) + + " → " + ellipsize(app.curApk.version, 8); + } + + if (app.installedVerCode > 0 && showStatusInstalled()) { + return ellipsize(app.installedVersion, 12) + " ✔"; + } + + return app.installedVersion; + } + + private void layoutIcon(ImageView icon, boolean compact) { + int size = (int)mContext.getResources().getDimension((compact + ? R.dimen.applist_icon_compact_size + : R.dimen.applist_icon_normal_size)); + + RelativeLayout.LayoutParams params = + (RelativeLayout.LayoutParams)icon.getLayoutParams(); + + params.height = size; + params.width = size; + + icon.setLayoutParams(params); } } diff --git a/src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java b/src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java index cd8946490..2df2e7133 100644 --- a/src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java +++ b/src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java @@ -44,7 +44,7 @@ public class AppListFragmentPageAdapter extends FragmentPagerAdapter { case 0: return parent.getString(R.string.tab_noninstalled); case 1: - return parent.getString(R.string.tab_installed); + return parent.getString(R.string.inst); case 2: return parent.getString(R.string.tab_updates) + " (" + parent.getManager().getCanUpdateAdapter().getCount() + ")"; diff --git a/src/org/fdroid/fdroid/views/fragments/AppListFragment.java b/src/org/fdroid/fdroid/views/fragments/AppListFragment.java index 5177c4ac9..98ee1d9b4 100644 --- a/src/org/fdroid/fdroid/views/fragments/AppListFragment.java +++ b/src/org/fdroid/fdroid/views/fragments/AppListFragment.java @@ -16,10 +16,12 @@ import org.fdroid.fdroid.views.AppListView; abstract class AppListFragment extends Fragment implements AdapterView.OnItemClickListener, Preferences.ChangeListener { - private FDroid parent; + protected FDroid parent; protected abstract AppListAdapter getAppListAdapter(); + protected abstract String getFromTitle(); + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -76,6 +78,7 @@ abstract class AppListFragment extends Fragment implements AdapterView.OnItemCli final DB.App app = (DB.App)getAppListAdapter().getItem(position); Intent intent = new Intent(getActivity(), AppDetails.class); intent.putExtra("appid", app.id); + intent.putExtra("from", getFromTitle()); startActivityForResult(intent, FDroid.REQUEST_APPDETAILS); } diff --git a/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java b/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java index 26f34e363..e8a50410a 100644 --- a/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java +++ b/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java @@ -57,4 +57,9 @@ public class AvailableAppsFragment extends AppListFragment implements AdapterVie protected AppListAdapter getAppListAdapter() { return getAppListManager().getAvailableAdapter(); } + + @Override + protected String getFromTitle() { + return getAppListManager().getCurrentCategory(); + } } diff --git a/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java b/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java index a390f365c..1b3ebe9a3 100644 --- a/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java +++ b/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java @@ -5,6 +5,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import org.fdroid.fdroid.R; import org.fdroid.fdroid.views.AppListAdapter; public class CanUpdateAppsFragment extends AppListFragment { @@ -18,4 +19,9 @@ public class CanUpdateAppsFragment extends AppListFragment { protected AppListAdapter getAppListAdapter() { return getAppListManager().getCanUpdateAdapter(); } + + @Override + protected String getFromTitle() { + return parent.getString(R.string.tab_updates); + } } diff --git a/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java b/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java index db3a93cfc..b27bec6b1 100644 --- a/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java +++ b/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java @@ -5,6 +5,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import org.fdroid.fdroid.R; import org.fdroid.fdroid.views.AppListAdapter; public class InstalledAppsFragment extends AppListFragment { @@ -18,4 +19,9 @@ public class InstalledAppsFragment extends AppListFragment { protected AppListAdapter getAppListAdapter() { return getAppListManager().getInstalledAdapter(); } + + @Override + protected String getFromTitle() { + return parent.getString(R.string.inst); + } }