diff --git a/.circleci/config.yml b/.circleci/config.yml index bec559ed2..6bac87a46 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,7 +21,10 @@ jobs: - v1-android- - run: - command: ./gradlew assembleDebug :core:testPlayDebugUnitTest -PdisablePreDex + # To build release, we need to create a temporary keystore that can be used to sign the app + command: | + keytool -noprompt -genkey -v -keystore "app/keystore" -alias alias -storepass password -keypass password -keyalg RSA -validity 10 -dname "CN=antennapod.org, OU=dummy, O=dummy, L=dummy, S=dummy, C=US" + ./gradlew assemblePlayRelease :core:testPlayReleaseUnitTest -PdisablePreDex no_output_timeout: 1800 - store_artifacts: diff --git a/.classpath b/.classpath deleted file mode 100644 index 3a0c88fe4..000000000 --- a/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.project b/.project deleted file mode 100644 index b3b010772..000000000 --- a/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - AntennaPod - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6677e0cd1..000000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: android -jdk: oraclejdk7 - -env: - matrix: - - ANDROID_SDKS=android-19,sysimg-19 ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a -before_install: - - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI - - emulator -avd test -no-skin -no-audio -no-window & - - cp src/de/danoeh/antennapod/util/flattr/FlattrConfig.java.example src/de/danoeh/antennapod/util/flattr/FlattrConfig.java - -before_script: - - chmod -R 777 ./ci/wait_for_emulator.sh - - ./ci/wait_for_emulator.sh - -script: - - gradle connectedAndroidTest diff --git a/.tx/config b/.tx/config index 0659eaff4..922e5c070 100644 --- a/.tx/config +++ b/.tx/config @@ -1,7 +1,7 @@ [main] host = https://www.transifex.com -[antennapod.english] +[antennapod.core-values] source_file = core/src/main/res/values/strings.xml source_lang = en trans.ast_ES = core/src/main/res/values-b+ast/strings.xml @@ -25,14 +25,14 @@ trans.he_IL = core/src/main/res/values-iw-rIL/strings.xml trans.hi_IN = core/src/main/res/values-hi-rIN/strings.xml trans.hu = core/src/main/res/values-hu/strings.xml trans.id = core/src/main/res/values-id/strings.xml -trans.it = core/src/main/res/values-it/strings.xml -trans.it_IT = core/src/main/res/values-it-rIT/strings.xml +trans.it_IT = core/src/main/res/values-it/strings.xml trans.is = core/src/main/res/values-is-rIS/strings.xml trans.ja = core/src/main/res/values-ja/strings.xml trans.kn_IN = core/src/main/res/values-kn-rIN/strings.xml trans.ko = core/src/main/res/values-ko/strings.xml trans.ko_KR = core/src/main/res/values-ko-rKR/strings.xml trans.lt = core/src/main/res/values-lt/strings.xml +trans.mk = core/src/main/res/values-mk/strings.xml trans.nb = core/src/main/res/values-nb/strings.xml trans.no = core/src/main/res/values-no/strings.xml trans.nl = core/src/main/res/values-nl/strings.xml @@ -58,16 +58,75 @@ trans.zh_TW = core/src/main/res/values-zh-rTW/strings.xml trans.zh_HK = core/src/main/res/values-zh-rHK/strings.xml [antennapod.description] -file_filter = app/src/main/play//listing/fulldescription source_file = app/src/main/play/en-US/listing/fulldescription source_lang = en +trans.ar = app/src/main/play/ar/listing/fulldescription +trans.az = app/src/main/play/az-AZ/listing/fulldescription +trans.bg = app/src/main/play/bg/listing/fulldescription +trans.ca = app/src/main/play/ca/listing/fulldescription +trans.cs = app/src/main/play/cs-CZ/listing/fulldescription +trans.da = app/src/main/play/da-DK/listing/fulldescription +trans.de = app/src/main/play/de-DE/listing/fulldescription +trans.el = app/src/main/play/el-GR/listing/fulldescription +trans.es = app/src/main/play/es-ES/listing/fulldescription +trans.et = app/src/main/play/et/listing/fulldescription +trans.fa = app/src/main/play/fa/listing/fulldescription +trans.fr = app/src/main/play/fr-FR/listing/fulldescription +trans.gl = app/src/main/play/gl-ES/listing/fulldescription +trans.hi_IN = app/src/main/play/hi-IN/listing/fulldescription +trans.hu = app/src/main/play/hu-HU/listing/fulldescription +trans.it_IT = app/src/main/play/it-IT/listing/fulldescription +trans.iw = app/src/main/play/iw-IL/listing/fulldescription +trans.ja = app/src/main/play/ja-JP/listing/fulldescription +trans.ko = app/src/main/play/ko-KR/listing/fulldescription +trans.lt = app/src/main/play/lt/listing/fulldescription +trans.nl = app/src/main/play/nl-NL/listing/fulldescription +trans.pl_PL = app/src/main/play/pl-PL/listing/fulldescription +trans.pt_BR = app/src/main/play/pt-BR/listing/fulldescription +trans.pt_PT = app/src/main/play/pt-PT/listing/fulldescription +trans.ro_RO = app/src/main/play/ro/listing/fulldescription +trans.ru_RU = app/src/main/play/ru-RU/listing/fulldescription +trans.sl_SI = app/src/main/play/sl/listing/fulldescription +trans.sv_SE = app/src/main/play/sv-SE/listing/fulldescription +trans.tr = app/src/main/play/tr-TR/listing/fulldescription +trans.uk_UA = app/src/main/play/uk/listing/fulldescription +trans.vi = app/src/main/play/vi/listing/fulldescription +trans.zh_CN = app/src/main/play/zh-CN/listing/fulldescription +trans.zh_TW = app/src/main/play/zh-TW/listing/fulldescription [antennapod.shortdescription] -file_filter = app/src/main/play//listing/shortdescription source_file = app/src/main/play/en-US/listing/shortdescription source_lang = en - -[antennapod.changelog] -file_filter = app/src/main/play//whatsnew -source_file = app/src/main/play/en-US/whatsnew -source_lang = en +trans.ar = app/src/main/play/ar/listing/shortdescription +trans.az = app/src/main/play/az-AZ/listing/shortdescription +trans.bg = app/src/main/play/bg/listing/shortdescription +trans.ca = app/src/main/play/ca/listing/shortdescription +trans.cs = app/src/main/play/cs-CZ/listing/shortdescription +trans.da = app/src/main/play/da-DK/listing/shortdescription +trans.de = app/src/main/play/de-DE/listing/shortdescription +trans.el = app/src/main/play/el-GR/listing/shortdescription +trans.es = app/src/main/play/es-ES/listing/shortdescription +trans.et = app/src/main/play/et/listing/shortdescription +trans.fa = app/src/main/play/fa/listing/shortdescription +trans.fr = app/src/main/play/fr-FR/listing/shortdescription +trans.gl = app/src/main/play/gl-ES/listing/shortdescription +trans.hi_IN = app/src/main/play/hi-IN/listing/shortdescription +trans.hu = app/src/main/play/hu-HU/listing/shortdescription +trans.it_IT = app/src/main/play/it-IT/listing/shortdescription +trans.iw = app/src/main/play/iw-IL/listing/shortdescription +trans.ja = app/src/main/play/ja-JP/listing/shortdescription +trans.ko = app/src/main/play/ko-KR/listing/shortdescription +trans.lt = app/src/main/play/lt/listing/shortdescription +trans.nl = app/src/main/play/nl-NL/listing/shortdescription +trans.pl_PL = app/src/main/play/pl-PL/listing/shortdescription +trans.pt_BR = app/src/main/play/pt-BR/listing/shortdescription +trans.pt_PT = app/src/main/play/pt-PT/listing/shortdescription +trans.ro_RO = app/src/main/play/ro/listing/shortdescription +trans.ru_RU = app/src/main/play/ru-RU/listing/shortdescription +trans.sl_SI = app/src/main/play/sl/listing/shortdescription +trans.sv_SE = app/src/main/play/sv-SE/listing/shortdescription +trans.tr = app/src/main/play/tr-TR/listing/shortdescription +trans.uk_UA = app/src/main/play/uk/listing/shortdescription +trans.vi = app/src/main/play/vi/listing/shortdescription +trans.zh_CN = app/src/main/play/zh-CN/listing/shortdescription +trans.zh_TW = app/src/main/play/zh-TW/listing/shortdescription diff --git a/CHANGELOG.md b/CHANGELOG.md index a050dd9c9..2899d1fd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,25 @@ Change Log ========== + +Version 1.7.1 +------------- + +* Fix for database corruption + +Version 1.7.0 +------------- + +* NEW ExoPlayer (experimental) +* Fix for Bluetooth Forward (Oreo) +* Preference redesign + search +* Notification improvements +* Different screens for feed info and settings +* Sort Queue with Random or Smart Shuffle +* True Black Theme for AMOLED +* Improvements to feed parsing +* Fix for app being killed by Android Oreo + Version 1.6.5 ------------- diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 837c412c5..891a9784c 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1,107 +1,168 @@ DEVELOPERS ========== +Alan Orth Alexander Terczka +alifeflow +amhokies +Anders Bo Rasmussen Andrew Gaul Andrey Krutov Anthony Lieuallen axq +brad ByteHamster +Cameron Banga Christian Ludwig Christopher Szucko +Cj Malone Colin Willson +Cédric Cabessa +Danial Klimkin Daniel Oeh David Carver David Reiss Dean Brettle dethstar +Dirk Mueller Domingos Lopes drabux +egsavage +EirikV Eoin Mcloughlin +eraymond Ercan Erden +Falko Lehmann +Hannes Achleitner +hannesa2 Hanno Zulla heckler01 Holger Jeromin +Humberto Fraga +InsidE James Falcon +Jan Niehusmann +Jens Klingenberg Jens Müller Johan Liesén +Kaligule Katrin Leinweber -keunes +Kevin Dalley Koen Glotzbach +kroegerama +Kurian Vithayathil LatinSuD Lee Yeong Khang lightonflux ligi +Luis Cruz +Marc Lasson Martin Fietz Martin Olsson mat tso +mateoeh +Matthew Gaffen Matthias Schütz +Maurice Gilden +Meir Schwarz Michael Kaiser Michael Scarito Mike Chelen +minusf +MolarAmbiguity Mounir Lamouri +mr-intj Nis Wechselberg +Oliver Crow +orelogo Paul Ortyl +Raghul +Raghul Jagannathan recalculated Ross Harrison +Sam Lee Sam Whited +saqura +Selivanov Pavel +Serge Seth Golub +sevenmaster +Shantana Hardy Simon Danner Simon Rutishauser Simon Schubert +Soso Tughushi +Spencer Visick Stefan Mitrik Terence Eden Tim Butram Tobias Preuss Tom Hennen +Tom Tom tommy watson +tuxayo twiceyuan Udi Finkelstein +VarunBarad volhol Volker Hollich WangYun William Seemann +ydinath TRANSLATORS =========== -Arabic: abuzar3.khalid, iDemo -Azerbaijani: phoenixar -Catalan: dvd1985, javiercoll, xc70 -Catalan (Spain): javiercoll -Chinese (China): bebeauties38, dudeG, Felix2yu, gaohongyuan, Guaidaodl, linxiangyu, molisiye, tupunco, wongsyrone, yangyang, YogaGuru +Arabic: abdelrahman.fahem93, abdunnasir, abuzar3.khalid, desha, iDemo, mohamedagamy, msahouli, nabilMaghura +Asturian (Spain): enolp +Azerbaijani: danieloeh, kotfenix +Bulgarian: solusitor +Catalan: dvd1985, exort12, javiercoll, lambdani, marcmetallextrem, xc70 +Catalan (Spain): 00c0c0, javiercoll +Chinese: dillonbecker, RainSlide, xukeek, yangyang +Chinese (China): bebeauties38, domingos86, dudeG, ErlichLiu, Felix2yu, gaohongyuan, Guaidaodl, Huck0, iconteral, jhxie, kavdx, kyleehee, linxiangyu, molisiye, owen8877, RainSlide, stellaxuyi, tupunco, wi24rd, wongsyrone, xukeek, yangyang, yiqiok, YogaGuru +Chinese (Taiwan): gugod, nigelinux, pggdt, ymhuang0808 Czech (Czech Republic): elich, Hanzmeister, mcepl, petnek, svetlemodry -Danish: CasperHN -Dutch: e2jk, glotzbach, rwv +Danish: CasperHN, jhertel +Dutch: e2jk, glotzbach, rwv, Vistaus English: mfietz, sterylmreep +Estonian: Eraser Finnish: danieloeh -French: cactux, ChaoticMind, clombion, e2jk, lacouture, Matth78, mfietz, repat, sterylmreep, vcariven -German: 112358, altegedanken, bitsunited, ChaoticMind, Chaquotay, dab0015, DJaeger, HolgerJeromin, kalei, lohmann, mfietz, nilso, picsel2, repat, SAPlayer, schafia, ypid -Greek: AlexanderKanetakis -Hebrew (Israel): amir.dafnyman -Hindi (India): purple.coder, siddhusengar -Hungarian: glatz.balazs, naren93 -Indonesian: luke137, silvanael16 -Italian: aalex70, apanontin, Guybrush88, theloca95 -Italian (Italy): aalex70, apanontin, Guybrush88, m.chinni, theloca95 +French: cactux, ChaoticMind, clombion, e2jk, lacouture, Matth78, mfietz, Poussinou, PRIMOKORN, repat, sterylmreep, TacoTheDank, Tilwa, vcariven, whenrow +Galician: antiparvos, pikamoku, Raichely +German: 112358, altegedanken, barilla, bitsunited, Buggi, ceving, ChaoticMind, Chaquotay, dab0015, dadosch, DerSilly, DJaeger, elkangaroo, enz, fidel, finsterwalder, Foso, GNi33, HolgerJeromin, kalei, lohmann, LostInWeb, mfietz, nilso, repat, SAPlayer, schafia, Schroedingberg, sevenmaster, sucaml, Teaspoon, theonlytruth, weltenwort, Wyrrrd, ypid +Greek: antonist, danieloeh, hua2016s, MSavoritias, pavlosv +Hebrew (Israel): amir.dafnyman, E1i9, mongoose4004, pinkasey, rellieberman, Yaron, הלוי11 +Hindi (India): nmabhinandan, purple.coder, siddhusengar +Hungarian: glatz.balazs, lna91, naren93, tszauer, ttyborg42 +Icelandic: marthjod +Indonesian: jff, luke137, rezafaiza, silvanael16 +Italian: aalex70, allin, apanontin, Bonnee, giuseppep, Guybrush88, marco_pag, neonsoftware, sevenmaster, theloca95 +Italian (Italy): aalex70, allin, apanontin, Bonnee, buongiorgio, giuseppep, Guybrush88, m.chinni, neonsoftware, nixxo, sevenmaster, theloca95 Japanese: Naofumi, RACER1, sh3llc4t, TranslatorG Kannada (India): thejeshgn -Korean: changwoo, halcyonest, seungrye, skcha +Korean: changwoo, seungrye, skcha Korean (South Korea): changwoo, seungrye +Lithuanian: naglis +Macedonian: krisfremen Norwegian: hakonanes, timbast -Norwegian Bokmål: hakonanes -Norwegian Bokmål (Norway): hakonanes, kongk, swordfighter, timbast -Polish: Iwangelion, maniexx, thedead4fun -Polish (Poland): Iwangelion, lomapur, maniexx, Mephistofeles, shark103, tyle -Portuguese: emansije, smarquespt -Portuguese (Brazil): alexupits, edman, Firmino, lipefire, lucasmotacr, mbaltar, rogervezaro, SamWilliam, silvanael16 -Romanian (Romania): corneliu.e, fuzzmz -Russian (Russia): astra1, Duke_Raven, mercutiy, null, overmind88, phoenixar, s.chebotar, skvheadless, whereisthetea, zhenya97 -Spanish: coperfix, dvd1985, Fitoschido, frandavid100, javiercoll, LatinSuD, tres.14159 -Spanish (Spain): dvd1985, e2jk, frandavid100 -Swedish (Sweden): albin.brantin, Bio, bpnilsson, ChaoticMind, Lumen, nilso, SharpMelon, TwoD -Turkish: basarancaner, brsata, overbite -Ukrainian (Ukraine): older, zhenya97 -Vietnamese: ppanhh, vietnamesel10n +Norwegian Bokmål: corkie, hakonanes +Norwegian Bokmål (Norway): corkie, hakonanes, kongk, timbast +Persian: ahangarha, F7D +Polish: Iwangelion, maniexx, mfloryan, thedead4fun +Polish (Poland): d6210809, Iwangelion, lomapur, mandlus, maniexx, Mephistofeles, shark103, tyle +Portuguese: domingos86, emansije, smarquespt +Portuguese (Brazil): alexupits, alysonborges, arua, caioau, carlo_valente, castrors, deandreamatias, edman, Firmino, jackmiras, Junin, lipefire, lluccia, lucasmotacr, mbaltar, rogervezaro, RubeensVinicius, SamWilliam, silvanael16 +Romanian (Romania): corneliu.e, fuzzmz, ralienpp +Russian (Russia): astra1, btimofeev, Duke_Raven, GaynullinDima, MegMasters98, mercutiy, null, overmind88, s.chebotar, shams4real, skvheadless, un_logic, whereisthetea, zhenya97 +Slovenian (Slovenia): panter23 +Spanish: AleksSyntek, coperfix, deandreamatias, domingos86, dvd1985, Fitoschido, frandavid100, hard_ware, javiercoll, Juanmuto, lambdani, LatinSuD, leogrignafini, palopezv, TacoTheDank, tres.14159, wakutiteo +Spanish (Spain): dvd1985, e2jk, frandavid100, hard_ware, palopezv, Raichely, TacoTheDank +Swahili (Kenya): BonfaceKilz +Swedish (Sweden): albin.brantin, Bio, bpnilsson, ChaoticMind, jony08, nilso, SharpMelon, TwoD +Telugu: veeven +Turkish: basarancaner, brsata, Erdy, golcuk, overbite +Ukrainian (Ukraine): older, sergiyr, zhenya97 +Vietnamese: abnvolk, nguyenvui, ppanhh, vietnamesel10n Vietnamese (Vietnam): bizover diff --git a/README.md b/README.md index 23d7e06d5..b84022e1f 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This is the official repository of AntennaPod, the easy-to-use, flexible and ope [Get it on Google Play](https://play.google.com/store/apps/details?id=de.danoeh.antennapod) -[Get it on F-Droid](https://f-droid.org/app/de.danoeh.antennapod) diff --git a/app/build.gradle b/app/build.gradle index 6c8abbdff..3299ab715 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,49 +1,27 @@ -import org.apache.tools.ant.filters.ReplaceTokens +plugins { + id('com.github.triplet.play') version '2.0.0' +} apply plugin: "com.android.application" -apply plugin: 'com.github.triplet.play' apply plugin: 'com.getkeepsafe.dexcount' -repositories { - maven { url "https://jitpack.io" } - mavenCentral() -} - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2' - } -} - -def getMyVersionName() { - def parsedManifestXml = (new XmlSlurper()) - .parse("${projectDir}/src/main/AndroidManifest.xml") - .declareNamespace(android: "http://schemas.android.com/apk/res/android") - return parsedManifestXml."@android:versionName" -} - -def getMyVersionCode() { - def parsedManifestXml = (new XmlSlurper()) - .parse("${projectDir}/src/main/AndroidManifest.xml") - .declareNamespace(android: "http://schemas.android.com/apk/res/android") - return parsedManifestXml."@android:versionCode".toInteger() -} +import org.apache.tools.ant.filters.ReplaceTokens android { compileSdkVersion rootProject.ext.compileSdkVersion - buildToolsVersion rootProject.ext.buildToolsVersion defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled true - versionCode getMyVersionCode() - versionName "${getMyVersionName()}" + vectorDrawables.useSupportLibrary true + // Version code schema: + // "1.2.3-SNAPSHOT" -> 1020300 + // "1.2.3-RC4" -> 1020304 + versionCode 1070196 + versionName "1.7.1" testApplicationId "de.test.antennapod" - testInstrumentationRunner "de.test.antennapod.AntennaPodTestRunner" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" generatedDensities = [] } @@ -95,7 +73,7 @@ android { release { resValue "string", "provider_authority", "de.danoeh.antennapod.provider" minifyEnabled true - proguardFile "proguard.cfg" + proguardFiles getDefaultProguardFile('proguard-android.txt'), "proguard.cfg" signingConfig signingConfigs.releaseConfig buildConfigField STRING, FLATTR_APP_KEY, mFlattrAppKey buildConfigField STRING, FLATTR_APP_SECRET, mFlattrAppSecret @@ -120,6 +98,10 @@ android { additionalParameters "--no-version-vectors" } + testOptions { + animationsDisabled = true + } + flavorDimensions "market" productFlavors { free { @@ -150,6 +132,7 @@ dependencies { implementation "com.android.support:gridlayout-v7:$supportVersion" implementation "com.android.support:percent:$supportVersion" implementation "com.android.support:recyclerview-v7:$supportVersion" + compileOnly 'com.google.android.wearable:wearable:2.2.0' implementation "org.apache.commons:commons-lang3:$commonslangVersion" implementation("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") { exclude group: "org.json", module: "json" @@ -157,14 +140,14 @@ dependencies { implementation "commons-io:commons-io:$commonsioVersion" implementation "org.jsoup:jsoup:$jsoupVersion" implementation "com.github.bumptech.glide:glide:$glideVersion" + annotationProcessor "com.github.bumptech.glide:compiler:$glideVersion" implementation "com.squareup.okhttp3:okhttp:$okhttpVersion" implementation "com.squareup.okhttp3:okhttp-urlconnection:$okhttpVersion" implementation "com.squareup.okio:okio:$okioVersion" implementation "de.greenrobot:eventbus:$eventbusVersion" - implementation "io.reactivex:rxandroid:$rxAndroidVersion" - implementation "io.reactivex:rxjava:$rxJavaVersion" - // And ProGuard rules for RxJava! - implementation "com.artemzin.rxjava:proguard-rules:$rxJavaRulesVersion" + implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion" + implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" + implementation "com.joanzapata.iconify:android-iconify-fontawesome:$iconifyVersion" implementation "com.joanzapata.iconify:android-iconify-material:$iconifyVersion" implementation("com.afollestad.material-dialogs:commons:$materialDialogsVersion") { @@ -176,18 +159,33 @@ dependencies { } implementation "com.github.shts:TriangleLabelView:$triangleLabelViewVersion" + implementation 'com.leinardi.android:speed-dial:1.0.2' // 1.0.2 uses support 27.1.1 ; newer versions use 28.0.0; implementation "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion" - implementation 'com.github.mfietz:fyydlin:v0.3' - implementation 'com.github.ByteHamster:SearchPreference:v1.0.8' + implementation 'com.github.mfietz:fyydlin:v0.4.2' + implementation 'com.github.ByteHamster:SearchPreference:v1.2.5' + implementation "org.awaitility:awaitility:$awaitilityVersion" androidTestImplementation "com.jayway.android.robotium:robotium-solo:$robotiumSoloVersion" + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-intents:3.0.2' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test:rules:1.0.2' } play { - serviceAccountEmail = '522080222319-compute@developer.gserviceaccount.com' - pk12File = file('../serviceaccount-c3d7d0f61387.p12') + if (project.hasProperty("antennaPodServiceAccountEmail")) { + serviceAccountEmail = antennaPodServiceAccountEmail + } else { + serviceAccountEmail = '522080222319-compute@developer.gserviceaccount.com' + } + if (project.hasProperty("antennaPodPk12File")) { + serviceAccountCredentials = file(antennaPodPk12File) + } else { + serviceAccountCredentials = file('../serviceaccount-c3d7d0f61387.p12') + } } // about.html is templatized so that we can automatically insert @@ -217,10 +215,3 @@ task copyTextFiles(type: Copy) { preBuild.dependsOn filterAbout, copyTextFiles -allprojects { - gradle.projectsEvaluated { - tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint" << "-Xlint:-deprecation" << "-Xlint:-serial" - } - } -} diff --git a/app/proguard.cfg b/app/proguard.cfg index 01b1708f7..6df2ae9bf 100644 --- a/app/proguard.cfg +++ b/app/proguard.cfg @@ -53,8 +53,12 @@ public *; } +# for okhttp -dontwarn okhttp3.** -dontwarn okio.** +-dontwarn javax.annotation.** +-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase +-dontwarn org.codehaus.mojo.animal_sniffer.* # for RxJava: -dontwarn sun.misc.Unsafe @@ -71,8 +75,6 @@ -dontwarn android.support.v7.** -dontwarn com.google.android.wearable.** --keepattributes *Annotation* - -keep class org.shredzone.flattr4j.** { *; } -dontwarn org.shredzone.flattr4j.** @@ -94,16 +96,19 @@ -keepclassmembers class ** { public void onEvent*(**); } +-keep class de.danoeh.antennapod.core.event.* # android-iconify -keep class com.joanzapata.** { *; } # Glide -keep public class * implements com.bumptech.glide.module.GlideModule --keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { - **[] $VALUES; - public *; +-keep public class * extends com.bumptech.glide.module.AppGlideModule +-keep public enum com.bumptech.glide.load.ImageHeaderParser$** { + **[] $VALUES; + public *; } +-dontwarn com.bumptech.glide.load.resource.bitmap.VideoDecoder # for ViewPageIndicator problems (https://github.com/JakeWharton/ViewPagerIndicator/issues/366): -dontwarn com.viewpagerindicator.LinePageIndicator @@ -125,3 +130,13 @@ -keep class com.squareup.moshi.** { *; } -keep interface com.squareup.moshi.** { *; } -keep public class retrofit2.adapter.rxjava.RxJavaCallAdapterFactory { *; } + +# awaitility +-dontwarn java.beans.BeanInfo +-dontwarn java.beans.Introspector +-dontwarn java.beans.IntrospectionException +-dontwarn java.beans.PropertyDescriptor +-dontwarn java.lang.management.ManagementFactory +-dontwarn java.lang.management.ThreadInfo +-dontwarn java.lang.management.ThreadMXBean + diff --git a/app/sampledata/episodes.json b/app/sampledata/episodes.json new file mode 100644 index 000000000..209cbf180 --- /dev/null +++ b/app/sampledata/episodes.json @@ -0,0 +1,34 @@ +{ + "data": [ + { + "title": "FLOSS Weekly 482: PyPI", + "status_label": "NEW", + "duration": "00:52:40", + "published_at": "2. May" + }, + { + "title": "FLOSS Weekly 479: Pidgin", + "status_label": " ", + "duration": "01:08:08", + "published_at": "11. Apr" + }, + { + "title": "Linux Outlaws 370 - Stay Free, Stay Open Source", + "status_label": "NEW", + "duration": "02:52:51", + "published_at": "29. Dec 2014" + }, + { + "title": "Linux Outlaws 368 - The Dark Ages of Free Software", + "status_label": " ", + "duration": "02:26:54", + "published_at": "14. Dec 2014" + }, + { + "title": "Linux Outlaws 365 - Last Stand", + "status_label": " ", + "duration": "00:39:59", + "published_at": "3. Nov 2014" + } + ] +} diff --git a/app/sampledata/inplaylist b/app/sampledata/inplaylist new file mode 100644 index 000000000..e78406d75 --- /dev/null +++ b/app/sampledata/inplaylist @@ -0,0 +1,2 @@ +@null +@drawable/ic_list_grey600_24dp \ No newline at end of file diff --git a/app/sampledata/secondaryaction b/app/sampledata/secondaryaction new file mode 100644 index 000000000..26083bc9c --- /dev/null +++ b/app/sampledata/secondaryaction @@ -0,0 +1,3 @@ +@drawable/ic_play_arrow_grey600_36dp +@drawable/ic_file_download_grey600_24dp +@drawable/ic_cancel_grey600_24dp \ No newline at end of file diff --git a/app/src/androidTest/java/de/test/antennapod/AntennaPodTestRunner.java b/app/src/androidTest/java/de/test/antennapod/AntennaPodTestRunner.java deleted file mode 100644 index c321e6494..000000000 --- a/app/src/androidTest/java/de/test/antennapod/AntennaPodTestRunner.java +++ /dev/null @@ -1,18 +0,0 @@ -package de.test.antennapod; - -import android.test.InstrumentationTestRunner; -import android.test.suitebuilder.TestSuiteBuilder; - -import junit.framework.TestSuite; - -public class AntennaPodTestRunner extends InstrumentationTestRunner { - - @Override - public TestSuite getAllTests() { - return new TestSuiteBuilder(AntennaPodTestRunner.class) - .includeAllPackagesUnderHere() - .excludePackages("de.test.antennapod.gpodnet") - .build(); - } - -} diff --git a/app/src/androidTest/java/de/test/antennapod/NthMatcher.java b/app/src/androidTest/java/de/test/antennapod/NthMatcher.java new file mode 100644 index 000000000..f9ecacda5 --- /dev/null +++ b/app/src/androidTest/java/de/test/antennapod/NthMatcher.java @@ -0,0 +1,38 @@ +package de.test.antennapod; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; + +import java.util.concurrent.atomic.AtomicInteger; + +public class NthMatcher { + public static Matcher first(final Matcher matcher) { + return nth(matcher, 1); + } + + public static Matcher second(final Matcher matcher) { + return nth(matcher, 2); + } + + private static Matcher nth(final Matcher matcher, final int index) { + return new BaseMatcher() { + AtomicInteger count = new AtomicInteger(0); + + @Override + public boolean matches(final Object item) { + if (matcher.matches(item)) { + if (count.incrementAndGet() == index) { + return true; + } + } + return false; + } + + @Override + public void describeTo(final Description description) { + description.appendText("should return first matching item"); + } + }; + } +} diff --git a/app/src/androidTest/java/de/test/antennapod/feed/FeedItemTest.java b/app/src/androidTest/java/de/test/antennapod/feed/FeedItemTest.java index db463132d..ced0d7a28 100644 --- a/app/src/androidTest/java/de/test/antennapod/feed/FeedItemTest.java +++ b/app/src/androidTest/java/de/test/antennapod/feed/FeedItemTest.java @@ -1,6 +1,7 @@ package de.test.antennapod.feed; import android.test.AndroidTestCase; + import de.danoeh.antennapod.core.feed.FeedItem; public class FeedItemTest extends AndroidTestCase { diff --git a/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java b/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java index a880c330b..91e31e73c 100644 --- a/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java +++ b/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java @@ -1,43 +1,43 @@ package de.test.antennapod.gpodnet; -import android.test.AndroidTestCase; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import android.support.test.runner.AndroidJUnit4; import de.danoeh.antennapod.core.gpoddernet.GpodnetService; import de.danoeh.antennapod.core.gpoddernet.GpodnetServiceException; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetDevice; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetTag; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; import static java.util.Collections.singletonList; /** * Test class for GpodnetService */ -public class GPodnetServiceTest extends AndroidTestCase { +@Ignore +@RunWith(AndroidJUnit4.class) +public class GPodnetServiceTest { private GpodnetService service; private static final String USER = ""; private static final String PW = ""; - @Override - protected void setUp() throws Exception { - super.setUp(); + @Before + protected void setUp() { service = new GpodnetService(); } - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - private void authenticate() throws GpodnetServiceException { service.authenticate(USER, PW); } + @Test public void testUploadSubscription() throws GpodnetServiceException { authenticate(); ArrayList l = new ArrayList<>(); @@ -45,6 +45,7 @@ public class GPodnetServiceTest extends AndroidTestCase { service.uploadSubscriptions(USER, "radio", l); } + @Test public void testUploadSubscription2() throws GpodnetServiceException { authenticate(); ArrayList l = new ArrayList<>(); @@ -53,6 +54,7 @@ public class GPodnetServiceTest extends AndroidTestCase { service.uploadSubscriptions(USER, "radio", l); } + @Test public void testUploadChanges() throws GpodnetServiceException { authenticate(); String[] URLS = {"http://bitsundso.de/feed", "http://gamesundso.de/feed", "http://cre.fm/feed/mp3/", "http://freakshow.fm/feed/m4a/"}; @@ -63,53 +65,63 @@ public class GPodnetServiceTest extends AndroidTestCase { service.uploadChanges(USER, "radio", added, removed); } + @Test public void testGetSubscriptionChanges() throws GpodnetServiceException { authenticate(); service.getSubscriptionChanges(USER, "radio", 1362322610L); } + @Test public void testGetSubscriptionsOfUser() throws GpodnetServiceException { authenticate(); service.getSubscriptionsOfUser(USER); } + @Test public void testGetSubscriptionsOfDevice() throws GpodnetServiceException { authenticate(); service.getSubscriptionsOfDevice(USER, "radio"); } + @Test public void testConfigureDevices() throws GpodnetServiceException { authenticate(); service.configureDevice(USER, "foo", "This is an updated caption", GpodnetDevice.DeviceType.LAPTOP); } + @Test public void testGetDevices() throws GpodnetServiceException { authenticate(); service.getDevices(USER); } + @Test public void testGetSuggestions() throws GpodnetServiceException { authenticate(); service.getSuggestions(10); } + @Test public void testTags() throws GpodnetServiceException { service.getTopTags(20); } + @Test public void testPodcastForTags() throws GpodnetServiceException { List tags = service.getTopTags(20); service.getPodcastsForTag(tags.get(1), 10); } + @Test public void testSearch() throws GpodnetServiceException { service.searchPodcasts("linux", 64); } + @Test public void testToplist() throws GpodnetServiceException { service.getPodcastToplist(10); } diff --git a/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java b/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java index 39abe4b7a..9419d2318 100644 --- a/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java @@ -1,6 +1,7 @@ package de.test.antennapod.handler; import android.content.Context; +import android.support.test.InstrumentationRegistry; import android.test.InstrumentationTestCase; import org.xml.sax.SAXException; @@ -17,7 +18,6 @@ import javax.xml.parsers.ParserConfigurationException; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.syndication.handler.FeedHandler; @@ -37,7 +37,7 @@ public class FeedHandlerTest extends InstrumentationTestCase { protected void setUp() throws Exception { super.setUp(); - Context context = getInstrumentation().getContext(); + Context context = InstrumentationRegistry.getTargetContext(); File destDir = context.getExternalFilesDir(FEEDS_DIR); assertNotNull(destDir); @@ -82,15 +82,7 @@ public class FeedHandlerTest extends InstrumentationTestCase { assertEquals(feed.getLink(), parsedFeed.getLink()); assertEquals(feed.getDescription(), parsedFeed.getDescription()); assertEquals(feed.getPaymentLink(), parsedFeed.getPaymentLink()); - - if (feed.getImage() != null) { - FeedImage image = feed.getImage(); - FeedImage parsedImage = parsedFeed.getImage(); - assertNotNull(parsedImage); - - assertEquals(image.getTitle(), parsedImage.getTitle()); - assertEquals(image.getDownload_url(), parsedImage.getDownload_url()); - } + assertEquals(feed.getImageUrl(), parsedFeed.getImageUrl()); if (feed.getItems() != null) { assertNotNull(parsedFeed.getItems()); @@ -119,14 +111,7 @@ public class FeedHandlerTest extends InstrumentationTestCase { assertEquals(media.getMime_type(), parsedMedia.getMime_type()); } - if (item.hasItemImage()) { - assertTrue(parsedItem.hasItemImage()); - FeedImage image = item.getImage(); - FeedImage parsedImage = parsedItem.getImage(); - - assertEquals(image.getTitle(), parsedImage.getTitle()); - assertEquals(image.getDownload_url(), parsedImage.getDownload_url()); - } + assertEquals(item.getImageUrl(), parsedFeed.getImageUrl()); if (item.getChapters() != null) { assertNotNull(parsedItem.getChapters()); @@ -158,12 +143,8 @@ public class FeedHandlerTest extends InstrumentationTestCase { } private Feed createTestFeed(int numItems, boolean withImage, boolean withFeedMedia, boolean withChapters) { - FeedImage image = null; - if (withImage) { - image = new FeedImage(0, "image", null, "http://example.com/picture", false); - } Feed feed = new Feed(0, null, "title", "http://example.com", "This is the description", - "http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", image, file.getAbsolutePath(), + "http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", "http://example.com/picture", file.getAbsolutePath(), "http://example.com/feed", true); feed.setItems(new ArrayList<>()); diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java index 93a9408b7..9cd7689ba 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java @@ -5,7 +5,6 @@ import android.test.FlakyTest; import android.test.InstrumentationTestCase; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.List; diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java index c9c715a86..a577e5e36 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java @@ -21,6 +21,7 @@ import de.danoeh.antennapod.core.util.flattr.FlattrStatus; */ class DBTestUtils { + private DBTestUtils(){} /** * Use this method when tests don't involve chapters. */ diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java index b1cc807ea..27d76116d 100644 --- a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java +++ b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java @@ -1,10 +1,14 @@ package de.test.antennapod.storage; import android.content.Context; +import android.content.SharedPreferences; import android.database.Cursor; +import android.preference.PreferenceManager; import android.test.InstrumentationTestCase; import android.util.Log; +import org.awaitility.Awaitility; + import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -15,15 +19,14 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.feed.SimpleChapter; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.PodDBAdapter; +import de.danoeh.antennapod.core.util.Consumer; /** * Test class for DBWriter @@ -58,6 +61,12 @@ public class DBWriterTest extends InstrumentationTestCase { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); adapter.close(); + + Context context = getInstrumentation().getTargetContext(); + SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit(); + prefEdit.putBoolean(UserPreferences.PREF_DELETE_REMOVES_FROM_QUEUE, true).commit(); + + UserPreferences.init(context); } public void testSetFeedMediaPlaybackInformation() @@ -124,89 +133,54 @@ public class DBWriterTest extends InstrumentationTestCase { assertNull(media.getFile_url()); } - public void testDeleteFeed() throws IOException, ExecutionException, InterruptedException, TimeoutException { - File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); - assertNotNull(destFolder); + public void testDeleteFeedMediaOfItemRemoveFromQueue() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + assertTrue(UserPreferences.shouldDeleteRemoveFromQueue()); + + File dest = new File(getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile"); + + assertTrue(dest.createNewFile()); Feed feed = new Feed("url", null, "title"); - feed.setItems(new ArrayList<>()); + List items = new ArrayList<>(); + List queue = new ArrayList<>(); + feed.setItems(items); + FeedItem item = new FeedItem(0, "Item", "Item", "url", new Date(), FeedItem.UNPLAYED, feed); - // create Feed image - File imgFile = new File(destFolder, "image"); - assertTrue(imgFile.createNewFile()); - FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true); - image.setOwner(feed); - feed.setImage(image); + FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", dest.getAbsolutePath(), "download_url", true, null, 0, 0); + item.setMedia(media); - List itemFiles = new ArrayList<>(); - // create items with downloaded media files - for (int i = 0; i < 10; i++) { - FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed, true); - feed.getItems().add(item); - - File enc = new File(destFolder, "file " + i); - assertTrue(enc.createNewFile()); - itemFiles.add(enc); - - FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", enc.getAbsolutePath(), "download_url", true, null, 0, 0); - item.setMedia(media); - - item.setChapters(new ArrayList<>()); - item.getChapters().add(new SimpleChapter(0, "item " + i, item, "example.com")); - } + items.add(item); + queue.add(item); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); adapter.setCompleteFeed(feed); + adapter.setQueue(queue); adapter.close(); + assertTrue(media.getId() != 0); + assertTrue(item.getId() != 0); + queue = DBReader.getQueue(); + assertTrue(queue.size() != 0); - assertTrue(feed.getId() != 0); - assertTrue(feed.getImage().getId() != 0); - for (FeedItem item : feed.getItems()) { - assertTrue(item.getId() != 0); - assertTrue(item.getMedia().getId() != 0); - assertTrue(item.getChapters().get(0).getId() != 0); - } - - DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); - - // check if files still exist - assertFalse(imgFile.exists()); - for (File f : itemFiles) { - assertFalse(f.exists()); - } - - adapter = PodDBAdapter.getInstance(); - adapter.open(); - Cursor c = adapter.getFeedCursor(feed.getId()); - assertEquals(0, c.getCount()); - c.close(); - c = adapter.getImageCursor(String.valueOf(image.getId())); - assertEquals(0, c.getCount()); - c.close(); - for (FeedItem item : feed.getItems()) { - c = adapter.getFeedItemCursor(String.valueOf(item.getId())); - assertEquals(0, c.getCount()); - c.close(); - c = adapter.getSingleFeedMediaCursor(item.getMedia().getId()); - assertEquals(0, c.getCount()); - c.close(); - c = adapter.getSimpleChaptersOfFeedItemCursor(item); - assertEquals(0, c.getCount()); - c.close(); - } - adapter.close(); + DBWriter.deleteFeedMediaOfItem(getInstrumentation().getTargetContext(), media.getId()); + Awaitility.await().until(() -> dest.exists() == false); + media = DBReader.getFeedMedia(media.getId()); + assertNotNull(media); + assertFalse(dest.exists()); + assertFalse(media.isDownloaded()); + assertNull(media.getFile_url()); + queue = DBReader.getQueue(); + assertTrue(queue.size() == 0); } - public void testDeleteFeedNoImage() throws ExecutionException, InterruptedException, IOException, TimeoutException { + public void testDeleteFeed() throws ExecutionException, InterruptedException, IOException, TimeoutException { File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); assertNotNull(destFolder); Feed feed = new Feed("url", null, "title"); feed.setItems(new ArrayList<>()); - feed.setImage(null); - List itemFiles = new ArrayList<>(); // create items with downloaded media files for (int i = 0; i < 10; i++) { @@ -261,13 +235,7 @@ public class DBWriterTest extends InstrumentationTestCase { Feed feed = new Feed("url", null, "title"); feed.setItems(null); - - // create Feed image - File imgFile = new File(destFolder, "image"); - assertTrue(imgFile.createNewFile()); - FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true); - image.setOwner(feed); - feed.setImage(image); + feed.setImageUrl("url"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); @@ -275,21 +243,14 @@ public class DBWriterTest extends InstrumentationTestCase { adapter.close(); assertTrue(feed.getId() != 0); - assertTrue(feed.getImage().getId() != 0); DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); - // check if files still exist - assertFalse(imgFile.exists()); - adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor c = adapter.getFeedCursor(feed.getId()); assertTrue(c.getCount() == 0); c.close(); - c = adapter.getImageCursor(String.valueOf(image.getId())); - assertTrue(c.getCount() == 0); - c.close(); adapter.close(); } @@ -300,12 +261,7 @@ public class DBWriterTest extends InstrumentationTestCase { Feed feed = new Feed("url", null, "title"); feed.setItems(new ArrayList<>()); - // create Feed image - File imgFile = new File(destFolder, "image"); - assertTrue(imgFile.createNewFile()); - FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true); - image.setOwner(feed); - feed.setImage(image); + feed.setImageUrl("url"); // create items for (int i = 0; i < 10; i++) { @@ -320,24 +276,18 @@ public class DBWriterTest extends InstrumentationTestCase { adapter.close(); assertTrue(feed.getId() != 0); - assertTrue(feed.getImage().getId() != 0); for (FeedItem item : feed.getItems()) { assertTrue(item.getId() != 0); } DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); - // check if files still exist - assertFalse(imgFile.exists()); adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor c = adapter.getFeedCursor(feed.getId()); assertTrue(c.getCount() == 0); c.close(); - c = adapter.getImageCursor(String.valueOf(image.getId())); - assertTrue(c.getCount() == 0); - c.close(); for (FeedItem item : feed.getItems()) { c = adapter.getFeedItemCursor(String.valueOf(item.getId())); assertTrue(c.getCount() == 0); @@ -346,65 +296,6 @@ public class DBWriterTest extends InstrumentationTestCase { adapter.close(); } - public void testDeleteFeedWithItemImages() throws InterruptedException, ExecutionException, TimeoutException, IOException { - File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); - assertNotNull(destFolder); - - Feed feed = new Feed("url", null, "title"); - feed.setItems(new ArrayList<>()); - - // create Feed image - File imgFile = new File(destFolder, "image"); - assertTrue(imgFile.createNewFile()); - FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true); - image.setOwner(feed); - feed.setImage(image); - - // create items with images - for (int i = 0; i < 10; i++) { - FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed); - feed.getItems().add(item); - File itemImageFile = new File(destFolder, "item-image-" + i); - FeedImage itemImage = new FeedImage(0, "item-image" + i, itemImageFile.getAbsolutePath(), "url", true); - item.setImage(itemImage); - } - - PodDBAdapter adapter = PodDBAdapter.getInstance(); - adapter.open(); - adapter.setCompleteFeed(feed); - adapter.close(); - - assertTrue(feed.getId() != 0); - assertTrue(feed.getImage().getId() != 0); - for (FeedItem item : feed.getItems()) { - assertTrue(item.getId() != 0); - assertTrue(item.getImage().getId() != 0); - } - - DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS); - - // check if files still exist - assertFalse(imgFile.exists()); - - adapter = PodDBAdapter.getInstance(); - adapter.open(); - Cursor c = adapter.getFeedCursor(feed.getId()); - assertTrue(c.getCount() == 0); - c.close(); - c = adapter.getImageCursor(String.valueOf(image.getId())); - assertTrue(c.getCount() == 0); - c.close(); - for (FeedItem item : feed.getItems()) { - c = adapter.getFeedItemCursor(String.valueOf(item.getId())); - assertTrue(c.getCount() == 0); - c.close(); - c = adapter.getImageCursor(String.valueOf(item.getImage().getId())); - assertEquals(0, c.getCount()); - c.close(); - } - adapter.close(); - } - public void testDeleteFeedWithQueueItems() throws ExecutionException, InterruptedException, TimeoutException { File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER); assertNotNull(destFolder); @@ -412,11 +303,7 @@ public class DBWriterTest extends InstrumentationTestCase { Feed feed = new Feed("url", null, "title"); feed.setItems(new ArrayList<>()); - // create Feed image - File imgFile = new File(destFolder, "image"); - FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true); - image.setOwner(feed); - feed.setImage(image); + feed.setImageUrl("url"); List itemFiles = new ArrayList<>(); // create items with downloaded media files @@ -437,7 +324,6 @@ public class DBWriterTest extends InstrumentationTestCase { adapter.close(); assertTrue(feed.getId() != 0); - assertTrue(feed.getImage().getId() != 0); for (FeedItem item : feed.getItems()) { assertTrue(item.getId() != 0); assertTrue(item.getMedia().getId() != 0); @@ -460,9 +346,6 @@ public class DBWriterTest extends InstrumentationTestCase { Cursor c = adapter.getFeedCursor(feed.getId()); assertTrue(c.getCount() == 0); c.close(); - c = adapter.getImageCursor(String.valueOf(image.getId())); - assertTrue(c.getCount() == 0); - c.close(); for (FeedItem item : feed.getItems()) { c = adapter.getFeedItemCursor(String.valueOf(item.getId())); assertTrue(c.getCount() == 0); @@ -484,11 +367,7 @@ public class DBWriterTest extends InstrumentationTestCase { Feed feed = new Feed("url", null, "title"); feed.setItems(new ArrayList<>()); - // create Feed image - File imgFile = new File(destFolder, "image"); - FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true); - image.setOwner(feed); - feed.setImage(image); + feed.setImageUrl("url"); List itemFiles = new ArrayList<>(); // create items with downloaded media files @@ -509,7 +388,6 @@ public class DBWriterTest extends InstrumentationTestCase { adapter.close(); assertTrue(feed.getId() != 0); - assertTrue(feed.getImage().getId() != 0); for (FeedItem item : feed.getItems()) { assertTrue(item.getId() != 0); assertTrue(item.getMedia().getId() != 0); @@ -522,9 +400,6 @@ public class DBWriterTest extends InstrumentationTestCase { Cursor c = adapter.getFeedCursor(feed.getId()); assertTrue(c.getCount() == 0); c.close(); - c = adapter.getImageCursor(String.valueOf(image.getId())); - assertTrue(c.getCount() == 0); - c.close(); for (FeedItem item : feed.getItems()) { c = adapter.getFeedItemCursor(String.valueOf(item.getId())); assertTrue(c.getCount() == 0); @@ -700,29 +575,16 @@ public class DBWriterTest extends InstrumentationTestCase { public void testRemoveQueueItem() throws InterruptedException, ExecutionException, TimeoutException { final int NUM_ITEMS = 10; final Context context = getInstrumentation().getTargetContext(); - Feed feed = new Feed("url", null, "title"); - feed.setItems(new ArrayList<>()); - for (int i = 0; i < NUM_ITEMS; i++) { - FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), FeedItem.PLAYED, feed); - feed.getItems().add(item); - } + Feed feed = createTestFeed(NUM_ITEMS); - PodDBAdapter adapter = PodDBAdapter.getInstance(); - adapter.open(); - adapter.setCompleteFeed(feed); - adapter.close(); - - for (FeedItem item : feed.getItems()) { - assertTrue(item.getId() != 0); - } for (int removeIndex = 0; removeIndex < NUM_ITEMS; removeIndex++) { final FeedItem item = feed.getItems().get(removeIndex); - adapter = PodDBAdapter.getInstance(); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); adapter.setQueue(feed.getItems()); adapter.close(); - DBWriter.removeQueueItem(context, item, false).get(TIMEOUT, TimeUnit.SECONDS); + DBWriter.removeQueueItem(context, false, item).get(TIMEOUT, TimeUnit.SECONDS); adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor queue = adapter.getQueueIDCursor(); @@ -742,6 +604,43 @@ public class DBWriterTest extends InstrumentationTestCase { } } + public void testRemoveQueueItemMultipleItems() throws InterruptedException, ExecutionException, TimeoutException { + // Setup test data + // + final int NUM_ITEMS = 5; + final int NUM_IN_QUEUE = NUM_ITEMS - 1; // the last one not in queue for boundary condition + final Context context = getInstrumentation().getTargetContext(); + Feed feed = createTestFeed(NUM_ITEMS); + + List itemsToAdd = feed.getItems().subList(0, NUM_IN_QUEUE); + withPodDB(adapter -> adapter.setQueue(itemsToAdd) ); + + // Actual tests + // + + // Use array rather than List to make codes more succinct + Long[] itemIds = toItemIds(feed.getItems()).toArray(new Long[0]); + + DBWriter.removeQueueItem(context, false, + itemIds[1], itemIds[3]).get(TIMEOUT, TimeUnit.SECONDS); + assertQueueByItemIds("Average case - 2 items removed successfully", + itemIds[0], itemIds[2]); + + DBWriter.removeQueueItem(context, false).get(TIMEOUT, TimeUnit.SECONDS); + assertQueueByItemIds("Boundary case - no items supplied. queue should see no change", + itemIds[0], itemIds[2]); + + DBWriter.removeQueueItem(context, false, + itemIds[0], itemIds[4], -1L).get(TIMEOUT, TimeUnit.SECONDS); + assertQueueByItemIds("Boundary case - items not in queue ignored", + itemIds[2]); + + DBWriter.removeQueueItem(context, false, + itemIds[2], -1L).get(TIMEOUT, TimeUnit.SECONDS); + assertQueueByItemIds("Boundary case - invalid itemIds ignored"); // the queue is empty + + } + public void testMoveQueueItem() throws InterruptedException, ExecutionException, TimeoutException { final int NUM_ITEMS = 10; Feed feed = new Feed("url", null, "title"); @@ -839,4 +738,53 @@ public class DBWriterTest extends InstrumentationTestCase { assertTrue(item.isPlayed()); } } + + private static Feed createTestFeed(int numItems) { + Feed feed = new Feed("url", null, "title"); + feed.setItems(new ArrayList<>()); + for (int i = 0; i < numItems; i++) { + FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), FeedItem.PLAYED, feed); + feed.getItems().add(item); + } + + withPodDB(adapter -> adapter.setCompleteFeed(feed)); + + for (FeedItem item : feed.getItems()) { + assertTrue(item.getId() != 0); + } + return feed; + } + + private static void withPodDB(Consumer action) { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + try { + adapter.open(); + action.accept(adapter); + } finally { + adapter.close(); + } + } + + private static void assertQueueByItemIds( + String message, + long... itemIdsExpected + ) { + List queue = DBReader.getQueue(); + List itemIdsActualList = toItemIds(queue); + List itemIdsExpectedList = new ArrayList(itemIdsExpected.length); + for (long id : itemIdsExpected) { + itemIdsExpectedList.add(id); + } + + assertEquals(message, itemIdsExpectedList, itemIdsActualList); + } + + private static List toItemIds(List items) { + List itemIds = new ArrayList(items.size()); + for(FeedItem item : items) { + itemIds.add(item.getId()); + } + return itemIds; + } + } diff --git a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java index 6156da926..9a60b04b8 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java @@ -2,16 +2,14 @@ package de.test.antennapod.ui; import android.content.Context; import android.content.SharedPreferences; -import android.test.ActivityInstrumentationTestCase2; -import android.test.FlakyTest; +import android.support.test.espresso.contrib.DrawerActions; +import android.support.test.espresso.intent.Intents; +import android.support.test.filters.FlakyTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; import android.widget.ListView; - import com.robotium.solo.Solo; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - +import com.robotium.solo.Timeout; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.OnlineFeedViewActivity; @@ -23,25 +21,46 @@ import de.danoeh.antennapod.fragment.DownloadsFragment; import de.danoeh.antennapod.fragment.EpisodesFragment; import de.danoeh.antennapod.fragment.PlaybackHistoryFragment; import de.danoeh.antennapod.fragment.QueueFragment; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.longClick; +import static android.support.test.espresso.intent.Intents.intended; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static de.test.antennapod.NthMatcher.first; +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertEquals; /** * User interface tests for MainActivity */ -public class MainActivityTest extends ActivityInstrumentationTestCase2 { +@RunWith(AndroidJUnit4.class) +public class MainActivityTest { private Solo solo; private UITestUtils uiTestUtils; - private SharedPreferences prefs; - public MainActivityTest() { - super(MainActivity.class); - } + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule<>(MainActivity.class); - @Override - protected void setUp() throws Exception { - super.setUp(); - Context context = getInstrumentation().getTargetContext(); + @Before + public void setUp() throws IOException { + Intents.init(); + Context context = mActivityRule.getActivity(); uiTestUtils = new UITestUtils(context); uiTestUtils.setup(); @@ -54,30 +73,26 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2()); openNavDrawer(); - solo.clickLongOnText(solo.getString(R.string.queue_label)); - solo.waitForDialogToOpen(); - solo.clickOnText(solo.getString(R.string.episodes_label)); - solo.clickOnText(solo.getString(R.string.playback_history_label)); - solo.clickOnText(solo.getString(R.string.confirm_label)); - solo.waitForDialogToClose(); + onView(first(withText(R.string.queue_label))).perform(longClick()); + onView(withText(R.string.episodes_label)).perform(click()); + onView(withText(R.string.playback_history_label)).perform(click()); + onView(withText(R.string.confirm_label)).perform(click()); + List hidden = UserPreferences.getHiddenDrawerItems(); assertEquals(2, hidden.size()); assertTrue(hidden.contains(EpisodesFragment.TAG)); assertTrue(hidden.contains(PlaybackHistoryFragment.TAG)); } + @Test public void testDrawerPreferencesUnhideSomeElements() { List hidden = Arrays.asList(PlaybackHistoryFragment.TAG, DownloadsFragment.TAG); UserPreferences.setHiddenDrawerItems(hidden); openNavDrawer(); - solo.clickLongOnText(solo.getString(R.string.queue_label)); - solo.waitForDialogToOpen(); - solo.clickOnText(solo.getString(R.string.downloads_label)); - solo.clickOnText(solo.getString(R.string.queue_label)); - solo.clickOnText(solo.getString(R.string.confirm_label)); - solo.waitForDialogToClose(); + onView(first(withText(R.string.queue_label))).perform(longClick()); + + onView(withText(R.string.downloads_label)).perform(click()); + onView(withText(R.string.queue_label)).perform(click()); + onView(withText(R.string.confirm_label)).perform(click()); + hidden = UserPreferences.getHiddenDrawerItems(); assertEquals(2, hidden.size()); assertTrue(hidden.contains(QueueFragment.TAG)); assertTrue(hidden.contains(PlaybackHistoryFragment.TAG)); } + + @Test public void testDrawerPreferencesHideAllElements() { UserPreferences.setHiddenDrawerItems(new ArrayList<>()); - String[] titles = getInstrumentation().getTargetContext().getResources().getStringArray(R.array.nav_drawer_titles); + String[] titles = mActivityRule.getActivity().getResources().getStringArray(R.array.nav_drawer_titles); openNavDrawer(); - solo.clickLongOnText(solo.getString(R.string.queue_label)); - solo.waitForDialogToOpen(); + onView(first(withText(R.string.queue_label))).perform(longClick()); for (String title : titles) { - solo.clickOnText(title); + onView(first(withText(title))).perform(click()); } - solo.clickOnText(solo.getString(R.string.confirm_label)); - solo.waitForDialogToClose(); + onView(withText(R.string.confirm_label)).perform(click()); + List hidden = UserPreferences.getHiddenDrawerItems(); assertEquals(titles.length, hidden.size()); for (String tag : MainActivity.NAV_DRAWER_TAGS) { @@ -208,21 +228,85 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2()); + openNavDrawer(); + onView(withText(R.string.downloads_label)).perform(click()); + openNavDrawer(); + + onView(first(withText(R.string.queue_label))).perform(longClick()); + onView(first(withText(R.string.downloads_label))).perform(click()); + onView(withText(R.string.confirm_label)).perform(click()); - openNavDrawer(); - String downloads = solo.getString(R.string.downloads_label); - solo.clickOnText(downloads); - solo.waitForView(android.R.id.list); - openNavDrawer(); - solo.clickLongOnText(downloads); - solo.waitForDialogToOpen(); - solo.clickOnText(downloads); - solo.clickOnText(solo.getString(R.string.confirm_label)); - solo.waitForDialogToClose(); List hidden = UserPreferences.getHiddenDrawerItems(); assertEquals(1, hidden.size()); assertTrue(hidden.contains(DownloadsFragment.TAG)); } + + @Test + public void testBackButtonBehaviorGoToPage() { + openNavDrawer(); + solo.clickOnText(solo.getString(R.string.settings_label)); + solo.clickOnText(solo.getString(R.string.user_interface_label)); + solo.clickOnText(solo.getString(R.string.pref_back_button_behavior_title)); + solo.clickOnText(solo.getString(R.string.back_button_go_to_page)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.subscriptions_label)); + solo.clickOnText(solo.getString(R.string.confirm_label)); + solo.goBackToActivity(MainActivity.class.getSimpleName()); + solo.goBack(); + assertEquals(solo.getString(R.string.subscriptions_label), getActionbarTitle()); + } + + @Test + public void testBackButtonBehaviorOpenDrawer() { + openNavDrawer(); + solo.clickOnText(solo.getString(R.string.settings_label)); + solo.clickOnText(solo.getString(R.string.user_interface_label)); + solo.clickOnText(solo.getString(R.string.pref_back_button_behavior_title)); + solo.clickOnText(solo.getString(R.string.back_button_open_drawer)); + solo.goBackToActivity(MainActivity.class.getSimpleName()); + solo.goBack(); + assertTrue(((MainActivity)solo.getCurrentActivity()).isDrawerOpen()); + } + + @Test + public void testBackButtonBehaviorDoubleTap() { + openNavDrawer(); + solo.clickOnText(solo.getString(R.string.settings_label)); + solo.clickOnText(solo.getString(R.string.user_interface_label)); + solo.clickOnText(solo.getString(R.string.pref_back_button_behavior_title)); + solo.clickOnText(solo.getString(R.string.back_button_double_tap)); + solo.goBackToActivity(MainActivity.class.getSimpleName()); + solo.goBack(); + solo.goBack(); + assertTrue(solo.getCurrentActivity().isFinishing()); + } + + @Test + public void testBackButtonBehaviorPrompt() { + openNavDrawer(); + solo.clickOnText(solo.getString(R.string.settings_label)); + solo.clickOnText(solo.getString(R.string.user_interface_label)); + solo.clickOnText(solo.getString(R.string.pref_back_button_behavior_title)); + solo.clickOnText(solo.getString(R.string.back_button_show_prompt)); + solo.goBackToActivity(MainActivity.class.getSimpleName()); + solo.goBack(); + solo.clickOnText(solo.getString(R.string.yes)); + solo.waitForDialogToClose(); + assertTrue(solo.getCurrentActivity().isFinishing()); + } + + @Test + public void testBackButtonBehaviorDefault() { + openNavDrawer(); + solo.clickOnText(solo.getString(R.string.settings_label)); + solo.clickOnText(solo.getString(R.string.user_interface_label)); + solo.clickOnText(solo.getString(R.string.pref_back_button_behavior_title)); + solo.clickOnText(solo.getString(R.string.back_button_default)); + solo.goBackToActivity(MainActivity.class.getSimpleName()); + solo.goBack(); + assertTrue(solo.getCurrentActivity().isFinishing()); + } } diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java index 293ed2848..55ed998bb 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java @@ -59,7 +59,7 @@ public class PlaybackSonicTest extends ActivityInstrumentationTestCase2 { - - private static final String TAG = "PreferencesTest"; +import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; +@RunWith(AndroidJUnit4.class) +public class PreferencesTest { private Solo solo; - private Context context; private Resources res; + private SharedPreferences prefs; - public PreferencesTest() { - super(PreferenceActivity.class); - } + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule<>(PreferenceActivity.class); - @Override - public void setUp() throws Exception { - super.setUp(); - solo = new Solo(getInstrumentation(), getActivity()); + @Before + public void setUp() { + solo = new Solo(getInstrumentation(), mActivityRule.getActivity()); Timeout.setSmallTimeout(500); Timeout.setLargeTimeout(1000); - context = getInstrumentation().getTargetContext(); - res = getActivity().getResources(); - UserPreferences.init(context); + res = mActivityRule.getActivity().getResources(); + UserPreferences.init(mActivityRule.getActivity()); + + prefs = PreferenceManager.getDefaultSharedPreferences(mActivityRule.getActivity()); + prefs.edit().clear(); + prefs.edit().putBoolean(UserPreferences.PREF_ENABLE_AUTODL, true).commit(); } - @Override - public void tearDown() throws Exception { + @After + public void tearDown() { solo.finishOpenedActivities(); - super.tearDown(); + prefs.edit().clear(); } + @Test public void testSwitchTheme() { final int theme = UserPreferences.getTheme(); int otherTheme; @@ -55,13 +78,13 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 UserPreferences.getTheme() != theme, Timeout.getLargeTimeout())); } + @Test public void testSwitchThemeBack() { final int theme = UserPreferences.getTheme(); int otherTheme; @@ -70,33 +93,23 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 UserPreferences.getTheme() != theme, Timeout.getLargeTimeout())); } - public void testExpandNotification() { - solo.clickOnText(solo.getString(R.string.user_interface_label)); - final int priority = UserPreferences.getNotifyPriority(); - solo.clickOnText(solo.getString(R.string.pref_expandNotify_title)); - assertTrue(solo.waitForCondition(() -> priority != UserPreferences.getNotifyPriority(), Timeout.getLargeTimeout())); - solo.clickOnText(solo.getString(R.string.pref_expandNotify_title)); - assertTrue(solo.waitForCondition(() -> priority == UserPreferences.getNotifyPriority(), Timeout.getLargeTimeout())); - } - + @Test public void testEnablePersistentPlaybackControls() { - solo.clickOnText(solo.getString(R.string.user_interface_label)); final boolean persistNotify = UserPreferences.isPersistNotify(); - solo.scrollDown(); - solo.scrollDown(); - solo.clickOnText(solo.getString(R.string.pref_persistNotify_title)); + clickPreference(withText(R.string.user_interface_label)); + clickPreference(withText(R.string.pref_persistNotify_title)); assertTrue(solo.waitForCondition(() -> persistNotify != UserPreferences.isPersistNotify(), Timeout.getLargeTimeout())); - solo.clickOnText(solo.getString(R.string.pref_persistNotify_title)); + clickPreference(withText(R.string.pref_persistNotify_title)); assertTrue(solo.waitForCondition(() -> persistNotify == UserPreferences.isPersistNotify(), Timeout.getLargeTimeout())); } + @Test public void testSetLockscreenButtons() { solo.clickOnText(solo.getString(R.string.user_interface_label)); solo.scrollDown(); @@ -123,6 +136,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 !UserPreferences.showSkipOnCompactNotification(), Timeout.getLargeTimeout())); } + @Test public void testEnqueueAtFront() { solo.clickOnText(solo.getString(R.string.playback_pref)); final boolean enqueueAtFront = UserPreferences.enqueueAtFront(); @@ -134,6 +148,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 enqueueAtFront == UserPreferences.enqueueAtFront(), Timeout.getLargeTimeout())); } + @Test public void testHeadPhonesDisconnect() { solo.clickOnText(solo.getString(R.string.playback_pref)); final boolean pauseOnHeadsetDisconnect = UserPreferences.isPauseOnHeadsetDisconnect(); @@ -143,6 +158,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 pauseOnHeadsetDisconnect == UserPreferences.isPauseOnHeadsetDisconnect(), Timeout.getLargeTimeout())); } + @Test public void testHeadPhonesReconnect() { solo.clickOnText(solo.getString(R.string.playback_pref)); if(UserPreferences.isPauseOnHeadsetDisconnect() == false) { @@ -156,6 +172,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 unpauseOnHeadsetReconnect == UserPreferences.isUnpauseOnHeadsetReconnect(), Timeout.getLargeTimeout())); } + @Test public void testBluetoothReconnect() { solo.clickOnText(solo.getString(R.string.playback_pref)); if(UserPreferences.isPauseOnHeadsetDisconnect() == false) { @@ -169,6 +186,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 unpauseOnBluetoothReconnect == UserPreferences.isUnpauseOnBluetoothReconnect(), Timeout.getLargeTimeout())); } + @Test public void testContinuousPlayback() { solo.clickOnText(solo.getString(R.string.playback_pref)); final boolean continuousPlayback = UserPreferences.isFollowQueue(); @@ -180,6 +198,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 continuousPlayback == UserPreferences.isFollowQueue(), Timeout.getLargeTimeout())); } + @Test public void testAutoDelete() { solo.clickOnText(solo.getString(R.string.storage_pref)); final boolean autoDelete = UserPreferences.isAutoDelete(); @@ -189,17 +208,15 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 autoDelete == UserPreferences.isAutoDelete(), Timeout.getLargeTimeout())); } + @Test public void testPlaybackSpeeds() { - solo.clickOnText(solo.getString(R.string.playback_pref)); - solo.scrollDown(); - solo.scrollDown(); - solo.clickOnText(solo.getString(R.string.pref_playback_speed_title)); - solo.waitForDialogToOpen(1000); + clickPreference(withText(R.string.playback_pref)); + clickPreference(withText(R.string.pref_playback_speed_title)); assertTrue(solo.searchText(res.getStringArray(R.array.playback_speed_values)[0])); - solo.clickOnText(solo.getString(R.string.cancel_label)); - solo.waitForDialogToClose(1000); + onView(withText(R.string.cancel_label)).perform(click()); } + @Test public void testPauseForInterruptions() { solo.clickOnText(solo.getString(R.string.playback_pref)); final boolean pauseForFocusLoss = UserPreferences.shouldPauseForFocusLoss(); @@ -209,6 +226,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 pauseForFocusLoss == UserPreferences.shouldPauseForFocusLoss(), Timeout.getLargeTimeout())); } + @Test public void testDisableUpdateInterval() { solo.clickOnText(solo.getString(R.string.network_pref)); solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_sum)); @@ -217,31 +235,31 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 UserPreferences.getUpdateInterval() == 0, 1000)); } + @Test public void testSetUpdateInterval() { - solo.clickOnText(solo.getString(R.string.network_pref)); - solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_title)); - solo.waitForDialogToOpen(); - solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_Interval)); - solo.waitForDialogToOpen(); + clickPreference(withText(R.string.network_pref)); + clickPreference(withText(R.string.pref_autoUpdateIntervallOrTime_title)); + onView(withText(R.string.pref_autoUpdateIntervallOrTime_Interval)).perform(click()); String search = "12 " + solo.getString(R.string.pref_update_interval_hours_plural); - solo.clickOnText(search); - solo.waitForDialogToClose(); + onView(withText(search)).perform(click()); assertTrue(solo.waitForCondition(() -> UserPreferences.getUpdateInterval() == TimeUnit.HOURS.toMillis(12), Timeout.getLargeTimeout())); } + @Test public void testMobileUpdates() { - solo.clickOnText(solo.getString(R.string.network_pref)); + clickPreference(withText(R.string.network_pref)); final boolean mobileUpdates = UserPreferences.isAllowMobileUpdate(); - solo.clickOnText(solo.getString(R.string.pref_mobileUpdate_title)); + clickPreference(withText(R.string.pref_mobileUpdate_title)); assertTrue(solo.waitForCondition(() -> mobileUpdates != UserPreferences.isAllowMobileUpdate(), Timeout.getLargeTimeout())); - solo.clickOnText(solo.getString(R.string.pref_mobileUpdate_title)); + clickPreference(withText(R.string.pref_mobileUpdate_title)); assertTrue(solo.waitForCondition(() -> mobileUpdates == UserPreferences.isAllowMobileUpdate(), Timeout.getLargeTimeout())); } + @Test public void testSetSequentialDownload() { - solo.clickOnText(solo.getString(R.string.network_pref)); - solo.clickOnText(solo.getString(R.string.pref_parallel_downloads_title)); + clickPreference(withText(R.string.network_pref)); + clickPreference(withText(R.string.pref_parallel_downloads_title)); solo.waitForDialogToOpen(); solo.clearEditText(0); solo.enterText(0, "1"); @@ -249,9 +267,10 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 UserPreferences.getParallelDownloads() == 1, Timeout.getLargeTimeout())); } + @Test public void testSetParallelDownloads() { - solo.clickOnText(solo.getString(R.string.network_pref)); - solo.clickOnText(solo.getString(R.string.pref_parallel_downloads_title)); + clickPreference(withText(R.string.network_pref)); + clickPreference(withText(R.string.pref_parallel_downloads_title)); solo.waitForDialogToOpen(); solo.clearEditText(0); solo.enterText(0, "10"); @@ -259,50 +278,50 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 UserPreferences.getParallelDownloads() == 10, Timeout.getLargeTimeout())); } + @Test public void testSetParallelDownloadsInvalidInput() { - solo.clickOnText(solo.getString(R.string.network_pref)); - solo.clickOnText(solo.getString(R.string.pref_parallel_downloads_title)); + clickPreference(withText(R.string.network_pref)); + clickPreference(withText(R.string.pref_parallel_downloads_title)); solo.waitForDialogToOpen(); solo.clearEditText(0); solo.enterText(0, "0"); - assertEquals("1", solo.getEditText(0).getText().toString()); + assertEquals("", solo.getEditText(0).getText().toString()); solo.clearEditText(0); solo.enterText(0, "100"); - assertEquals("50", solo.getEditText(0).getText().toString()); + assertEquals("", solo.getEditText(0).getText().toString()); } + @Test public void testSetEpisodeCache() { String[] entries = res.getStringArray(R.array.episode_cache_size_entries); String[] values = res.getStringArray(R.array.episode_cache_size_values); String entry = entries[entries.length/2]; final int value = Integer.valueOf(values[values.length/2]); - solo.clickOnText(solo.getString(R.string.network_pref)); - solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); - solo.waitForText(solo.getString(R.string.pref_automatic_download_title)); - solo.clickOnText(solo.getString(R.string.pref_episode_cache_title)); + clickPreference(withText(R.string.network_pref)); + clickPreference(withText(R.string.pref_automatic_download_title)); + clickPreference(withText(R.string.pref_episode_cache_title)); solo.waitForDialogToOpen(); solo.clickOnText(entry); assertTrue(solo.waitForCondition(() -> UserPreferences.getEpisodeCacheSize() == value, Timeout.getLargeTimeout())); } + @Test public void testSetEpisodeCacheMin() { String[] entries = res.getStringArray(R.array.episode_cache_size_entries); String[] values = res.getStringArray(R.array.episode_cache_size_values); String minEntry = entries[0]; final int minValue = Integer.valueOf(values[0]); - solo.clickOnText(solo.getString(R.string.network_pref)); - solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); - solo.waitForText(solo.getString(R.string.pref_automatic_download_title)); - if(!UserPreferences.isEnableAutodownload()) { - solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); - } - solo.clickOnText(solo.getString(R.string.pref_episode_cache_title)); + + clickPreference(withText(R.string.network_pref)); + clickPreference(withText(R.string.pref_automatic_download_title)); + clickPreference(withText(R.string.pref_episode_cache_title)); solo.waitForDialogToOpen(1000); solo.scrollUp(); solo.clickOnText(minEntry); assertTrue(solo.waitForCondition(() -> UserPreferences.getEpisodeCacheSize() == minValue, Timeout.getLargeTimeout())); } + @Test public void testSetEpisodeCacheMax() { String[] entries = res.getStringArray(R.array.episode_cache_size_entries); String[] values = res.getStringArray(R.array.episode_cache_size_values); @@ -311,24 +330,22 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 UserPreferences.getEpisodeCacheSize() == maxValue, Timeout.getLargeTimeout())); } + @Test public void testAutomaticDownload() { final boolean automaticDownload = UserPreferences.isEnableAutodownload(); - solo.clickOnText(solo.getString(R.string.network_pref)); - solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); - solo.waitForText(solo.getString(R.string.pref_automatic_download_title)); - solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); + clickPreference(withText(R.string.network_pref)); + clickPreference(withText(R.string.pref_automatic_download_title)); + clickPreference(withText(R.string.pref_automatic_download_title)); + assertTrue(solo.waitForCondition(() -> automaticDownload != UserPreferences.isEnableAutodownload(), Timeout.getLargeTimeout())); if(UserPreferences.isEnableAutodownload() == false) { - solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); + clickPreference(withText(R.string.pref_automatic_download_title)); } assertTrue(solo.waitForCondition(() -> UserPreferences.isEnableAutodownload() == true, Timeout.getLargeTimeout())); final boolean enableAutodownloadOnBattery = UserPreferences.isEnableAutodownloadOnBattery(); @@ -343,6 +360,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 enableWifiFilter == UserPreferences.isEnableAutodownloadWifiFilter(), Timeout.getLargeTimeout())); } + @Test public void testEpisodeCleanupQueueOnly() { solo.clickOnText(solo.getString(R.string.network_pref)); solo.clickOnText(solo.getString(R.string.pref_automatic_download_title)); @@ -356,6 +374,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 { EpisodeCleanupAlgorithm alg = UserPreferences.getEpisodeCleanupAlgorithm(); if (alg instanceof APCleanupAlgorithm) { APCleanupAlgorithm cleanupAlg = (APCleanupAlgorithm)alg; - return cleanupAlg.getNumberOfDaysAfterPlayback() == 5; + return cleanupAlg.getNumberOfHoursAfterPlayback() == 120; // 5 days } return false; }, Timeout.getLargeTimeout())); } - + @Test public void testRewindChange() { int seconds = UserPreferences.getRewindSecs(); int deltas[] = res.getIntArray(R.array.seek_delta_values); - solo.clickOnText(solo.getString(R.string.playback_pref)); - solo.scrollDown(); - solo.scrollDown(); - solo.clickOnText(solo.getString(R.string.pref_rewind)); + clickPreference(withText(R.string.playback_pref)); + clickPreference(withText(R.string.pref_rewind)); solo.waitForDialogToOpen(); int currentIndex = Arrays.binarySearch(deltas, seconds); @@ -419,24 +439,22 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 UserPreferences.getRewindSecs() == deltas[newIndex], Timeout.getLargeTimeout())); } + @Test public void testFastForwardChange() { - solo.clickOnText(solo.getString(R.string.playback_pref)); - solo.scrollDown(); - solo.scrollDown(); + clickPreference(withText(R.string.playback_pref)); for (int i = 2; i > 0; i--) { // repeat twice to catch any error where fastforward is tracking rewind int seconds = UserPreferences.getFastForwardSecs(); int deltas[] = res.getIntArray(R.array.seek_delta_values); - solo.clickOnText(solo.getString(R.string.pref_fast_forward)); + clickPreference(withText(R.string.pref_fast_forward)); solo.waitForDialogToOpen(); int currentIndex = Arrays.binarySearch(deltas, seconds); @@ -445,12 +463,66 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2 UserPreferences.getFastForwardSecs() == deltas[newIndex], Timeout.getLargeTimeout())); } } + + @Test + public void testBackButtonBehaviorGoToPageSelector() { + clickPreference(withText(R.string.user_interface_label)); + clickPreference(withText(R.string.pref_back_button_behavior_title)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.back_button_go_to_page)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.queue_label)); + solo.clickOnText(solo.getString(R.string.confirm_label)); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonBehavior() == UserPreferences.BackButtonBehavior.GO_TO_PAGE, + Timeout.getLargeTimeout())); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonGoToPage().equals(QueueFragment.TAG), + Timeout.getLargeTimeout())); + clickPreference(withText(R.string.pref_back_button_behavior_title)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.back_button_go_to_page)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.episodes_label)); + solo.clickOnText(solo.getString(R.string.confirm_label)); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonBehavior() == UserPreferences.BackButtonBehavior.GO_TO_PAGE, + Timeout.getLargeTimeout())); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonGoToPage().equals(EpisodesFragment.TAG), + Timeout.getLargeTimeout())); + clickPreference(withText(R.string.pref_back_button_behavior_title)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.back_button_go_to_page)); + solo.waitForDialogToOpen(); + solo.clickOnText(solo.getString(R.string.subscriptions_label)); + solo.clickOnText(solo.getString(R.string.confirm_label)); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonBehavior() == UserPreferences.BackButtonBehavior.GO_TO_PAGE, + Timeout.getLargeTimeout())); + assertTrue(solo.waitForCondition(() -> UserPreferences.getBackButtonGoToPage().equals(SubscriptionFragment.TAG), + Timeout.getLargeTimeout())); + } + + @Test + public void testDeleteRemovesFromQueue() { + clickPreference(withText(R.string.storage_pref)); + if (!UserPreferences.shouldDeleteRemoveFromQueue()) { + clickPreference(withText(R.string.pref_delete_removes_from_queue_title)); + assertTrue(solo.waitForCondition(UserPreferences::shouldDeleteRemoveFromQueue, Timeout.getLargeTimeout())); + } + final boolean deleteRemovesFromQueue = UserPreferences.shouldDeleteRemoveFromQueue(); + solo.clickOnText(solo.getString(R.string.pref_delete_removes_from_queue_title)); + assertTrue(solo.waitForCondition(() -> deleteRemovesFromQueue != UserPreferences.shouldDeleteRemoveFromQueue(), Timeout.getLargeTimeout())); + solo.clickOnText(solo.getString(R.string.pref_delete_removes_from_queue_title)); + assertTrue(solo.waitForCondition(() -> deleteRemovesFromQueue == UserPreferences.shouldDeleteRemoveFromQueue(), Timeout.getLargeTimeout())); + } + + private void clickPreference(Matcher matcher) { + onView(withId(R.id.list)) + .perform(RecyclerViewActions.actionOnItem(hasDescendant(matcher), click())); + } } diff --git a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java index 3af22af9d..ff5374268 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java @@ -22,7 +22,6 @@ import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.event.QueueEvent; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.storage.PodDBAdapter; @@ -136,12 +135,9 @@ class UITestUtils { public void addHostedFeedData() throws IOException { if (feedDataHosted) throw new IllegalStateException("addHostedFeedData was called twice on the same instance"); for (int i = 0; i < NUM_FEEDS; i++) { - File bitmapFile = newBitmapFile("image" + i); - FeedImage image = new FeedImage(0, "image " + i, null, hostFile(bitmapFile), false); Feed feed = new Feed(0, null, "Title " + i, "http://example.com/" + i, "Description of feed " + i, - "http://example.com/pay/feed" + i, "author " + i, "en", Feed.TYPE_RSS2, "feed" + i, image, null, + "http://example.com/pay/feed" + i, "author " + i, "en", Feed.TYPE_RSS2, "feed" + i, null, null, "http://example.com/feed/src/" + i, false); - image.setOwner(feed); // create items List items = new ArrayList<>(); @@ -187,12 +183,6 @@ class UITestUtils { List queue = new ArrayList<>(); for (Feed feed : hostedFeeds) { feed.setDownloaded(true); - if (feed.getImage() != null) { - FeedImage image = feed.getImage(); - int fileId = Integer.parseInt(StringUtils.substringAfter(image.getDownload_url(), "files/")); - image.setFile_url(server.accessFile(fileId).getAbsolutePath()); - image.setDownloaded(true); - } if (downloadEpisodes) { for (FeedItem item : feed.getItems()) { if (item.hasMedia()) { diff --git a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java index 53fd7d7fd..45ba472ff 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java @@ -38,9 +38,6 @@ public class UITestUtilsTest extends InstrumentationTestCase { for (Feed feed : feeds) { testUrlReachable(feed.getDownload_url()); - if (feed.getImage() != null) { - testUrlReachable(feed.getImage().getDownload_url()); - } for (FeedItem item : feed.getItems()) { if (item.hasMedia()) { testUrlReachable(item.getMedia().getDownload_url()); @@ -66,9 +63,6 @@ public class UITestUtilsTest extends InstrumentationTestCase { for (Feed feed : uiTestUtils.hostedFeeds) { assertTrue(feed.getId() != 0); - if (feed.getImage() != null) { - assertTrue(feed.getImage().getId() != 0); - } for (FeedItem item : feed.getItems()) { assertTrue(item.getId() != 0); if (item.hasMedia()) { diff --git a/app/src/androidTest/java/de/test/antennapod/util/ConverterTest.java b/app/src/androidTest/java/de/test/antennapod/util/ConverterTest.java deleted file mode 100644 index 47fca41ba..000000000 --- a/app/src/androidTest/java/de/test/antennapod/util/ConverterTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.test.antennapod.util; - -import android.test.AndroidTestCase; - -import de.danoeh.antennapod.core.util.Converter; - -/** - * Test class for converter - */ -public class ConverterTest extends AndroidTestCase { - - public void testGetDurationStringLong() throws Exception { - String expected = "13:05:10"; - int input = 47110000; - assertEquals(expected, Converter.getDurationStringLong(input)); - } - - public void testGetDurationStringShort() throws Exception { - String expected = "13:05"; - int input = 47110000; - assertEquals(expected, Converter.getDurationStringShort(input)); - } - - public void testDurationStringLongToMs() throws Exception { - String input = "01:20:30"; - long expected = 4830000; - assertEquals(expected, Converter.durationStringLongToMs(input)); - } - - public void testDurationStringShortToMs() throws Exception { - String input = "8:30"; - long expected = 30600000; - assertEquals(expected, Converter.durationStringShortToMs(input)); - } -} diff --git a/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java b/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java index 7e535e12c..4bef14cd9 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java +++ b/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java @@ -30,12 +30,12 @@ public class TimelineTest extends InstrumentationTestCase { context = getInstrumentation().getTargetContext(); } - private Playable newTestPlayable(List chapters, String shownotes) { + private Playable newTestPlayable(List chapters, String shownotes, int duration) { FeedItem item = new FeedItem(0, "Item", "item-id", "http://example.com/item", new Date(), FeedItem.PLAYED, null); item.setChapters(chapters); item.setContentEncoded(shownotes); FeedMedia media = new FeedMedia(item, "http://example.com/episode", 100, "audio/mp3"); - media.setDuration(Integer.MAX_VALUE); + media.setDuration(duration); item.setMedia(media); return media; } @@ -44,7 +44,17 @@ public class TimelineTest extends InstrumentationTestCase { final String timeStr = "10:11:12"; final long time = 3600 * 1000 * 10 + 60 * 1000 * 11 + 12 * 1000; - Playable p = newTestPlayable(null, "

Some test text with a timecode " + timeStr + " here.

"); + Playable p = newTestPlayable(null, "

Some test text with a timecode " + timeStr + " here.

", Integer.MAX_VALUE); + Timeline t = new Timeline(context, p); + String res = t.processShownotes(true); + checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); + } + + public void testProcessShownotesAddTimecodeHHMMSSMoreThen24HoursNoChapters() throws Exception { + final String timeStr = "25:00:00"; + final long time = 25 * 60 * 60 * 1000; + + Playable p = newTestPlayable(null, "

Some test text with a timecode " + timeStr + " here.

", Integer.MAX_VALUE); Timeline t = new Timeline(context, p); String res = t.processShownotes(true); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); @@ -54,17 +64,67 @@ public class TimelineTest extends InstrumentationTestCase { final String timeStr = "10:11"; final long time = 3600 * 1000 * 10 + 60 * 1000 * 11; - Playable p = newTestPlayable(null, "

Some test text with a timecode " + timeStr + " here.

"); + Playable p = newTestPlayable(null, "

Some test text with a timecode " + timeStr + " here.

", Integer.MAX_VALUE); Timeline t = new Timeline(context, p); String res = t.processShownotes(true); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } + public void testProcessShownotesAddTimecodeMMSSNoChapters() throws Exception { + final String timeStr = "10:11"; + final long time = 10 * 60 * 1000 + 11 * 1000; + + Playable p = newTestPlayable(null, "

Some test text with a timecode " + timeStr + " here.

", 11 * 60 * 1000); + Timeline t = new Timeline(context, p); + String res = t.processShownotes(true); + checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); + } + + public void testProcessShownotesAddTimecodeHMMSSNoChapters() throws Exception { + final String timeStr = "2:11:12"; + final long time = 2 * 60 * 60 * 1000 + 11 * 60 * 1000 + 12 * 1000; + + Playable p = newTestPlayable(null, "

Some test text with a timecode " + timeStr + " here.

", Integer.MAX_VALUE); + Timeline t = new Timeline(context, p); + String res = t.processShownotes(true); + checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); + } + + public void testProcessShownotesAddTimecodeMSSNoChapters() throws Exception { + final String timeStr = "1:12"; + final long time = 60 * 1000 + 12 * 1000; + + Playable p = newTestPlayable(null, "

Some test text with a timecode " + timeStr + " here.

", 2 * 60 * 1000); + Timeline t = new Timeline(context, p); + String res = t.processShownotes(true); + checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); + } + + public void testProcessShownotesAddTimecodeMultipleFormatsNoChapters() throws Exception { + final String[] timeStrings = new String[]{ "10:12", "1:10:12" }; + + Playable p = newTestPlayable(null, "

Some test text with a timecode " + timeStrings[0] + " here. Hey look another one " + timeStrings[1] + " here!

", 2 * 60 * 60 * 1000); + Timeline t = new Timeline(context, p); + String res = t.processShownotes(true); + checkLinkCorrect(res, new long[]{ 10 * 60 * 1000 + 12 * 1000, 60 * 60 * 1000 + 10 * 60 * 1000 + 12 * 1000 }, timeStrings); + } + + public void testProcessShownotesAddTimecodeMultipleShortFormatNoChapters() throws Exception { + + // One of these timecodes fits as HH:MM and one does not so both should be parsed as MM:SS. + final String[] timeStrings = new String[]{ "10:12", "2:12" }; + + Playable p = newTestPlayable(null, "

Some test text with a timecode " + timeStrings[0] + " here. Hey look another one " + timeStrings[1] + " here!

", 3 * 60 * 60 * 1000); + Timeline t = new Timeline(context, p); + String res = t.processShownotes(true); + checkLinkCorrect(res, new long[]{ 10 * 60 * 1000 + 12 * 1000, 2 * 60 * 1000 + 12 * 1000 }, timeStrings); + } + public void testProcessShownotesAddTimecodeParentheses() throws Exception { final String timeStr = "10:11"; final long time = 3600 * 1000 * 10 + 60 * 1000 * 11; - Playable p = newTestPlayable(null, "

Some test text with a timecode (" + timeStr + ") here.

"); + Playable p = newTestPlayable(null, "

Some test text with a timecode (" + timeStr + ") here.

", Integer.MAX_VALUE); Timeline t = new Timeline(context, p); String res = t.processShownotes(true); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); @@ -74,7 +134,7 @@ public class TimelineTest extends InstrumentationTestCase { final String timeStr = "10:11"; final long time = 3600 * 1000 * 10 + 60 * 1000 * 11; - Playable p = newTestPlayable(null, "

Some test text with a timecode [" + timeStr + "] here.

"); + Playable p = newTestPlayable(null, "

Some test text with a timecode [" + timeStr + "] here.

", Integer.MAX_VALUE); Timeline t = new Timeline(context, p); String res = t.processShownotes(true); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); @@ -84,12 +144,27 @@ public class TimelineTest extends InstrumentationTestCase { final String timeStr = "10:11"; final long time = 3600 * 1000 * 10 + 60 * 1000 * 11; - Playable p = newTestPlayable(null, "

Some test text with a timecode <" + timeStr + "> here.

"); + Playable p = newTestPlayable(null, "

Some test text with a timecode <" + timeStr + "> here.

", Integer.MAX_VALUE); Timeline t = new Timeline(context, p); String res = t.processShownotes(true); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } + public void testProcessShownotesAndInvalidTimecode() throws Exception { + final String[] timeStrs = new String[] {"2:1", "0:0", "000", "00", "00:000"}; + + StringBuilder shownotes = new StringBuilder("

Some test text with timecodes "); + for (String timeStr : timeStrs) { + shownotes.append(timeStr).append(" "); + } + shownotes.append("here.

"); + + Playable p = newTestPlayable(null, shownotes.toString(), Integer.MAX_VALUE); + Timeline t = new Timeline(context, p); + String res = t.processShownotes(true); + checkLinkCorrect(res, new long[0], new String[0]); + } + private void checkLinkCorrect(String res, long[] timecodes, String[] timecodeStr) { assertNotNull(res); Document d = Jsoup.parse(res); diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java index afe15f1b2..8d2408b45 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java +++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java @@ -56,6 +56,11 @@ public class AtomGenerator implements FeedGenerator{ xml.text(feed.getDescription()); xml.endTag(null, "subtitle"); } + if (feed.getImageUrl() != null) { + xml.startTag(null, "logo"); + xml.text(feed.getImageUrl()); + xml.endTag(null, "logo"); + } if (feed.getPaymentLink() != null) { GeneratorUtil.addPaymentLink(xml, feed.getPaymentLink(), false); diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/GeneratorUtil.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/GeneratorUtil.java index 7f6f0fb0f..89542d222 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/GeneratorUtil.java +++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/GeneratorUtil.java @@ -8,6 +8,7 @@ import java.io.IOException; * Utility methods for FeedGenerator */ class GeneratorUtil { + private GeneratorUtil(){} public static void addPaymentLink(XmlSerializer xml, String paymentLink, boolean withNamespace) throws IOException { String ns = (withNamespace) ? "http://www.w3.org/2005/Atom" : null; diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java index f2d53799d..5f8b4d18c 100644 --- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java +++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java @@ -54,6 +54,13 @@ public class RSS2Generator implements FeedGenerator{ xml.text(feed.getLanguage()); xml.endTag(null, "language"); } + if (feed.getImageUrl() != null) { + xml.startTag(null, "image"); + xml.startTag(null, "url"); + xml.text(feed.getImageUrl()); + xml.endTag(null, "url"); + xml.endTag(null, "image"); + } if (feed.getPaymentLink() != null) { GeneratorUtil.addPaymentLink(xml, feed.getPaymentLink(), true); diff --git a/app/src/free/play b/app/src/free/play new file mode 120000 index 000000000..e9d641154 --- /dev/null +++ b/app/src/free/play @@ -0,0 +1 @@ +../main/play \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c7541cb59..216afc6b7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,14 +1,8 @@ - + android:installLocation="auto"> + @@ -47,10 +41,13 @@ + @@ -391,10 +388,6 @@ android:resource="@xml/provider_paths"/> - - diff --git a/app/src/main/assets/LICENSE_SIL.txt b/app/src/main/assets/LICENSE_SIL.txt new file mode 100644 index 000000000..f5ed6fa72 --- /dev/null +++ b/app/src/main/assets/LICENSE_SIL.txt @@ -0,0 +1,91 @@ +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/app/src/main/assets/logo.png b/app/src/main/assets/logo.png index d0e988a6d..3b5261b28 100755 Binary files a/app/src/main/assets/logo.png and b/app/src/main/assets/logo.png differ diff --git a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java index 3abf7557a..fde9af16f 100644 --- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java +++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java @@ -20,7 +20,7 @@ public class PodcastApp extends Application { try { Class.forName("de.danoeh.antennapod.config.ClientConfigurator"); } catch (Exception e) { - throw new RuntimeException("ClientConfigurator not found"); + throw new RuntimeException("ClientConfigurator not found", e); } } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java index 4d9b50073..ecfdf24b0 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java @@ -21,10 +21,10 @@ import java.nio.charset.Charset; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; -import rx.Single; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Displays the 'about' screen @@ -35,7 +35,7 @@ public class AboutActivity extends AppCompatActivity { private WebView webView; private LinearLayout webViewContainer; - private Subscription subscription; + private Disposable disposable; @Override protected void onCreate(Bundle savedInstanceState) { @@ -43,8 +43,8 @@ public class AboutActivity extends AppCompatActivity { super.onCreate(savedInstanceState); getSupportActionBar().setDisplayShowHomeEnabled(true); setContentView(R.layout.about); - webViewContainer = (LinearLayout) findViewById(R.id.webViewContainer); - webView = (WebView) findViewById(R.id.webViewAbout); + webViewContainer = findViewById(R.id.webViewContainer); + webView = findViewById(R.id.webViewAbout); webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { @@ -69,13 +69,16 @@ public class AboutActivity extends AppCompatActivity { } private void loadAsset(String filename) { - subscription = Single.create(subscriber -> { + disposable = Single.create(subscriber -> { InputStream input = null; try { TypedArray res = AboutActivity.this.getTheme().obtainStyledAttributes( - new int[] { android.R.attr.textColorPrimary }); - int colorResource = res.getColor(0, 0); - String colorString = String.format("#%06X", 0xFFFFFF & colorResource); + new int[] { R.attr.about_screen_font_color, R.attr.about_screen_background, + R.attr.about_screen_card_background, R.attr.about_screen_card_border}); + String fontColor = String.format("#%06X", 0xFFFFFF & res.getColor(0, 0)); + String backgroundColor = String.format("#%06X", 0xFFFFFF & res.getColor(1, 0)); + String cardBackground = String.format("#%06X", 0xFFFFFF & res.getColor(2, 0)); + String cardBorder = String.format("#%06X", 0xFFFFFF & res.getColor(3, 0)); res.recycle(); input = getAssets().open(filename); String webViewData = IOUtils.toString(input, Charset.defaultCharset()); @@ -92,7 +95,7 @@ public class AboutActivity extends AppCompatActivity { " src: url('file:///android_asset/Roboto-Light.ttf');" + " }" + " * {" + - " color: %s;" + + " color: @fontcolor@;" + " font-family: roboto-Light;" + " font-size: 8pt;" + " }" + @@ -100,7 +103,10 @@ public class AboutActivity extends AppCompatActivity { "

" + webViewData + "

"; webViewData = webViewData.replace("\n", "
"); } - webViewData = String.format(webViewData, colorString); + webViewData = webViewData.replace("@fontcolor@", fontColor); + webViewData = webViewData.replace("@background@", backgroundColor); + webViewData = webViewData.replace("@card_background@", cardBackground); + webViewData = webViewData.replace("@card_border@", cardBorder); subscriber.onSuccess(webViewData); } catch (IOException e) { Log.e(TAG, Log.getStackTraceString(e)); @@ -109,7 +115,7 @@ public class AboutActivity extends AppCompatActivity { IOUtils.closeQuietly(input); } }) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( webViewData -> @@ -140,8 +146,8 @@ public class AboutActivity extends AppCompatActivity { @Override protected void onDestroy() { super.onDestroy(); - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } if (webViewContainer != null && webView != null) { webViewContainer.removeAllViews(); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java index 207aec20f..67dda01cf 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java @@ -12,8 +12,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; -import de.danoeh.antennapod.core.util.playback.ExternalMedia; -import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter; import de.danoeh.antennapod.dialog.VariableSpeedDialog; /** @@ -28,20 +26,7 @@ public class AudioplayerActivity extends MediaplayerInfoActivity { protected void onResume() { super.onResume(); if (TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) { - Intent intent = getIntent(); - if (intent.getData() == null) { - return; - } - Log.d(TAG, "Received VIEW intent: " + intent.getData().getPath()); - ExternalMedia media = new ExternalMedia(intent.getData().getPath(), - MediaType.AUDIO); - - new PlaybackServiceStarter(this, media) - .startWhenPrepared(true) - .shouldStream(false) - .prepareImmediately(true) - .start(); - + playExternalMedia(getIntent(), MediaType.AUDIO); } else if (PlaybackService.isCasting()) { Intent intent = PlaybackService.getPlayerActivityIntent(this); if (intent.getComponent() != null && diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java index 390d4cef8..33def125e 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java @@ -64,11 +64,11 @@ public class DirectoryChooserActivity extends AppCompatActivity { getSupportActionBar().setDisplayHomeAsUpEnabled(true); setContentView(R.layout.directory_chooser); - butConfirm = (Button) findViewById(R.id.butConfirm); - butCancel = (Button) findViewById(R.id.butCancel); - butNavUp = (ImageButton) findViewById(R.id.butNavUp); - txtvSelectedFolder = (TextView) findViewById(R.id.txtvSelectedFolder); - listDirectories = (ListView) findViewById(R.id.directory_list); + butConfirm = findViewById(R.id.butConfirm); + butCancel = findViewById(R.id.butCancel); + butNavUp = findViewById(R.id.butNavUp); + txtvSelectedFolder = findViewById(R.id.txtvSelectedFolder); + listDirectories = findViewById(R.id.directory_list); butConfirm.setOnClickListener(new OnClickListener() { diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java index e726afaec..5e04d743d 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java @@ -49,11 +49,11 @@ public class DownloadAuthenticationActivity extends AppCompatActivity { } setContentView(R.layout.download_authentication_activity); - TextView txtvDescription = (TextView) findViewById(R.id.txtvDescription); - etxtUsername = (EditText) findViewById(R.id.etxtUsername); - etxtPassword = (EditText) findViewById(R.id.etxtPassword); - Button butConfirm = (Button) findViewById(R.id.butConfirm); - Button butCancel = (Button) findViewById(R.id.butCancel); + TextView txtvDescription = findViewById(R.id.txtvDescription); + etxtUsername = findViewById(R.id.etxtUsername); + etxtPassword = findViewById(R.id.etxtPassword); + Button butConfirm = findViewById(R.id.butConfirm); + Button butCancel = findViewById(R.id.butCancel); Validate.isTrue(getIntent().hasExtra(ARG_DOWNLOAD_REQUEST), "Download request missing"); DownloadRequest request = getIntent().getParcelableExtra(ARG_DOWNLOAD_REQUEST); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java index 6b1272b01..bfa694e5c 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java @@ -16,8 +16,15 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; + import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import com.joanzapata.iconify.Iconify; + +import org.apache.commons.lang3.StringUtils; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; import de.danoeh.antennapod.core.feed.Feed; @@ -30,13 +37,11 @@ import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.LangUtils; import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; -import org.apache.commons.lang3.StringUtils; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Maybe; +import io.reactivex.MaybeOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Displays information about a feed. @@ -56,7 +61,7 @@ public class FeedInfoActivity extends AppCompatActivity { private TextView txtvAuthor; private TextView txtvUrl; - private Subscription subscription; + private Disposable disposable; private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() { @@ -82,52 +87,57 @@ public class FeedInfoActivity extends AppCompatActivity { getSupportActionBar().setDisplayHomeAsUpEnabled(true); long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1); - imgvCover = (ImageView) findViewById(R.id.imgvCover); - txtvTitle = (TextView) findViewById(R.id.txtvTitle); - TextView txtvAuthorHeader = (TextView) findViewById(R.id.txtvAuthor); - ImageView imgvBackground = (ImageView) findViewById(R.id.imgvBackground); + imgvCover = findViewById(R.id.imgvCover); + txtvTitle = findViewById(R.id.txtvTitle); + TextView txtvAuthorHeader = findViewById(R.id.txtvAuthor); + ImageView imgvBackground = findViewById(R.id.imgvBackground); findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE); findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE); // https://github.com/bumptech/glide/issues/529 imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000)); - txtvDescription = (TextView) findViewById(R.id.txtvDescription); - lblLanguage = (TextView) findViewById(R.id.lblLanguage); - txtvLanguage = (TextView) findViewById(R.id.txtvLanguage); - lblAuthor = (TextView) findViewById(R.id.lblAuthor); - txtvAuthor = (TextView) findViewById(R.id.txtvDetailsAuthor); - txtvUrl = (TextView) findViewById(R.id.txtvUrl); + txtvDescription = findViewById(R.id.txtvDescription); + lblLanguage = findViewById(R.id.lblLanguage); + txtvLanguage = findViewById(R.id.txtvLanguage); + lblAuthor = findViewById(R.id.lblAuthor); + txtvAuthor = findViewById(R.id.txtvDetailsAuthor); + txtvUrl = findViewById(R.id.txtvUrl); txtvUrl.setOnClickListener(copyUrlToClipboard); - subscription = Observable.fromCallable(()-> DBReader.getFeed(feedId)) - .subscribeOn(Schedulers.newThread()) + disposable = Maybe.create((MaybeOnSubscribe) emitter -> { + Feed feed = DBReader.getFeed(feedId); + if (feed != null) { + emitter.onSuccess(feed); + } else { + emitter.onComplete(); + } + }) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { - if (result == null) { - Log.e(TAG, "Activity was started with invalid arguments"); - finish(); - } feed = result; Log.d(TAG, "Language is " + feed.getLanguage()); Log.d(TAG, "Author is " + feed.getAuthor()); Log.d(TAG, "URL is " + feed.getDownload_url()); Glide.with(FeedInfoActivity.this) .load(feed.getImageLocation()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(imgvCover); Glide.with(FeedInfoActivity.this) .load(feed.getImageLocation()) - .placeholder(R.color.image_readability_tint) - .error(R.color.image_readability_tint) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .transform(new FastBlurTransformation(FeedInfoActivity.this)) - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.image_readability_tint) + .error(R.color.image_readability_tint) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .transform(new FastBlurTransformation()) + .dontAnimate()) .into(imgvBackground); txtvTitle.setText(feed.getTitle()); @@ -164,14 +174,17 @@ public class FeedInfoActivity extends AppCompatActivity { }, error -> { Log.d(TAG, Log.getStackTraceString(error)); finish(); + }, () -> { + Log.e(TAG, "Activity was started with invalid arguments"); + finish(); }); } @Override public void onDestroy() { super.onDestroy(); - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java index 5e15585a5..4698ed90e 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java @@ -1,6 +1,5 @@ package de.danoeh.antennapod.activity; -import android.content.ClipData; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -24,8 +23,10 @@ import android.widget.ImageView; import android.widget.RadioButton; import android.widget.Spinner; import android.widget.TextView; -import android.widget.Toast; + import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.dialog.ConfirmationDialog; import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; @@ -40,10 +41,11 @@ import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Maybe; +import io.reactivex.MaybeOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Displays information about a feed. @@ -67,23 +69,7 @@ public class FeedSettingsActivity extends AppCompatActivity { private Spinner spnAutoDelete; private boolean filterInclude = true; - private Subscription subscription; - - - private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() { - @Override - public void onClick(View v) { - if(feed != null && feed.getDownload_url() != null) { - String url = feed.getDownload_url(); - ClipData clipData = ClipData.newPlainText(url, url); - android.content.ClipboardManager cm = (android.content.ClipboardManager) FeedSettingsActivity.this - .getSystemService(Context.CLIPBOARD_SERVICE); - cm.setPrimaryClip(clipData); - Toast t = Toast.makeText(FeedSettingsActivity.this, R.string.copied_url_msg, Toast.LENGTH_SHORT); - t.show(); - } - } - }; + private Disposable disposable; private boolean authInfoChanged = false; @@ -127,57 +113,62 @@ public class FeedSettingsActivity extends AppCompatActivity { getSupportActionBar().setDisplayHomeAsUpEnabled(true); long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1); - imgvCover = (ImageView) findViewById(R.id.imgvCover); - txtvTitle = (TextView) findViewById(R.id.txtvTitle); - TextView txtvAuthorHeader = (TextView) findViewById(R.id.txtvAuthor); - ImageView imgvBackground = (ImageView) findViewById(R.id.imgvBackground); + imgvCover = findViewById(R.id.imgvCover); + txtvTitle = findViewById(R.id.txtvTitle); + TextView txtvAuthorHeader = findViewById(R.id.txtvAuthor); + ImageView imgvBackground = findViewById(R.id.imgvBackground); findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE); findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE); // https://github.com/bumptech/glide/issues/529 imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000)); - cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload); - cbxKeepUpdated = (CheckBox) findViewById(R.id.cbxKeepUpdated); - spnAutoDelete = (Spinner) findViewById(R.id.spnAutoDelete); - etxtUsername = (EditText) findViewById(R.id.etxtUsername); - etxtPassword = (EditText) findViewById(R.id.etxtPassword); - etxtFilterText = (EditText) findViewById(R.id.etxtEpisodeFilterText); - rdoFilterInclude = (RadioButton) findViewById(R.id.radio_filter_include); + cbxAutoDownload = findViewById(R.id.cbxAutoDownload); + cbxKeepUpdated = findViewById(R.id.cbxKeepUpdated); + spnAutoDelete = findViewById(R.id.spnAutoDelete); + etxtUsername = findViewById(R.id.etxtUsername); + etxtPassword = findViewById(R.id.etxtPassword); + etxtFilterText = findViewById(R.id.etxtEpisodeFilterText); + rdoFilterInclude = findViewById(R.id.radio_filter_include); rdoFilterInclude.setOnClickListener(v -> { filterInclude = true; filterTextChanged = true; }); - rdoFilterExclude = (RadioButton) findViewById(R.id.radio_filter_exclude); + rdoFilterExclude = findViewById(R.id.radio_filter_exclude); rdoFilterExclude.setOnClickListener(v -> { filterInclude = false; filterTextChanged = true; }); - subscription = Observable.fromCallable(()-> DBReader.getFeed(feedId)) - .subscribeOn(Schedulers.newThread()) + disposable = Maybe.create((MaybeOnSubscribe) emitter -> { + Feed feed = DBReader.getFeed(feedId); + if (feed != null) { + emitter.onSuccess(feed); + } else { + emitter.onComplete(); + } + }) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { - if (result == null) { - Log.e(TAG, "Activity was started with invalid arguments"); - finish(); - } feed = result; FeedPreferences prefs = feed.getPreferences(); Glide.with(FeedSettingsActivity.this) .load(feed.getImageLocation()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(imgvCover); Glide.with(FeedSettingsActivity.this) .load(feed.getImageLocation()) - .placeholder(R.color.image_readability_tint) - .error(R.color.image_readability_tint) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .transform(new FastBlurTransformation(FeedSettingsActivity.this)) - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.image_readability_tint) + .error(R.color.image_readability_tint) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .transform(new FastBlurTransformation()) + .dontAnimate()) .into(imgvBackground); txtvTitle.setText(feed.getTitle()); @@ -259,6 +250,9 @@ public class FeedSettingsActivity extends AppCompatActivity { }, error -> { Log.d(TAG, Log.getStackTraceString(error)); finish(); + }, () -> { + Log.e(TAG, "Activity was started with invalid arguments"); + finish(); }); } @@ -296,8 +290,8 @@ public class FeedSettingsActivity extends AppCompatActivity { @Override public void onDestroy() { super.onDestroy(); - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java index 26352f58f..2b4384a02 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java @@ -41,9 +41,9 @@ public class FlattrAuthActivity extends AppCompatActivity { if (BuildConfig.DEBUG) Log.d(TAG, "Activity created"); getSupportActionBar().setDisplayHomeAsUpEnabled(true); setContentView(R.layout.flattr_auth); - txtvExplanation = (TextView) findViewById(R.id.txtvExplanation); - butAuthenticate = (Button) findViewById(R.id.but_authenticate); - butReturn = (Button) findViewById(R.id.but_return_home); + txtvExplanation = findViewById(R.id.txtvExplanation); + butAuthenticate = findViewById(R.id.but_authenticate); + butReturn = findViewById(R.id.but_return_home); butReturn.setOnClickListener(v -> { Intent intent = new Intent(FlattrAuthActivity.this, MainActivity.class); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java index 91462bce9..e6c9c37cc 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java @@ -13,9 +13,7 @@ import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.MenuItem; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.storage.PodDBAdapter; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -26,6 +24,10 @@ import java.io.IOException; import java.io.InputStream; import java.nio.channels.FileChannel; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.storage.PodDBAdapter; + /** * Displays the 'import/export' screen */ diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index 294ab5af8..9f4fbe271 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -27,11 +27,10 @@ import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; +import android.widget.Toast; import com.bumptech.glide.Glide; -import de.danoeh.antennapod.core.event.ServiceEvent; -import de.danoeh.antennapod.core.util.gui.NotificationUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.Validate; @@ -44,17 +43,20 @@ import de.danoeh.antennapod.core.dialog.ConfirmationDialog; import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.event.ProgressEvent; import de.danoeh.antennapod.core.event.QueueEvent; +import de.danoeh.antennapod.core.event.ServiceEvent; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.Flavors; +import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.StorageUtils; +import de.danoeh.antennapod.core.util.download.AutoUpdateManager; +import de.danoeh.antennapod.core.util.gui.NotificationUtils; import de.danoeh.antennapod.dialog.RatingDialog; import de.danoeh.antennapod.dialog.RenameFeedDialog; import de.danoeh.antennapod.fragment.AddFeedFragment; @@ -67,10 +69,10 @@ import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.fragment.SubscriptionFragment; import de.danoeh.antennapod.menuhandler.NavDrawerActivity; import de.greenrobot.event.EventBus; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * The activity that is shown when the user launches the app. @@ -120,7 +122,9 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi private ProgressDialog pd; - private Subscription subscription; + private Disposable disposable; + + private long lastBackButtonPressTime = 0; @Override public void onCreate(Bundle savedInstanceState) { @@ -129,7 +133,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi StorageUtils.checkStorageAvailability(this); setContentView(R.layout.main); - toolbar = (Toolbar) findViewById(R.id.toolbar); + toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @@ -141,8 +145,8 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi currentTitle = getTitle(); - drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); - navList = (ListView) findViewById(R.id.nav_list); + drawerLayout = findViewById(R.id.drawer_layout); + navList = findViewById(R.id.nav_list); navDrawer = findViewById(R.id.nav_layout); drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close); @@ -470,7 +474,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi protected void onResume() { super.onResume(); StorageUtils.checkStorageAvailability(this); - DBTasks.checkShouldRefreshFeeds(getApplicationContext()); + AutoUpdateManager.checkShouldRefreshFeeds(getApplicationContext()); Intent intent = getIntent(); if (intent.hasExtra(EXTRA_FEED_ID) || @@ -487,8 +491,8 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); EventBus.getDefault().unregister(this); - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } if(pd != null) { pd.dismiss(); @@ -627,8 +631,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi remover.skipOnCompletion = true; int playerStatus = PlaybackPreferences.getCurrentPlayerStatus(); if(playerStatus == PlaybackPreferences.PLAYER_STATUS_PLAYING) { - sendBroadcast(new Intent( - PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE)); + IntentUtils.sendLocalBroadcast(MainActivity.this, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE); } } remover.executeAsync(); @@ -643,10 +646,40 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi @Override public void onBackPressed() { - if(isDrawerOpen()) { + if (isDrawerOpen()) { drawerLayout.closeDrawer(navDrawer); - } else { + } else if (getSupportFragmentManager().getBackStackEntryCount() != 0) { super.onBackPressed(); + } else { + switch (UserPreferences.getBackButtonBehavior()) { + case OPEN_DRAWER: + drawerLayout.openDrawer(navDrawer); + break; + case SHOW_PROMPT: + new AlertDialog.Builder(this) + .setMessage(R.string.close_prompt) + .setPositiveButton(R.string.yes, (dialogInterface, i) -> MainActivity.super.onBackPressed()) + .setNegativeButton(R.string.no, null) + .setCancelable(false) + .show(); + break; + case DOUBLE_TAP: + if (lastBackButtonPressTime < System.currentTimeMillis() - 2000) { + Toast.makeText(this, R.string.double_tap_toast, Toast.LENGTH_SHORT).show(); + lastBackButtonPressTime = System.currentTimeMillis(); + } else { + super.onBackPressed(); + } + break; + case GO_TO_PAGE: + if (getLastNavFragment().equals(UserPreferences.getBackButtonGoToPage())) { + super.onBackPressed(); + } else { + loadFragment(UserPreferences.getBackButtonGoToPage(), null); + } + break; + default: super.onBackPressed(); + } } } @@ -717,8 +750,8 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi }; private void loadData() { - subscription = Observable.fromCallable(DBReader::getNavDrawerData) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(DBReader::getNavDrawerData) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { boolean handleIntent = (navDrawerData == null); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java index 091f8daab..f3b83638d 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -1,9 +1,11 @@ package de.danoeh.antennapod.activity; +import android.Manifest; import android.annotation.TargetApi; import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.PixelFormat; @@ -11,7 +13,9 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityOptionsCompat; +import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.Menu; @@ -37,28 +41,33 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.event.ServiceEvent; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.util.Consumer; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.Flavors; +import de.danoeh.antennapod.core.util.Function; +import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.ShareUtils; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.Supplier; import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; +import de.danoeh.antennapod.core.util.playback.ExternalMedia; import de.danoeh.antennapod.core.util.playback.MediaPlayerError; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; +import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter; import de.danoeh.antennapod.dialog.SleepTimerDialog; import de.danoeh.antennapod.dialog.VariableSpeedDialog; -import rx.Observable; -import rx.android.schedulers.AndroidSchedulers; -import rx.functions.Action1; -import rx.functions.Func1; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** @@ -69,6 +78,10 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements private static final String TAG = "MediaplayerActivity"; private static final String PREFS = "MediaPlayerActivityPreferences"; private static final String PREF_SHOW_TIME_LEFT = "showTimeLeft"; + private static final int REQUEST_CODE_STORAGE = 42; + private static final float PLAYBACK_SPEED_STEP = 0.05f; + private static final float DEFAULT_MIN_PLAYBACK_SPEED = 0.5f; + private static final float DEFAULT_MAX_PLAYBACK_SPEED = 2.5f; PlaybackController controller; @@ -86,6 +99,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements private boolean isFavorite = false; + private Disposable disposable; + private PlaybackController newPlaybackController() { return new PlaybackController(this, false) { @@ -222,8 +237,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements Log.d(TAG, "onCreate()"); StorageUtils.checkStorageAvailability(this); - orientation = getResources().getConfiguration().orientation; getWindow().setFormat(PixelFormat.TRANSPARENT); + setupGUI(); + loadMediaInfo(); } @Override @@ -256,15 +272,10 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements private void onBufferUpdate(float progress) { if (sbPosition != null) { - sbPosition.setSecondaryProgress((int) progress * sbPosition.getMax()); + sbPosition.setSecondaryProgress((int) (progress * sbPosition.getMax())); } } - /** - * Current screen orientation. - */ - private int orientation; - @Override protected void onStart() { super.onStart(); @@ -272,8 +283,6 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements controller.release(); } controller = newPlaybackController(); - setupGUI(); - loadMediaInfo(); onPositionObserverUpdate(); } @@ -284,6 +293,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements controller.release(); controller = null; // prevent leak } + if (disposable != null) { + disposable.dispose(); + } super.onStop(); } @@ -460,7 +472,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements final Button butDecSpeed = (Button) dialog.findViewById(R.id.butDecSpeed); butDecSpeed.setOnClickListener(v -> { if(controller != null && controller.canSetPlaybackSpeed()) { - barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() - 2); + barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() - 1); } else { VariableSpeedDialog.showGetPluginDialog(this); } @@ -468,7 +480,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements final Button butIncSpeed = (Button) dialog.findViewById(R.id.butIncSpeed); butIncSpeed.setOnClickListener(v -> { if(controller != null && controller.canSetPlaybackSpeed()) { - barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() + 2); + barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() + 1); } else { VariableSpeedDialog.showGetPluginDialog(this); } @@ -483,12 +495,20 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements UserPreferences.setPlaybackSpeed(String.valueOf(currentSpeed)); } + String[] availableSpeeds = UserPreferences.getPlaybackSpeedArray(); + final float minPlaybackSpeed = availableSpeeds.length > 1 ? + Float.valueOf(availableSpeeds[0]) : DEFAULT_MIN_PLAYBACK_SPEED; + float maxPlaybackSpeed = availableSpeeds.length > 1 ? + Float.valueOf(availableSpeeds[availableSpeeds.length - 1]) : DEFAULT_MAX_PLAYBACK_SPEED; + int progressMax = (int) ((maxPlaybackSpeed - minPlaybackSpeed) / PLAYBACK_SPEED_STEP); + barPlaybackSpeed.setMax(progressMax); + txtvPlaybackSpeed.setText(String.format("%.2fx", currentSpeed)); barPlaybackSpeed.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if(controller != null && controller.canSetPlaybackSpeed()) { - float playbackSpeed = (progress + 10) / 20.0f; + float playbackSpeed = progress * PLAYBACK_SPEED_STEP + minPlaybackSpeed; controller.setPlaybackSpeed(playbackSpeed); String speedPref = String.format(Locale.US, "%.2f", playbackSpeed); UserPreferences.setPlaybackSpeed(speedPref); @@ -496,7 +516,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements txtvPlaybackSpeed.setText(speedStr); } else if(fromUser) { float speed = Float.valueOf(UserPreferences.getPlaybackSpeed()); - barPlaybackSpeed.post(() -> barPlaybackSpeed.setProgress((int) (20 * speed) - 10)); + barPlaybackSpeed.post(() -> barPlaybackSpeed.setProgress( + (int) ((speed - minPlaybackSpeed) / PLAYBACK_SPEED_STEP))); } } @@ -511,7 +532,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements public void onStopTrackingTouch(SeekBar seekBar) { } }); - barPlaybackSpeed.setProgress((int) (20 * currentSpeed) - 10); + barPlaybackSpeed.setProgress((int) ((currentSpeed - minPlaybackSpeed) / PLAYBACK_SPEED_STEP)); final SeekBar barLeftVolume = (SeekBar) dialog.findViewById(R.id.volume_left); barLeftVolume.setProgress(UserPreferences.getLeftVolumePercentage()); @@ -525,6 +546,22 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements stereoToMono.setText(stereoToMono.getText() + " [" + sonicOnly + "]"); } + if (UserPreferences.useExoplayer()) { + barRightVolume.setEnabled(false); + } + + final CheckBox skipSilence = (CheckBox) dialog.findViewById(R.id.skipSilence); + skipSilence.setChecked(UserPreferences.isSkipSilence()); + if (!UserPreferences.useExoplayer()) { + skipSilence.setEnabled(false); + String exoplayerOnly = getString(R.string.exoplayer_only); + skipSilence.setText(skipSilence.getText() + " [" + exoplayerOnly + "]"); + } + skipSilence.setOnCheckedChangeListener((buttonView, isChecked) -> { + UserPreferences.setSkipSilence(isChecked); + controller.setSkipSilence(isChecked); + }); + barLeftVolume.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { @@ -635,7 +672,6 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements if (controller != null) { controller.init(); } - } } @@ -690,7 +726,6 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements if(controller == null || controller.getMedia() == null) { return false; } - Playable media = controller.getMedia(); SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE); showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false); onPositionObserverUpdate(); @@ -722,8 +757,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements R.string.pref_rewind); private final Supplier getPrefSecsFn; - private final Func1 getTextViewFn; - private final Action1 setPrefSecsFn; + private final Function getTextViewFn; + private final Consumer setPrefSecsFn; private final int titleResourceID; /** @@ -735,7 +770,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements * @param setPrefSecsFn Handle to function that sets the preference (setting) for the skip delta value (and optionally updates the button label with the current values) * @param titleResourceID ID of the resource string with the title for a view */ - SkipDirection(Supplier getPrefSecsFn, Func1 getTextViewFn, Action1 setPrefSecsFn, int titleResourceID) { + SkipDirection(Supplier getPrefSecsFn, Function getTextViewFn, Consumer setPrefSecsFn, int titleResourceID) { this.getPrefSecsFn = getPrefSecsFn; this.getTextViewFn = getTextViewFn; this.setPrefSecsFn = setPrefSecsFn; @@ -754,10 +789,10 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements * @param activity MediaplyerActivity that contains textview to update the display of the skip delta setting (or null if nothing to update) */ public void setPrefSkipSeconds(int seconds, @Nullable Activity activity) { - setPrefSecsFn.call(seconds); + setPrefSecsFn.accept(seconds); if (activity != null && activity instanceof MediaplayerActivity) { - TextView tv = getTextViewFn.call((MediaplayerActivity)activity); + TextView tv = getTextViewFn.apply((MediaplayerActivity)activity); if (tv != null) tv.setText(String.valueOf(seconds)); } } @@ -795,13 +830,13 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements void setupGUI() { setContentView(getContentViewResourceId()); - sbPosition = (SeekBar) findViewById(R.id.sbPosition); - txtvPosition = (TextView) findViewById(R.id.txtvPosition); + sbPosition = findViewById(R.id.sbPosition); + txtvPosition = findViewById(R.id.txtvPosition); SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE); showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false); Log.d("timeleft", showTimeLeft ? "true" : "false"); - txtvLength = (TextView) findViewById(R.id.txtvLength); + txtvLength = findViewById(R.id.txtvLength); if (txtvLength != null) { txtvLength.setOnClickListener(v -> { showTimeLeft = !showTimeLeft; @@ -825,18 +860,18 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements }); } - butRev = (ImageButton) findViewById(R.id.butRev); - txtvRev = (TextView) findViewById(R.id.txtvRev); + butRev = findViewById(R.id.butRev); + txtvRev = findViewById(R.id.txtvRev); if (txtvRev != null) { txtvRev.setText(String.valueOf(UserPreferences.getRewindSecs())); } - butPlay = (ImageButton) findViewById(R.id.butPlay); - butFF = (ImageButton) findViewById(R.id.butFF); - txtvFF = (TextView) findViewById(R.id.txtvFF); + butPlay = findViewById(R.id.butPlay); + butFF = findViewById(R.id.butFF); + txtvFF = findViewById(R.id.txtvFF); if (txtvFF != null) { txtvFF.setText(String.valueOf(UserPreferences.getFastForwardSecs())); } - butSkip = (ImageButton) findViewById(R.id.butSkip); + butSkip = findViewById(R.id.butSkip); // SEEKBAR SETUP @@ -863,7 +898,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements } if (butSkip != null) { - butSkip.setOnClickListener(v -> sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE))); + butSkip.setOnClickListener(v -> + IntentUtils.sendLocalBroadcast(MediaplayerActivity.this, PlaybackService.ACTION_SKIP_CURRENT_EPISODE)); } } @@ -937,22 +973,62 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements private void checkFavorite() { Playable playable = controller.getMedia(); - if (playable != null && playable instanceof FeedMedia) { - FeedItem feedItem = ((FeedMedia) playable).getItem(); - if (feedItem != null) { - Observable.fromCallable(() -> DBReader.getFeedItem(feedItem.getId())) - .subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe( - item -> { - boolean isFav = item.isTagged(FeedItem.TAG_FAVORITE); - if (isFavorite != isFav) { - isFavorite = isFav; - invalidateOptionsMenu(); - } - }, error -> Log.e(TAG, Log.getStackTraceString(error))); + if (!(playable instanceof FeedMedia)) { + return; + } + FeedItem feedItem = ((FeedMedia) playable).getItem(); + if (feedItem == null) { + return; + } + if (disposable != null) { + disposable.dispose(); + } + disposable = Observable.fromCallable(() -> DBReader.getFeedItem(feedItem.getId())) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + item -> { + boolean isFav = item.isTagged(FeedItem.TAG_FAVORITE); + if (isFavorite != isFav) { + isFavorite = isFav; + invalidateOptionsMenu(); + } + }, error -> Log.e(TAG, Log.getStackTraceString(error))); + } + + void playExternalMedia(Intent intent, MediaType type) { + if (intent == null || intent.getData() == null) { + return; + } + if (Build.VERSION.SDK_INT >= 23 + && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + + if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) { + Toast.makeText(this, R.string.needs_storage_permission, Toast.LENGTH_LONG).show(); + } else { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + REQUEST_CODE_STORAGE); + } + return; + } + + Log.d(TAG, "Received VIEW intent: " + intent.getData().getPath()); + ExternalMedia media = new ExternalMedia(intent.getData().getPath(), type); + + new PlaybackServiceStarter(this, media) + .startWhenPrepared(true) + .shouldStream(false) + .prepareImmediately(true) + .start(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + if (requestCode == REQUEST_CODE_STORAGE) { + if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { + Toast.makeText(this, R.string.needs_storage_permission, Toast.LENGTH_LONG).show(); } } } - } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java index f3ed1cb62..3db00edc9 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java @@ -46,8 +46,9 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlayerStatus; import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.util.IntentUtils; +import de.danoeh.antennapod.core.util.download.AutoUpdateManager; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; import de.danoeh.antennapod.dialog.RenameFeedDialog; @@ -62,10 +63,10 @@ import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.fragment.SubscriptionFragment; import de.danoeh.antennapod.menuhandler.NavDrawerActivity; import de.greenrobot.event.EventBus; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Activity for playing files that do not require a video surface. @@ -105,7 +106,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem private ViewPager pager; private MediaplayerInfoPagerAdapter pagerAdapter; - private Subscription subscription; + private Disposable disposable; @Override protected void onPause() { @@ -126,8 +127,8 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem if(pagerAdapter != null) { pagerAdapter.setController(null); } - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } EventDistributor.getInstance().unregister(contentUpdate); saveCurrentFragment(); @@ -186,7 +187,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem pagerAdapter.onMediaChanged(media); pagerAdapter.setController(controller); } - DBTasks.checkShouldRefreshFeeds(getApplicationContext()); + AutoUpdateManager.checkShouldRefreshFeeds(getApplicationContext()); EventDistributor.getInstance().register(contentUpdate); EventBus.getDefault().register(this); @@ -226,18 +227,18 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem @Override protected void setupGUI() { super.setupGUI(); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setTitle(""); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { findViewById(R.id.shadow).setVisibility(View.GONE); - AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appBar); + AppBarLayout appBarLayout = findViewById(R.id.appBar); float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics()); appBarLayout.setElevation(px); } - drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); - navList = (ListView) findViewById(R.id.nav_list); + drawerLayout = findViewById(R.id.drawer_layout); + navList = findViewById(R.id.nav_list); navDrawer = findViewById(R.id.nav_layout); drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close); @@ -273,14 +274,15 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem startActivity(new Intent(MediaplayerInfoActivity.this, PreferenceActivity.class)); }); - butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed); - butCastDisconnect = (ImageButton) findViewById(R.id.butCastDisconnect); + butPlaybackSpeed = findViewById(R.id.butPlaybackSpeed); + butCastDisconnect = findViewById(R.id.butCastDisconnect); - pager = (ViewPager) findViewById(R.id.pager); + pager = findViewById(R.id.pager); + pager.setOffscreenPageLimit(3); pagerAdapter = new MediaplayerInfoPagerAdapter(getSupportFragmentManager(), media); pagerAdapter.setController(controller); pager.setAdapter(pagerAdapter); - CirclePageIndicator pageIndicator = (CirclePageIndicator) findViewById(R.id.page_indicator); + CirclePageIndicator pageIndicator = findViewById(R.id.page_indicator); pageIndicator.setViewPager(pager); loadLastFragment(); pager.onSaveInstanceState(); @@ -356,7 +358,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem @Override public boolean onOptionsItemSelected(MenuItem item) { - return drawerToggle != null && drawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item); + return (drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) || super.onOptionsItemSelected(item); } @Override @@ -413,8 +415,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem Log.d(TAG, "Currently playing episode is about to be deleted, skipping"); remover.skipOnCompletion = true; if(controller.getStatus() == PlayerStatus.PLAYING) { - sendBroadcast(new Intent( - PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE)); + IntentUtils.sendLocalBroadcast(MediaplayerInfoActivity.this, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE); } } } @@ -472,8 +473,8 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem private DBReader.NavDrawerData navDrawerData; private void loadData() { - subscription = Observable.fromCallable(DBReader::getNavDrawerData) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(DBReader::getNavDrawerData) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { navDrawerData = result; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java index f859f5466..145908e97 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.annotation.UiThread; import android.support.v4.app.NavUtils; import android.support.v7.app.ActionBar; @@ -27,6 +28,7 @@ import android.widget.Spinner; import android.widget.TextView; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import org.apache.commons.lang3.StringUtils; import org.jsoup.Jsoup; @@ -56,19 +58,21 @@ import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.syndication.handler.FeedHandler; +import de.danoeh.antennapod.core.syndication.handler.FeedHandlerResult; import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException; import de.danoeh.antennapod.core.util.DownloadError; import de.danoeh.antennapod.core.util.FileNameGenerator; +import de.danoeh.antennapod.core.util.Optional; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.URLChecker; import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer; import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText; import de.danoeh.antennapod.dialog.AuthenticationDialog; import de.greenrobot.event.EventBus; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Downloads a feed from a feed URL and parses it. Subclasses can display the @@ -97,15 +101,15 @@ public class OnlineFeedViewActivity extends AppCompatActivity { private Button subscribeButton; - private Subscription download; - private Subscription parser; - private Subscription updater; + private Disposable download; + private Disposable parser; + private Disposable updater; private final EventDistributor.EventListener listener = new EventDistributor.EventListener() { @Override public void update(EventDistributor eventDistributor, Integer arg) { if ((arg & EventDistributor.FEED_LIST_UPDATE) != 0) { updater = Observable.fromCallable(DBReader::getFeedList) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( feeds -> { @@ -139,26 +143,33 @@ public class OnlineFeedViewActivity extends AppCompatActivity { StorageUtils.checkStorageAvailability(this); - final String feedUrl; + String feedUrl = null; if (getIntent().hasExtra(ARG_FEEDURL)) { feedUrl = getIntent().getStringExtra(ARG_FEEDURL); } else if (TextUtils.equals(getIntent().getAction(), Intent.ACTION_SEND) || TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) { - feedUrl = (TextUtils.equals(getIntent().getAction(), Intent.ACTION_SEND)) + feedUrl = TextUtils.equals(getIntent().getAction(), Intent.ACTION_SEND) ? getIntent().getStringExtra(Intent.EXTRA_TEXT) : getIntent().getDataString(); if (actionBar != null) { actionBar.setTitle(R.string.add_feed_label); } - } else { - throw new IllegalArgumentException("Activity must be started with feedurl argument!"); } - Log.d(TAG, "Activity was started with url " + feedUrl); - setLoadingLayout(); - if (savedInstanceState == null) { - startFeedDownload(feedUrl, null, null); + if (feedUrl == null) { + Log.e(TAG, "feedUrl is null."); + new AlertDialog.Builder(OnlineFeedViewActivity.this). + setNeutralButton(android.R.string.ok, + (dialog, which) -> finish()). + setTitle(R.string.error_label). + setMessage(R.string.null_value_podcast_error).create().show(); } else { - startFeedDownload(feedUrl, savedInstanceState.getString("username"), savedInstanceState.getString("password")); + Log.d(TAG, "Activity was started with url " + feedUrl); + setLoadingLayout(); + if (savedInstanceState == null) { + startFeedDownload(feedUrl, null, null); + } else { + startFeedDownload(feedUrl, savedInstanceState.getString("username"), savedInstanceState.getString("password")); + } } } @@ -212,13 +223,13 @@ public class OnlineFeedViewActivity extends AppCompatActivity { public void onDestroy() { super.onDestroy(); if(updater != null) { - updater.unsubscribe(); + updater.dispose(); } if(download != null) { - download.unsubscribe(); + download.dispose(); } if(parser != null) { - parser.unsubscribe(); + parser.dispose(); } } @@ -273,18 +284,13 @@ public class OnlineFeedViewActivity extends AppCompatActivity { downloader.call(); return downloader.getResult(); }) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::checkDownloadResult, error -> Log.e(TAG, Log.getStackTraceString(error))); } - private void checkDownloadResult(DownloadStatus status) { - if (status == null) { - Log.wtf(TAG, "DownloadStatus returned by Downloader was null"); - finish(); - return; - } + private void checkDownloadResult(@NonNull DownloadStatus status) { if (status.isCancelled()) { return; } @@ -306,35 +312,17 @@ public class OnlineFeedViewActivity extends AppCompatActivity { } private void parseFeed() { - if (feed == null || feed.getFile_url() == null && feed.isDownloaded()) { + if (feed == null || (feed.getFile_url() == null && feed.isDownloaded())) { throw new IllegalStateException("feed must be non-null and downloaded when parseFeed is called"); } Log.d(TAG, "Parsing feed"); - parser = Observable.fromCallable(() -> { - FeedHandler handler = new FeedHandler(); - try { - return handler.parseFeed(feed); - } catch (UnsupportedFeedtypeException e) { - Log.d(TAG, "Unsupported feed type detected"); - if (TextUtils.equals("html", e.getRootElement().toLowerCase())) { - showFeedDiscoveryDialog(new File(feed.getFile_url()), feed.getDownload_url()); - return null; - } else { - throw e; - } - } catch (Exception e) { - Log.e(TAG, Log.getStackTraceString(e)); - throw e; - } finally { - boolean rc = new File(feed.getFile_url()).delete(); - Log.d(TAG, "Deleted feed source file. Result: " + rc); - } - }) - .subscribeOn(Schedulers.newThread()) + parser = Observable.fromCallable(this::doParseFeed) + .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - if(result != null) { + .subscribe(optionalResult -> { + if(optionalResult.isPresent()) { + FeedHandlerResult result = optionalResult.get(); beforeShowFeedInformation(result.feed); showFeedInformation(result.feed, result.alternateFeedUrls); } @@ -342,9 +330,37 @@ public class OnlineFeedViewActivity extends AppCompatActivity { String errorMsg = DownloadError.ERROR_PARSER_EXCEPTION.getErrorString( OnlineFeedViewActivity.this) + " (" + error.getMessage() + ")"; showErrorDialog(errorMsg); + Log.d(TAG, "Feed parser exception: " + Log.getStackTraceString(error)); }); } + @NonNull + private Optional doParseFeed() throws Exception { + FeedHandler handler = new FeedHandler(); + try { + return Optional.of(handler.parseFeed(feed)); + } catch (UnsupportedFeedtypeException e) { + Log.d(TAG, "Unsupported feed type detected"); + if ("html".equalsIgnoreCase(e.getRootElement())) { + boolean dialogShown = showFeedDiscoveryDialog(new File(feed.getFile_url()), feed.getDownload_url()); + if (dialogShown) { + return Optional.empty(); + } else { + Log.d(TAG, "Supplied feed is an HTML web page that has no references to any feed"); + throw e; + } + } else { + throw e; + } + } catch (Exception e) { + Log.e(TAG, Log.getStackTraceString(e)); + throw e; + } finally { + boolean rc = new File(feed.getFile_url()).delete(); + Log.d(TAG, "Deleted feed source file. Result: " + rc); + } + } + /** * Called after the feed has been downloaded and parsed and before showFeedInformation is called. * This method is executed on a background thread @@ -378,29 +394,30 @@ public class OnlineFeedViewActivity extends AppCompatActivity { this.feed = feed; this.selectedDownloadUrl = feed.getDownload_url(); EventDistributor.getInstance().register(listener); - ListView listView = (ListView) findViewById(R.id.listview); + ListView listView = findViewById(R.id.listview); LayoutInflater inflater = LayoutInflater.from(this); View header = inflater.inflate(R.layout.onlinefeedview_header, listView, false); listView.addHeaderView(header); listView.setAdapter(new FeedItemlistDescriptionAdapter(this, 0, feed.getItems())); - ImageView cover = (ImageView) header.findViewById(R.id.imgvCover); - TextView title = (TextView) header.findViewById(R.id.txtvTitle); - TextView author = (TextView) header.findViewById(R.id.txtvAuthor); - TextView description = (TextView) header.findViewById(R.id.txtvDescription); - Spinner spAlternateUrls = (Spinner) header.findViewById(R.id.spinnerAlternateUrls); + ImageView cover = header.findViewById(R.id.imgvCover); + TextView title = header.findViewById(R.id.txtvTitle); + TextView author = header.findViewById(R.id.txtvAuthor); + TextView description = header.findViewById(R.id.txtvDescription); + Spinner spAlternateUrls = header.findViewById(R.id.spinnerAlternateUrls); - subscribeButton = (Button) header.findViewById(R.id.butSubscribe); + subscribeButton = header.findViewById(R.id.butSubscribe); - if (feed.getImage() != null && StringUtils.isNotBlank(feed.getImage().getDownload_url())) { + if (StringUtils.isNotBlank(feed.getImageUrl())) { Glide.with(this) - .load(feed.getImage().getDownload_url()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .load(feed.getImageUrl()) + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(cover); } @@ -527,21 +544,25 @@ public class OnlineFeedViewActivity extends AppCompatActivity { } } - private void showFeedDiscoveryDialog(File feedFile, String baseUrl) { + /** + * + * @return true if a FeedDiscoveryDialog is shown, false otherwise (e.g., due to no feed found). + */ + private boolean showFeedDiscoveryDialog(File feedFile, String baseUrl) { FeedDiscoverer fd = new FeedDiscoverer(); final Map urlsMap; try { urlsMap = fd.findLinks(feedFile, baseUrl); if (urlsMap == null || urlsMap.isEmpty()) { - return; + return false; } } catch (IOException e) { e.printStackTrace(); - return; + return false; } if (isPaused || isFinishing()) { - return; + return false; } final List titles = new ArrayList<>(); @@ -577,6 +598,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity { } dialog = ab.show(); }); + return true; } private class FeedViewAuthenticationDialog extends AuthenticationDialog { diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java index cd375a65a..72759c59c 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java @@ -39,9 +39,9 @@ public class OpmlFeedChooserActivity extends AppCompatActivity { super.onCreate(savedInstanceState); setContentView(R.layout.opml_selection); - butConfirm = (Button) findViewById(R.id.butConfirm); - butCancel = (Button) findViewById(R.id.butCancel); - feedlist = (ListView) findViewById(R.id.feedlist); + butConfirm = findViewById(R.id.butConfirm); + butCancel = findViewById(R.id.butCancel); + feedlist = findViewById(R.id.feedlist); feedlist.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); listAdapter = new ArrayAdapter<>(this, diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java index ed7ab5d34..a63d3b735 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java @@ -36,16 +36,16 @@ public class OpmlImportFromPathActivity extends OpmlImportBaseActivity { getSupportActionBar().setDisplayHomeAsUpEnabled(true); setContentView(R.layout.opml_import); - final TextView txtvHeaderExplanation1 = (TextView) findViewById(R.id.txtvHeadingExplanation1); - final TextView txtvExplanation1 = (TextView) findViewById(R.id.txtvExplanation1); - final TextView txtvHeaderExplanation2 = (TextView) findViewById(R.id.txtvHeadingExplanation2); - final TextView txtvExplanation2 = (TextView) findViewById(R.id.txtvExplanation2); - final TextView txtvHeaderExplanation3 = (TextView) findViewById(R.id.txtvHeadingExplanation3); + final TextView txtvHeaderExplanation1 = findViewById(R.id.txtvHeadingExplanation1); + final TextView txtvExplanation1 = findViewById(R.id.txtvExplanation1); + final TextView txtvHeaderExplanation2 = findViewById(R.id.txtvHeadingExplanation2); + final TextView txtvExplanation2 = findViewById(R.id.txtvExplanation2); + final TextView txtvHeaderExplanation3 = findViewById(R.id.txtvHeadingExplanation3); - Button butChooseFilesystem = (Button) findViewById(R.id.butChooseFileFromFilesystem); + Button butChooseFilesystem = findViewById(R.id.butChooseFileFromFilesystem); butChooseFilesystem.setOnClickListener(v -> chooseFileFromFilesystem()); - Button butChooseExternal = (Button) findViewById(R.id.butChooseFileFromExternal); + Button butChooseExternal = findViewById(R.id.butChooseFileFromExternal); butChooseExternal.setOnClickListener(v -> chooseFileFromExternal()); int nextOption = 1; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java index b01cf43e4..dc5570dc0 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java @@ -14,6 +14,8 @@ import de.danoeh.antennapod.core.export.opml.OpmlElement; */ public class OpmlImportHolder { + private OpmlImportHolder(){} + private static ArrayList readElements; public static ArrayList getReadElements() { diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java index 3f005fe36..452e91bd3 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java @@ -12,11 +12,11 @@ import android.view.MenuItem; import android.view.ViewGroup; import android.widget.FrameLayout; -import java.lang.ref.WeakReference; - -import com.bytehamster.lib.preferencesearch.SearchPreference; import com.bytehamster.lib.preferencesearch.SearchPreferenceResult; import com.bytehamster.lib.preferencesearch.SearchPreferenceResultListener; + +import java.lang.ref.WeakReference; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.preferences.PreferenceController; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java index b92ac8577..52102eee1 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java @@ -1,23 +1,51 @@ package de.danoeh.antennapod.activity; import android.content.Intent; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v7.app.AppCompatActivity; +import android.widget.ProgressBar; + +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.storage.PodDBAdapter; +import io.reactivex.Completable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; /** - * Creator: vbarad - * Date: 2016-12-03 - * Project: AntennaPod + * Shows the AntennaPod logo while waiting for the main activity to start */ - public class SplashActivity extends AppCompatActivity { - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.splash); - Intent intent = new Intent(this, MainActivity.class); - startActivity(intent); - finish(); - } + ProgressBar progressBar = findViewById(R.id.progressBar); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + Drawable wrapDrawable = DrawableCompat.wrap(progressBar.getIndeterminateDrawable()); + DrawableCompat.setTint(wrapDrawable, 0xffffffff); + progressBar.setIndeterminateDrawable(DrawableCompat.unwrap(wrapDrawable)); + } else { + progressBar.getIndeterminateDrawable().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_IN); + } + + Completable.create(subscriber -> { + // Trigger schema updates + PodDBAdapter.getInstance().open(); + PodDBAdapter.getInstance().close(); + subscriber.onComplete(); + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(() -> { + Intent intent = new Intent(SplashActivity.this, MainActivity.class); + startActivity(intent); + finish(); + }); + } } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java index b2ff43c43..37199ccf7 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java @@ -20,10 +20,10 @@ import de.danoeh.antennapod.adapter.StatisticsListAdapter; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.Converter; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Displays the 'statistics' screen @@ -35,7 +35,7 @@ public class StatisticsActivity extends AppCompatActivity private static final String PREF_NAME = "StatisticsActivityPrefs"; private static final String PREF_COUNT_ALL = "countAll"; - private Subscription subscription; + private Disposable disposable; private TextView totalTimeTextView; private ListView feedStatisticsList; private ProgressBar progressBar; @@ -53,9 +53,9 @@ public class StatisticsActivity extends AppCompatActivity prefs = getSharedPreferences(PREF_NAME, MODE_PRIVATE); countAll = prefs.getBoolean(PREF_COUNT_ALL, false); - totalTimeTextView = (TextView) findViewById(R.id.total_time); - feedStatisticsList = (ListView) findViewById(R.id.statistics_list); - progressBar = (ProgressBar) findViewById(R.id.progressBar); + totalTimeTextView = findViewById(R.id.total_time); + feedStatisticsList = findViewById(R.id.statistics_list); + progressBar = findViewById(R.id.progressBar); listAdapter = new StatisticsListAdapter(this); listAdapter.setCountAll(countAll); feedStatisticsList.setAdapter(listAdapter); @@ -119,21 +119,19 @@ public class StatisticsActivity extends AppCompatActivity } private void loadStatistics() { - if (subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } - subscription = Observable.fromCallable(() -> DBReader.getStatistics(countAll)) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(() -> DBReader.getStatistics(countAll)) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { - if (result != null) { - totalTimeTextView.setText(Converter - .shortLocalizedDuration(this, countAll ? result.totalTimeCountAll : result.totalTime)); - listAdapter.update(result.feedTime); - progressBar.setVisibility(View.GONE); - totalTimeTextView.setVisibility(View.VISIBLE); - feedStatisticsList.setVisibility(View.VISIBLE); - } + totalTimeTextView.setText(Converter + .shortLocalizedDuration(this, countAll ? result.totalTimeCountAll : result.totalTime)); + listAdapter.update(result.feedTime); + progressBar.setVisibility(View.GONE); + totalTimeTextView.setVisibility(View.VISIBLE); + feedStatisticsList.setVisibility(View.VISIBLE); }, error -> Log.e(TAG, Log.getStackTraceString(error))); } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java index a2a49f54e..20e34cc52 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java @@ -42,7 +42,7 @@ public class StorageErrorActivity extends AppCompatActivity { setContentView(R.layout.storage_error); - Button btnChooseDataFolder = (Button) findViewById(R.id.btnChooseDataFolder); + Button btnChooseDataFolder = findViewById(R.id.btnChooseDataFolder); btnChooseDataFolder.setOnClickListener(v -> { if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT && Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) { diff --git a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java index c8fb12abc..fa5012b74 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java @@ -8,6 +8,7 @@ import android.os.Bundle; import android.os.Handler; import android.support.v4.view.WindowCompat; import android.support.v7.app.ActionBar; +import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.view.Menu; @@ -22,20 +23,19 @@ import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.SeekBar; + +import java.lang.ref.WeakReference; +import java.util.concurrent.atomic.AtomicBoolean; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlayerStatus; import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; -import de.danoeh.antennapod.core.util.playback.ExternalMedia; import de.danoeh.antennapod.core.util.playback.Playable; -import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter; import de.danoeh.antennapod.view.AspectRatioVideoView; -import java.lang.ref.WeakReference; -import java.util.concurrent.atomic.AtomicBoolean; - /** * Activity for playing video files. */ @@ -47,6 +47,7 @@ public class VideoplayerActivity extends MediaplayerActivity { */ private boolean videoControlsShowing = true; private boolean videoSurfaceCreated = false; + private boolean playbackStoppedUponExitVideo = false; private boolean destroyingDueToReload = false; private VideoControlsHider videoControlsHider = new VideoControlsHider(this); @@ -77,18 +78,9 @@ public class VideoplayerActivity extends MediaplayerActivity { @Override protected void onResume() { super.onResume(); - if (getIntent().getAction() != null - && getIntent().getAction().equals(Intent.ACTION_VIEW)) { - Intent intent = getIntent(); - Log.d(TAG, "Received VIEW intent: " + intent.getData().getPath()); - ExternalMedia media = new ExternalMedia(intent.getData().getPath(), - MediaType.VIDEO); - - new PlaybackServiceStarter(this, media) - .startWhenPrepared(true) - .shouldStream(false) - .prepareImmediately(true) - .start(); + playbackStoppedUponExitVideo = false; + if (TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) { + playExternalMedia(getIntent(), MediaType.VIDEO); } else if (PlaybackService.isCasting()) { Intent intent = PlaybackService.getPlayerActivityIntent(this); if (!intent.getComponent().getClassName().equals(VideoplayerActivity.class.getName())) { @@ -101,12 +93,32 @@ public class VideoplayerActivity extends MediaplayerActivity { @Override protected void onStop() { + stopPlaybackIfUserPreferencesSpecified(); // MUST be called before super.onStop(), while it still has member variable controller super.onStop(); if (!PictureInPictureUtil.isInPictureInPictureMode(this)) { videoControlsHider.stop(); } } + void stopPlaybackIfUserPreferencesSpecified() { + // to avoid the method being called twice during leaving Videoplayer + // , which will double-pause the media + // (it is usually first called by surfaceHolderCallback.surfaceDestroyed(), + // then VideoplayerActivity.onStop() , but sometimes VideoplayerActivity.onStop() + // will first be invoked.) + if (playbackStoppedUponExitVideo) { + return; + } + playbackStoppedUponExitVideo = true; + + if (controller != null && !destroyingDueToReload + && UserPreferences.getVideoBackgroundBehavior() + != UserPreferences.VideoBackgroundBehavior.CONTINUE_PLAYING) { + Log.v(TAG, "stop video playback per UserPreference"); + controller.notifyVideoSurfaceAbandoned(); + } + } + @Override public void onUserLeaveHint () { if (!PictureInPictureUtil.isInPictureInPictureMode(this) && UserPreferences.getVideoBackgroundBehavior() @@ -153,11 +165,11 @@ public class VideoplayerActivity extends MediaplayerActivity { } super.setupGUI(); getSupportActionBar().setDisplayHomeAsUpEnabled(true); - controls = (LinearLayout) findViewById(R.id.controls); - videoOverlay = (LinearLayout) findViewById(R.id.overlay); - videoview = (AspectRatioVideoView) findViewById(R.id.videoview); - videoframe = (FrameLayout) findViewById(R.id.videoframe); - progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator); + controls = findViewById(R.id.controls); + videoOverlay = findViewById(R.id.overlay); + videoview = findViewById(R.id.videoview); + videoframe = findViewById(R.id.videoframe); + progressIndicator = findViewById(R.id.progressIndicator); videoview.getHolder().addCallback(surfaceHolderCallback); videoframe.setOnTouchListener(onVideoviewTouched); videoOverlay.setOnTouchListener((view, motionEvent) -> true); // To suppress touches directly below the slider @@ -285,13 +297,12 @@ public class VideoplayerActivity extends MediaplayerActivity { @Override public void surfaceDestroyed(SurfaceHolder holder) { - Log.d(TAG, "Videosurface was destroyed"); + Log.d(TAG, "Videosurface was destroyed." ); + Log.v(TAG, " hasController=" + (controller != null) + + " , destroyingDueToReload=" + destroyingDueToReload + + " , videoBackgroundBehavior=" + UserPreferences.getVideoBackgroundBehavior()); videoSurfaceCreated = false; - if (controller != null && !destroyingDueToReload - && UserPreferences.getVideoBackgroundBehavior() - != UserPreferences.VideoBackgroundBehavior.CONTINUE_PLAYING) { - controller.notifyVideoSurfaceAbandoned(); - } + stopPlaybackIfUserPreferencesSpecified(); } }; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java index 8f447ac90..8fcdb4371 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java @@ -45,8 +45,6 @@ import de.danoeh.antennapod.core.service.GpodnetSyncService; public class GpodnetAuthenticationActivity extends AppCompatActivity { private static final String TAG = "GpodnetAuthActivity"; - private static final String CURRENT_STEP = "current_step"; - private ViewFlipper viewFlipper; private static final int STEP_DEFAULT = -1; @@ -72,7 +70,7 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity { setContentView(R.layout.gpodnetauth_activity); service = new GpodnetService(); - viewFlipper = (ViewFlipper) findViewById(R.id.viewflipper); + viewFlipper = findViewById(R.id.viewflipper); LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); views = new View[]{ @@ -109,11 +107,11 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity { } private void setupLoginView(View view) { - final EditText username = (EditText) view.findViewById(R.id.etxtUsername); - final EditText password = (EditText) view.findViewById(R.id.etxtPassword); - final Button login = (Button) view.findViewById(R.id.butLogin); - final TextView txtvError = (TextView) view.findViewById(R.id.txtvError); - final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.progBarLogin); + final EditText username = view.findViewById(R.id.etxtUsername); + final EditText password = view.findViewById(R.id.etxtPassword); + final Button login = view.findViewById(R.id.butLogin); + final TextView txtvError = view.findViewById(R.id.txtvError); + final ProgressBar progressBar = view.findViewById(R.id.progBarLogin); password.setOnEditorActionListener((v, actionID, event) -> actionID == EditorInfo.IME_ACTION_GO && login.performClick()); @@ -177,13 +175,13 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity { } private void setupDeviceView(View view) { - final EditText deviceID = (EditText) view.findViewById(R.id.etxtDeviceID); - final EditText caption = (EditText) view.findViewById(R.id.etxtCaption); - final Button createNewDevice = (Button) view.findViewById(R.id.butCreateNewDevice); - final Button chooseDevice = (Button) view.findViewById(R.id.butChooseExistingDevice); - final TextView txtvError = (TextView) view.findViewById(R.id.txtvError); - final ProgressBar progBarCreateDevice = (ProgressBar) view.findViewById(R.id.progbarCreateDevice); - final Spinner spinnerDevices = (Spinner) view.findViewById(R.id.spinnerChooseDevice); + final EditText deviceID = view.findViewById(R.id.etxtDeviceID); + final EditText caption = view.findViewById(R.id.etxtCaption); + final Button createNewDevice = view.findViewById(R.id.butCreateNewDevice); + final Button chooseDevice = view.findViewById(R.id.butChooseExistingDevice); + final TextView txtvError = view.findViewById(R.id.txtvError); + final ProgressBar progBarCreateDevice = view.findViewById(R.id.progbarCreateDevice); + final Spinner spinnerDevices = view.findViewById(R.id.spinnerChooseDevice); // load device list @@ -348,8 +346,8 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity { } private void setupFinishView(View view) { - final Button sync = (Button) view.findViewById(R.id.butSyncNow); - final Button back = (Button) view.findViewById(R.id.butGoMainscreen); + final Button sync = view.findViewById(R.id.butSyncNow); + final Button back = view.findViewById(R.id.butGoMainscreen); sync.setOnClickListener(v -> { GpodnetSyncService.sendSyncIntent(GpodnetAuthenticationActivity.this); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java index 715318db1..0b2b81edb 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java @@ -1,6 +1,7 @@ package de.danoeh.antennapod.adapter; import android.os.Build; +import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; @@ -19,7 +20,6 @@ import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; -import com.bumptech.glide.Glide; import com.joanzapata.iconify.Iconify; import java.lang.ref.WeakReference; @@ -28,13 +28,12 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.glide.ApGlideSettings; -import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.DateUtils; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.NetworkUtils; +import de.danoeh.antennapod.core.util.ThemeUtils; import de.danoeh.antennapod.fragment.ItemFragment; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; @@ -51,7 +50,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter= 23) { holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL); } - holder.pubDate = (TextView) view + holder.pubDate = view .findViewById(R.id.txtvPublished); holder.statusUnread = view.findViewById(R.id.statusUnread); - holder.butSecondary = (ImageButton) view + holder.butSecondary = view .findViewById(R.id.butSecondaryAction); - holder.queueStatus = (ImageView) view + holder.queueStatus = view .findViewById(R.id.imgvInPlaylist); - holder.progress = (ProgressBar) view + holder.progress = view .findViewById(R.id.pbar_progress); - holder.cover = (ImageView) view.findViewById(R.id.imgvCover); - holder.txtvDuration = (TextView) view.findViewById(R.id.txtvDuration); + holder.cover = view.findViewById(R.id.imgvCover); + holder.txtvDuration = view.findViewById(R.id.txtvDuration); holder.item = null; holder.mainActivityRef = mainActivityRef; // so we can grab this later @@ -111,7 +106,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter { - this.position = holder.getAdapterPosition(); + this.selectedItem = item; return false; }); holder.item = item; @@ -196,12 +191,17 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter { @@ -57,12 +57,12 @@ public class ChaptersListAdapter extends ArrayAdapter { convertView = inflater.inflate(R.layout.simplechapter_item, parent, false); holder.view = convertView; - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); + holder.title = convertView.findViewById(R.id.txtvTitle); defaultTextColor = holder.title.getTextColors().getDefaultColor(); - holder.start = (TextView) convertView.findViewById(R.id.txtvStart); - holder.link = (TextView) convertView.findViewById(R.id.txtvLink); - holder.duration = (TextView) convertView.findViewById(R.id.txtvDuration); - holder.butPlayChapter = (ImageButton) convertView.findViewById(R.id.butPlayChapter); + holder.start = convertView.findViewById(R.id.txtvStart); + holder.link = convertView.findViewById(R.id.txtvLink); + holder.duration = convertView.findViewById(R.id.txtvDuration); + holder.butPlayChapter = convertView.findViewById(R.id.butPlayChapter); convertView.setTag(holder); } else { holder = (Holder) convertView.getTag(); @@ -143,9 +143,7 @@ public class ChaptersListAdapter extends ArrayAdapter { Chapter current = ChapterUtils.getCurrentChapter(media); if (current == sc) { - boolean darkTheme = UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark; - int highlight = darkTheme ? R.color.highlight_dark : R.color.highlight_light; - int playingBackGroundColor = ContextCompat.getColor(getContext(), highlight); + int playingBackGroundColor = ThemeUtils.getColorFromAttr(getContext(), R.attr.currently_playing_background); holder.view.setBackgroundColor(playingBackGroundColor); } else { holder.view.setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent)); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/CoverLoader.java b/app/src/main/java/de/danoeh/antennapod/adapter/CoverLoader.java new file mode 100644 index 000000000..54ecdae77 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/adapter/CoverLoader.java @@ -0,0 +1,113 @@ +package de.danoeh.antennapod.adapter; + +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestBuilder; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.CustomViewTarget; + +import java.lang.ref.WeakReference; + +import com.bumptech.glide.request.transition.Transition; +import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.core.glide.ApGlideSettings; + +public class CoverLoader { + private String uri; + private String fallbackUri; + private TextView txtvPlaceholder; + private ImageView imgvCover; + private MainActivity activity; + private int errorResource = -1; + + public CoverLoader(MainActivity activity) { + this.activity = activity; + } + + public CoverLoader withUri(String uri) { + this.uri = uri; + return this; + } + + public CoverLoader withFallbackUri(String uri) { + fallbackUri = uri; + return this; + } + + public CoverLoader withCoverView(ImageView coverView) { + imgvCover = coverView; + return this; + } + + public CoverLoader withError(int errorResource) { + this.errorResource = errorResource; + return this; + } + + public CoverLoader withPlaceholderView(TextView placeholderView) { + txtvPlaceholder = placeholderView; + return this; + } + + public void load() { + RequestOptions options = new RequestOptions() + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate(); + + if (errorResource != -1) { + options = options.error(errorResource); + } + + RequestBuilder builder = Glide.with(activity) + .load(uri) + .apply(options); + + if (fallbackUri != null && txtvPlaceholder != null && imgvCover != null) { + builder = builder.error(Glide.with(activity) + .load(fallbackUri) + .apply(options)); + } + + builder.into(new CoverTarget(txtvPlaceholder, imgvCover)); + } + + class CoverTarget extends CustomViewTarget { + private final WeakReference placeholder; + private final WeakReference cover; + + public CoverTarget(TextView txtvPlaceholder, ImageView imgvCover) { + super(imgvCover); + placeholder = new WeakReference<>(txtvPlaceholder); + cover = new WeakReference<>(imgvCover); + } + + @Override + public void onLoadFailed(Drawable errorDrawable) { + + } + + @Override + public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { + TextView txtvPlaceholder = placeholder.get(); + if (txtvPlaceholder != null) { + txtvPlaceholder.setVisibility(View.INVISIBLE); + } + ImageView ivCover = cover.get(); + ivCover.setImageDrawable(resource); + } + + @Override + protected void onResourceCleared(@Nullable Drawable placeholder) { + ImageView ivCover = cover.get(); + ivCover.setImageDrawable(placeholder); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java b/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java deleted file mode 100644 index ba6e7b25d..000000000 --- a/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.danoeh.antennapod.adapter; - -import android.graphics.drawable.Drawable; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.resource.drawable.GlideDrawable; -import com.bumptech.glide.request.animation.GlideAnimation; -import com.bumptech.glide.request.target.GlideDrawableImageViewTarget; - -import java.lang.ref.WeakReference; - -import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.core.glide.ApGlideSettings; - -class CoverTarget extends GlideDrawableImageViewTarget { - - private final WeakReference fallback; - private final WeakReference placeholder; - private final WeakReference cover; - private final WeakReference mainActivity; - - public CoverTarget(String fallbackUri, TextView txtvPlaceholder, ImageView imgvCover, MainActivity activity) { - super(imgvCover); - fallback = new WeakReference<>(fallbackUri); - placeholder = new WeakReference<>(txtvPlaceholder); - cover = new WeakReference<>(imgvCover); - mainActivity = new WeakReference<>(activity); - } - - @Override - public void onLoadFailed(Exception e, Drawable errorDrawable) { - String fallbackUri = fallback.get(); - TextView txtvPlaceholder = placeholder.get(); - ImageView imgvCover = cover.get(); - if (fallbackUri != null && txtvPlaceholder != null && imgvCover != null) { - MainActivity activity = mainActivity.get(); - Glide.with(activity) - .load(fallbackUri) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() - .into(new CoverTarget(null, txtvPlaceholder, imgvCover, activity)); - } - } - - @Override - public void onResourceReady(GlideDrawable drawable, GlideAnimation anim) { - super.onResourceReady(drawable, anim); - TextView txtvPlaceholder = placeholder.get(); - if (txtvPlaceholder != null) { - txtvPlaceholder.setVisibility(View.INVISIBLE); - } - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java index d8f324e8a..f54b9266e 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java @@ -1,12 +1,10 @@ package de.danoeh.antennapod.adapter; import android.content.Context; -import android.content.Intent; import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; -import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter; import org.apache.commons.lang3.Validate; import de.danoeh.antennapod.R; @@ -20,15 +18,17 @@ import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; +import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.NetworkUtils; +import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter; /** * Default implementation of an ActionButtonCallback */ public class DefaultActionButtonCallback implements ActionButtonCallback { - private static final String TAG = "DefaultActionButtonCallback"; + private static final String TAG = "DefaultActionBtnCb"; private final Context context; @@ -82,17 +82,13 @@ public class DefaultActionButtonCallback implements ActionButtonCallback { } } else { // media is downloaded if (media.isCurrentlyPlaying()) { - new PlaybackServiceStarter(context, media) - .startWhenPrepared(true) - .shouldStream(false) - .start(); - context.sendBroadcast(new Intent(PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE)); + IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE); } else if (media.isCurrentlyPaused()) { - new PlaybackServiceStarter(context, media) + new PlaybackServiceStarter(context, media) // need to start the service in case it's been stopped by system. .startWhenPrepared(true) .shouldStream(false) .start(); - context.sendBroadcast(new Intent(PlaybackService.ACTION_RESUME_PLAY_CURRENT_EPISODE)); + IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_RESUME_PLAY_CURRENT_EPISODE); } else { DBTasks.playMedia(context, media, false, true, false); } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java index 7c0be47b6..789c01a26 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java @@ -19,7 +19,6 @@ import com.joanzapata.iconify.widget.IconTextView; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.storage.DBReader; @@ -50,15 +49,15 @@ public class DownloadLogAdapter extends BaseAdapter { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.downloadlog_item, parent, false); - holder.icon = (IconTextView) convertView.findViewById(R.id.txtvIcon); - holder.retry = (IconButton) convertView.findViewById(R.id.btnRetry); - holder.date = (TextView) convertView.findViewById(R.id.txtvDate); - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); + holder.icon = convertView.findViewById(R.id.txtvIcon); + holder.retry = convertView.findViewById(R.id.btnRetry); + holder.date = convertView.findViewById(R.id.txtvDate); + holder.title = convertView.findViewById(R.id.txtvTitle); if(Build.VERSION.SDK_INT >= 23) { holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL); } - holder.type = (TextView) convertView.findViewById(R.id.txtvType); - holder.reason = (TextView) convertView.findViewById(R.id.txtvReason); + holder.type = convertView.findViewById(R.id.txtvType); + holder.reason = convertView.findViewById(R.id.txtvReason); convertView.setTag(holder); } else { holder = (Holder) convertView.getTag(); @@ -67,8 +66,6 @@ public class DownloadLogAdapter extends BaseAdapter { holder.type.setText(R.string.download_type_feed); } else if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { holder.type.setText(R.string.download_type_media); - } else if (status.getFeedfileType() == FeedImage.FEEDFILETYPE_FEEDIMAGE) { - holder.type.setText(R.string.download_type_image); } if (status.getTitle() != null) { holder.title.setText(status.getTitle()); @@ -94,8 +91,7 @@ public class DownloadLogAdapter extends BaseAdapter { } holder.reason.setText(reasonText); holder.reason.setVisibility(View.VISIBLE); - if(status.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE && - !newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) { + if(!newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) { holder.retry.setVisibility(View.VISIBLE); holder.retry.setOnClickListener(clickListener); ButtonHolder btnHolder; diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java index c4f476634..cd636af43 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java @@ -13,9 +13,11 @@ import android.widget.TextView; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.glide.ApGlideSettings; +import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.DateUtils; @@ -60,16 +62,16 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter { .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.downloaded_episodeslist_item, parent, false); - holder.imageView = (ImageView) convertView.findViewById(R.id.imgvImage); - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); + holder.imageView = convertView.findViewById(R.id.imgvImage); + holder.title = convertView.findViewById(R.id.txtvTitle); if(Build.VERSION.SDK_INT >= 23) { holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL); } - holder.txtvSize = (TextView) convertView.findViewById(R.id.txtvSize); - holder.queueStatus = (ImageView) convertView.findViewById(R.id.imgvInPlaylist); - holder.pubDate = (TextView) convertView + holder.txtvSize = convertView.findViewById(R.id.txtvSize); + holder.queueStatus = convertView.findViewById(R.id.imgvInPlaylist); + holder.pubDate = convertView .findViewById(R.id.txtvPublished); - holder.butSecondary = (ImageButton) convertView + holder.butSecondary = convertView .findViewById(R.id.butSecondaryAction); convertView.setTag(holder); } else { @@ -78,11 +80,12 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter { Glide.with(context) .load(item.getImageLocation()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(holder.imageView); if(item.isPlayed()) { @@ -98,7 +101,7 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter { holder.pubDate.setText(pubDateStr); FeedItem.State state = item.getState(); - if (state == FeedItem.State.PLAYING) { + if (state == FeedItem.State.PLAYING && PlaybackService.isRunning) { holder.butSecondary.setEnabled(false); holder.butSecondary.setAlpha(0.5f); } else { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java index 5bc67a95a..b85d1d35d 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java @@ -59,14 +59,14 @@ public class DownloadlistAdapter extends BaseAdapter { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.downloadlist_item, parent, false); - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); - holder.downloaded = (TextView) convertView + holder.title = convertView.findViewById(R.id.txtvTitle); + holder.downloaded = convertView .findViewById(R.id.txtvDownloaded); - holder.percent = (TextView) convertView + holder.percent = convertView .findViewById(R.id.txtvPercent); - holder.progbar = (ProgressBar) convertView + holder.progbar = convertView .findViewById(R.id.progProgress); - holder.butSecondary = (ImageButton) convertView + holder.butSecondary = convertView .findViewById(R.id.butSecondaryAction); convertView.setTag(holder); @@ -121,15 +121,6 @@ public class DownloadlistAdapter extends BaseAdapter { ImageButton butSecondary; } - public int getSelectedItemIndex() { - return selectedItemIndex; - } - - public void setSelectedItemIndex(int selectedItemIndex) { - this.selectedItemIndex = selectedItemIndex; - notifyDataSetChanged(); - } - public interface ItemAccess { int getCount(); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java index e29781be1..738a0a636 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java @@ -21,7 +21,6 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; -import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.DateUtils; import de.danoeh.antennapod.core.util.LongList; @@ -60,11 +59,7 @@ public class FeedItemlistAdapter extends BaseAdapter { this.actionButtonUtils = new ActionButtonUtils(context); this.makePlayedItemsTransparent = makePlayedItemsTransparent; - if(UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) { - playingBackGroundColor = ContextCompat.getColor(context, R.color.highlight_dark); - } else { - playingBackGroundColor = ContextCompat.getColor(context, R.color.highlight_light); - } + playingBackGroundColor = ThemeUtils.getColorFromAttr(context, R.attr.currently_playing_background); normalBackGroundColor = ContextCompat.getColor(context, android.R.color.transparent); } @@ -95,24 +90,24 @@ public class FeedItemlistAdapter extends BaseAdapter { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.feeditemlist_item, parent, false); - holder.container = (LinearLayout) convertView + holder.container = convertView .findViewById(R.id.container); - holder.title = (TextView) convertView.findViewById(R.id.txtvItemname); + holder.title = convertView.findViewById(R.id.txtvItemname); if(Build.VERSION.SDK_INT >= 23) { holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL); } - holder.lenSize = (TextView) convertView + holder.lenSize = convertView .findViewById(R.id.txtvLenSize); - holder.butAction = (ImageButton) convertView + holder.butAction = convertView .findViewById(R.id.butSecondaryAction); - holder.published = (TextView) convertView + holder.published = convertView .findViewById(R.id.txtvPublished); - holder.inPlaylist = (ImageView) convertView + holder.inPlaylist = convertView .findViewById(R.id.imgvInPlaylist); - holder.type = (ImageView) convertView.findViewById(R.id.imgvType); + holder.type = convertView.findViewById(R.id.imgvType); holder.statusUnread = convertView .findViewById(R.id.statusUnread); - holder.episodeProgress = (ProgressBar) convertView + holder.episodeProgress = convertView .findViewById(R.id.pbar_episode_progress); convertView.setTag(holder); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java index 5b205e91f..c10bb7638 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java @@ -34,9 +34,9 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter { LayoutInflater inflater = (LayoutInflater) getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.itemdescription_listitem, parent, false); - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); - holder.pubDate = (TextView) convertView.findViewById(R.id.txtvPubDate); - holder.description = (TextView) convertView.findViewById(R.id.txtvDescription); + holder.title = convertView.findViewById(R.id.txtvTitle); + holder.pubDate = convertView.findViewById(R.id.txtvPubDate); + holder.description = convertView.findViewById(R.id.txtvDescription); convertView.setTag(holder); } else { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java index 2daa5e70f..be8e52cfc 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java @@ -8,6 +8,7 @@ import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.preference.PreferenceManager; import android.support.v7.app.AlertDialog; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -17,6 +18,7 @@ import android.widget.RelativeLayout; import android.widget.TextView; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.widget.IconTextView; @@ -212,11 +214,18 @@ public class NavListAdapter extends BaseAdapter v = getFeedView(position, convertView, parent); } if (v != null && viewType != VIEW_TYPE_SECTION_DIVIDER) { - TextView txtvTitle = (TextView) v.findViewById(R.id.txtvTitle); + TextView txtvTitle = v.findViewById(R.id.txtvTitle); + TypedValue typedValue = new TypedValue(); + if (position == itemAccess.getSelectedItemIndex()) { txtvTitle.setTypeface(null, Typeface.BOLD); + v.getContext().getTheme().resolveAttribute(de.danoeh.antennapod.core.R.attr.drawer_activated_color, typedValue, true); + v.setBackgroundResource(typedValue.resourceId); + } else { txtvTitle.setTypeface(null, Typeface.NORMAL); + v.getContext().getTheme().resolveAttribute(de.danoeh.antennapod.core.R.attr.nav_drawer_background, typedValue, true); + v.setBackgroundResource(typedValue.resourceId); } } return v; @@ -235,9 +244,9 @@ public class NavListAdapter extends BaseAdapter convertView = inflater.inflate(R.layout.nav_listitem, parent, false); - holder.image = (ImageView) convertView.findViewById(R.id.imgvCover); - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); - holder.count = (TextView) convertView.findViewById(R.id.txtvCount); + holder.image = convertView.findViewById(R.id.imgvCover); + holder.title = convertView.findViewById(R.id.txtvTitle); + holder.count = convertView.findViewById(R.id.txtvCount); convertView.setTag(holder); } else { holder = (NavHolder) convertView.getTag(); @@ -325,10 +334,10 @@ public class NavListAdapter extends BaseAdapter convertView = inflater.inflate(R.layout.nav_feedlistitem, parent, false); - holder.image = (ImageView) convertView.findViewById(R.id.imgvCover); - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); - holder.failure = (IconTextView) convertView.findViewById(R.id.itxtvFailure); - holder.count = (TextView) convertView.findViewById(R.id.txtvCount); + holder.image = convertView.findViewById(R.id.imgvCover); + holder.title = convertView.findViewById(R.id.txtvTitle); + holder.failure = convertView.findViewById(R.id.itxtvFailure); + holder.count = convertView.findViewById(R.id.txtvCount); convertView.setTag(holder); } else { holder = (FeedHolder) convertView.getTag(); @@ -336,11 +345,12 @@ public class NavListAdapter extends BaseAdapter Glide.with(context) .load(feed.getImageLocation()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(holder.image); holder.title.setText(feed.getTitle()); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java index 01dd4c2de..df8cafb9d 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java @@ -23,6 +23,7 @@ import android.widget.ProgressBar; import android.widget.TextView; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import com.joanzapata.iconify.Iconify; import org.apache.commons.lang3.ArrayUtils; @@ -40,6 +41,7 @@ import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.DateUtils; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.NetworkUtils; +import de.danoeh.antennapod.core.util.ThemeUtils; import de.danoeh.antennapod.fragment.ItemFragment; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; @@ -75,11 +77,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter= 23) { title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL); } - pubDate = (TextView) v.findViewById(R.id.txtvPubDate); - progressLeft = (TextView) v.findViewById(R.id.txtvProgressLeft); - progressRight = (TextView) v.findViewById(R.id.txtvProgressRight); - butSecondary = (ImageButton) v.findViewById(R.id.butSecondaryAction); - progressBar = (ProgressBar) v.findViewById(R.id.progressBar); + pubDate = v.findViewById(R.id.txtvPubDate); + progressLeft = v.findViewById(R.id.txtvProgressLeft); + progressRight = v.findViewById(R.id.txtvProgressRight); + butSecondary = v.findViewById(R.id.butSecondaryAction); + progressBar = v.findViewById(R.id.progressBar); v.setTag(this); v.setOnClickListener(this); v.setOnCreateContextMenuListener(this); @@ -294,12 +292,12 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter= 23) { holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL); } - holder.cover = (ImageView) convertView + holder.cover = convertView .findViewById(R.id.imgvFeedimage); - holder.subtitle = (TextView) convertView + holder.subtitle = convertView .findViewById(R.id.txtvSubtitle); convertView.setTag(holder); @@ -81,11 +82,12 @@ public class SearchlistAdapter extends BaseAdapter { Glide.with(context) .load(feed.getImageLocation()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(holder.cover); } else if (component.getClass() == FeedItem.class) { @@ -100,11 +102,12 @@ public class SearchlistAdapter extends BaseAdapter { Glide.with(context) .load(item.getFeed().getImageLocation()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(holder.cover); } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java index 50255c11f..31e82dbe0 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java @@ -13,6 +13,7 @@ import com.bumptech.glide.Glide; import java.util.ArrayList; import java.util.List; +import com.bumptech.glide.request.RequestOptions; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.glide.ApGlideSettings; @@ -62,9 +63,9 @@ public class StatisticsListAdapter extends BaseAdapter { convertView = inflater.inflate(R.layout.statistics_listitem, parent, false); - holder.image = (ImageView) convertView.findViewById(R.id.imgvCover); - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); - holder.time = (TextView) convertView.findViewById(R.id.txtvTime); + holder.image = convertView.findViewById(R.id.imgvCover); + holder.title = convertView.findViewById(R.id.txtvTitle); + holder.time = convertView.findViewById(R.id.txtvTime); convertView.setTag(holder); } else { holder = (StatisticsHolder) convertView.getTag(); @@ -72,11 +73,12 @@ public class StatisticsListAdapter extends BaseAdapter { Glide.with(context) .load(feed.getImageLocation()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(holder.image); holder.title.setText(feed.getTitle()); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java index bb76ab501..763dcb57d 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java @@ -14,6 +14,7 @@ import com.bumptech.glide.Glide; import java.lang.ref.WeakReference; +import com.bumptech.glide.request.RequestOptions; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.feed.Feed; @@ -89,9 +90,9 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI LayoutInflater layoutInflater = (LayoutInflater) mainActivityRef.get().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = layoutInflater.inflate(R.layout.subscription_item, parent, false); - holder.feedTitle = (TextView) convertView.findViewById(R.id.txtvTitle); - holder.imageView = (ImageView) convertView.findViewById(R.id.imgvCover); - holder.count = (TriangleLabelView) convertView.findViewById(R.id.triangleCountView); + holder.feedTitle = convertView.findViewById(R.id.txtvTitle); + holder.imageView = convertView.findViewById(R.id.imgvCover); + holder.count = convertView.findViewById(R.id.triangleCountView); convertView.setTag(holder); @@ -108,7 +109,7 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI holder.count.setVisibility(View.INVISIBLE); // when this holder is reused, we could else end up with a cover image - Glide.clear(holder.imageView); + Glide.with(mainActivityRef.get()).clear(holder.imageView); return convertView; } @@ -125,13 +126,13 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI } else { holder.count.setVisibility(View.GONE); } - Glide.with(mainActivityRef.get()) - .load(feed.getImageLocation()) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() - .into(new CoverTarget(null, holder.feedTitle, holder.imageView, mainActivityRef.get())); + + new CoverLoader(mainActivityRef.get()) + .withUri(feed.getImageLocation()) + .withPlaceholderView(holder.feedTitle) + .withCoverView(holder.imageView) + .withError(R.color.light_gray) + .load(); return convertView; } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java index aea3d583f..06c80e173 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java @@ -10,6 +10,7 @@ import android.widget.TextView; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import org.apache.commons.lang3.StringUtils; import java.util.List; @@ -40,10 +41,10 @@ public class PodcastListAdapter extends ArrayAdapter { .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.gpodnet_podcast_listitem, parent, false); - holder.image = (ImageView) convertView.findViewById(R.id.imgvCover); - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); - holder.subscribers = (TextView) convertView.findViewById(R.id.txtvSubscribers); - holder.url = (TextView) convertView.findViewById(R.id.txtvUrl); + holder.image = convertView.findViewById(R.id.imgvCover); + holder.title = convertView.findViewById(R.id.txtvTitle); + holder.subscribers = convertView.findViewById(R.id.txtvSubscribers); + holder.url = convertView.findViewById(R.id.txtvUrl); convertView.setTag(holder); } else { holder = (Holder) convertView.getTag(); @@ -52,11 +53,12 @@ public class PodcastListAdapter extends ArrayAdapter { if (StringUtils.isNotBlank(podcast.getLogoUrl())) { Glide.with(convertView.getContext()) .load(podcast.getLogoUrl()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(holder.image); } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/TagListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/TagListAdapter.java index b4eadefb5..52fca792e 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/TagListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/TagListAdapter.java @@ -34,8 +34,8 @@ public class TagListAdapter extends ArrayAdapter { .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.gpodnet_tag_listitem, parent, false); - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); - holder.usage = (TextView) convertView.findViewById(R.id.txtvUsage); + holder.title = convertView.findViewById(R.id.txtvTitle); + holder.usage = convertView.findViewById(R.id.txtvUsage); convertView.setTag(holder); } else { holder = (Holder) convertView.getTag(); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java index e493a2ecc..2cf17c85f 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java @@ -12,6 +12,8 @@ import android.widget.TextView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.request.RequestOptions; +import de.danoeh.antennapod.core.glide.ApGlideSettings; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -80,10 +82,11 @@ public class ItunesAdapter extends ArrayAdapter { //Update the empty imageView with the image from the feed Glide.with(context) .load(podcast.imageUrl) - .placeholder(R.color.light_gray) - .diskCacheStrategy(DiskCacheStrategy.NONE) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .fitCenter() + .dontAnimate()) .into(viewHolder.coverView); //Feed the grid view @@ -132,7 +135,7 @@ public class ItunesAdapter extends ArrayAdapter { } public static Podcast fromSearch(SearchHit searchHit) { - return new Podcast(searchHit.getTitle(), searchHit.getImageUrl(), searchHit.getXmlUrl()); + return new Podcast(searchHit.getTitle(), searchHit.getThumbImageURL(), searchHit.getXmlUrl()); } /** @@ -182,9 +185,9 @@ public class ItunesAdapter extends ArrayAdapter { * @param view GridView cell */ PodcastViewHolder(View view){ - coverView = (ImageView) view.findViewById(R.id.imgvCover); - titleView = (TextView) view.findViewById(R.id.txtvTitle); - urlView = (TextView) view.findViewById(R.id.txtvUrl); + coverView = view.findViewById(R.id.imgvCover); + titleView = view.findViewById(R.id.txtvTitle); + urlView = view.findViewById(R.id.txtvUrl); } } } diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java index b6cf5cb84..219725b01 100644 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java @@ -12,7 +12,7 @@ import de.danoeh.antennapod.core.export.ExportWriter; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.LangUtils; -import rx.Observable; +import io.reactivex.Observable; /** * Writes an OPML file into the export directory in the background. @@ -23,15 +23,15 @@ public class ExportWorker { private static final String TAG = "ExportWorker"; private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds"; - private final ExportWriter exportWriter; - private final File output; + private final @NonNull ExportWriter exportWriter; + private final @NonNull File output; - public ExportWorker(ExportWriter exportWriter) { + public ExportWorker(@NonNull ExportWriter exportWriter) { this(exportWriter, new File(UserPreferences.getDataFolder(EXPORT_DIR), DEFAULT_OUTPUT_NAME + "." + exportWriter.fileExtension())); } - private ExportWorker(ExportWriter exportWriter, @NonNull File output) { + private ExportWorker(@NonNull ExportWriter exportWriter, @NonNull File output) { this.exportWriter = exportWriter; this.output = output; } @@ -57,7 +57,7 @@ public class ExportWorker { subscriber.onError(e); } } - subscriber.onCompleted(); + subscriber.onComplete(); } }); } diff --git a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java index d2498955c..4138738f6 100644 --- a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java +++ b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java @@ -8,6 +8,8 @@ import de.danoeh.antennapod.core.ClientConfig; */ class ClientConfigurator { + private ClientConfigurator(){} + static { ClientConfig.USER_AGENT = "AntennaPod/" + BuildConfig.VERSION_NAME; ClientConfig.applicationCallbacks = new ApplicationCallbacksImpl(); diff --git a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java index 83dd3fe9c..eb70d8e0b 100644 --- a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java +++ b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java @@ -2,7 +2,6 @@ package de.danoeh.antennapod.config; import android.content.Context; import android.content.Intent; - import android.os.Build; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.AudioplayerActivity; diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/AuthenticationDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/AuthenticationDialog.java index 6f9e221ec..2c41b8cb8 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/AuthenticationDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/AuthenticationDialog.java @@ -35,11 +35,11 @@ public abstract class AuthenticationDialog extends Dialog { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.authentication_dialog); - final EditText etxtUsername = (EditText) findViewById(R.id.etxtUsername); - final EditText etxtPassword = (EditText) findViewById(R.id.etxtPassword); - final CheckBox saveUsernamePassword = (CheckBox) findViewById(R.id.chkSaveUsernamePassword); - final Button butConfirm = (Button) findViewById(R.id.butConfirm); - final Button butCancel = (Button) findViewById(R.id.butCancel); + final EditText etxtUsername = findViewById(R.id.etxtUsername); + final EditText etxtPassword = findViewById(R.id.etxtPassword); + final CheckBox saveUsernamePassword = findViewById(R.id.chkSaveUsernamePassword); + final Button butConfirm = findViewById(R.id.butConfirm); + final Button butCancel = findViewById(R.id.butCancel); if (titleRes != 0) { setTitle(titleRes); diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java index 93425949c..c28342374 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java @@ -29,9 +29,9 @@ public class AutoFlattrPreferenceDialog { AlertDialog.Builder builder = new AlertDialog.Builder(activity); @SuppressLint("InflateParams") View view = activity.getLayoutInflater().inflate(R.layout.autoflattr_preference_dialog, null); - final CheckBox chkAutoFlattr = (CheckBox) view.findViewById(R.id.chkAutoFlattr); - final SeekBar skbPercent = (SeekBar) view.findViewById(R.id.skbPercent); - final TextView txtvStatus = (TextView) view.findViewById(R.id.txtvStatus); + final CheckBox chkAutoFlattr = view.findViewById(R.id.chkAutoFlattr); + final SeekBar skbPercent = view.findViewById(R.id.skbPercent); + final TextView txtvStatus = view.findViewById(R.id.txtvStatus); chkAutoFlattr.setChecked(UserPreferences.isAutoFlattr()); skbPercent.setEnabled(chkAutoFlattr.isChecked()); diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java index 10ce12771..ab9b7fcf5 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java @@ -1,11 +1,20 @@ package de.danoeh.antennapod.dialog; +import android.app.AlertDialog; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.support.annotation.IdRes; +import android.support.annotation.NonNull; +import android.support.annotation.PluralsRes; +import android.support.annotation.StringRes; +import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v4.app.Fragment; import android.support.v4.util.ArrayMap; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -13,11 +22,12 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; -import android.widget.Button; import android.widget.ListView; -import android.widget.Toast; + +import com.leinardi.android.speeddial.SpeedDialView; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -34,22 +44,42 @@ public class EpisodesApplyActionFragment extends Fragment { public static final String TAG = "EpisodeActionFragment"; - private static final int ACTION_QUEUE = 1; - private static final int ACTION_MARK_PLAYED = 2; - private static final int ACTION_MARK_UNPLAYED = 4; - private static final int ACTION_DOWNLOAD = 8; - public static final int ACTION_REMOVE = 16; - private static final int ACTION_ALL = ACTION_QUEUE | ACTION_MARK_PLAYED | ACTION_MARK_UNPLAYED - | ACTION_DOWNLOAD | ACTION_REMOVE; + public static final int ACTION_ADD_TO_QUEUE = 1; + private static final int ACTION_REMOVE_FROM_QUEUE = 2; + private static final int ACTION_MARK_PLAYED = 4; + private static final int ACTION_MARK_UNPLAYED = 8; + private static final int ACTION_DOWNLOAD = 16; + public static final int ACTION_DELETE = 32; + private static final int ACTION_ALL = ACTION_ADD_TO_QUEUE | ACTION_REMOVE_FROM_QUEUE + | ACTION_MARK_PLAYED | ACTION_MARK_UNPLAYED | ACTION_DOWNLOAD | ACTION_DELETE; + + /** + * Specify an action (defined by #flag) 's UI bindings. + * + * Includes: the menu / action item and the actual logic + */ + private class ActionBinding { + int flag; + @IdRes + final int actionItemId; + @NonNull + final Runnable action; + + ActionBinding(int flag, @IdRes int actionItemId, @NonNull Runnable action) { + this.flag = flag; + this.actionItemId = actionItemId; + this.action = action; + } + } + + private final List actionBindings; private ListView mListView; private ArrayAdapter mAdapter; - private Button btnAddToQueue; - private Button btnMarkAsPlayed; - private Button btnMarkAsUnplayed; - private Button btnDownload; - private Button btnDelete; + private SpeedDialView mSpeedDialView; + @NonNull + private CharSequence actionBarTitleOriginal = ""; private final Map idMap = new ArrayMap<>(); private final List episodes = new ArrayList<>(); @@ -59,6 +89,23 @@ public class EpisodesApplyActionFragment extends Fragment { private MenuItem mSelectToggle; + public EpisodesApplyActionFragment() { + actionBindings = Arrays.asList( + new ActionBinding(ACTION_ADD_TO_QUEUE, + R.id.add_to_queue_batch, this::queueChecked), + new ActionBinding(ACTION_REMOVE_FROM_QUEUE, + R.id.remove_from_queue_batch, this::removeFromQueueChecked), + new ActionBinding(ACTION_MARK_PLAYED, + R.id.mark_read_batch, this::markedCheckedPlayed), + new ActionBinding(ACTION_MARK_UNPLAYED, + R.id.mark_unread_batch, this::markedCheckedUnplayed), + new ActionBinding(ACTION_DOWNLOAD, + R.id.download_batch, this::downloadChecked), + new ActionBinding(ACTION_DELETE, + R.id.delete_batch, this::deleteChecked) + ); + } + public static EpisodesApplyActionFragment newInstance(List items) { return newInstance(items, ACTION_ALL); } @@ -76,6 +123,7 @@ public class EpisodesApplyActionFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setRetainInstance(true); setHasOptionsMenu(true); } @@ -84,7 +132,7 @@ public class EpisodesApplyActionFragment extends Fragment { Bundle savedInstanceState) { View view = inflater.inflate(R.layout.episodes_apply_action_fragment, container, false); - mListView = (ListView) view.findViewById(android.R.id.list); + mListView = view.findViewById(android.R.id.list); mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); mListView.setOnItemClickListener((ListView, view1, position, rowId) -> { long id = episodes.get(position).getId(); @@ -95,62 +143,85 @@ public class EpisodesApplyActionFragment extends Fragment { } refreshCheckboxes(); }); + mListView.setOnItemLongClickListener((adapterView, view12, position, id) -> { + new AlertDialog.Builder(getActivity()) + .setItems(R.array.batch_long_press_options, (dialogInterface, item) -> { + int direction; + if (item == 0) { + direction = -1; + } else { + direction = 1; + } + + int currentPosition = position + direction; + while (currentPosition >= 0 && currentPosition < episodes.size()) { + long id1 = episodes.get(currentPosition).getId(); + if (!checkedIds.contains(id1)) { + checkedIds.add(id1); + } + currentPosition += direction; + } + refreshCheckboxes(); + }).show(); + return true; + }); for(FeedItem episode : episodes) { titles.add(episode.getTitle()); } mAdapter = new ArrayAdapter<>(getActivity(), - android.R.layout.simple_list_item_multiple_choice, titles); + R.layout.simple_list_item_multiple_choice_on_start, titles); mListView.setAdapter(mAdapter); - checkAll(); - int lastVisibleDiv = 0; - btnAddToQueue = (Button) view.findViewById(R.id.btnAddToQueue); - if((actions & ACTION_QUEUE) != 0) { - btnAddToQueue.setOnClickListener(v -> queueChecked()); - lastVisibleDiv = R.id.divider1; - } else { - btnAddToQueue.setVisibility(View.GONE); - view.findViewById(R.id.divider1).setVisibility(View.GONE); - } - btnMarkAsPlayed = (Button) view.findViewById(R.id.btnMarkAsPlayed); - if((actions & ACTION_MARK_PLAYED) != 0) { - btnMarkAsPlayed.setOnClickListener(v -> markedCheckedPlayed()); - lastVisibleDiv = R.id.divider2; - } else { - btnMarkAsPlayed.setVisibility(View.GONE); - view.findViewById(R.id.divider2).setVisibility(View.GONE); - } - btnMarkAsUnplayed = (Button) view.findViewById(R.id.btnMarkAsUnplayed); - if((actions & ACTION_MARK_UNPLAYED) != 0) { - btnMarkAsUnplayed.setOnClickListener(v -> markedCheckedUnplayed()); - lastVisibleDiv = R.id.divider3; - } else { - btnMarkAsUnplayed.setVisibility(View.GONE); - view.findViewById(R.id.divider3).setVisibility(View.GONE); - } - btnDownload = (Button) view.findViewById(R.id.btnDownload); - if((actions & ACTION_DOWNLOAD) != 0) { - btnDownload.setOnClickListener(v -> downloadChecked()); - lastVisibleDiv = R.id.divider4; - } else { - btnDownload.setVisibility(View.GONE); - view.findViewById(R.id.divider4).setVisibility(View.GONE); - } - btnDelete = (Button) view.findViewById(R.id.btnDelete); - if((actions & ACTION_REMOVE) != 0) { - btnDelete.setOnClickListener(v -> deleteChecked()); - } else { - btnDelete.setVisibility(View.GONE); - if(lastVisibleDiv > 0) { - view.findViewById(lastVisibleDiv).setVisibility(View.GONE); + saveActionBarTitle(); // needed when we dynamically change the title based on selection + + // Init action UI (via a FAB Speed Dial) + mSpeedDialView = view.findViewById(R.id.fabSD); + mSpeedDialView.inflate(R.menu.episodes_apply_action_speeddial); + + // show only specified actions, and bind speed dial UIs to the actual logic + for (ActionBinding binding : actionBindings) { + if ((actions & binding.flag) == 0) { + mSpeedDialView.removeActionItemById(binding.actionItemId); } } + mSpeedDialView.setOnActionSelectedListener(actionItem -> { + ActionBinding selectedBinding = null; + for (ActionBinding binding : actionBindings) { + if (actionItem.getId() == binding.actionItemId) { + selectedBinding = binding; + break; + } + } + if (selectedBinding != null) { + selectedBinding.action.run(); + } else { + Log.e(TAG, "Unrecognized speed dial action item. Do nothing. id=" + actionItem.getId()); + } + return true; + }); + + showSpeedDialIfAnyChecked(); + return view; } + @Override + public void onStop() { + restoreActionBarTitle(); // it might have been changed to "N selected". Restore original. + super.onStop(); + } + + private void showSpeedDialIfAnyChecked() { + mSpeedDialView.setVisibility(checkedIds.size() > 0 ? View.VISIBLE : View.GONE); + } + + private void hideSpeedDial() { + mSpeedDialView.setVisibility(View.GONE); + } + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); @@ -173,11 +244,9 @@ public class EpisodesApplyActionFragment extends Fragment { int[] icon = new int[1]; if (checkedIds.size() == episodes.size()) { - icon[0] = R.attr.ic_check_box; - } else if (checkedIds.size() == 0) { - icon[0] = R.attr.ic_check_box_outline; + icon[0] = R.attr.ic_select_none; } else { - icon[0] = R.attr.ic_indeterminate_check_box; + icon[0] = R.attr.ic_select_all; } TypedArray a = getActivity().obtainStyledAttributes(icon); @@ -189,7 +258,7 @@ public class EpisodesApplyActionFragment extends Fragment { @Override public boolean onOptionsItemSelected(MenuItem item) { - int resId = 0; + @StringRes int resId = 0; switch(item.getItemId()) { case R.id.select_options: return true; @@ -249,7 +318,8 @@ public class EpisodesApplyActionFragment extends Fragment { return true; } if(resId != 0) { - Toast.makeText(getActivity(), resId, Toast.LENGTH_SHORT).show(); + Snackbar.make(getActivity().findViewById(R.id.content), resId, Snackbar.LENGTH_SHORT) + .show(); return true; } else { return false; @@ -387,21 +457,56 @@ public class EpisodesApplyActionFragment extends Fragment { mListView.setItemChecked(i, checked); } ActivityCompat.invalidateOptionsMenu(EpisodesApplyActionFragment.this.getActivity()); + showSpeedDialIfAnyChecked(); + updateActionBarTitle(); + } + + private void saveActionBarTitle() { + ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); + if (actionBar != null) { + CharSequence title = actionBar.getTitle(); + if (title == null) { + title = ""; + } + actionBarTitleOriginal = title; + } + } + + private void restoreActionBarTitle() { + ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); + if (actionBar != null) { + actionBar.setTitle(actionBarTitleOriginal); + } + } + + private void updateActionBarTitle() { + ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); + if (actionBar != null) { + CharSequence title = checkedIds.size() > 0 ? + getString(R.string.num_selected_label, checkedIds.size()) : + actionBarTitleOriginal; + actionBar.setTitle(title); + } } private void queueChecked() { DBWriter.addQueueItem(getActivity(), true, checkedIds.toArray()); - close(); + close(R.plurals.added_to_queue_batch_label, checkedIds.size()); + } + + private void removeFromQueueChecked() { + DBWriter.removeQueueItem(getActivity(), true, checkedIds.toArray()); + close(R.plurals.removed_from_queue_batch_label, checkedIds.size()); } private void markedCheckedPlayed() { DBWriter.markItemPlayed(FeedItem.PLAYED, checkedIds.toArray()); - close(); + close(R.plurals.marked_read_batch_label, checkedIds.size()); } private void markedCheckedUnplayed() { DBWriter.markItemPlayed(FeedItem.UNPLAYED, checkedIds.toArray()); - close(); + close(R.plurals.marked_unread_batch_label, checkedIds.size()); } private void downloadChecked() { @@ -418,7 +523,7 @@ public class EpisodesApplyActionFragment extends Fragment { e.printStackTrace(); DownloadRequestErrorDialogCreator.newRequestErrorDialog(getActivity(), e.getMessage()); } - close(); + close(R.plurals.downloading_batch_label, checkedIds.size()); } private void deleteChecked() { @@ -428,10 +533,18 @@ public class EpisodesApplyActionFragment extends Fragment { DBWriter.deleteFeedMediaOfItem(getActivity(), episode.getMedia().getId()); } } - close(); + close(R.plurals.deleted_episode_batch_label, checkedIds.size()); } - private void close() { + private void close(@PluralsRes int msgId, int numItems) { + if (numItems > 0) { + Snackbar.make(getActivity().findViewById(R.id.content), + getResources().getQuantityString(msgId, numItems, numItems), + Snackbar.LENGTH_LONG + ) + .setAction(android.R.string.ok, v -> {}) + .show(); + } getActivity().getSupportFragmentManager().popBackStack(); } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java index e64f1e08b..933ced0f9 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java @@ -17,6 +17,9 @@ import de.danoeh.antennapod.core.preferences.GpodnetPreferences; * Creates a dialog that lets the user change the hostname for the gpodder.net service. */ public class GpodnetSetHostnameDialog { + + private GpodnetSetHostnameDialog(){} + private static final String TAG = "GpodnetSetHostnameDialog"; public static AlertDialog createDialog(final Context context) { diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java index b9276982a..8f2629b43 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java @@ -29,15 +29,15 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.service.download.ProxyConfig; +import io.reactivex.Single; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; import okhttp3.Credentials; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import rx.Observable; -import rx.Subscriber; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; public class ProxyDialog { @@ -55,7 +55,7 @@ public class ProxyDialog { private boolean testSuccessful = false; private TextView txtvMessage; - private Subscription subscription; + private Disposable disposable; public ProxyDialog(Context context) { this.context = context; @@ -102,7 +102,7 @@ public class ProxyDialog { .autoDismiss(false) .build(); View view = dialog.getCustomView(); - spType = (Spinner) view.findViewById(R.id.spType); + spType = view.findViewById(R.id.spType); String[] types = { Proxy.Type.DIRECT.name(), Proxy.Type.HTTP.name() }; ArrayAdapter adapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, types); @@ -110,22 +110,22 @@ public class ProxyDialog { spType.setAdapter(adapter); ProxyConfig proxyConfig = UserPreferences.getProxyConfig(); spType.setSelection(adapter.getPosition(proxyConfig.type.name())); - etHost = (EditText) view.findViewById(R.id.etHost); + etHost = view.findViewById(R.id.etHost); if(!TextUtils.isEmpty(proxyConfig.host)) { etHost.setText(proxyConfig.host); } etHost.addTextChangedListener(requireTestOnChange); - etPort = (EditText) view.findViewById(R.id.etPort); + etPort = view.findViewById(R.id.etPort); if(proxyConfig.port > 0) { etPort.setText(String.valueOf(proxyConfig.port)); } etPort.addTextChangedListener(requireTestOnChange); - etUsername = (EditText) view.findViewById(R.id.etUsername); + etUsername = view.findViewById(R.id.etUsername); if(!TextUtils.isEmpty(proxyConfig.username)) { etUsername.setText(proxyConfig.username); } etUsername.addTextChangedListener(requireTestOnChange); - etPassword = (EditText) view.findViewById(R.id.etPassword); + etPassword = view.findViewById(R.id.etPassword); if(!TextUtils.isEmpty(proxyConfig.password)) { etPassword.setText(proxyConfig.username); } @@ -146,7 +146,7 @@ public class ProxyDialog { enableSettings(false); } }); - txtvMessage = (TextView) view.findViewById(R.id.txtvMessage); + txtvMessage = view.findViewById(R.id.txtvMessage); checkValidity(); return dialog; } @@ -229,8 +229,8 @@ public class ProxyDialog { } private void test() { - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } if(!checkValidity()) { setTestRequired(true); @@ -243,7 +243,7 @@ public class ProxyDialog { txtvMessage.setTextColor(textColorPrimary); txtvMessage.setText("{fa-circle-o-notch spin} " + checking); txtvMessage.setVisibility(View.VISIBLE); - subscription = Observable.create((Observable.OnSubscribe) subscriber -> { + disposable = Single.create((SingleOnSubscribe) emitter -> { String type = (String) spType.getSelectedItem(); String host = etHost.getText().toString(); String port = etPort.getText().toString(); @@ -275,13 +275,12 @@ public class ProxyDialog { .build(); try { Response response = client.newCall(request).execute(); - subscriber.onNext(response); + emitter.onSuccess(response); } catch(IOException e) { - subscriber.onError(e); + emitter.onError(e); } - subscriber.onCompleted(); }) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( response -> { diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java index 72000170e..ece184035 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java @@ -17,6 +17,8 @@ import de.danoeh.antennapod.R; public class RatingDialog { + private RatingDialog(){} + private static final String TAG = RatingDialog.class.getSimpleName(); private static final int AFTER_DAYS = 7; diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java index be7850495..4b8601ec6 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java @@ -61,11 +61,11 @@ public abstract class SleepTimerDialog { dialog = builder.build(); View view = dialog.getView(); - etxtTime = (EditText) view.findViewById(R.id.etxtTime); - spTimeUnit = (Spinner) view.findViewById(R.id.spTimeUnit); - cbShakeToReset = (CheckBox) view.findViewById(R.id.cbShakeToReset); - cbVibrate = (CheckBox) view.findViewById(R.id.cbVibrate); - chAutoEnable = (CheckBox) view.findViewById(R.id.chAutoEnable); + etxtTime = view.findViewById(R.id.etxtTime); + spTimeUnit = view.findViewById(R.id.spTimeUnit); + cbShakeToReset = view.findViewById(R.id.cbShakeToReset); + cbVibrate = view.findViewById(R.id.cbVibrate); + chAutoEnable = view.findViewById(R.id.chAutoEnable); etxtTime.setText(SleepTimerPreferences.lastTimerValue()); etxtTime.addTextChangedListener(new TextWatcher() { diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java index 6a975fe49..cf9a2907b 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java @@ -52,7 +52,7 @@ public class VariableSpeedDialog { builder.neutralText(R.string.close_label); builder.onPositive((dialog, which) -> { if (Build.VERSION.SDK_INT >= 16) { // just to be safe - UserPreferences.enableSonic(true); + UserPreferences.enableSonic(); if(showSpeedSelector) { showSpeedSelectorDialog(context); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java index c050221e1..ee2373da8 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java @@ -32,18 +32,18 @@ public class AddFeedFragment extends Fragment { super.onCreateView(inflater, container, savedInstanceState); View root = inflater.inflate(R.layout.addfeed, container, false); - final EditText etxtFeedurl = (EditText) root.findViewById(R.id.etxtFeedurl); + final EditText etxtFeedurl = root.findViewById(R.id.etxtFeedurl); Bundle args = getArguments(); if (args != null && args.getString(ARG_FEED_URL) != null) { etxtFeedurl.setText(args.getString(ARG_FEED_URL)); } - Button butSearchITunes = (Button) root.findViewById(R.id.butSearchItunes); - Button butBrowserGpoddernet = (Button) root.findViewById(R.id.butBrowseGpoddernet); - Button butSearchFyyd = (Button) root.findViewById(R.id.butSearchFyyd); - Button butOpmlImport = (Button) root.findViewById(R.id.butOpmlImport); - Button butConfirm = (Button) root.findViewById(R.id.butConfirm); + Button butSearchITunes = root.findViewById(R.id.butSearchItunes); + Button butBrowserGpoddernet = root.findViewById(R.id.butBrowseGpoddernet); + Button butSearchFyyd = root.findViewById(R.id.butSearchFyyd); + Button butOpmlImport = root.findViewById(R.id.butOpmlImport); + Button butConfirm = root.findViewById(R.id.butConfirm); final MainActivity activity = (MainActivity) getActivity(); activity.getSupportActionBar().setTitle(R.string.add_feed_label); @@ -66,4 +66,15 @@ public class AddFeedFragment extends Fragment { return root; } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setRetainInstance(true); + + // So, we certainly *don't* have an options menu, + // but unless we say we do, old options menus sometimes + // persist. mfietz thinks this causes the ActionBar to be invalidated + setHasOptionsMenu(true); + } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java index f3846c8a4..20913d414 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -4,6 +4,9 @@ import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.LinearLayoutManager; @@ -18,6 +21,7 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ProgressBar; +import android.widget.TextView; import android.widget.Toast; import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration; @@ -36,22 +40,22 @@ import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; -import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.MenuItemUtils; import de.greenrobot.event.EventBus; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Shows unread or recently published episodes @@ -72,6 +76,7 @@ public class AllEpisodesFragment extends Fragment { RecyclerView recyclerView; AllEpisodesRecycleAdapter listAdapter; private ProgressBar progLoading; + private View emptyView; List episodes; private List downloaderList; @@ -82,7 +87,7 @@ public class AllEpisodesFragment extends Fragment { private boolean isUpdatingFeeds; boolean isMenuInvalidationAllowed = false; - Subscription subscription; + Disposable disposable; private LinearLayoutManager layoutManager; boolean showOnlyNewEpisodes() { return false; } @@ -123,8 +128,8 @@ public class AllEpisodesFragment extends Fragment { public void onStop() { super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } } @@ -273,17 +278,23 @@ public class AllEpisodesFragment extends Fragment { if(item.getItemId() == R.id.share_item) { return true; // avoids that the position is reset when we need it in the submenu } - int pos = listAdapter.getPosition(); - if(pos < 0) { - return false; - } - FeedItem selectedItem = itemAccess.getItem(pos); + FeedItem selectedItem = listAdapter.getSelectedItem(); if (selectedItem == null) { - Log.i(TAG, "Selected item at position " + pos + " was null, ignoring selection"); + Log.i(TAG, "Selected item was null, ignoring selection"); return super.onContextItemSelected(item); } + // Mark as seen contains UI logic specific to All/New/FavoriteSegments, + // e.g., Undo with Snackbar, + // and is handled by this class rather than the generic FeedItemMenuHandler + // Undo is useful for Mark as seen, given there is no UI to undo it otherwise, + // i.e., there is context menu item for Mark as new + if (R.id.mark_as_seen_item == item.getItemId()) { + markItemAsSeenWithUndo(selectedItem); + return true; + } + return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem); } @@ -301,7 +312,7 @@ public class AllEpisodesFragment extends Fragment { View root = inflater.inflate(fragmentResource, container, false); - recyclerView = (RecyclerView) root.findViewById(android.R.id.list); + recyclerView = root.findViewById(android.R.id.list); RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); if (animator instanceof SimpleItemAnimator) { ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); @@ -311,7 +322,7 @@ public class AllEpisodesFragment extends Fragment { recyclerView.setHasFixedSize(true); recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build()); - progLoading = (ProgressBar) root.findViewById(R.id.progLoading); + progLoading = root.findViewById(R.id.progLoading); if (!itemsLoaded) { progLoading.setVisibility(View.VISIBLE); @@ -323,17 +334,31 @@ public class AllEpisodesFragment extends Fragment { onFragmentLoaded(); } + emptyView = (View) root.findViewById(R.id.emptyView); + emptyView.setVisibility(View.GONE); + ((TextView)emptyView.findViewById(R.id.emptyViewTitle)).setText(R.string.no_all_episodes_head_label); + ((TextView)emptyView.findViewById(R.id.emptyViewMessage)).setText(R.string.no_all_episodes_label); + return root; } private void onFragmentLoaded() { - if (listAdapter == null) { - MainActivity mainActivity = (MainActivity) getActivity(); - listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess, - new DefaultActionButtonCallback(mainActivity), showOnlyNewEpisodes()); - listAdapter.setHasStableIds(true); - recyclerView.setAdapter(listAdapter); + if (episodes != null && episodes.size() > 0) { + if (listAdapter == null) { + MainActivity mainActivity = (MainActivity) getActivity(); + listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess, + new DefaultActionButtonCallback(mainActivity), showOnlyNewEpisodes()); + listAdapter.setHasStableIds(true); + recyclerView.setAdapter(listAdapter); + } + emptyView.setVisibility(View.GONE); + recyclerView.setVisibility(View.VISIBLE); + } else { + listAdapter = null; + recyclerView.setVisibility(View.GONE); + emptyView.setVisibility(View.VISIBLE); } + listAdapter.notifyDataSetChanged(); restoreScrollPosition(); getActivity().supportInvalidateOptionsMenu(); @@ -406,20 +431,26 @@ public class AllEpisodesFragment extends Fragment { public void onEventMainThread(FeedItemEvent event) { Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - if(episodes == null || listAdapter == null) { + if (episodes == null || listAdapter == null) { return; } - for(int i=0, size = event.items.size(); i < size; i++) { - FeedItem item = event.items.get(i); + for (FeedItem item : event.items) { int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId()); - if(pos >= 0) { + if (pos >= 0) { episodes.remove(pos); - episodes.add(pos, item); - listAdapter.notifyItemChanged(pos); + if (shouldUpdatedItemRemainInList(item)) { + episodes.add(pos, item); + listAdapter.notifyItemChanged(pos); + } else { + listAdapter.notifyItemRemoved(pos); + } } } } + protected boolean shouldUpdatedItemRemainInList(FeedItem item) { + return true; + } public void onEventMainThread(DownloadEvent event) { Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); @@ -454,31 +485,63 @@ public class AllEpisodesFragment extends Fragment { } void loadItems() { - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } if (viewsCreated && !itemsLoaded) { recyclerView.setVisibility(View.GONE); + emptyView.setVisibility(View.GONE); progLoading.setVisibility(View.VISIBLE); } - subscription = Observable.fromCallable(this::loadData) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(this::loadData) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(data -> { recyclerView.setVisibility(View.VISIBLE); progLoading.setVisibility(View.GONE); - if (data != null) { - episodes = data; - itemsLoaded = true; - if (viewsCreated) { - onFragmentLoaded(); - } + episodes = data; + itemsLoaded = true; + if (viewsCreated) { + onFragmentLoaded(); } }, error -> Log.e(TAG, Log.getStackTraceString(error))); } + @NonNull List loadData() { return DBReader.getRecentlyPublishedEpisodes(RECENT_EPISODES_LIMIT); } + void markItemAsSeenWithUndo(FeedItem item) { + if (item == null) { + return; + } + + Log.d(TAG, "markItemAsSeenWithUndo(" + item.getId() + ")"); + if (disposable != null) { + disposable.dispose(); + } + // we're marking it as unplayed since the user didn't actually play it + // but they don't want it considered 'NEW' anymore + DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); + + final Handler h = new Handler(getActivity().getMainLooper()); + final Runnable r = () -> { + FeedMedia media = item.getMedia(); + if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) { + DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId()); + } + }; + + Snackbar snackbar = Snackbar.make(getView(), getString(R.string.marked_as_seen_label), + Snackbar.LENGTH_LONG); + snackbar.setAction(getString(R.string.undo), v -> { + DBWriter.markItemPlayed(FeedItem.NEW, item.getId()); + // don't forget to cancel the thing that's going to remove the media + h.removeCallbacks(r); + }); + snackbar.show(); + h.postDelayed(r, (int)Math.ceil(snackbar.getDuration() * 1.05f)); + } + } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java index f59bc88bf..b52fd444f 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java @@ -1,8 +1,6 @@ package de.danoeh.antennapod.fragment; import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.util.Log; @@ -12,9 +10,6 @@ import android.view.MenuItem; import android.view.View; import android.widget.ListView; -import com.joanzapata.iconify.IconDrawable; -import com.joanzapata.iconify.fonts.FontAwesomeIcons; - import java.util.List; import de.danoeh.antennapod.R; @@ -22,15 +17,15 @@ import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.DownloadedEpisodesListAdapter; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import de.danoeh.antennapod.view.EmptyViewHandler; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Displays all running downloads and provides a button to delete them @@ -48,7 +43,7 @@ public class CompletedDownloadsFragment extends ListFragment { private boolean viewCreated = false; - private Subscription subscription; + private Disposable disposable; @Override public void onCreate(Bundle savedInstanceState) { @@ -67,16 +62,16 @@ public class CompletedDownloadsFragment extends ListFragment { public void onStop() { super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } } @Override public void onDetach() { super.onDetach(); - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } } @@ -85,8 +80,8 @@ public class CompletedDownloadsFragment extends ListFragment { super.onDestroyView(); listAdapter = null; viewCreated = false; - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } } @@ -112,6 +107,11 @@ public class CompletedDownloadsFragment extends ListFragment { if (items != null && getActivity() != null) { onFragmentLoaded(); } + + EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); + emptyView.setTitle(R.string.no_comp_downloads_head_label); + emptyView.setMessage(R.string.no_comp_downloads_label); + emptyView.attachToListView(getListView()); } @Override @@ -149,7 +149,7 @@ public class CompletedDownloadsFragment extends ListFragment { switch (item.getItemId()) { case R.id.episode_actions: EpisodesApplyActionFragment fragment = EpisodesApplyActionFragment - .newInstance(items, EpisodesApplyActionFragment.ACTION_REMOVE); + .newInstance(items, EpisodesApplyActionFragment.ACTION_DELETE | EpisodesApplyActionFragment.ACTION_ADD_TO_QUEUE); ((MainActivity) getActivity()).loadChildFragment(fragment); return true; default: @@ -188,21 +188,19 @@ public class CompletedDownloadsFragment extends ListFragment { }; private void loadItems() { - if(subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } if (items == null && viewCreated) { setListShown(false); } - subscription = Observable.fromCallable(DBReader::getDownloadedItems) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(DBReader::getDownloadedItems) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { - if (result != null) { - items = result; - if (viewCreated && getActivity() != null) { - onFragmentLoaded(); - } + items = result; + if (viewCreated && getActivity() != null) { + onFragmentLoaded(); } }, error -> Log.e(TAG, Log.getStackTraceString(error))); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java index 1d3fcefba..ef65a5755 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java @@ -11,6 +11,7 @@ import android.widget.TextView; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MediaplayerInfoActivity.MediaplayerInfoContentFragment; import de.danoeh.antennapod.core.glide.ApGlideSettings; @@ -22,7 +23,6 @@ import de.danoeh.antennapod.core.util.playback.Playable; public class CoverFragment extends Fragment implements MediaplayerInfoContentFragment { private static final String TAG = "CoverFragment"; - private static final String ARG_PLAYABLE = "arg.playable"; private Playable media; @@ -48,10 +48,11 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + setRetainInstance(true); root = inflater.inflate(R.layout.cover_fragment, container, false); - txtvPodcastTitle = (TextView) root.findViewById(R.id.txtvPodcastTitle); - txtvEpisodeTitle = (TextView) root.findViewById(R.id.txtvEpisodeTitle); - imgvCover = (ImageView) root.findViewById(R.id.imgvCover); + txtvPodcastTitle = root.findViewById(R.id.txtvPodcastTitle); + txtvEpisodeTitle = root.findViewById(R.id.txtvEpisodeTitle); + imgvCover = root.findViewById(R.id.imgvCover); return root; } @@ -61,9 +62,10 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra txtvEpisodeTitle.setText(media.getEpisodeTitle()); Glide.with(this) .load(media.getImageLocation()) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .dontAnimate() - .fitCenter() + .apply(new RequestOptions() + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .dontAnimate() + .fitCenter()) .into(imgvCover); } else { Log.w(TAG, "loadMediaInfo was called while media was null"); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java index ae9c60f65..973772049 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java @@ -12,21 +12,23 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.ListView; +import android.widget.TextView; import java.util.List; -import android.widget.TextView; import de.danoeh.antennapod.R; import de.danoeh.antennapod.adapter.DownloadLogAdapter; import de.danoeh.antennapod.core.feed.EventDistributor; +import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import de.danoeh.antennapod.view.EmptyViewHandler; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Shows the download log @@ -41,7 +43,7 @@ public class DownloadLogFragment extends ListFragment { private boolean viewsCreated = false; private boolean itemsLoaded = false; - private Subscription subscription; + private Disposable disposable; @Override public void onStart() { @@ -55,8 +57,8 @@ public class DownloadLogFragment extends ListFragment { public void onStop() { super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } } @@ -74,6 +76,12 @@ public class DownloadLogFragment extends ListFragment { if (itemsLoaded) { onFragmentLoaded(); } + + EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); + emptyView.setTitle(R.string.no_log_downloads_head_label); + emptyView.setMessage(R.string.no_log_downloads_label); + emptyView.attachToListView(getListView()); + } private void onFragmentLoaded() { @@ -93,10 +101,18 @@ public class DownloadLogFragment extends ListFragment { DownloadStatus status = adapter.getItem(position); String url = "unknown"; String message = getString(R.string.download_successful); - FeedMedia media = DBReader.getFeedMedia(status.getFeedfileId()); - if (media != null) { - url = media.getDownload_url(); + if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { + FeedMedia media = DBReader.getFeedMedia(status.getFeedfileId()); + if (media != null) { + url = media.getDownload_url(); + } + } else if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { + Feed feed = DBReader.getFeed(status.getFeedfileId()); + if (feed != null) { + url = feed.getDownload_url(); + } } + if (!status.isSuccessful()) { message = status.getReasonDetailed(); } @@ -178,11 +194,11 @@ public class DownloadLogFragment extends ListFragment { } private void loadItems() { - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } - subscription = Observable.fromCallable(DBReader::getDownloadLog) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(DBReader::getDownloadLog) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { if (result != null) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java index 9c4d00e31..aa6029c84 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java @@ -38,12 +38,12 @@ public class DownloadsFragment extends Fragment { super.onCreateView(inflater, container, savedInstanceState); View root = inflater.inflate(R.layout.pager_fragment, container, false); - viewPager = (ViewPager)root.findViewById(R.id.viewpager); + viewPager = root.findViewById(R.id.viewpager); DownloadsPagerAdapter pagerAdapter = new DownloadsPagerAdapter(getChildFragmentManager(), getResources()); viewPager.setAdapter(pagerAdapter); // Give the TabLayout the ViewPager - tabLayout = (TabLayout) root.findViewById(R.id.sliding_tabs); + tabLayout = root.findViewById(R.id.sliding_tabs); tabLayout.setupWithViewPager(viewPager); return root; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java index 417ecff89..0610bfd24 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java @@ -46,11 +46,11 @@ public class EpisodesFragment extends Fragment { ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.episodes_label); View rootView = inflater.inflate(R.layout.pager_fragment, container, false); - viewPager = (ViewPager)rootView.findViewById(R.id.viewpager); + viewPager = rootView.findViewById(R.id.viewpager); viewPager.setAdapter(new EpisodesPagerAdapter(getChildFragmentManager(), getResources())); // Give the TabLayout the ViewPager - tabLayout = (TabLayout) rootView.findViewById(R.id.sliding_tabs); + tabLayout = rootView.findViewById(R.id.sliding_tabs); tabLayout.setupWithViewPager(viewPager); return rootView; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java index b072aeaf2..de2f04590 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java @@ -16,13 +16,17 @@ import android.widget.TextView; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.service.playback.PlaybackService; -import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; +import io.reactivex.Maybe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Fragment which is supposed to be displayed outside of the MediaplayerActivity @@ -38,6 +42,7 @@ public class ExternalPlayerFragment extends Fragment { private TextView mFeedName; private ProgressBar mProgressBar; private PlaybackController controller; + private Disposable disposable; public ExternalPlayerFragment() { super(); @@ -48,12 +53,12 @@ public class ExternalPlayerFragment extends Fragment { Bundle savedInstanceState) { View root = inflater.inflate(R.layout.external_player_fragment, container, false); - fragmentLayout = (ViewGroup) root.findViewById(R.id.fragmentLayout); - imgvCover = (ImageView) root.findViewById(R.id.imgvCover); - txtvTitle = (TextView) root.findViewById(R.id.txtvTitle); - butPlay = (ImageButton) root.findViewById(R.id.butPlay); - mFeedName = (TextView) root.findViewById(R.id.txtvAuthor); - mProgressBar = (ProgressBar) root.findViewById(R.id.episodeProgress); + fragmentLayout = root.findViewById(R.id.fragmentLayout); + imgvCover = root.findViewById(R.id.imgvCover); + txtvTitle = root.findViewById(R.id.txtvTitle); + butPlay = root.findViewById(R.id.butPlay); + mFeedName = root.findViewById(R.id.txtvAuthor); + mProgressBar = root.findViewById(R.id.episodeProgress); fragmentLayout.setOnClickListener(v -> { Log.d(TAG, "layoutInfo was clicked"); @@ -78,7 +83,7 @@ public class ExternalPlayerFragment extends Fragment { super.onActivityCreated(savedInstanceState); controller = setupPlaybackController(); butPlay.setOnClickListener(v -> { - if(controller != null) { + if (controller != null) { controller.playPause(); } }); @@ -127,8 +132,9 @@ public class ExternalPlayerFragment extends Fragment { @Override public void onResume() { super.onResume(); - controller.init(); onPositionObserverUpdate(); + + controller.init(); } @Override @@ -138,6 +144,9 @@ public class ExternalPlayerFragment extends Fragment { if (controller != null) { controller.release(); } + if (disposable != null) { + disposable.dispose(); + } } @Override @@ -158,7 +167,7 @@ public class ExternalPlayerFragment extends Fragment { controller = setupPlaybackController(); if (butPlay != null) { butPlay.setOnClickListener(v -> { - if(controller != null) { + if (controller != null) { controller.playPause(); } }); @@ -173,7 +182,25 @@ public class ExternalPlayerFragment extends Fragment { return false; } - Playable media = controller.getMedia(); + if (disposable != null) { + disposable.dispose(); + } + disposable = Maybe.create(emitter -> { + Playable media = controller.getMedia(); + if (media != null) { + emitter.onSuccess(media); + } else { + emitter.onComplete(); + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(media -> updateUi((Playable) media), + error -> Log.e(TAG, Log.getStackTraceString(error))); + return true; + } + + private void updateUi(Playable media) { if (media != null) { txtvTitle.setText(media.getEpisodeTitle()); mFeedName.setText(media.getFeedTitle()); @@ -181,11 +208,12 @@ public class ExternalPlayerFragment extends Fragment { Glide.with(getActivity()) .load(media.getImageLocation()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(imgvCover); fragmentLayout.setVisibility(View.VISIBLE); @@ -194,18 +222,11 @@ public class ExternalPlayerFragment extends Fragment { } else { butPlay.setVisibility(View.VISIBLE); } - return true; } else { - Log.w(TAG, "loadMediaInfo was called while the media object of playbackService was null!"); - return false; + Log.w(TAG, "loadMediaInfo was called while the media object of playbackService was null!"); } } - private String getPositionString(int position, int duration) { - return Converter.getDurationStringLong(position) + " / " - + Converter.getDurationStringLong(duration); - } - public PlaybackController getPlaybackControllerTestingOnly() { return controller; } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java index 76d19d61c..cda89bbd3 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java @@ -8,6 +8,7 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; import java.util.List; @@ -50,6 +51,8 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = super.onCreateViewHelper(inflater, container, savedInstanceState, R.layout.all_episodes_fragment); + ((TextView)root.findViewById(R.id.emptyViewTitle)).setText(R.string.no_fav_episodes_head_label); + ((TextView)root.findViewById(R.id.emptyViewMessage)).setText(R.string.no_fav_episodes_label); ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { @Override @@ -62,8 +65,8 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment { AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder)viewHolder; Log.d(TAG, "remove(" + holder.getItemId() + ")"); - if (subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } FeedItem item = holder.getFeedItem(); if (item != null) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java index 6ee9ce467..dadc596e2 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java @@ -28,9 +28,9 @@ import de.danoeh.antennapod.menuhandler.MenuItemUtils; import de.mfietz.fyydlin.FyydClient; import de.mfietz.fyydlin.FyydResponse; import de.mfietz.fyydlin.SearchHit; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; import static de.danoeh.antennapod.adapter.itunes.ItunesAdapter.Podcast; import static java.util.Collections.emptyList; @@ -55,7 +55,7 @@ public class FyydSearchFragment extends Fragment { * List of podcasts retreived from the search */ private List searchResults; - private Subscription subscription; + private Disposable disposable; /** * Constructor @@ -75,7 +75,7 @@ public class FyydSearchFragment extends Fragment { Bundle savedInstanceState) { // Inflate the layout for this fragment View root = inflater.inflate(R.layout.fragment_itunes_search, container, false); - gridView = (GridView) root.findViewById(R.id.gridView); + gridView = root.findViewById(R.id.gridView); adapter = new ItunesAdapter(getActivity(), new ArrayList<>()); gridView.setAdapter(adapter); @@ -87,10 +87,10 @@ public class FyydSearchFragment extends Fragment { intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, podcast.title); startActivity(intent); }); - progressBar = (ProgressBar) root.findViewById(R.id.progressBar); - txtvError = (TextView) root.findViewById(R.id.txtvError); - butRetry = (Button) root.findViewById(R.id.butRetry); - txtvEmpty = (TextView) root.findViewById(android.R.id.empty); + progressBar = root.findViewById(R.id.progressBar); + txtvError = root.findViewById(R.id.txtvError); + butRetry = root.findViewById(R.id.butRetry); + txtvEmpty = root.findViewById(android.R.id.empty); return root; } @@ -98,8 +98,8 @@ public class FyydSearchFragment extends Fragment { @Override public void onDestroy() { super.onDestroy(); - if (subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } adapter = null; } @@ -141,12 +141,12 @@ public class FyydSearchFragment extends Fragment { } private void search(String query) { - if (subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } showOnlyProgressBar(); - subscription = client.searchPodcasts(query) - .subscribeOn(Schedulers.newThread()) + disposable = client.searchPodcasts(query, 10) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { progressBar.setVisibility(View.GONE); @@ -174,7 +174,7 @@ public class FyydSearchFragment extends Fragment { if (!response.getData().isEmpty()) { adapter.clear(); searchResults = new ArrayList<>(); - for (SearchHit searchHit : response.getData().values()) { + for (SearchHit searchHit : response.getData()) { Podcast podcast = Podcast.fromSearch(searchHit); searchResults.add(podcast); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java index 417af6133..0faf450aa 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java @@ -11,6 +11,7 @@ import android.content.res.TypedArray; import android.graphics.Color; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.util.Log; import android.view.ContextMenu; @@ -39,10 +40,10 @@ import de.danoeh.antennapod.core.util.ShownotesProvider; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; import de.danoeh.antennapod.core.util.playback.Timeline; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Displays the description of a Playable object in a Webview. @@ -66,7 +67,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo private ShownotesProvider shownotesProvider; private Playable media; - private Subscription webViewLoader; + private Disposable webViewLoader; /** * URL that was selected via long-press. @@ -113,10 +114,13 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo Log.d(TAG, "Creating view"); webvDescription = new WebView(getActivity().getApplicationContext()); webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + TypedArray ta = getActivity().getTheme().obtainStyledAttributes(new int[] {android.R.attr.colorBackground}); - int backgroundColor = ta.getColor(0, UserPreferences.getTheme() == - R.style.Theme_AntennaPod_Dark ? Color.BLACK : Color.WHITE); + boolean black = UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark + || UserPreferences.getTheme() == R.style.Theme_AntennaPod_TrueBlack; + int backgroundColor = ta.getColor(0, black ? Color.BLACK : Color.WHITE); + ta.recycle(); webvDescription.setBackgroundColor(backgroundColor); if (!NetworkUtils.networkAvailable()) { @@ -164,7 +168,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo super.onDestroy(); Log.d(TAG, "Fragment destroyed"); if (webViewLoader != null) { - webViewLoader.unsubscribe(); + webViewLoader.dispose(); } if (webvDescription != null) { webvDescription.removeAllViews(); @@ -195,7 +199,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo } else if (args.containsKey(ARG_FEEDITEM_ID)) { long id = getArguments().getLong(ARG_FEEDITEM_ID); Observable.defer(() -> Observable.just(DBReader.getFeedItem(id))) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(feedItem -> { shownotesProvider = feedItem; @@ -295,21 +299,22 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo private void load() { Log.d(TAG, "load()"); if(webViewLoader != null) { - webViewLoader.unsubscribe(); + webViewLoader.dispose(); } if(shownotesProvider == null) { return; } - webViewLoader = Observable.defer(() -> Observable.just(loadData())) - .subscribeOn(Schedulers.newThread()) + webViewLoader = Observable.fromCallable(this::loadData) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(data -> { - webvDescription.loadDataWithBaseURL(null, data, "text/html", + webvDescription.loadDataWithBaseURL("https://127.0.0.1", data, "text/html", "utf-8", "about:blank"); Log.d(TAG, "Webview loaded"); }, error -> Log.e(TAG, Log.getStackTraceString(error))); } + @NonNull private String loadData() { Timeline timeline = new Timeline(getActivity(), shownotesProvider); return timeline.processShownotes(highlightTimecodes); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java index 6b589493b..e114ef405 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java @@ -31,11 +31,10 @@ import android.widget.TextView; import android.widget.Toast; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.widget.IconButton; -import de.danoeh.antennapod.core.service.playback.PlaybackService; -import de.danoeh.antennapod.core.util.NetworkUtils; import org.apache.commons.lang3.ArrayUtils; import java.util.List; @@ -53,26 +52,27 @@ import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.Downloader; +import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; -import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.DateUtils; import de.danoeh.antennapod.core.util.Flavors; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.LongList; +import de.danoeh.antennapod.core.util.NetworkUtils; import de.danoeh.antennapod.core.util.ShareUtils; import de.danoeh.antennapod.core.util.playback.Timeline; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.view.OnSwipeGesture; import de.danoeh.antennapod.view.SwipeGestureDetector; import de.greenrobot.event.EventBus; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Displays information about a FeedItem and actions. @@ -135,7 +135,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { private IconButton butAction2; private Menu popupMenu; - private Subscription subscription; + private Disposable disposable; /** * URL that was selected via long-press. @@ -166,26 +166,27 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { super.onCreateView(inflater, container, savedInstanceState); View layout = inflater.inflate(R.layout.feeditem_fragment, container, false); - root = (ViewGroup) layout.findViewById(R.id.content_root); + root = layout.findViewById(R.id.content_root); - LinearLayout header = (LinearLayout) root.findViewById(R.id.header); + LinearLayout header = root.findViewById(R.id.header); if(feedItems.length > 0) { header.setOnTouchListener((v, event) -> headerGestureDetector.onTouchEvent(event)); } - txtvPodcast = (TextView) layout.findViewById(R.id.txtvPodcast); + txtvPodcast = layout.findViewById(R.id.txtvPodcast); txtvPodcast.setOnClickListener(v -> openPodcast()); - txtvTitle = (TextView) layout.findViewById(R.id.txtvTitle); + txtvTitle = layout.findViewById(R.id.txtvTitle); if(Build.VERSION.SDK_INT >= 23) { txtvTitle.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL); } - txtvDuration = (TextView) layout.findViewById(R.id.txtvDuration); - txtvPublished = (TextView) layout.findViewById(R.id.txtvPublished); + txtvDuration = layout.findViewById(R.id.txtvDuration); + txtvPublished = layout.findViewById(R.id.txtvPublished); if (Build.VERSION.SDK_INT >= 14) { // ellipsize is causing problems on old versions, see #448 txtvTitle.setEllipsize(TextUtils.TruncateAt.END); } - webvDescription = (WebView) layout.findViewById(R.id.webvDescription); - if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) { + webvDescription = layout.findViewById(R.id.webvDescription); + if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark || + UserPreferences.getTheme() == R.style.Theme_AntennaPod_TrueBlack) { if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null); } @@ -215,12 +216,12 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { }); registerForContextMenu(webvDescription); - imgvCover = (ImageView) layout.findViewById(R.id.imgvCover); + imgvCover = layout.findViewById(R.id.imgvCover); imgvCover.setOnClickListener(v -> openPodcast()); - progbarDownload = (ProgressBar) layout.findViewById(R.id.progbarDownload); - progbarLoading = (ProgressBar) layout.findViewById(R.id.progbarLoading); - butAction1 = (IconButton) layout.findViewById(R.id.butAction1); - butAction2 = (IconButton) layout.findViewById(R.id.butAction2); + progbarDownload = layout.findViewById(R.id.progbarDownload); + progbarLoading = layout.findViewById(R.id.progbarLoading); + butAction1 = layout.findViewById(R.id.butAction1); + butAction2 = layout.findViewById(R.id.butAction2); butAction1.setOnClickListener(v -> { if (item == null) { @@ -285,8 +286,8 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { @Override public void onDestroyView() { super.onDestroyView(); - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } if (webvDescription != null && root != null) { root.removeView(webvDescription); @@ -357,7 +358,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { private void onFragmentLoaded() { if (webviewData != null) { - webvDescription.loadDataWithBaseURL(null, webviewData, "text/html", "utf-8", "about:blank"); + webvDescription.loadDataWithBaseURL("https://127.0.0.1", webviewData, "text/html", "utf-8", "about:blank"); } updateAppearance(); } @@ -378,11 +379,12 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { Glide.with(getActivity()) .load(item.getImageLocation()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(imgvCover); progbarDownload.setVisibility(View.GONE); @@ -435,7 +437,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { } FeedItem.State state = item.getState(); - if (butAction2Text == R.string.delete_label && state == FeedItem.State.PLAYING) { + if (butAction2Text == R.string.delete_label && state == FeedItem.State.PLAYING && PlaybackService.isRunning) { butAction2.setEnabled(false); butAction2.setAlpha(0.5f); } else { @@ -571,12 +573,12 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { }; private void load() { - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } progbarLoading.setVisibility(View.VISIBLE); - subscription = Observable.fromCallable(this::loadInBackground) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(this::loadInBackground) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { progbarLoading.setVisibility(View.GONE); @@ -586,6 +588,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { }, error -> Log.e(TAG, Log.getStackTraceString(error))); } + @Nullable private FeedItem loadInBackground() { FeedItem feedItem = DBReader.getFeedItem(feedItems[feedItemPos]); if (feedItem != null) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java index 83d6f9615..dfd9ac924 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -4,10 +4,9 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.res.TypedArray; -import android.graphics.Color; import android.graphics.LightingColorFilter; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v4.app.ListFragment; import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.SearchView; @@ -26,18 +25,17 @@ import android.widget.RelativeLayout; import android.widget.TextView; import com.bumptech.glide.Glide; -import com.joanzapata.iconify.IconDrawable; +import com.bumptech.glide.request.RequestOptions; import com.joanzapata.iconify.Iconify; -import com.joanzapata.iconify.fonts.FontAwesomeIcons; import com.joanzapata.iconify.widget.IconTextView; -import de.danoeh.antennapod.activity.FeedSettingsActivity; import org.apache.commons.lang3.Validate; import java.util.List; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.FeedInfoActivity; +import de.danoeh.antennapod.activity.FeedSettingsActivity; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.DefaultActionButtonCallback; import de.danoeh.antennapod.adapter.FeedItemlistAdapter; @@ -55,7 +53,6 @@ import de.danoeh.antennapod.core.feed.FeedItemFilter; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.glide.FastBlurTransformation; -import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.storage.DBReader; @@ -71,10 +68,10 @@ import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; import de.danoeh.antennapod.menuhandler.MenuItemUtils; import de.greenrobot.event.EventBus; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Displays a list of FeedItems. @@ -114,7 +111,7 @@ public class ItemlistFragment extends ListFragment { private TextView txtvInformation; - private Subscription subscription; + private Disposable disposable; /** * Creates new ItemlistFragment which shows the Feeditems of a specific @@ -165,8 +162,8 @@ public class ItemlistFragment extends ListFragment { super.onPause(); EventDistributor.getInstance().unregister(contentUpdate); EventBus.getDefault().unregister(this); - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } } @@ -417,13 +414,10 @@ public class ItemlistFragment extends ListFragment { } - private boolean insideOnFragmentLoaded = false; - private void onFragmentLoaded() { if(!isVisible()) { return; } - insideOnFragmentLoaded = true; if (adapter == null) { setListAdapter(null); setupHeaderView(); @@ -440,9 +434,6 @@ public class ItemlistFragment extends ListFragment { if (feed != null && feed.getNextPageLink() == null && listFooter != null) { getListView().removeFooterView(listFooter.getRoot()); } - - insideOnFragmentLoaded = false; - } private void refreshHeaderView() { @@ -486,14 +477,14 @@ public class ItemlistFragment extends ListFragment { View header = inflater.inflate(R.layout.feeditemlist_header, lv, false); lv.addHeaderView(header); - txtvTitle = (TextView) header.findViewById(R.id.txtvTitle); - TextView txtvAuthor = (TextView) header.findViewById(R.id.txtvAuthor); - imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground); - imgvCover = (ImageView) header.findViewById(R.id.imgvCover); - ImageButton butShowInfo = (ImageButton) header.findViewById(R.id.butShowInfo); - ImageButton butShowSettings = (ImageButton) header.findViewById(R.id.butShowSettings); - txtvInformation = (TextView) header.findViewById(R.id.txtvInformation); - txtvFailure = (IconTextView) header.findViewById(R.id.txtvFailure); + txtvTitle = header.findViewById(R.id.txtvTitle); + TextView txtvAuthor = header.findViewById(R.id.txtvAuthor); + imgvBackground = header.findViewById(R.id.imgvBackground); + imgvCover = header.findViewById(R.id.imgvCover); + ImageButton butShowInfo = header.findViewById(R.id.butShowInfo); + ImageButton butShowSettings = header.findViewById(R.id.butShowSettings); + txtvInformation = header.findViewById(R.id.txtvInformation); + txtvFailure = header.findViewById(R.id.txtvFailure); txtvTitle.setText(feed.getTitle()); txtvAuthor.setText(feed.getAuthor()); @@ -529,20 +520,22 @@ public class ItemlistFragment extends ListFragment { private void loadFeedImage() { Glide.with(getActivity()) .load(feed.getImageLocation()) - .placeholder(R.color.image_readability_tint) - .error(R.color.image_readability_tint) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .transform(new FastBlurTransformation(getActivity())) - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.image_readability_tint) + .error(R.color.image_readability_tint) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .transform(new FastBlurTransformation()) + .dontAnimate()) .into(imgvBackground); Glide.with(getActivity()) .load(feed.getImageLocation()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) .into(imgvCover); } @@ -618,23 +611,22 @@ public class ItemlistFragment extends ListFragment { private void loadItems() { - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } - subscription = Observable.fromCallable(this::loadData) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(this::loadData) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { - if (result != null) { - feed = result; - itemsLoaded = true; - if (viewsCreated) { - onFragmentLoaded(); - } + feed = result; + itemsLoaded = true; + if (viewsCreated) { + onFragmentLoaded(); } }, error -> Log.e(TAG, Log.getStackTraceString(error))); } + @Nullable private Feed loadData() { Feed feed = DBReader.getFeed(feedID); DBReader.loadAdditionalFeedItemListData(feed.getItems()); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java index 08610c1f3..486727313 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java @@ -36,13 +36,14 @@ import de.danoeh.antennapod.adapter.itunes.ItunesAdapter; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.menuhandler.MenuItemUtils; +import io.reactivex.Single; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; import static de.danoeh.antennapod.adapter.itunes.ItunesAdapter.Podcast; @@ -69,7 +70,7 @@ public class ItunesSearchFragment extends Fragment { */ private List searchResults; private List topList; - private Subscription subscription; + private Disposable disposable; /** * Replace adapter data with provided search results from SearchTask. @@ -109,7 +110,7 @@ public class ItunesSearchFragment extends Fragment { Bundle savedInstanceState) { // Inflate the layout for this fragment View root = inflater.inflate(R.layout.fragment_itunes_search, container, false); - gridView = (GridView) root.findViewById(R.id.gridView); + gridView = root.findViewById(R.id.gridView); adapter = new ItunesAdapter(getActivity(), new ArrayList<>()); gridView.setAdapter(adapter); @@ -127,7 +128,7 @@ public class ItunesSearchFragment extends Fragment { } else { gridView.setVisibility(View.GONE); progressBar.setVisibility(View.VISIBLE); - subscription = Observable.create((Observable.OnSubscribe) subscriber -> { + disposable = Single.create((SingleOnSubscribe) emitter -> { OkHttpClient client = AntennapodHttpClient.getHttpClient(); Request.Builder httpReq = new Request.Builder() .url(podcast.feedUrl) @@ -139,17 +140,16 @@ public class ItunesSearchFragment extends Fragment { JSONObject result = new JSONObject(resultString); JSONObject results = result.getJSONArray("results").getJSONObject(0); String feedUrl = results.getString("feedUrl"); - subscriber.onNext(feedUrl); + emitter.onSuccess(feedUrl); } else { String prefix = getString(R.string.error_msg_prefix); - subscriber.onError(new IOException(prefix + response)); + emitter.onError(new IOException(prefix + response)); } } catch (IOException | JSONException e) { - subscriber.onError(e); + emitter.onError(e); } - subscriber.onCompleted(); }) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(feedUrl -> { progressBar.setVisibility(View.GONE); @@ -170,10 +170,10 @@ public class ItunesSearchFragment extends Fragment { }); } }); - progressBar = (ProgressBar) root.findViewById(R.id.progressBar); - txtvError = (TextView) root.findViewById(R.id.txtvError); - butRetry = (Button) root.findViewById(R.id.butRetry); - txtvEmpty = (TextView) root.findViewById(android.R.id.empty); + progressBar = root.findViewById(R.id.progressBar); + txtvError = root.findViewById(R.id.txtvError); + butRetry = root.findViewById(R.id.butRetry); + txtvEmpty = root.findViewById(android.R.id.empty); loadToplist(); @@ -183,8 +183,8 @@ public class ItunesSearchFragment extends Fragment { @Override public void onDestroy() { super.onDestroy(); - if (subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } adapter = null; } @@ -228,15 +228,15 @@ public class ItunesSearchFragment extends Fragment { } private void loadToplist() { - if (subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } gridView.setVisibility(View.GONE); txtvError.setVisibility(View.GONE); butRetry.setVisibility(View.GONE); txtvEmpty.setVisibility(View.GONE); progressBar.setVisibility(View.VISIBLE); - subscription = Observable.create((Observable.OnSubscribe>) subscriber -> { + disposable = Single.create((SingleOnSubscribe>) emitter -> { String lang = Locale.getDefault().getLanguage(); String url = "https://itunes.apple.com/" + lang + "/rss/toppodcasts/limit=25/explicit=true/json"; OkHttpClient client = AntennapodHttpClient.getHttpClient(); @@ -268,15 +268,14 @@ public class ItunesSearchFragment extends Fragment { } else { String prefix = getString(R.string.error_msg_prefix); - subscriber.onError(new IOException(prefix + response)); + emitter.onError(new IOException(prefix + response)); } } catch (IOException | JSONException e) { - subscriber.onError(e); + emitter.onError(e); } - subscriber.onNext(results); - subscriber.onCompleted(); + emitter.onSuccess(results); }) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(podcasts -> { progressBar.setVisibility(View.GONE); @@ -293,15 +292,15 @@ public class ItunesSearchFragment extends Fragment { } private void search(String query) { - if (subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } gridView.setVisibility(View.GONE); txtvError.setVisibility(View.GONE); butRetry.setVisibility(View.GONE); txtvEmpty.setVisibility(View.GONE); progressBar.setVisibility(View.VISIBLE); - subscription = rx.Observable.create((Observable.OnSubscribe>) subscriber -> { + disposable = Single.create((SingleOnSubscribe>) subscriber -> { String encodedQuery = null; try { encodedQuery = URLEncoder.encode(query, "UTF-8"); @@ -312,8 +311,7 @@ public class ItunesSearchFragment extends Fragment { encodedQuery = query; // failsafe } - //Spaces in the query need to be replaced with '+' character. - String formattedUrl = String.format(API_URL, query).replace(' ', '+'); + String formattedUrl = String.format(API_URL, encodedQuery); OkHttpClient client = AntennapodHttpClient.getHttpClient(); Request.Builder httpReq = new Request.Builder() @@ -341,10 +339,9 @@ public class ItunesSearchFragment extends Fragment { } catch (IOException | JSONException e) { subscriber.onError(e); } - subscriber.onNext(podcasts); - subscriber.onCompleted(); + subscriber.onSuccess(podcasts); }) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(podcasts -> { progressBar.setVisibility(View.GONE); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java index c136eb6ae..c2b61bf75 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java @@ -1,25 +1,19 @@ package de.danoeh.antennapod.fragment; import android.os.Bundle; -import android.os.Handler; -import android.support.design.widget.Snackbar; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - +import android.widget.TextView; import java.util.List; - import de.danoeh.antennapod.R; import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter; import de.danoeh.antennapod.core.event.FeedItemEvent; import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; @@ -31,9 +25,7 @@ import de.danoeh.antennapod.core.util.FeedItemUtil; public class NewEpisodesFragment extends AllEpisodesFragment { public static final String TAG = "NewEpisodesFragment"; - private static final String PREF_NAME = "PrefNewEpisodesFragment"; - @Override protected boolean showOnlyNewEpisodes() { return true; } @@ -46,24 +38,16 @@ public class NewEpisodesFragment extends AllEpisodesFragment { } @Override - public void onEventMainThread(FeedItemEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - if(episodes == null) { - return; - } - for(FeedItem item : event.items) { - int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId()); - if(pos >= 0 && item.isTagged(FeedItem.TAG_QUEUE)) { - episodes.remove(pos); - listAdapter.notifyItemRemoved(pos); - } - } + protected boolean shouldUpdatedItemRemainInList(FeedItem item) { + return item.isNew(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = super.onCreateViewHelper(inflater, container, savedInstanceState, R.layout.all_episodes_fragment); + ((TextView)root.findViewById(R.id.emptyViewTitle)).setText(R.string.no_new_episodes_head_label); + ((TextView)root.findViewById(R.id.emptyViewMessage)).setText(R.string.no_new_episodes_label); ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { @Override @@ -74,33 +58,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment { @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) { AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder)viewHolder; - - Log.d(TAG, "remove(" + holder.getItemId() + ")"); - if (subscription != null) { - subscription.unsubscribe(); - } - FeedItem item = holder.getFeedItem(); - // we're marking it as unplayed since the user didn't actually play it - // but they don't want it considered 'NEW' anymore - DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); - - final Handler h = new Handler(getActivity().getMainLooper()); - final Runnable r = () -> { - FeedMedia media = item.getMedia(); - if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) { - DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId()); - } - }; - - Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_seen_label), - Snackbar.LENGTH_LONG); - snackbar.setAction(getString(R.string.undo), v -> { - DBWriter.markItemPlayed(FeedItem.NEW, item.getId()); - // don't forget to cancel the thing that's going to remove the media - h.removeCallbacks(r); - }); - snackbar.show(); - h.postDelayed(r, (int)Math.ceil(snackbar.getDuration() * 1.05f)); + markItemAsSeenWithUndo(holder.getFeedItem()); } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index fb6280021..e8f35b180 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.fragment; import android.content.Context; import android.content.res.TypedArray; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.ListFragment; import android.support.v4.view.MenuItemCompat; import android.util.Log; @@ -29,11 +30,12 @@ import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.LongList; +import de.danoeh.antennapod.view.EmptyViewHandler; import de.greenrobot.event.EventBus; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; public class PlaybackHistoryFragment extends ListFragment { @@ -50,7 +52,7 @@ public class PlaybackHistoryFragment extends ListFragment { private List downloaderList; - private Subscription subscription; + private Disposable disposable; @Override public void onAttach(Context context) { @@ -81,6 +83,12 @@ public class PlaybackHistoryFragment extends ListFragment { if (itemsLoaded) { onFragmentLoaded(); } + + EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); + emptyView.setTitle(R.string.no_history_head_label); + emptyView.setMessage(R.string.no_history_label); + emptyView.attachToListView(getListView()); + } @@ -107,16 +115,16 @@ public class PlaybackHistoryFragment extends ListFragment { public void onStop() { super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } } @Override public void onDetach() { super.onDetach(); - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } } @@ -269,11 +277,11 @@ public class PlaybackHistoryFragment extends ListFragment { }; private void loadItems() { - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } - subscription = Observable.fromCallable(this::loadData) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(this::loadData) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { if (result != null) { @@ -286,6 +294,7 @@ public class PlaybackHistoryFragment extends ListFragment { }, error -> Log.e(TAG, Log.getStackTraceString(error))); } + @NonNull private List loadData() { List history = DBReader.getPlaybackHistory(); DBReader.loadAdditionalFeedItemListData(history); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java index bae77d58b..873612fd6 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java @@ -21,7 +21,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ProgressBar; import android.widget.TextView; -import android.widget.Toast; import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration; @@ -46,7 +45,6 @@ import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; -import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.FeedItemUtil; @@ -55,10 +53,10 @@ import de.danoeh.antennapod.core.util.QueueSorter; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.MenuItemUtils; import de.greenrobot.event.EventBus; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Shows all items in the queue @@ -74,7 +72,7 @@ public class QueueFragment extends Fragment { private TextView infoBar; private RecyclerView recyclerView; private QueueRecyclerAdapter recyclerAdapter; - private TextView txtvEmpty; + private View emptyView; private ProgressBar progLoading; private List queue; @@ -86,7 +84,7 @@ public class QueueFragment extends Fragment { private static final String PREF_SCROLL_POSITION = "scroll_position"; private static final String PREF_SCROLL_OFFSET = "scroll_offset"; - private Subscription subscription; + private Disposable disposable; private LinearLayoutManager layoutManager; private ItemTouchHelper itemTouchHelper; @@ -120,8 +118,8 @@ public class QueueFragment extends Fragment { saveScrollPosition(); EventDistributor.getInstance().unregister(contentUpdate); EventBus.getDefault().unregister(this); - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } } @@ -382,8 +380,8 @@ public class QueueFragment extends Fragment { ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.queue_label); View root = inflater.inflate(R.layout.queue_fragment, container, false); - infoBar = (TextView) root.findViewById(R.id.info_bar); - recyclerView = (RecyclerView) root.findViewById(R.id.recyclerView); + infoBar = root.findViewById(R.id.info_bar); + recyclerView = root.findViewById(R.id.recyclerView); RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); if (animator instanceof SimpleItemAnimator) { ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); @@ -425,15 +423,15 @@ public class QueueFragment extends Fragment { @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } final int position = viewHolder.getAdapterPosition(); Log.d(TAG, "remove(" + position + ")"); final FeedItem item = queue.get(position); final boolean isRead = item.isPlayed(); DBWriter.markItemPlayed(FeedItem.PLAYED, false, item.getId()); - DBWriter.removeQueueItem(getActivity(), item, true); + DBWriter.removeQueueItem(getActivity(), true, item); Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_read_label), Snackbar.LENGTH_LONG); snackbar.setAction(getString(R.string.undo), v -> { DBWriter.addQueueItemAt(getActivity(), item.getId(), position, false); @@ -489,35 +487,39 @@ public class QueueFragment extends Fragment { private void reallyMoved(int from, int to) { // Write drag operation to database - Log.d(TAG, "Write to database move(" + dragFrom + ", " + dragTo + ")"); - DBWriter.moveQueueItem(dragFrom, dragTo, true); + Log.d(TAG, "Write to database move(" + from + ", " + to + ")"); + DBWriter.moveQueueItem(from, to, true); } } ); itemTouchHelper.attachToRecyclerView(recyclerView); + //empty view + emptyView = (View) root.findViewById(R.id.emptyView); + emptyView.setVisibility(View.GONE); + ((TextView)emptyView.findViewById(R.id.emptyViewTitle)).setText(R.string.no_items_header_label); + ((TextView)emptyView.findViewById(R.id.emptyViewMessage)).setText(R.string.no_items_label); - txtvEmpty = (TextView) root.findViewById(android.R.id.empty); - txtvEmpty.setVisibility(View.GONE); - progLoading = (ProgressBar) root.findViewById(R.id.progLoading); + progLoading = root.findViewById(R.id.progLoading); progLoading.setVisibility(View.VISIBLE); return root; } private void onFragmentLoaded(final boolean restoreScrollPosition) { - if (recyclerAdapter == null) { - MainActivity activity = (MainActivity) getActivity(); - recyclerAdapter = new QueueRecyclerAdapter(activity, itemAccess, - new DefaultActionButtonCallback(activity), itemTouchHelper); - recyclerAdapter.setHasStableIds(true); - recyclerView.setAdapter(recyclerAdapter); - } - if(queue == null || queue.size() == 0) { - recyclerView.setVisibility(View.GONE); - txtvEmpty.setVisibility(View.VISIBLE); - } else { - txtvEmpty.setVisibility(View.GONE); + if (queue != null && queue.size() > 0) { + if (recyclerAdapter == null) { + MainActivity activity = (MainActivity) getActivity(); + recyclerAdapter = new QueueRecyclerAdapter(activity, itemAccess, + new DefaultActionButtonCallback(activity), itemTouchHelper); + recyclerAdapter.setHasStableIds(true); + recyclerView.setAdapter(recyclerAdapter); + } + emptyView.setVisibility(View.GONE); recyclerView.setVisibility(View.VISIBLE); + } else { + recyclerAdapter = null; + recyclerView.setVisibility(View.GONE); + emptyView.setVisibility(View.VISIBLE); } if (restoreScrollPosition) { @@ -535,9 +537,12 @@ public class QueueFragment extends Fragment { String info = queue.size() + getString(R.string.episodes_suffix); if(queue.size() > 0) { long timeLeft = 0; + float playbackSpeed = Float.valueOf(UserPreferences.getPlaybackSpeed()); for(FeedItem item : queue) { if(item.getMedia() != null) { - timeLeft += item.getMedia().getDuration() - item.getMedia().getPosition(); + timeLeft += + (long) ((item.getMedia().getDuration() - item.getMedia().getPosition()) + / playbackSpeed); } } info += " \u2022 "; @@ -622,25 +627,23 @@ public class QueueFragment extends Fragment { private void loadItems(final boolean restoreScrollPosition) { Log.d(TAG, "loadItems()"); - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } if (queue == null) { recyclerView.setVisibility(View.GONE); - txtvEmpty.setVisibility(View.GONE); + emptyView.setVisibility(View.GONE); progLoading.setVisibility(View.VISIBLE); } - subscription = Observable.fromCallable(DBReader::getQueue) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(DBReader::getQueue) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(items -> { - if(items != null) { - progLoading.setVisibility(View.GONE); - queue = items; - onFragmentLoaded(restoreScrollPosition); - if(recyclerAdapter != null) { - recyclerAdapter.notifyDataSetChanged(); - } + progLoading.setVisibility(View.GONE); + queue = items; + onFragmentLoaded(restoreScrollPosition); + if(recyclerAdapter != null) { + recyclerAdapter.notifyDataSetChanged(); } }, error -> Log.e(TAG, Log.getStackTraceString(error))); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java index 66c59b7f7..3c40b542c 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java @@ -20,6 +20,7 @@ import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DownloadRequester; +import de.danoeh.antennapod.view.EmptyViewHandler; import de.greenrobot.event.EventBus; /** @@ -44,6 +45,12 @@ public class RunningDownloadsFragment extends ListFragment { adapter = new DownloadlistAdapter(getActivity(), itemAccess); setListAdapter(adapter); + + EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); + emptyView.setTitle(R.string.no_run_downloads_head_label); + emptyView.setMessage(R.string.no_run_downloads_label); + emptyView.attachToListView(getListView()); + } @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java index f64b4c20a..1d7ac8824 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.fragment; import android.content.Context; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.ListFragment; import android.support.v4.view.MenuItemCompat; import android.support.v7.app.AppCompatActivity; @@ -24,10 +25,10 @@ import de.danoeh.antennapod.core.feed.FeedComponent; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.SearchResult; import de.danoeh.antennapod.core.storage.FeedSearcher; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Performs a search operation on all feeds or one specific feed and displays the search result. @@ -44,7 +45,7 @@ public class SearchFragment extends ListFragment { private boolean viewCreated = false; private boolean itemsLoaded = false; - private Subscription subscription; + private Disposable disposable; /** * Create a new SearchFragment that searches all feeds. @@ -85,8 +86,8 @@ public class SearchFragment extends ListFragment { @Override public void onStop() { super.onStop(); - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } EventDistributor.getInstance().unregister(contentUpdate); } @@ -94,8 +95,8 @@ public class SearchFragment extends ListFragment { @Override public void onDetach() { super.onDetach(); - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } } @@ -205,26 +206,25 @@ public class SearchFragment extends ListFragment { private void search() { - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } if (viewCreated && !itemsLoaded) { setListShown(false); } - subscription = Observable.fromCallable(this::performSearch) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(this::performSearch) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { - if (result != null) { - itemsLoaded = true; - searchResults = result; - if (viewCreated) { - onFragmentLoaded(); - } + itemsLoaded = true; + searchResults = result; + if (viewCreated) { + onFragmentLoaded(); } }, error -> Log.e(TAG, Log.getStackTraceString(error))); } + @NonNull private List performSearch() { Bundle args = getArguments(); String query = args.getString(ARG_QUERY); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java index 1247aacbb..5f09be8ce 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java @@ -1,7 +1,6 @@ package de.danoeh.antennapod.fragment; import android.content.DialogInterface; -import android.content.Intent; import android.os.Bundle; import android.support.v4.app.Fragment; import android.util.Log; @@ -26,11 +25,12 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.dialog.RenameFeedDialog; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Fragment for displaying feed subscriptions @@ -48,7 +48,7 @@ public class SubscriptionFragment extends Fragment { private int mPosition = -1; - private Subscription subscription; + private Disposable disposable; public SubscriptionFragment() { } @@ -68,7 +68,7 @@ public class SubscriptionFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_subscriptions, container, false); - subscriptionGridLayout = (GridView) root.findViewById(R.id.subscriptions_grid); + subscriptionGridLayout = root.findViewById(R.id.subscriptions_grid); registerForContextMenu(subscriptionGridLayout); return root; } @@ -94,17 +94,17 @@ public class SubscriptionFragment extends Fragment { @Override public void onDestroy() { super.onDestroy(); - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } } private void loadSubscriptions() { - if(subscription != null) { - subscription.unsubscribe(); + if(disposable != null) { + disposable.dispose(); } - subscription = Observable.fromCallable(DBReader::getNavDrawerData) - .subscribeOn(Schedulers.newThread()) + disposable = Observable.fromCallable(DBReader::getNavDrawerData) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { navDrawerData = result; @@ -161,7 +161,7 @@ public class SubscriptionFragment extends Fragment { dialog.dismiss(); Observable.fromCallable(() -> DBWriter.markFeedSeen(feed.getId())) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> loadSubscriptions(), error -> Log.e(TAG, Log.getStackTraceString(error))); @@ -178,7 +178,7 @@ public class SubscriptionFragment extends Fragment { public void onConfirmButtonPressed(DialogInterface dialog) { dialog.dismiss(); Observable.fromCallable(() -> DBWriter.markFeedRead(feed.getId())) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> loadSubscriptions(), error -> Log.e(TAG, Log.getStackTraceString(error))); @@ -211,8 +211,8 @@ public class SubscriptionFragment extends Fragment { remover.skipOnCompletion = true; int playerStatus = PlaybackPreferences.getCurrentPlayerStatus(); if(playerStatus == PlaybackPreferences.PLAYER_STATUS_PLAYING) { - getActivity().sendBroadcast(new Intent( - PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE)); + IntentUtils.sendLocalBroadcast(getContext(), PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE); + } } remover.executeAsync(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java index b48027668..4dc114f9b 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java @@ -31,12 +31,12 @@ public class GpodnetMainFragment extends Fragment { super.onCreateView(inflater, container, savedInstanceState); View root = inflater.inflate(R.layout.pager_fragment, container, false); - viewPager = (ViewPager)root.findViewById(R.id.viewpager); + viewPager = root.findViewById(R.id.viewpager); GpodnetPagerAdapter pagerAdapter = new GpodnetPagerAdapter(getChildFragmentManager(), getResources()); viewPager.setAdapter(pagerAdapter); // Give the TabLayout the ViewPager - tabLayout = (TabLayout) root.findViewById(R.id.sliding_tabs); + tabLayout = root.findViewById(R.id.sliding_tabs); tabLayout.setupWithViewPager(viewPager); return root; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java index 055358c64..49851ebb4 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java @@ -78,10 +78,10 @@ public abstract class PodcastListFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.gpodnet_podcast_list, container, false); - gridView = (GridView) root.findViewById(R.id.gridView); - progressBar = (ProgressBar) root.findViewById(R.id.progressBar); - txtvError = (TextView) root.findViewById(R.id.txtvError); - butRetry = (Button) root.findViewById(R.id.butRetry); + gridView = root.findViewById(R.id.gridView); + progressBar = root.findViewById(R.id.progressBar); + txtvError = root.findViewById(R.id.txtvError); + butRetry = root.findViewById(R.id.butRetry); gridView.setOnItemClickListener((parent, view, position, id) -> onPodcastSelected((GpodnetPodcast) gridView.getAdapter().getItem(position))); diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java index de47ee5e4..3f8d88af7 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java @@ -101,7 +101,8 @@ public class FeedItemMenuHandler { mi.setItemVisibility(R.id.share_download_url_with_position_item, false); } - mi.setItemVisibility(R.id.share_file, hasMedia && selectedItem.getMedia().fileExists()); + boolean fileDownloaded = hasMedia && selectedItem.getMedia().fileExists(); + mi.setItemVisibility(R.id.share_file, fileDownloaded); if (selectedItem.isPlayed()) { mi.setItemVisibility(R.id.mark_read_item, false); @@ -130,6 +131,8 @@ public class FeedItemMenuHandler { mi.setItemVisibility(R.id.add_to_favorites_item, !isFavorite); mi.setItemVisibility(R.id.remove_from_favorites_item, isFavorite); + mi.setItemVisibility(R.id.remove_item, fileDownloaded); + return true; } @@ -158,7 +161,7 @@ public class FeedItemMenuHandler { FeedItem selectedItem) { switch (menuItemId) { case R.id.skip_episode_item: - context.sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE)); + IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SKIP_CURRENT_EPISODE); break; case R.id.remove_item: DBWriter.deleteFeedMediaOfItem(context, selectedItem.getMedia().getId()); @@ -196,7 +199,7 @@ public class FeedItemMenuHandler { DBWriter.addQueueItem(context, selectedItem); break; case R.id.remove_from_queue_item: - DBWriter.removeQueueItem(context, selectedItem, true); + DBWriter.removeQueueItem(context, true, selectedItem); break; case R.id.add_to_favorites_item: DBWriter.addFavoriteItem(selectedItem); diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java index ab7d0e7c6..bd4fe9bcf 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java @@ -30,6 +30,9 @@ import de.danoeh.antennapod.core.util.ShareUtils; * Handles interactions with the FeedItemMenu. */ public class FeedMenuHandler { + + private FeedMenuHandler(){ } + private static final String TAG = "FeedMenuHandler"; public static boolean onCreateOptionsMenu(MenuInflater inflater, Menu menu) { diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java index ac703e13e..7b9fcad9b 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java @@ -19,8 +19,9 @@ public class MenuItemUtils extends de.danoeh.antennapod.core.menuhandler.MenuIte public static void adjustTextColor(Context context, SearchView sv) { if(Build.VERSION.SDK_INT < 14) { - EditText searchEditText = (EditText) sv.findViewById(R.id.search_src_text); - if(UserPreferences.getTheme() == de.danoeh.antennapod.R.style.Theme_AntennaPod_Dark) { + EditText searchEditText = sv.findViewById(R.id.search_src_text); + if (UserPreferences.getTheme() == de.danoeh.antennapod.R.style.Theme_AntennaPod_Dark + || UserPreferences.getTheme() == R.style.Theme_AntennaPod_TrueBlack) { searchEditText.setTextColor(Color.WHITE); } else { searchEditText.setTextColor(Color.BLACK); diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java index e500267fe..b810cbfa6 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java @@ -9,6 +9,7 @@ import android.support.v7.preference.PreferenceViewHolder; import android.util.AttributeSet; import android.util.TypedValue; import android.widget.TextView; + import de.danoeh.antennapod.R; public class MasterSwitchPreference extends SwitchPreference { diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/NumberPickerPreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/NumberPickerPreference.java new file mode 100644 index 000000000..50e76838c --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/preferences/NumberPickerPreference.java @@ -0,0 +1,107 @@ +package de.danoeh.antennapod.preferences; + +import android.app.AlertDialog; +import android.content.Context; +import android.support.v7.preference.Preference; +import android.text.InputFilter; +import android.util.AttributeSet; +import android.view.View; +import android.view.WindowManager; +import android.widget.EditText; + +import de.danoeh.antennapod.R; + +public class NumberPickerPreference extends Preference { + private Context context; + private int defaultValue = 0; + private int minValue = 0; + private int maxValue = Integer.MAX_VALUE; + + public NumberPickerPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(context, attrs); + } + + public NumberPickerPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + public NumberPickerPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public NumberPickerPreference(Context context) { + super(context); + this.context = context; + } + + private void init(Context context, AttributeSet attrs) { + this.context = context; + + for (int i = 0; i < attrs.getAttributeCount(); i++) { + String name = attrs.getAttributeName(i); + String value = attrs.getAttributeValue(i); + switch (name) { + case "defaultValue": + defaultValue = Integer.parseInt(value); + break; + case "minValue": + minValue = Integer.parseInt(value); + break; + case "maxValue": + maxValue = Integer.parseInt(value); + break; + } + } + } + + @Override + protected void onClick() { + super.onClick(); + + View view = View.inflate(context, R.layout.numberpicker, null); + EditText number = view.findViewById(R.id.number); + number.setText(getSharedPreferences().getString(getKey(), ""+defaultValue)); + number.setFilters(new InputFilter[]{(source, start, end, dest, dstart, dend) -> { + try { + String newVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend); + newVal = newVal.substring(0, dstart) + source.toString() + newVal.substring(dstart); + int input = Integer.parseInt(newVal); + if (input >= minValue && input <= maxValue) { + return null; + } + } catch (NumberFormatException nfe) { + nfe.printStackTrace(); + } + return ""; + }}); + + AlertDialog dialog = new AlertDialog.Builder(context) + .setTitle(getTitle()) + .setView(view) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> { + try { + String numberString = number.getText().toString(); + int value = Integer.parseInt(numberString); + + if (value < minValue || value > maxValue) { + return; + } + + getSharedPreferences().edit().putString(getKey(), "" + value).apply(); + + if (getOnPreferenceChangeListener() != null) { + getOnPreferenceChangeListener().onPreferenceChange(this, value); + } + } catch (NumberFormatException e) { + // Do not set value + } + }) + .create(); + dialog.show(); + dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java index 9bb0edeb2..a157a2cfa 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -36,24 +36,9 @@ import android.widget.ListView; import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; - import com.bytehamster.lib.preferencesearch.SearchConfiguration; import com.bytehamster.lib.preferencesearch.SearchPreference; -import de.danoeh.antennapod.activity.AboutActivity; -import de.danoeh.antennapod.activity.ImportExportActivity; -import de.danoeh.antennapod.activity.MediaplayerActivity; -import de.danoeh.antennapod.activity.OpmlImportFromPathActivity; -import de.danoeh.antennapod.activity.PreferenceActivity; -import de.danoeh.antennapod.activity.StatisticsActivity; -import de.danoeh.antennapod.core.export.html.HtmlWriter; -import de.danoeh.antennapod.core.export.opml.OpmlWriter; -import de.danoeh.antennapod.core.service.GpodnetSyncService; -import de.danoeh.antennapod.dialog.AuthenticationDialog; -import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog; -import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog; -import de.danoeh.antennapod.dialog.ProxyDialog; -import de.danoeh.antennapod.dialog.VariableSpeedDialog; -import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; + import org.apache.commons.lang3.ArrayUtils; import java.io.File; @@ -67,18 +52,33 @@ import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.CrashReportWriter; import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.AboutActivity; import de.danoeh.antennapod.activity.DirectoryChooserActivity; +import de.danoeh.antennapod.activity.ImportExportActivity; import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.activity.MediaplayerActivity; +import de.danoeh.antennapod.activity.OpmlImportFromPathActivity; +import de.danoeh.antennapod.activity.PreferenceActivity; +import de.danoeh.antennapod.activity.StatisticsActivity; import de.danoeh.antennapod.asynctask.ExportWorker; import de.danoeh.antennapod.core.export.ExportWriter; +import de.danoeh.antennapod.core.export.html.HtmlWriter; +import de.danoeh.antennapod.core.export.opml.OpmlWriter; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.service.GpodnetSyncService; import de.danoeh.antennapod.core.util.flattr.FlattrUtils; +import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; +import de.danoeh.antennapod.dialog.AuthenticationDialog; +import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog; import de.danoeh.antennapod.dialog.ChooseDataFolderDialog; -import rx.Observable; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog; +import de.danoeh.antennapod.dialog.ProxyDialog; +import de.danoeh.antennapod.dialog.VariableSpeedDialog; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; import static de.danoeh.antennapod.activity.PreferenceActivity.PARAM_RESOURCE; @@ -137,7 +137,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } }; private CheckBoxPreference[] selectedNetworks; - private Subscription subscription; + private Disposable disposable; public PreferenceController(PreferenceUI ui) { this.ui = ui; @@ -147,12 +147,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if(key.equals(UserPreferences.PREF_SONIC)) { - CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC); - if(prefSonic != null) { - prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false)); - } - } + } @@ -167,7 +162,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc break; case R.xml.preferences_autodownload: setupAutoDownloadScreen(); - buildAutodownloadSelectedNetworsPreference(); + buildAutodownloadSelectedNetworksPreference(); setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter()); buildEpisodeCleanupPreference(); break; @@ -232,6 +227,33 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc return true; }); + ui.findPreference(UserPreferences.PREF_BACK_BUTTON_BEHAVIOR) + .setOnPreferenceChangeListener((preference, newValue) -> { + if (newValue.equals("page")) { + final Context context = ui.getActivity(); + final String[] navTitles = context.getResources().getStringArray(R.array.back_button_go_to_pages); + final String[] navTags = context.getResources().getStringArray(R.array.back_button_go_to_pages_tags); + final String choice[] = { UserPreferences.getBackButtonGoToPage() }; + + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(R.string.back_button_go_to_page_title); + builder.setSingleChoiceItems(navTitles, ArrayUtils.indexOf(navTags, UserPreferences.getBackButtonGoToPage()), (dialogInterface, i) -> { + if (i >= 0) { + choice[0] = navTags[i]; + } + }); + builder.setPositiveButton(R.string.confirm_label, (dialogInterface, i) -> UserPreferences.setBackButtonGoToPage(choice[0])); + builder.setNegativeButton(R.string.cancel_label, null); + builder.create().show(); + return true; + } else { + return true; + } + }); + + if (Build.VERSION.SDK_INT >= 26) { + ui.findPreference(UserPreferences.PREF_EXPANDED_NOTIFICATION).setVisible(false); + } } private void setupStorageScreen() { @@ -467,18 +489,10 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc ui.findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS) .setOnPreferenceChangeListener( (preference, o) -> { - if (o instanceof String) { - try { - int value = Integer.parseInt((String) o); - if (1 <= value && value <= 50) { - setParallelDownloadsText(value); - return true; - } - } catch (NumberFormatException e) { - return false; - } + if (o instanceof Integer) { + setParallelDownloadsText((Integer) o); } - return false; + return true; } ); // validate and set correct value: number of downloads between 1 and 50 (inclusive) @@ -567,31 +581,24 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc config.setFragmentContainerViewId(R.id.content); config.setBreadcrumbsEnabled(true); - config.index() - .addBreadcrumb(getTitleOfPage(R.xml.preferences_user_interface)) - .addFile(R.xml.preferences_user_interface); - config.index() - .addBreadcrumb(getTitleOfPage(R.xml.preferences_playback)) - .addFile(R.xml.preferences_playback); - config.index() - .addBreadcrumb(getTitleOfPage(R.xml.preferences_network)) - .addFile(R.xml.preferences_network); - config.index() - .addBreadcrumb(getTitleOfPage(R.xml.preferences_storage)) - .addFile(R.xml.preferences_storage); - config.index() + config.index(R.xml.preferences_user_interface) + .addBreadcrumb(getTitleOfPage(R.xml.preferences_user_interface)); + config.index(R.xml.preferences_playback) + .addBreadcrumb(getTitleOfPage(R.xml.preferences_playback)); + config.index(R.xml.preferences_network) + .addBreadcrumb(getTitleOfPage(R.xml.preferences_network)); + config.index(R.xml.preferences_storage) + .addBreadcrumb(getTitleOfPage(R.xml.preferences_storage)); + config.index(R.xml.preferences_autodownload) .addBreadcrumb(getTitleOfPage(R.xml.preferences_network)) .addBreadcrumb(R.string.automation) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_autodownload)) - .addFile(R.xml.preferences_autodownload); - config.index() + .addBreadcrumb(getTitleOfPage(R.xml.preferences_autodownload)); + config.index(R.xml.preferences_gpodder) .addBreadcrumb(getTitleOfPage(R.xml.preferences_integrations)) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_gpodder)) - .addFile(R.xml.preferences_gpodder); - config.index() + .addBreadcrumb(getTitleOfPage(R.xml.preferences_gpodder)); + config.index(R.xml.preferences_flattr) .addBreadcrumb(getTitleOfPage(R.xml.preferences_integrations)) - .addBreadcrumb(getTitleOfPage(R.xml.preferences_flattr)) - .addFile(R.xml.preferences_flattr); + .addBreadcrumb(getTitleOfPage(R.xml.preferences_flattr)); } public PreferenceFragmentCompat openScreen(int preferences, AppCompatActivity activity) { @@ -637,7 +644,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc final AlertDialog.Builder alert = new AlertDialog.Builder(context) .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()); Observable observable = new ExportWorker(exportWriter).exportObservable(); - subscription = observable.subscribeOn(Schedulers.newThread()) + disposable = observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(output -> { alert.setTitle(R.string.export_success_title); @@ -645,7 +652,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc alert.setMessage(message); alert.setPositiveButton(R.string.send_label, (dialog, which) -> { Uri fileUri = FileProvider.getUriForFile(context.getApplicationContext(), - "de.danoeh.antennapod.provider", output); + context.getString(R.string.provider_authority), output); Intent sendIntent = new Intent(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_SUBJECT, context.getResources().getText(R.string.opml_export_label)); @@ -715,8 +722,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } public void unsubscribeExportSubscription() { - if (subscription != null) { - subscription.unsubscribe(); + if (disposable != null) { + disposable.dispose(); } } @@ -832,8 +839,11 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc entries[x] = res.getString(R.string.episode_cleanup_never); } else if (v == 0) { entries[x] = res.getString(R.string.episode_cleanup_after_listening); + } else if (v > 0 && v < 24) { + entries[x] = res.getQuantityString(R.plurals.episode_cleanup_hours_after_listening, v, v); } else { - entries[x] = res.getQuantityString(R.plurals.episode_cleanup_days_after_listening, v, v); + int numDays = (int)(v / 24); // assume underlying value will be NOT fraction of days, e.g., 36 (hours) + entries[x] = res.getQuantityString(R.plurals.episode_cleanup_days_after_listening, numDays, numDays); } } pref.setEntries(entries); @@ -891,11 +901,10 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } private void checkSonicItemVisibility() { - if (Build.VERSION.SDK_INT >= 16) { - ui.findPreference(UserPreferences.PREF_SONIC).setEnabled(true); - } else { - Preference prefSonic = ui.findPreference(UserPreferences.PREF_SONIC); - prefSonic.setSummary("[Android 4.1+]\n" + prefSonic.getSummary()); + if (Build.VERSION.SDK_INT < 16) { + ListPreference p = (ListPreference) ui.findPreference(UserPreferences.PREF_MEDIA_PLAYER); + p.setEntries(R.array.media_player_options_no_sonic); + p.setEntryValues(R.array.media_player_values_no_sonic); } } @@ -959,7 +968,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc return val == null ? "" : val; } - private void buildAutodownloadSelectedNetworsPreference() { + private void buildAutodownloadSelectedNetworksPreference() { final Activity activity = ui.getActivity(); if (selectedNetworks != null) { diff --git a/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java b/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java index 75cbd8b5a..03958508d 100644 --- a/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java +++ b/app/src/main/java/de/danoeh/antennapod/spa/SPAUtil.java @@ -33,7 +33,7 @@ public class SPAUtil { * sent before. */ public static synchronized boolean sendSPAppsQueryFeedsIntent(Context context) { - if (context == null) throw new IllegalArgumentException("context = null"); + assert context != null : "context = null"; final Context appContext = context.getApplicationContext(); if (appContext == null) { Log.wtf(TAG, "Unable to get application context"); diff --git a/app/src/main/java/de/danoeh/antennapod/view/EmptyViewHandler.java b/app/src/main/java/de/danoeh/antennapod/view/EmptyViewHandler.java new file mode 100644 index 000000000..e3fd63235 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/view/EmptyViewHandler.java @@ -0,0 +1,59 @@ +package de.danoeh.antennapod.view; + +import android.app.Activity; +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; +import android.widget.TextView; + +import de.danoeh.antennapod.R; + +public class EmptyViewHandler extends View { + private Activity activity; + private int title; + private int message; + + public EmptyViewHandler(Context context) { + super(context); + this.setActivity((Activity) context); + } + + public int getTitle() { + return title; + } + + public void setTitle(int title) { + this.title = title; + } + + public int getMessage() { + return message; + } + + public void setMessage(int message) { + this.message = message; + } + + public void attachToListView(ListView listView){ + + View emptyView = getActivity().getLayoutInflater().inflate(R.layout.empty_view_layout, null); + ((ViewGroup) listView.getParent()).addView(emptyView); + listView.setEmptyView(emptyView); + + TextView tvTitle = (TextView) emptyView.findViewById(R.id.emptyViewTitle); + tvTitle.setText(title); + + TextView tvMessage = (TextView) emptyView.findViewById(R.id.emptyViewMessage); + tvMessage.setText(message); + + } + + public Activity getActivity() { + return activity; + } + + public void setActivity(Activity activity) { + this.activity = activity; + } +} diff --git a/app/src/main/play/ar/listing/fulldescription b/app/src/main/play/ar/listing/fulldescription index 87b477fdc..27abb5532 100644 --- a/app/src/main/play/ar/listing/fulldescription +++ b/app/src/main/play/ar/listing/fulldescription @@ -1,4 +1,4 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
+AntennaPod هو مدير للبودكاست واللاعب الذي يتيح لك الوصول الفوري إلى ملايين البودكاست المجانية والمدفوعة ، من البودكاسترات المستقلة إلى دور النشر الكبيرة مثل بي بي سي ، إن بي آر وسي إن إن. يمكنك إضافة واستيراد وتصدير خلاصاتهم الخالية من المتاعب باستخدام قاعدة بيانات بودكاست iTunes أو ملفات OPML أو عناوين URL RSS بسيطة. يمكنك توفير الجهد واستخدام طاقة البطارية واستخدام البيانات المتنقلة مع عناصر تحكم تلقائية قوية لتنزيل الحلقات (حدد الأوقات والفترات الزمنية وشبكات WiFi) وحذف الحلقات (استنادًا إلى إعداداتك المفضلة وتأخير الإعدادات).
But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. diff --git a/app/src/main/play/ar/listing/shortdescription b/app/src/main/play/ar/listing/shortdescription new file mode 100644 index 000000000..7afb5a62d --- /dev/null +++ b/app/src/main/play/ar/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast & radio manager and player \ No newline at end of file diff --git a/app/src/main/play/ar/listing/title b/app/src/main/play/ar/listing/title new file mode 100644 index 000000000..6c7c64cfc --- /dev/null +++ b/app/src/main/play/ar/listing/title @@ -0,0 +1 @@ +AntennaPod diff --git a/app/src/main/play/ast_ES/listing/fulldescription b/app/src/main/play/ast_ES/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/ast_ES/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/az/listing/fulldescription b/app/src/main/play/az/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/az/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/bg/listing/shortdescription b/app/src/main/play/bg/listing/shortdescription new file mode 100644 index 000000000..7afb5a62d --- /dev/null +++ b/app/src/main/play/bg/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast & radio manager and player \ No newline at end of file diff --git a/app/src/main/play/bg/listing/title b/app/src/main/play/bg/listing/title new file mode 100644 index 000000000..6c7c64cfc --- /dev/null +++ b/app/src/main/play/bg/listing/title @@ -0,0 +1 @@ +AntennaPod diff --git a/app/src/main/play/ca/listing/title b/app/src/main/play/ca/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/ca/listing/title +++ b/app/src/main/play/ca/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/ca_ES/listing/fulldescription b/app/src/main/play/ca_ES/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/ca_ES/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/cs-CZ/listing/title b/app/src/main/play/cs-CZ/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/cs-CZ/listing/title +++ b/app/src/main/play/cs-CZ/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/cs_CZ/listing/fulldescription b/app/src/main/play/cs_CZ/listing/fulldescription deleted file mode 100644 index 4e15342ee..000000000 --- a/app/src/main/play/cs_CZ/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Používejte AntennaPod ve vlastním jazyce (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Přidejte se ke komunitě AntennaPod!
-AntennaPod je aktivně vyvíjen dobrovolníky. Můžete přispět také svým kódem nebo komentáři! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Máte dotaz nebo chcete poslat svůj názor? -https://twitter.com/@AntennaPod - -Překlady jsou spravovány pomocí služby Transifex:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/da-DK/listing/fulldescription b/app/src/main/play/da-DK/listing/fulldescription index 1d19da2e8..8f48ef070 100644 --- a/app/src/main/play/da-DK/listing/fulldescription +++ b/app/src/main/play/da-DK/listing/fulldescription @@ -1,20 +1,43 @@ -AntennaPod er en open-source podcast afspiller for Android 2.3.3 og nyere. Den tilbyder alle basale features du forventer fra en podcastafspiller, som streaming og download af episoder, opdaterer automatisk feeds eller tilføjer dem automatisk i en kø så du kan høre dem senere. Derudover lader AntennaPod dig flattr podcasts og episoder inde i appen. +AntennaPod er en app til håndtering og afspilning af podcasts. Den giver dig øjeblikkelig adgang til millioner af gratis og betalte podcasts, fra uafhængige podcastere til store udgivere som BBC, NPR, CNN og DR. Tilføj, importer og eksporter deres feeds problemfrit ved hjælp af iTunes-podcastdatabasen, OPML-filer eller enkle RSS-webadresser. Spar kræfter, batteristrøm og mobilt dataforbrug med kraftfulde automatiske styringsværktøjer til at hente udsendelser (angiv tidspunkter, tidsintervaller og udvalgte wi-fi-netværk) og sletning af episoder (baseret på dine foretrukne udsendelser og forsinkelsesindstillinger).
+Men vigtigst af alt: Hent, stream eller sæt udsendelser i kø og nyd dem på den måde du kan lide med justerbare hastigheder, kapitelunderstøttelse og en søvntimer. Du kan endda vise din påskønnelse over for indholdsskaberne med vores Flattr-integration. -Indtil nu er følgende features blevet implementeret: +AntennaPod er lavet af en podcast-entusiast og er gratis og fri i alle betydninger: open source, ingen udgifter, ingen reklamer. -* Download og Streaming af episoder -* Variabel afspilningshastighed (kræver Presto Sound Library eller Prestissimo) -* Understøttelse af Atom og RSS feeds -* Understøttelse af password-beskyttede feeds og episoder -* Support for searching iTunes listings -* OPML import og eksport -* Flattr integration inkluderer automatisk flattring -* Afspiller widget -* Søg -* Automatisk opdatering af feeds -* Automatisk download af nye episoder -* Sleep timer -* Adgang til gpodder.net's podcast bibliotek -* Synkronisering af abonnementer med gpodder.net's service -* Understøtter af MP3 kapitler, VorbisComment kapitler and Podlove Simple Chapters -* Understøtter side-delte feeds (http://podlove.org/paged-feeds/) \ No newline at end of file +Alle funktioner:
+IMPORTER, ORGANISER OG AFSPIL
+• Tilføj og importer feeds via iTunes- og gpodder.net-oversigterne, OPML-filer og RSS- eller Atom-links
+• Håndter afspilning fra hvor som helst: widget på startskærmen, systemnotifikation, samt hovedtelefon- og bluetooth-styring
+• Lyt på din egen måde med justerbar afspilningshastighed, kapitelunderstøttelse (MP3, VorbisComment og Podlove), erindring af afspilningsposition og en avanceret søvntimer (ryst for at nulstille, sænke lydstyrken og afspille langsommere)
+• Tilgå feeds og udsendelser beskyttet med adgangskode
+• Brug sideinddelte feeds (www.podlove.org/paged-feeds) + +HOLD STYR PÅ, DEL OG ANERKEND
+• Hold styr på det bedste af det bedste ved at markere udsendelser som foretrukne
+• Find en bestemt udsendelse via afspilningshistorikken eller ved at søge (titler og beskrivelser)
+• Del udsendelser og feeds via avancerede valgmuligheder for sociale medier, gpodder.net-tjenesterne og OPML-eksport
+• Støt indholdsskabere med Flattr-integration, inklusive automatisk flattring + +STYR SYSTEMET
+• Tag styring over automatiseret hentning: vælg feeds, udeluk mobile netværk, vælg specifikke wi-fi-netvæk, kræv at telefonen oplader og indstil tidspunkter eller tidsintervaller +• Håndter lagerforbruget ved at indstille antallet af udsendelser, der skal gemmes, smart sletning (baseret på dine foretrukne og afspilningsstatus) og ved at vælge den lagerplacering, du foretrækker
+• Brug AntennaPod på dit eget sprog (EN, DE, DA, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
+• Tilpas appen til dit miljø med det lyse eller mørke tema
+• Sikkerhedskopier dine abonnementer med gpodder.net-integrationen og OPML-eksport + +Bliv en del af AntennaPod-fællesskabet!
+AntennaPod er under aktiv udvikling af frivillige. Du kan også bidrage, enten med kode eller kommentarer! + +GitHub er stedet for forslag tli ny funktionalitet, fejlrapporter og kodebidrag:
+https://www.github.com/AntennaPod/AntennaPod + +Vores Google-gruppe er stedet til at dele dine ideer, foretrukne podcast-øjeblikke og taknemmelighed til alle de frivillige:
+https://groups.google.com/forum/#!forum/antennapod + +Har du et spørgsmål eller vil du give os en tilbagemelding? +https://twitter.com/@AntennaPod + +Transifex er stedet, hvis du vil hjælpe med oversættelser:
+https://www.transifex.com/antennapod/antennapod + +Prøv vores beta-testprogram for at få de nyeste funktioner først:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/da-DK/listing/title b/app/src/main/play/da-DK/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/da-DK/listing/title +++ b/app/src/main/play/da-DK/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/da/listing/fulldescription b/app/src/main/play/da/listing/fulldescription deleted file mode 100644 index 241066fd4..000000000 --- a/app/src/main/play/da/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod er en app til håndtering og afspilning af podcasts. Den giver dig øjeblikkelig adgang til millioner af gratis og betalte podcasts, fra uafhængige podcastere til store udgivere som BBC, NPR, CNN og DR. Tilføj, importer og eksporter deres feeds problemfrit ved hjælp af iTunes-podcastdatabasen, OPML-filer eller enkle RSS-webadresser. Spar kræfter, batteristrøm og mobilt dataforbrug med kraftfulde automatiske styringsværktøjer til at hente udsendelser (angiv tidspunkter, tidsintervaller og udvalgte wi-fi-netværk) og sletning af episoder (baseret på dine foretrukne udsendelser og forsinkelsesindstillinger).
-Men vigtigst af alt: Hent, stream eller sæt udsendelser i kø og nyd dem på den måde du kan lide med justerbare hastigheder, kapitelunderstøttelse og en søvntimer. Du kan endda vise din påskønnelse over for indholdsskaberne med vores Flattr-integration. - -AntennaPod er lavet af en podcast-entusiast og er gratis og fri i alle betydninger: open source, ingen udgifter, ingen reklamer. - -Alle funktioner:
-IMPORTER, ORGANISER OG AFSPIL
-• Tilføj og importer feeds via iTunes- og gpodder.net-oversigterne, OPML-filer og RSS- eller Atom-links
-• Håndter afspilning fra hvor som helst: widget på startskærmen, systemnotifikation, samt hovedtelefon- og bluetooth-styring
-• Lyt på din egen måde med justerbar afspilningshastighed, kapitelunderstøttelse (MP3, VorbisComment og Podlove), erindring af afspilningsposition og en avanceret søvntimer (ryst for at nulstille, sænke lydstyrken og afspille langsommere)
-• Tilgå feeds og udsendelser beskyttet med adgangskode
-• Brug sideinddelte feeds (www.podlove.org/paged-feeds) - -HOLD STYR PÅ, DEL OG ANERKEND
-• Hold styr på det bedste af det bedste ved at markere udsendelser som foretrukne
-• Find en bestemt udsendelse via afspilningshistorikken eller ved at søge (titler og beskrivelser)
-• Del udsendelser og feeds via avancerede valgmuligheder for sociale medier, gpodder.net-tjenesterne og OPML-eksport
-• Støt indholdsskabere med Flattr-integration, inklusive automatisk flattring - -STYR SYSTEMET
-• Tag styring over automatiseret hentning: vælg feeds, udeluk mobile netværk, vælg specifikke wi-fi-netvæk, kræv at telefonen oplader og indstil tidspunkter eller tidsintervaller -• Håndter lagerforbruget ved at indstille antallet af udsendelser, der skal gemmes, smart sletning (baseret på dine foretrukne og afspilningsstatus) og ved at vælge den lagerplacering, du foretrækker
-• Brug AntennaPod på dit eget sprog (EN, DE, DA, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Tilpas appen til dit miljø med det lyse og mørke tema
-• Sikkerhedskopier dine abonnementer med gpodder.net-integrationen og OPML-eksport - -Bliv en del af AntennaPod-fællesskabet!
-AntennaPod er under aktiv udvikling af frivillige. Du kan også bidrage, med kode eller kommentarer! - -GitHub er stedet for forslag tli ny funktionalitet, fejlrapporter og kodebidrag:
-https://www.github.com/AntennaPod/AntennaPod - -Vores Google-gruppe er stedet til at dele dine ideer, foretrukne podcast-øjeblikke og taknemmelighed til alle de frivillige:
-https://groups.google.com/forum/#!forum/antennapod - -Har du et spørgsmål eller vil du give os en tilbagemelding? -https://twitter.com/@AntennaPod - -Transifex er stedet, hvis du vil hjælpe med oversættelser:
-https://www.transifex.com/antennapod/antennapod - -Prøv vores beta-testprogram for at få de nyeste funktioner først:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/de-DE/listing/fulldescription b/app/src/main/play/de-DE/listing/fulldescription index c2299c44f..0e09c5c29 100644 --- a/app/src/main/play/de-DE/listing/fulldescription +++ b/app/src/main/play/de-DE/listing/fulldescription @@ -1,20 +1,43 @@ -AntennaPod ist ein Open-Source Podcastmanager für Android 2.3.3+. Er bietet alle grundlegenden Funktionen, die Sie von einem Podcatcher erwarten. Dazu gehören das Streaming und Herunterladen von Episoden, alle Feeds automatisch zu aktualisieren oder sie einer Warteschlange hinzuzufügen, um sie später zu hören. Darüber hinaus können Sie mit AntennaPod Podcasts und Episoden aus der App heraus flattrn. +AntennaPod ist ein Podcast-Manager und -Player, der Dir unmittelbar Zugriff auf Millionen von freien und kostenpflichtigen Podcasts ermöglicht, angefangen von unabhängigen Podcastern bis hin zu großen Rundfunkanstalten wie BBC, NPR und CNN. Abonniere, importiere und exportiere deine Feeds mühelos mit Hilfe des iTunes-Verzeichnisses, OPML-Dateien oder einfachen RSS-URLs. Reduziere Aufwand, Stromverbrauch und Datenverbrauch durch die Kontrolle der Downloads (bestimmte Uhrzeiten, Intervalle, WiFi-Netze) und des Löschens von Episoden (basierend auf deinen Favoriten und weiteren Einstellungen).
+Aber am wichtigsten: Downloade, streame oder füge Episoden zur Abspielliste hinzu und genieße sie mit einstellbarer Abspielgeschwindigkeit, Unterstützung von Kapiteln und Schlummerfunktion. Mit Flattr kannst du den Podcastern sogar deine Wertschätzung zeigen. -Bisher sind folgende Funktionen eingebaut: +AntennaPod ist, von Podcast-Enthusiasten gemacht, frei im Sinne des Wortes: Open Source, keine Kosten, keine Werbung. -* Herunterladen und Streamen von Episoden -Variable Abspielgeschwindigkeit (benötigt Presto Sound Library oder Prestissimo) -* Unterstützung von Atom- und RSS-Feeds -* Unterstützung für Passwort-geschützte Feeds und Episoden -* Unterstützung für Auflistungen die in iTunes gesucht werden -* OPML-Import und -Export -* Flattr-Integration, einschließlich automatischem Flattrn -* Player-Homescreen-Widget -* Suche -* Automatische Feed-Aktualisierungen -* Automatisches Herunterladen von neuen Episoden -* Schlummerfunktion -* Zugang zum gpodder.net-Verzeichnis hinzugefügt -* Option zum Synchronisieren der Podcast-Abonnements mit dem gpodder.net-Service hinzugefügt -* Unterstützt Kapitelmarken in MP3 und VorbisComment, sowie Podlove Simple Chapters -* Unterstützt Paged Feeds (http://podlove.org/paged-feeds/) \ No newline at end of file +Alle Funktionen:
+IMPORTIERE, ORGANISIERE UND HÖRE
+• Importiere oder füge Feeds über das iTunes und gPodder.net Verzeichnis, OMPL Dateien und RSS oder Atom Links hinzu. +• Bediene die Wiedergabe von überall: Homescreen-Widget, Benachrichtigung und Koopfhörer- und Bluetooth-Bedienelementen
+• Genieße das Zuhören auf deine Art mit einstellbarer Abspielgeschwindigkeit, der Unterstützung von Kapiteln (MP3, OGG, Podlove) und ausgereifter Schlummerfunktion (durch Schütteln zurücksetzen, Lautstärke verringern und Geschwindigkeit verlangsamen) +• Greife auf Passwort-geschützte Feeds und Episoden zu
+• Nutze den Vorteil von Paged Feeds (http://www.podlove.org/paged-feeds) + +ORDNE, TEILE & GENIEßE +• Bleib an den Besten der Besten dran, indem Du Episoden als Favoriten markierst
+• Finde Episoden durch die Liste zuletzt gespielter Episoden oder durch Suche in Titel und Shownotes +• Teile Episoden and Feeds über soziale Medien, E-Mail, den gPodder.net-Dienst oder als OPML-Export +• Unterstütze die Autoren von Inhalten mit Flattr (inklusive automatischem Flattren) + +STEUER DAS SYSTEM
+• Kontrolliere automatisches Herunterladen: Wähle Feeds aus, schließe mobile Netze aus, suche bestimmte WiFi-Netze aus, setze voraus, dass das Smartphone geladen wird und lege Zeitpunkte oder Intervalle fest
+• Verwalte deinen Speicherplatz durch das Festlegen der Anzahl gespeicherter Episoden, schlaues Löschen und durch Auswahl des Speicherortes
+• Benutze AntennaPod in deiner Sprache (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
+• Passe das Aussehen mit dem hellen oder dunklen Theme an
+• Sichere deine Abonnements mit gPodder.net oder über den OPML-Export + +Tritt der AntennaPod-Community bei!
+AntennaPod wird aktiv von Freiwilligen weiterentwickelt. Auch du kannst bei der Entwicklung mit Quellcode oder Kommentaren mitwirken! + +Wir verwenden GitHub für Funktionswünsche (Feature Requests), Fehlerberichte (Bug Reports) und zum Beisteuern von Code (Code Contributions). +https://www.github.com/AntennaPod/AntennaPod + +Teile deine Idee und Lieblingspodcastmomente und äußere Deine Dankbarkeit gegenüber allen Freiwilligen in unserer Google Group:
+https://groups.google.com/forum/#!forum/antennapod (Englisch) + +Du hast eine Frage oder willst uns Feedback geben? +https://twitter.com/@AntennaPod + +Mit Transifex kannst du uns beim Übersetzen helfen:
+https://www.transifex.com/antennapod/antennapod + +Probiere unser Beta-Testing-Programm aus, um die neusten Funktionen als Erster zu erhalten:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/de-DE/listing/title b/app/src/main/play/de-DE/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/de-DE/listing/title +++ b/app/src/main/play/de-DE/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/de/listing/fulldescription b/app/src/main/play/de/listing/fulldescription deleted file mode 100644 index e5d7ec72a..000000000 --- a/app/src/main/play/de/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod ist ein Podcast-Manager und -Player, der Dir unmittelbar Zugriff auf Millionen von freien und bezahlten Podcasts ermöglicht, angefangen von unabhängigen Podcastern zu großen Rundfunkanstalten oder Hörfunksendern wie BBC, NPR und CNN. Abonniere, importiere und exportiere deine Feeds mühelos mit Hilfe des iTunes-Verzeichnisses, OPML-Dateien oder einfachen RSS-URLs. Reduziere Aufwand, Stromverbrauch und Datenverbrauch durch die Kontrolle der Downloads (bestimmte Uhrzeiten, Intervalle, WiFi-Netze) und des Löschens von Episoden (basierend auf deinen Favoriten und weiteren Einstellungen).
-Aber am wichtigsten: Downloade, streame oder füge Episoden zur Abspielliste hinzu und genieße sie mit einstellbarer Abspielgeschwindigkeit, Unterstützung von Kapiteln und Schlummerfunktion. Mit Flattr kannst du den Podcastern sogar deine Wertschätzung zeigen. - -AntennaPod ist, von Podcast-Enthusiasten gemacht, frei im Sinne des Wortes: Open Source, keine Kosten, keine Werbung. - -Alle Funktionen:
-IMPORTIERE, ORGANISIERE UND HÖRE
-• Importiere oder füge Feeds über das iTunes und gPodder.net Verzeichnis, OMPL Dateien und RSS oder Atom Links hinzu. -• Bediene die Wiedergabe von überall: Homescreen-Widget, Benachrichtigung und Koopfhörer- und Bluetooth-Bedienelementen
-• Genieße das Zuhören auf deine Art mit einstellbarer Abspielgeschwindigkeit, der Unterstützung von Kapiteln (MP3, OGG, Podlove) und ausgereifter Schlummerfunktion (durch Schütteln zurücksetzen, Lautstärke verringern und Geschwindigkeit verlangsamen) -• Greife auf Passwort-geschützte Feeds und Episoden zu
-• Nutze den Vorteil von Paged Feeds (http://www.podlove.org/paged-feeds) - -ORDNE, TEILE & GENIEßE -• Bleib an den Besten der Besten dran, indem Du Episoden als Favoriten markierst
-• Finde Episoden durch die Liste zuletzt gespielter Episoden oder durch Suche in Titel und Shownotes -• Teile Episoden and Feeds über soziale Medien, E-Mail, den gPodder.net-Dienst oder als OPML-Export -• Unterstütze die Autoren von Inhalten mit Flattr (inklusive automatischem Flattren) - -STEUER DAS SYSTEM
-• Kontrolliere automatisches Herunterladen: Wähle Feeds aus, schließe mobile Netze aus, suche bestimmte WiFi-Netze aus, setze voraus, dass das Smartphone geladen wird und lege Zeitpunkte oder Intervalle fest
-• Verwalte deinen Speicherplatz durch das Festlegen der Anzahl gespeicherter Episoden, schlaues Löschen und durch Auswahl des Speicherortes
-• Benutze AntennaPod in deiner Sprache (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Passe das Aussehen mit dem hellen oder dunklen Theme an
-• Sichere deine Abonnements mit gPodder.net oder über den OPML-Export - -Trete der AntennaPod-Community bei!
-AntennaPod wird aktiv von Freiwilligen weiterentwickelt. Auch du kannst bei der Entwicklung mit Quellcode oder Kommentaren mitwirken! - -Wir verwenden GitHub für Funktionswünsche (Feature Requests), Fehlerberichte (Bug Reports) und zum Beisteuern von Code (Code Contributions). -https://www.github.com/AntennaPod/AntennaPod - -Teile deine Idee und Lieblingspodcastmomente und äußere Deine Dankbarkeit gegenüber allen Freiwilligen in unserer Google Group:
-https://groups.google.com/forum/#!forum/antennapod (Englisch) - -Du hast eine Frage oder willst uns Feedback geben? -https://twitter.com/@AntennaPod - -Mit Transifex kannst du uns beim Übersetzen helfen:
-https://www.transifex.com/antennapod/antennapod - -Probiere unser Beta-Testing-Programm aus, um die neusten Funktionen als Erster zu erhalten:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/el-GR/listing/fulldescription b/app/src/main/play/el-GR/listing/fulldescription new file mode 100644 index 000000000..f0ec3ae38 --- /dev/null +++ b/app/src/main/play/el-GR/listing/fulldescription @@ -0,0 +1,43 @@ +Το Antennapod είναι μία εφαρμογή διαχείρισης και εκτέλεσης podcasts που σας δίνει άμεση πρόσβαση σε εκατομμύρια δωρεάν και επί πληρωμή podcasts, από ανεξάρτητους podcasters έως μεγάλους εκδοτικούς οίκους όπως το BBC, NPR και CNN. Μπορείτε εύκολα να προσθέσετε, να εισάγετε και να εξάγετε τις ροές τους χρησιμοποιώντας τη βάση δεδομένων podcast του iTunes, αρχεία OPML ή απλά RSS URLs. Γλυτώστε προσπάθεια, μπαταρία και χρήση δεδομένων κινητής τηλεφωνίας με ισχυρές ρυθμίσεις αυτοματισμών για λήψη επεισοδίων (ορίστε τους χρόνους, τα διαστήματα και τα δίκτυα WiFi) και σβήστε επεισόδια (με βάση τα αγαπημένα σας και τις ρυθμίσεις καθυστέρησης).
+Αλλά το πλέον σημαντικό: Κατεβάστε, κάντε stream ή βάλτε στη σειρά επεισόδια και απολαύστε τα όπως επιθυμήτε με ρυθμιζόμενη ταχύτητα αναπαραγωγής, υποστήριξη κεφάλαιων και χρονόμετρο απενεργοποίησης. Μπορείτε ακόμη και να δείξετε την αγάπη σας στους δημιουργούς περιεχομένου μέσω της ενσωμάτωσης του Flattr. + +Φτιαγμένο από λάτρη των podcast, το AntennaPod είναι ελεύθερο με όλες τις έννοιες της λέξης: ανοικτού λογισμικού, χωρίς κόστη, χωρίς διαφημίσεις. + +Όλα τα χαρακτηριστικά:
+ΕΙΣΑΓΩΓΉ, ΟΡΓΆΝΩΣΗ ΚΑΙ ΕΚΤΈΛΕΣΗ
+• Προσθέστε και εισάγετε ροές μέσω των φακέλων του iTunes και του gPodder.net, αρχείων OPML και RSS ή συνδέσμους Atom
+• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
+• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
+• Access password-protected feeds and episodes
+• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE
+• Keep track of the best of the best by marking episodes as favourites
+• Find that one episode through the playback history or by searching (titles and shownotes)
+• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
+• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM
+• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
+• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
+• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
+• Adapt to your environment using the light and dark theme
+• Back-up your subscriptions with the gPodder.net integration and OPML export + +Ενταχθείτε στη κοινότητα του AntennaPod!
+Το AntennaPod βρίσκεται υπό ενεργή ανάπτυξη από εθελοντές. Μπορείτε και εσείς να συνεισφέρετε, με κώδικα ή με κάποιο σχόλιο. + +Το Github είναι το μέρος να επισκεφθείτε για να ζητήσετε καινούρια χαρακτηριστικά, να αναφέρετε σφάλματα και για συνεισφορά κώδικα:
+https://www.github.com/AntennaPod/AntennaPod + +Το Google Group μας είναι το μέρος να μοιραστείτε τις ιδέες σας, τις αγαπημένες σας στιγμές ενασχόλησης με τα podcasts και ευγνωμοσύνη σε όλους τους εθελοντές:
+https://groups.google.com/forum/#!forum/antennapod + +Έχετε κάποια ερώτηση ή θέλετε να μας δώσετε κάποια ανατροφοδότηση; +https://twitter.com/@AntennaPod + +Το Transifex είναι το μέρος για να βοηθήσετε με τις μεταφράσεις:
+https://www.transifex.com/antennapod/antennapod + +Ελέγξτε το πρόγραμμά μας Beta Testing για να λαμβάνετε τα τελευταία χαρακτηριστικά πρώτοι:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/el-GR/listing/shortdescription b/app/src/main/play/el-GR/listing/shortdescription new file mode 100644 index 000000000..7afb5a62d --- /dev/null +++ b/app/src/main/play/el-GR/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast & radio manager and player \ No newline at end of file diff --git a/app/src/main/play/el-GR/listing/title b/app/src/main/play/el-GR/listing/title new file mode 100644 index 000000000..6c7c64cfc --- /dev/null +++ b/app/src/main/play/el-GR/listing/title @@ -0,0 +1 @@ +AntennaPod diff --git a/app/src/main/play/el/listing/fulldescription b/app/src/main/play/el/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/el/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/en-US/listing/fulldescription b/app/src/main/play/en-US/listing/fulldescription index 87b477fdc..2f5b4b2ff 100644 --- a/app/src/main/play/en-US/listing/fulldescription +++ b/app/src/main/play/en-US/listing/fulldescription @@ -1,4 +1,4 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
+AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based on your favourites and delay settings).
But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. @@ -40,4 +40,4 @@ Transifex is the place to help with translations:
https://www.transifex.com/antennapod/antennapod Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod diff --git a/app/src/main/play/en-US/listing/shortdescription b/app/src/main/play/en-US/listing/shortdescription index 7afb5a62d..acf136ae9 100644 --- a/app/src/main/play/en-US/listing/shortdescription +++ b/app/src/main/play/en-US/listing/shortdescription @@ -1 +1 @@ -Easy-to-use, flexible and open-source podcast & radio manager and player \ No newline at end of file +Easy-to-use, flexible and open-source podcast manager and player diff --git a/app/src/main/play/es-ES/listing/fulldescription b/app/src/main/play/es-ES/listing/fulldescription index 5cc6c5bf5..b1a87b434 100644 --- a/app/src/main/play/es-ES/listing/fulldescription +++ b/app/src/main/play/es-ES/listing/fulldescription @@ -1,40 +1,43 @@ -AntennaPod is un gestor y reproductor de podcast que te da acceso instantáneo a millones de podcast gratuitos y de pago, desde podcasters independientes a grandes estaciones como la BBC, NPR y CNN. Agrega, importa y exporta las fuentes de manera sencilla usando el listado de iTunes, archivos OPML o las URL de tipo RSS. Ahorra esfuerzo, batería y datos con los controles de descarga (a horas o intervalos específicos, o redes WiFi) y de borrado de episodios (basado en favoritos y ajustes de tiempo).
-Y lo más importante: descarga, escucha en stream y disfrutalos como quieras con velocidad de reproducción variable, soporte para capítulos y temporizador de sueño. Incluso puedes mostrar tu gratitud a los creadores de contenido mediante Flattr. +AntennaPod es un administrador y reproductor de pódcast que te da acceso instantáneo a millones de pódcast gratuitos y de pago, desde editores independientes a grandes editoriales como la BBC, NPR y CNN. Agrega, importa y exporta tus fuentes sin complicaciones usando la base de datos de pódcast de iTunes, archivos OPML o las URL de tipo RSS. Ahorra esfuerzo, energía de la batería y uso de datos móviles con potentes controles de automatización para descargar episodios (especifica horarios, intervalos y redes wifi) y elimina episodios (según tus favoritos y la configuración de retardo).
+Y lo más importante: descarga, escucha en continuo o pon en cola los episodios y disfrútalos como quieras con velocidades de reproducción ajustables, soporte de capítulos y temporizador de apagado. Incluso puedes mostrar tu gratitud a los creadores de contenido mediante Flattr. -Hecho por entusiastas del podcasting, AntennaPod es libre, gratuito y sin publicidad. +Creado por entusiastas del pódcast, AntennaPod es libre en todos los sentidos: código abierto, gratuito y sin publicidad. -Características:
+Todas las características:
IMPORTAR, ORGANIZAR Y REPRODUCIR
-• Añadir e importar feeds mediante los directorios iTunes o gPodder.net, archivos OPML y los enlaces RSS y Atom
-• Gestiona la reproducción desde cualquier parte: widget, notificación del sistema y controles de auricular y bluetooth
-• Disfruta escuchando a tu manera ajustando la velocidad de reproducción, con soporte para capítulos (MP3, VorbisComment y Podlove), recordando la posición de reproducción y un temporizador de sueño (agita para reiniciar, bajada de volumen y ralentización)
-• Accede a feeds y episodios protegidos con contraseña
-• Accede a feeds paginados (www.podlove.org/paged-feeds) +• Añade e importa fuentes mediante los directorios de iTunes y gPodder.net, archivos OPML y enlaces RSS o Atom
+• Administra la reproducción desde cualquier parte: control en pantalla de inicio, notificación del sistema y controles de auricular y bluetooth
+• Disfruta escuchando a tu manera con velocidad de reproducción ajustable, soporte de capítulos (MP3, VorbisComment y Podlove), recordatorio del punto de reproducción y el temporizador de sueño avanzado (agita para restablecer, bajar el volumen y disminuir la velocidad de reproducción)
+• Accede a fuentes y episodios protegidos con contraseña
+• Aprovecha las fuentes paginadas (www.podlove.org/paged-feeds) -RECUERDA, COMPARTE Y APRECIA -• Ten localizado lo mejor de lo mejor marcando episodios como favoritos
-• Encuentra ese episodio consultando el histórico o buscándolo (por título o por notas de episodio)
-• Comparte episodios feeds con opciones avanzadas de redes sociales, email, servicios gPodder.net y exportación OPML
-• Ayuda a los creadores de contenido con la integración Flatter, siendo posible hacer Flattr automático +MANTÉN UN SEGUIMIENTO, COMPARTE Y APRECIA +• Haz un seguimiento de lo mejor de lo mejor marcando episodios como favoritos
+• Encuentra ese episodio a través del historial de reproducción o por búsqueda (títulos y notas de episodios)
+• Comparte episodios y fuentes a través de las avanzadas redes sociales y opciones de correo electrónico, los servicios de gPodder.net y la exportación OPML
+• Ayuda a los creadores de contenido con la integración de Flattr, incluso automáticamente CONTROLA EL SISTEMA
-• Toma el control de la descarga automática: elige los feeds, excluye las redes móviles, elige redes WiFi específicas, hazlo sólo si el teléfono está cargando o a ciertas horas o intervalos
-• Gestiona el almacenamiento configurando la cantidad de episodios en caché, configura borrado inteligente (basado en favoritos y el estado de reproducción) y eligiendo tu ubicación favorita
+• Controla las descargas automáticas: elige las fuentes, excluye las redes móviles, selecciona redes wifi específicas, o solo cuando el teléfono se esté cargando y establece horarios o intervalos
+• Administra el almacenamiento configurando la cantidad de episodios almacenados, el borrado inteligente (según tus favoritos y el estado de reproducción) y selecciona tu ubicación preferida
• Usa AntennaPod en tu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
• Adáptate a tu entorno usando el tema claro u oscuro
-• Haz backup de tus suscripciones usando gPodder.net o exportando a OPML +• Haz una copia de seguridad de tus suscripciones con la integración de gPodder.net y la exportación OPML ¡Únete a la comunidad AntennaPod!
AntennaPod está en continuo desarrollo por voluntarios. ¡Tú también puedes contribuir, con tu código o con tus comentarios! GitHub es el sitio que debes visitar para solicitar características nuevas, reportar fallos y contribuir con código
-www.github.com/AntennaPod/AntennaPod +https://www.github.com/AntennaPod/AntennaPod -Nuestro Grupo de Google es el sitio para compartir tus ideas, tus momentos favoritos de podcasting y tu gratitud a los voluntarios:
+Nuestro Grupo de Google es el sitio para compartir tus ideas, momentos favoritos de tus pódcast y tu gratitud a los voluntarios:
https://groups.google.com/forum/#!forum/antennapod -Transifex es el sitio para ayudar con las traducciones:
-www.transifex.com/antennapod/antennapod +¿Tienes una pregunta o quieres darnos tu opinión? +https://twitter.com/@AntennaPod -Echa un vistazo a nuestro programa de Beta Testing para ser el primero en usar las nuevas características:
-www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file +Transifex es el sitio para ayudar con las traducciones:
+https://www.transifex.com/antennapod/antennapod + +Echa un vistazo a nuestro programa de pruebas Beta y ser el primero en usar las nuevas características:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/es-ES/listing/shortdescription b/app/src/main/play/es-ES/listing/shortdescription index e5b6ace85..37723ed99 100644 --- a/app/src/main/play/es-ES/listing/shortdescription +++ b/app/src/main/play/es-ES/listing/shortdescription @@ -1 +1 @@ -Reproductor y gestor de podcast de código abierto, flexible y fácil de usar \ No newline at end of file +Gestor y reproductor de radio y pódcast fácil, flexible y de código abierto \ No newline at end of file diff --git a/app/src/main/play/es-ES/listing/title b/app/src/main/play/es-ES/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/es-ES/listing/title +++ b/app/src/main/play/es-ES/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/es/listing/fulldescription b/app/src/main/play/es/listing/fulldescription deleted file mode 100644 index 2f1c8861a..000000000 --- a/app/src/main/play/es/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is un gestor y reproductor de podcast que te da acceso instantáneo a millones de podcast gratuitos y de pago, desde podcasters independientes a grandes estaciones como la BBC, NPR y CNN. Agrega, importa y exporta las fuentes de manera sencilla usando el listado de iTunes, archivos OPML o las URL de tipo RSS. Ahorra esfuerzo, batería y datos con los controles de descarga (a horas o intervalos específicos, o redes WiFi) y de borrado de episodios (basado en favoritos y ajustes de tiempo).
-Y lo más importante: descarga, escucha en stream y disfrutalos como quieras con velocidad de reproducción variable, soporte para capítulos y temporizador de sueño. Incluso puedes mostrar tu gratitud a los creadores de contenido mediante Flattr. - -Hecho por entusiastas del podcasting, AntennaPod es libre, gratuito y sin publicidad. - -Características:
-IMPORTAR, ORGANIZAR Y REPRODUCIR
-• Añadir e importar feeds mediante los directorios iTunes o gPodder.net, archivos OPML y los enlaces RSS y Atom
-• Gestiona la reproducción desde cualquier parte: widget, notificación del sistema y controles de auricular y bluetooth
-• Disfruta escuchando a tu manera ajustando la velocidad de reproducción, con soporte para capítulos (MP3, VorbisComment y Podlove), recordando la posición de reproducción y un temporizador de sueño (agita para reiniciar, bajada de volumen y ralentización)
-• Accede a feeds y episodios protegidos con contraseña
-• Accede a feeds paginados (www.podlove.org/paged-feeds) - -RECUERDA, COMPARTE Y APRECIA -• Ten localizado lo mejor de lo mejor marcando episodios como favoritos
-• Encuentra ese episodio consultando el histórico o buscándolo (por título o por notas de episodio)
-• Comparte episodios feeds con opciones avanzadas de redes sociales, email, servicios gPodder.net y exportación OPML
-• Ayuda a los creadores de contenido con la integración Flatter, siendo posible hacer Flattr automático - -CONTROLA EL SISTEMA
-• Toma el control de la descarga automática: elige los feeds, excluye las redes móviles, elige redes WiFi específicas, hazlo sólo si el teléfono está cargando o a ciertas horas o intervalos
-• Gestiona el almacenamiento configurando la cantidad de episodios en caché, configura borrado inteligente (basado en favoritos y el estado de reproducción) y eligiendo tu ubicación favorita
-• Usa AntennaPod en tu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adáptate a tu entorno usando el tema claro u oscuro
-• Haz backup de tus suscripciones usando gPodder.net o exportando a OPML - -¡Únete a la comunidad AntennaPod!
-AntennaPod está en continuo desarrollo por voluntarios. ¡Tú también puedes contribuir, con tu código o con tus comentarios! - -GitHub es el sitio que debes visitar para solicitar características nuevas, reportar fallos y contribuir con código
-https://www.github.com/AntennaPod/AntennaPod - -Nuestro Grupo de Google es el sitio para compartir tus ideas, tus momentos favoritos de podcasting y tu gratitud a los voluntarios:
-https://groups.google.com/forum/#!forum/antennapod - -¿Tienes una pregunta o quieres darnos tu opinión? -https://twitter.com/@AntennaPod - -Transifex es el sitio para ayudar con las traducciones:
-https://www.transifex.com/antennapod/antennapod - -Echa un vistazo a nuestro programa de Beta Testing para ser el primero en usar las nuevas características:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/es_ES/listing/fulldescription b/app/src/main/play/es_ES/listing/fulldescription deleted file mode 100644 index 1ce12e3b4..000000000 --- a/app/src/main/play/es_ES/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -¡Únete a la comunidad de AntennaPod!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/et/listing/shortdescription b/app/src/main/play/et/listing/shortdescription new file mode 100644 index 000000000..7afb5a62d --- /dev/null +++ b/app/src/main/play/et/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast & radio manager and player \ No newline at end of file diff --git a/app/src/main/play/et/listing/title b/app/src/main/play/et/listing/title new file mode 100644 index 000000000..6c7c64cfc --- /dev/null +++ b/app/src/main/play/et/listing/title @@ -0,0 +1 @@ +AntennaPod diff --git a/app/src/main/play/fa/listing/shortdescription b/app/src/main/play/fa/listing/shortdescription new file mode 100644 index 000000000..7afb5a62d --- /dev/null +++ b/app/src/main/play/fa/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast & radio manager and player \ No newline at end of file diff --git a/app/src/main/play/fa/listing/title b/app/src/main/play/fa/listing/title new file mode 100644 index 000000000..6c7c64cfc --- /dev/null +++ b/app/src/main/play/fa/listing/title @@ -0,0 +1 @@ +AntennaPod diff --git a/app/src/main/play/fi/listing/fulldescription b/app/src/main/play/fi/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/fi/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/fr-FR/listing/fulldescription b/app/src/main/play/fr-FR/listing/fulldescription index 61177b28a..372e1da60 100644 --- a/app/src/main/play/fr-FR/listing/fulldescription +++ b/app/src/main/play/fr-FR/listing/fulldescription @@ -1,40 +1,43 @@ -AntennaPod est un lecteur et gestionnaire de podcast permettant l'accès à des millions de podcast gratuits ou payants produit aussi bien par des podcasters indépendants que de gros éditeurs comme la BBC, NPR ou CNN. Ajoutez, importez et exportez leurs flux facilement à partir d'ITunes, de fichiers OPML ou simplement à partir de liens RSS. Économisez votre temps, votre batterie et votre consommation internet grâce à une automatisation puissante des téléchargements (quand, à quel rythme et à partir de quel réseau wifi) et de la suppression des épisodes (à partir d'un certains temps ou des favoris)
-Encore plus important : téléchargez, streamez ou mettez dans votre liste de lecture vos épisodes et écoutez les à votre manière grâce à une vitesse de lecture réglable, au support des chapitres et une fonction de mise en veille automatique. Vous pouvez même montrer votre appréciation aux créateurs de contenu avec notre intégration de Flattr. +AntennaPod est un lecteur et gestionnaire de podcast permettant l'accès à des millions de podcast gratuits ou payants produit aussi bien par des podcasters indépendants que de gros éditeurs comme la BBC, NPR ou CNN. Ajoutez, importez et exportez leurs flux facilement à partir d'ITunes, de fichiers OPML ou simplement à partir de liens RSS. Gagnez du temps, préservez votre batterie et consommation internet grâce à une automatisation puissante des téléchargements (date, fréquence, choix du réseau WiFi, etc...) et des suppressions d’épisodes écoutés (selon vos critères)
+Avant tout : téléchargez, streamez ou ajoutez à la liste de lecture vos épisodes et écoutez les comme vous voulez grâce au réglage de vitesse de lecture, au support des chapitres et au minuteur d'arrêt. Vous pouvez même montrer votre appréciation aux créateurs de contenu avec notre intégration de Flattr. -Programmé par des fans de podcast, AntennaPod est gratuit dans tous les sens du terme : open source, aucun cout et pas de publicité. +Conçu par des fans de podcast, AntennaPod est gratuit dans tous les sens du terme : open source, gratuit et sans publicité. Caractéristiques complètes :
-Importer, gérer et écouter
-• Ajouter et importer à partir d'iTunes, gPodder.net, de fichiers OPML ou de liens RSS ou Atom
-• Gérez la lecture de n'importe où : widget sur l'écran d'accueil, notification système, commande casque ou bluetooth
-• Ecoutez à votre façon grâce à une vitesse de lecture réglable, au support des chapitres (MP3, VorbisComment et Podlove), enregistrement de la position de lecture et une mise en veille automatique puissante (secouer pour prolonger le minuteur, baisse du volume et ralentissement de la lecture)
+IMPORTER, GÉRER ET ÉCOUTER
+• Ajouter et importer à partir d'iTunes, gPodder.net, fichiers OPML, liens RSS ou Atom
+• Gérez la lecture de n'importe où : widget sur l'écran d'accueil, notification système, commande casque ou Bluetooth
+• Écoutez à votre façon grâce à une vitesse de lecture réglable, au support des chapitres (MP3, VorbisComment et Podlove), à l'enregistrement de la position de lecture et à une mise en veille automatique puissante (secouez pour prolonger le minuteur, baisser le volume et ralentir la lecture)
• Accès aux flux et épisodes protégés par mot de passe
-• Tirez profit des flux à plusieurs pages (www.podlove.org/paged-feeds) +• Tirez profit des flux paginés (www.podlove.org/paged-feeds) -GARDEZ TRACE, PARTAGEZ & APPRECIEZ
-• Gardez trace des meilleurs épisodes en les marquant comme favoris
-• Retrouvez un épisode à partir de l'historique de lecture ou en cherchant (les titres et les commentaires des épisodes)
-• Partagez vos épisodes ou flux à travers des options de réseaux sociaux et email avancées, du service gPodder.net ou par des exports OPML
+SUIVEZ, PARTAGEZ & PROFITEZ
+• Marquer les meilleurs épisodes en tant que favoris
+• Retrouvez un épisode à partir de l'historique de lecture ou en recherchant parmi les titres et commentaires des épisodes précédents
+• Partagez vos épisodes et flux sur les réseaux sociaux, par email, sur gPodder.net ou en les exportant au format OPML
• Soutenez les créateurs de contenu avec l'intégration à Flattr et la possibilité de flatter automatiquement CONTRÔLER LE SYSTÈME
-• Prenez le contrôle avec l'automatisation des téléchargements : choisissez les flux, empêchez l'utilisation du réseau mobile, sélectionnez les réseaux WIFI à utiliser, exigez que le téléphone soit en train de charger et spécifiez quand ou à quel rythme
-• Gérez l'espace de stockage en paramétrant le nombre d'épisodes à garder, de leurs suppressions automatique (à partir de vos favoris et du statut de lecture) et de l'emplacement où les enregistrer
+• Prenez le contrôle en automatisant vos téléchargements : choix des flux, restriction de la connexion mobile, sélection du réseau WIFI à utiliser, uniquement durant la recharge et spécifiez la fréquence de mise à jour vous-même
+• Gérez l'espace de stockage en paramétrant le nombre d'épisodes à garder, leur suppression automatique (en fonction de vos favoris et de leur statut) et leur emplacement sur le disque
• Utilisez AntennaPod dans votre langue (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adaptez à votre environnement avec un thème clair ou sombre
-• Sauvegardez vos abonnements avec l'intération à gPodder.net ou des exports OPML +• Choix d'un thème clair ou sombre selon vos préférences
+• Sauvegardez vos abonnements avec l’intégration à gPodder.net et les exports OPML Rejoignez la communauté d'AntennaPod !
-AntennaPod est développé activement par des volontaires. Vous pouvez aussi contribuer avec du code ou des commentaires ! +AntennaPod est développé activement par des volontaires. Vous pouvez aussi contribuer avec du code, des traductions ou des commentaires ! GitHub est l'endroit où aller pour demander de nouvelles options, faire part de bug ou pour contribuer au code :
-www.github.com/AntennaPod/AntennaPod +https://www.github.com/AntennaPod/AntennaPod -Notre groupe Google est l'endroit où aller pour partager vos idées, moments préférés de podcast et vos remerciements aux volontaires :
+Rejoignez notre Google Group pour partager vos idées, podcast préférés et vos remerciements à tous les bénévoles :
https://groups.google.com/forum/#!forum/antennapod -Transifex est le lieu où vous pouvez aider à la traduction :
-www.transifex.com/antennapod/antennapod +Vous avez une question ou des suggestions ? +https://twitter.com/@AntennaPod + +Retrouvez nous sur Transifex pour contribuer à la traduction de cette app :
+https://www.transifex.com/antennapod/antennapod Jetez un coup d’œil à notre programme de version Beta pour bénéficier des dernières options :
-www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/fr-FR/listing/shortdescription b/app/src/main/play/fr-FR/listing/shortdescription index 61c3c7e20..93944d272 100644 --- a/app/src/main/play/fr-FR/listing/shortdescription +++ b/app/src/main/play/fr-FR/listing/shortdescription @@ -1 +1 @@ -Un lecteur et gestionnaire de podcast facile à utiliser et flexible \ No newline at end of file +Un lecteur de podcast simple et flexible \ No newline at end of file diff --git a/app/src/main/play/fr-FR/listing/title b/app/src/main/play/fr-FR/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/fr-FR/listing/title +++ b/app/src/main/play/fr-FR/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/fr/listing/fulldescription b/app/src/main/play/fr/listing/fulldescription deleted file mode 100644 index 372e1da60..000000000 --- a/app/src/main/play/fr/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod est un lecteur et gestionnaire de podcast permettant l'accès à des millions de podcast gratuits ou payants produit aussi bien par des podcasters indépendants que de gros éditeurs comme la BBC, NPR ou CNN. Ajoutez, importez et exportez leurs flux facilement à partir d'ITunes, de fichiers OPML ou simplement à partir de liens RSS. Gagnez du temps, préservez votre batterie et consommation internet grâce à une automatisation puissante des téléchargements (date, fréquence, choix du réseau WiFi, etc...) et des suppressions d’épisodes écoutés (selon vos critères)
-Avant tout : téléchargez, streamez ou ajoutez à la liste de lecture vos épisodes et écoutez les comme vous voulez grâce au réglage de vitesse de lecture, au support des chapitres et au minuteur d'arrêt. Vous pouvez même montrer votre appréciation aux créateurs de contenu avec notre intégration de Flattr. - -Conçu par des fans de podcast, AntennaPod est gratuit dans tous les sens du terme : open source, gratuit et sans publicité. - -Caractéristiques complètes :
-IMPORTER, GÉRER ET ÉCOUTER
-• Ajouter et importer à partir d'iTunes, gPodder.net, fichiers OPML, liens RSS ou Atom
-• Gérez la lecture de n'importe où : widget sur l'écran d'accueil, notification système, commande casque ou Bluetooth
-• Écoutez à votre façon grâce à une vitesse de lecture réglable, au support des chapitres (MP3, VorbisComment et Podlove), à l'enregistrement de la position de lecture et à une mise en veille automatique puissante (secouez pour prolonger le minuteur, baisser le volume et ralentir la lecture)
-• Accès aux flux et épisodes protégés par mot de passe
-• Tirez profit des flux paginés (www.podlove.org/paged-feeds) - -SUIVEZ, PARTAGEZ & PROFITEZ
-• Marquer les meilleurs épisodes en tant que favoris
-• Retrouvez un épisode à partir de l'historique de lecture ou en recherchant parmi les titres et commentaires des épisodes précédents
-• Partagez vos épisodes et flux sur les réseaux sociaux, par email, sur gPodder.net ou en les exportant au format OPML
-• Soutenez les créateurs de contenu avec l'intégration à Flattr et la possibilité de flatter automatiquement - -CONTRÔLER LE SYSTÈME
-• Prenez le contrôle en automatisant vos téléchargements : choix des flux, restriction de la connexion mobile, sélection du réseau WIFI à utiliser, uniquement durant la recharge et spécifiez la fréquence de mise à jour vous-même
-• Gérez l'espace de stockage en paramétrant le nombre d'épisodes à garder, leur suppression automatique (en fonction de vos favoris et de leur statut) et leur emplacement sur le disque
-• Utilisez AntennaPod dans votre langue (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Choix d'un thème clair ou sombre selon vos préférences
-• Sauvegardez vos abonnements avec l’intégration à gPodder.net et les exports OPML - -Rejoignez la communauté d'AntennaPod !
-AntennaPod est développé activement par des volontaires. Vous pouvez aussi contribuer avec du code, des traductions ou des commentaires ! - -GitHub est l'endroit où aller pour demander de nouvelles options, faire part de bug ou pour contribuer au code :
-https://www.github.com/AntennaPod/AntennaPod - -Rejoignez notre Google Group pour partager vos idées, podcast préférés et vos remerciements à tous les bénévoles :
-https://groups.google.com/forum/#!forum/antennapod - -Vous avez une question ou des suggestions ? -https://twitter.com/@AntennaPod - -Retrouvez nous sur Transifex pour contribuer à la traduction de cette app :
-https://www.transifex.com/antennapod/antennapod - -Jetez un coup d’œil à notre programme de version Beta pour bénéficier des dernières options :
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/gl/listing/fulldescription b/app/src/main/play/gl-ES/listing/fulldescription similarity index 100% rename from app/src/main/play/gl/listing/fulldescription rename to app/src/main/play/gl-ES/listing/fulldescription diff --git a/app/src/main/play/gl-ES/listing/shortdescription b/app/src/main/play/gl-ES/listing/shortdescription new file mode 100644 index 000000000..9b18a10fc --- /dev/null +++ b/app/src/main/play/gl-ES/listing/shortdescription @@ -0,0 +1 @@ +Xestor/Reprodutor de podcast e radio doado de usar, flexible e de fontes abertas \ No newline at end of file diff --git a/app/src/main/play/gl-ES/listing/title b/app/src/main/play/gl-ES/listing/title new file mode 100644 index 000000000..6c7c64cfc --- /dev/null +++ b/app/src/main/play/gl-ES/listing/title @@ -0,0 +1 @@ +AntennaPod diff --git a/app/src/main/play/he_IL/listing/fulldescription b/app/src/main/play/he_IL/listing/fulldescription deleted file mode 100644 index b4ac8ca6c..000000000 --- a/app/src/main/play/he_IL/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -מיוצרת על ידי חובבי פודקאסטים, אנטנהפוד הינה תוכנה חינמית בכל מובן המילה: קוד פתוח, ללא עלות וללא פרסומות. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/hi-IN/listing/fulldescription b/app/src/main/play/hi-IN/listing/fulldescription index f4687b885..c4d6594b9 100644 --- a/app/src/main/play/hi-IN/listing/fulldescription +++ b/app/src/main/play/hi-IN/listing/fulldescription @@ -1,20 +1,43 @@ -ऐन्टेनापॉड एंड्रॉयड 2.3.3 और ऊपर के लिए एक खुला स्रोत पॉडकास्ट प्रबंधक है. यह आपको स्वचालित रूप से सभी फ़ीड ताज़ा या बाद में उन्हें सुनने के लिए एक कतार में जोड़ने, एपिसोड स्ट्रीमिंग और डाउनलोड करने, एक पॉडकैचर से उम्मीद रखने वाली सभी बुनियादी सुविधाएँ प्रदान करता है. इसके अलावा, ऐन्टेनापॉड आपको अनुप्रयोग के भीतर से फ्लेटर पॉडकास्ट और प्रकरणों की सुविधा देता है. +एन्टेनापॉड एक पॉडकास्ट मेनेजर और प्लेयर है जो आपको स्वतंत्र पॉडकास्टर्स से लेकर बीबीसी, एनपीआर और सीएनएन जैसे बड़े पब्लिशिंग घरों के लाखों मुफ्त और भुगतान पॉडकास्ट की तुरंत उपलब्धि करता है। आईट्यून्स पॉडकास्ट डेटाबेस, ओपीएमएल फाइल्स या सरल आरएसएस यूआरएल का उपयोग करके उनके फीड्स बिना कोई परेशानी के जोड़ें, आयात और निर्यात करें। एपिसोड डाउनलोड करने (समय, अंतराल और वाईफाई नेटवर्क निर्दिष्ट करके) और एपिसोड को हटाने (आपके पसंदीदा और देरी की सेटिंग्स के आधार पर) के लिए इसमे शक्तिशाली स्वचालन नियंत्रनो है जो बैटरी पावर और मोबाइल डेटा की बचत करे।
+परंतु सबसे महत्वपूर्ण बात: एपिसोड्स डाउनलोड करें, स्ट्रीम करें या पंक्ति बनाएं और एडजस्टेबल प्लेबैक गति, अध्याय समर्थन और टाइमर् के साथ उन्हे अपने अंदाज़ में आनंद लें। आप हमारे फ्लाटर एकीकरण के साथ निर्माताओ को अपना प्यार भी जता सकते हैं। -So far the following features are implemented: +पॉडकास्ट-उत्साही द्वारा निर्मित, एन्टेनापॉड पूर्ण रूप से ओपन सोर्स, मुफ्त और विज्ञापन हीन है। -* डाउनलोड और एपिसोड के स्ट्रीमिंग -* चर गति प्लेबैक (सफ़ाई ध्वनि पुस्तकालय या प्रेस्टिसीमो कि आवश्यकता है) - * एटम और आरएसएस फ़ीड के लिए सहायता -* Support for password-protected feeds and episodes -* Support for searching iTunes listings -* ओएमपीएल आयात और निर्यात -* Flattr integration including automatic flattring -* प्लेयर होमस्क्रीन विजेट -* खोज -* स्वचालित फ़ीड अद्यतन -* नए एपिसोड की स्वचालित डाउनलोड -* स्लीप टाइमर -* Gpodder.net podcast निर्देशिका के लिए प्रवेश -* gpodder.net सेवा के साथ सदस्यता सिंक्रनाइज़ -* Supports MP3 chapters, VorbisComment chapters and Podlove Simple Chapters -* Supports paged feeds (http://podlove.org/paged-feeds/) \ No newline at end of file +सारे विशेषताएं:
+आयात करे, व्यवस्थित करे और चलाएं
+• आईट्यून्स और gPodder.net डिरेक्टरीज़, ओपीएमएल फाइल्स और आरएसएस या एटम लिंक्स के माध्यम से फीड्स जोड़ें और आयात करें।
+• कहीं से भी प्लेबैक मेनेज करें: होमस्क्रीन विजेट, सिस्टम अधिसूचना और इयरप्लग और ब्लूटूथ नियंत्रण
+• एडजस्टेबल प्लेबैक गति, अध्याय समर्थन (MP3, वोर्बीस कमेंट और पॉडलव), याद रखी प्लेबैक स्थान और आधुनिक टाइमर (हिलाकर रीसेट करे, आवाज़ धीमी करे और प्लेबैक गति कम करें) के साथ अपने अंदाज़ में सुनने का आनंद लें
+• पासवर्ड-संरक्षित फीड्स और एपिसोड्स की पहुँच प्राप्त करे
+• पेज्ड् फीड्स का लाभ उठाएं (www.podlove.org/paged-feeds) + +जुड़े रहे, शेयर करे और सराहिये
+• सबसे श्रेष्ठ का ट्रैक रखने, उस एपिसोड को पसंदीदा के रूप में चिह्नित करे
+• प्लेबैक इतिहास द्वारा या (शीर्षक और शोनोट्स) को खोजकर, आपका वो एक एपिसोड पाय
+• उन्नत सोशल मीडिया और ईमेल विकल्पों, gPodder.net सेवाओं और ओपीएमएल निर्यात के माध्यम से एपिसोड्स और फ़ीड शेयर करें
+• स्वचालित फ्लाटरिंग सहित फ्लाटर एकीकरण द्वारा निर्माताओ का समर्थन करे + +सिस्टम को काबू में करें
+• स्वचालित डौन्लोडस पर पूरा नियंत्रित रखे: फीड्स चुने, मोबाइल और वैफै नेटवर्क चुने, फोन चार्जिंग की आवश्यकता, समय और अंतराल निर्दिष्ट करे
+• कैश किए गए एपिसोड की मात्रा निर्धारित करना, स्मार्ट विलोपन करना (आपके पसंदीदा सूची और प्ले स्थिति के आधार पर) और अपनी प्राथमिक स्थान चुनना
+• एन्टेनापॉड को अपनी भाषा में इस्तेमाल करें (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
+• लाइट और डार्क थीम का उपयोग करके, अपने पर्यावरण से अनुकूलित बनाए
+• gPodder.net एकीकरण और ओपीएमएल निर्यात द्वारा अपने सब्स्क्रिप्शन्स बैकअप करें। + +एन्टेंनापॉड समुदाय में शामिल होइए।
+एन्टेंनापॉड स्वयंसेवकों द्वारा सक्रिय विकास में है। आप भी कोड या कमेंट के साथ योगदान कर सकते हैं। + +सुविधा अनुरोध, बग रिपोर्ट और कोड योगदान के लिए गिटहब पर जाएं:
+https://www.github.com/AntennaPod/AntennaPod + +हमारा गूगल ग्रुप आपके विचारों, पसंदीदा पॉडकास्टिंग पल और सभी स्वयंसेवकों के प्रति आभार साझा करने का स्थान है:
+https://groups.google.com/forum/#!forum/antennapod + +क्या आप का कोई सवाल पूछना चाहते है या कोई सुझाव देना चाहते है? +https://twitter.com/@AntennaPod + +अनुवादो की सहायता करने ट्रांसिफेक्स पर जाएं:
+https://www.transifex.com/antennapod/antennapod + +नवीनतम विशेषताएं को सबसे पहले पाने हमारे बीटा परीक्षण कार्यक्रम में शामिल होइए:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/hi-IN/listing/title b/app/src/main/play/hi-IN/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/hi-IN/listing/title +++ b/app/src/main/play/hi-IN/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/hi_IN/listing/fulldescription b/app/src/main/play/hi_IN/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/hi_IN/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/hu/listing/fulldescription b/app/src/main/play/hu/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/hu/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/id/listing/fulldescription b/app/src/main/play/id/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/id/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/is/listing/fulldescription b/app/src/main/play/is/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/is/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/it-IT/listing/fulldescription b/app/src/main/play/it-IT/listing/fulldescription index a88d693e0..3d0425660 100644 --- a/app/src/main/play/it-IT/listing/fulldescription +++ b/app/src/main/play/it-IT/listing/fulldescription @@ -1,40 +1,43 @@ -AntennaPod è un riproduttore e gestore di podcast che ti da accesso immediato a milioni di podcast gratuiti e a pagamento, dai podcaster indipendenti alle più grandi case editrici come BBC, NPR e CNN. Aggiungi, importa e esporta in modo semplici usando il database di podcast di iTunes, da file OPML o da semplici URL RSS. Risparmia fatica, batteria e dati con il potente controllo automatizzato per il download di episodi (orari specifici, intervalli e reti WiFi) e l'eliminazione degli episodi.
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. +AntennaPod è un gestore e player di podcast che ti dà accesso istantaneo a milioni di podcast gratuiti e a pagamento, da podcaster indipendenti a grandi case editrici come BBC, NPR e CNN. Aggiungi, Importa ed esporta facilmente i Feed dal database di iTunes, file OPML oppure semplici collegamenti RSS. Risparmia fatica, batteria e dati con potenti controlli automatici per scaricare gli episodi (specifica orari, intervalli e reti WiFi) ed eliminare gli episodi.
+Ma soprattutto: Scarica, fai Stream o metti in coda gli episodi e goditeli come preferisci cambiando la velocità di riproduzione, saltando tra capitoli e impostando lo sleep timer. Puoi persino mostrare il tuo amore attraverso l'integrazione con Flattr. -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. +Creato da amatori del podcast, AntennaPod è free in tutti i sensi: open-source, nessun costo, nessuna pubblicità. -Funzioni:
+Tutte le funzioni:
IMPORTA, ORGANIZZA E RIPRODUCI
-• Aggiungi e importa feed via iTunes, gPodder.net, file OPML e link RSS o Atom
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Accedi a feed e episodi protetti da password
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) +• Aggiungi ed importa i feed tramite i database di iTunes e gPodder.net, file OPML e link RSS o Atom
+• Gestisci la riproduzione in ogni modo: attraverso il widget per la home, le notifiche di sistema oppure tramite i controlli sulle cuffie, sia cablate che bluetooth
+• Goditi l'ascolto a modo tuo attraverso la velocità di riproduzione regolabile, il supporto ai capitoli (MP3, VorbisComment e Podlove), la memoria della posizione di riproduzione e un timer di riproduzione avanzato (scuoti per reimpostare, abbassamento del volume e rallentamento di riproduzione)
+• Accedi a feed ed episodi protetti da password
+• Approfitta dei paged feeds (www.podlove.org/paged-feeds) -TIENI TRACCIA, CONDIVIDI & APPREZZA
-• Tieni traccia del meglio del meglio segnando i tuoi episodi preferiti
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring +TIENI TRACCIA, CONDIVIDI E APPREZZA
+• Tieni traccia degli episodi migliori aggiungendoli ai preferiti
+• Trova episodi specifici nella cronologia di riproduzione o cercando tra titoli e descrizioni
+• Condividi episodi e feed attraverso le opzioni avanzate di condivisione verso social e emali, i servizi online di gPodder.net e l'esportazione in file OPML
+• Supporta i creatori attraverso Flattr consentendo anche il flattring automatico CONTROLLA IL SISTEMA
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export +• Prendi il controllo dei download automatici: scegli i Feed, escludi le reti cellulari, seleziona reti WiFi specifiche, attiva solo a telefono in carica e imposta orari e intervalli.
+• Gestisci la memoria impostando il numero massimo di episodi scaricati, l'eliminazione automatica (basata sui tuoi preferiti e lo stato di riproduzione) e selezionando la tua posizione preferita in memoria
+• Utilizza AntennaPod nella tua lingua (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
+• Adatta all'ambiente usando il tema chiaro e quello scuro
+• Fai il backup delle tue iscrizione con gPodder.net e l'esportazione OPML -Entra nella community di AntennaPod!
-AntennaPod è sviluppato da volontari. Anche tu puoi contribuire, con il codice o con dei commenti! +Unisciti alla comunità di AntennaPod!
+AntennaPod è in fase attiva di sviluppo da parte di volontari. Anche te puoi contribuire, con codice o commenti! -GitHub è il posto nel quale fare richieste, segnalare bug e contribuire allo sviluppo:
-www.github.com/AntennaPod/AntennaPod +Per chiedere nuove funzioni, contribuire con del codice o segnalare problemi, puoi trovarci su GitHub: +https://www.github.com/AntennaPod/AntennaPod -Il nostro Gruppo Google è il posto dove condividere le tue idee, podcast preferiti e gratitudine a tutti i nostri volontari:
+Il nostro Gruppo Google è il posto giusto per condividere le tue idee, i tuoi più bei momenti di podcasting e per mostrare gratitudine ai volontari
https://groups.google.com/forum/#!forum/antennapod -Transifex è il posto dove puoi aiutare a tradurre AntennaPod:
-www.transifex.com/antennapod/antennapod +Hai una domanda o vuoi fornirci un feedback? +https://twitter.com/@AntennaPod -Check out our Beta Testing programme to get the latest features first:
-www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file +Transifex è il posto in cui aiutare con le traduzioni:
+https://www.transifex.com/antennapod/antennapod + +Dai un'occhiata al nostro programma di beta testing per ricevere per primo le funzioni più recenti:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/it-IT/listing/title b/app/src/main/play/it-IT/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/it-IT/listing/title +++ b/app/src/main/play/it-IT/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/it/listing/fulldescription b/app/src/main/play/it/listing/fulldescription deleted file mode 100644 index 3d0425660..000000000 --- a/app/src/main/play/it/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod è un gestore e player di podcast che ti dà accesso istantaneo a milioni di podcast gratuiti e a pagamento, da podcaster indipendenti a grandi case editrici come BBC, NPR e CNN. Aggiungi, Importa ed esporta facilmente i Feed dal database di iTunes, file OPML oppure semplici collegamenti RSS. Risparmia fatica, batteria e dati con potenti controlli automatici per scaricare gli episodi (specifica orari, intervalli e reti WiFi) ed eliminare gli episodi.
-Ma soprattutto: Scarica, fai Stream o metti in coda gli episodi e goditeli come preferisci cambiando la velocità di riproduzione, saltando tra capitoli e impostando lo sleep timer. Puoi persino mostrare il tuo amore attraverso l'integrazione con Flattr. - -Creato da amatori del podcast, AntennaPod è free in tutti i sensi: open-source, nessun costo, nessuna pubblicità. - -Tutte le funzioni:
-IMPORTA, ORGANIZZA E RIPRODUCI
-• Aggiungi ed importa i feed tramite i database di iTunes e gPodder.net, file OPML e link RSS o Atom
-• Gestisci la riproduzione in ogni modo: attraverso il widget per la home, le notifiche di sistema oppure tramite i controlli sulle cuffie, sia cablate che bluetooth
-• Goditi l'ascolto a modo tuo attraverso la velocità di riproduzione regolabile, il supporto ai capitoli (MP3, VorbisComment e Podlove), la memoria della posizione di riproduzione e un timer di riproduzione avanzato (scuoti per reimpostare, abbassamento del volume e rallentamento di riproduzione)
-• Accedi a feed ed episodi protetti da password
-• Approfitta dei paged feeds (www.podlove.org/paged-feeds) - -TIENI TRACCIA, CONDIVIDI E APPREZZA
-• Tieni traccia degli episodi migliori aggiungendoli ai preferiti
-• Trova episodi specifici nella cronologia di riproduzione o cercando tra titoli e descrizioni
-• Condividi episodi e feed attraverso le opzioni avanzate di condivisione verso social e emali, i servizi online di gPodder.net e l'esportazione in file OPML
-• Supporta i creatori attraverso Flattr consentendo anche il flattring automatico - -CONTROLLA IL SISTEMA
-• Prendi il controllo dei download automatici: scegli i Feed, escludi le reti cellulari, seleziona reti WiFi specifiche, attiva solo a telefono in carica e imposta orari e intervalli.
-• Gestisci la memoria impostando il numero massimo di episodi scaricati, l'eliminazione automatica (basata sui tuoi preferiti e lo stato di riproduzione) e selezionando la tua posizione preferita in memoria
-• Utilizza AntennaPod nella tua lingua (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adatta all'ambiente usando il tema chiaro e quello scuro
-• Fai il backup delle tue iscrizione con gPodder.net e l'esportazione OPML - -Unisciti alla comunità di AntennaPod!
-AntennaPod è in fase attiva di sviluppo da parte di volontari. Anche te puoi contribuire, con codice o commenti! - -Per chiedere nuove funzioni, contribuire con del codice o segnalare problemi, puoi trovarci su GitHub: -https://www.github.com/AntennaPod/AntennaPod - -Il nostro Gruppo Google è il posto giusto per condividere le tue idee, i tuoi più bei momenti di podcasting e per mostrare gratitudine ai volontari
-https://groups.google.com/forum/#!forum/antennapod - -Hai una domanda o vuoi fornirci un feedback? -https://twitter.com/@AntennaPod - -Transifex è il posto in cui aiutare con le traduzioni:
-https://www.transifex.com/antennapod/antennapod - -Dai un'occhiata al nostro programma di beta testing per ricevere per primo le funzioni più recenti:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/it_IT/listing/fulldescription b/app/src/main/play/it_IT/listing/fulldescription deleted file mode 100644 index eb2abb40d..000000000 --- a/app/src/main/play/it_IT/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod è un riproduttore e gestore di podcast che ti da accesso immediato a milioni di podcast gratuiti e a pagamento, dai podcaster indipendenti alle più grandi emittenti come BBC, NPR e CNN. Aggiungi, importa e esporta in modo semplici usando il database di podcast di iTunes, da file OPML o da semplici URL RSS. Risparmia fatica, batteria e dati con il potente controllo automatizzato per il download di episodi (orari specifici, intervalli e reti WiFi) e l'eliminazione degli episodi.
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Creato da amanti dei podcast, AntennaPod è libero in tutti i sensi: open source, gratis, senza pubblicità. - -Funzioni:
-IMPORTA, ORGANIZZA E RIPRODUCI
-• Aggiungi e importa feed via iTunes, gPodder.net, file OPML e link RSS o Atom
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Accedi a feed e episodi protetti da password
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -TIENI TRACCIA, CONDIVIDI & APPREZZA
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Supporta i creatori di contenuti tramite l'integrazione con Flattr e il flattring automatico - -CONTROLLA IL SISTEMA
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Usa AntennaPod nella tua lingua (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Entra nella community di AntennaPod!
-AntennaPod è sviluppato da volontari. Anche tu puoi contribuire, con il codice o con dei commenti! - -GitHub è il posto nel quale fare richieste, segnalare bug e contribuire allo sviluppo:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Hai una domanda o vuoi darci un feedback? -https://twitter.com/@AntennaPod - -Transifex è il posto dove puoi contribuire alla traduzione di AntennaPod:
-https://www.transifex.com/antennapod/antennapod - -Dai un'occhiata al nostro programma di Beta Testing per avere accesso in anticipo alle nuove features:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/iw-IL/listing/shortdescription b/app/src/main/play/iw-IL/listing/shortdescription index ad3ccb1f8..7afb5a62d 100644 --- a/app/src/main/play/iw-IL/listing/shortdescription +++ b/app/src/main/play/iw-IL/listing/shortdescription @@ -1 +1 @@ -An open-source podcast manager for Android \ No newline at end of file +Easy-to-use, flexible and open-source podcast & radio manager and player \ No newline at end of file diff --git a/app/src/main/play/iw-IL/listing/title b/app/src/main/play/iw-IL/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/iw-IL/listing/title +++ b/app/src/main/play/iw-IL/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/ja-JP/listing/fulldescription b/app/src/main/play/ja-JP/listing/fulldescription index 38f6deffb..b85f6787e 100644 --- a/app/src/main/play/ja-JP/listing/fulldescription +++ b/app/src/main/play/ja-JP/listing/fulldescription @@ -7,13 +7,12 @@ AntennaPodは、独自のポッドキャスターから、BBC、NPR、CNNなど インポート、整理、再生
• iTunesや、gPodder.netディレクトリ、OPMLファイル、RSSまたはAtom経由でフィードを追加およびインポートします
• 様々な場所で再生を管理します: ホーム画面ウィジェット、システム通知、イヤホン、Bluetoothコントロール
-• 再生速度の調整、チャプターのサポート (MP3、VorbisCommentとPodlove)、再生位置の保存、高度なスリープタイマー (シェイクしてリセット、音量を小さく、再生速度を遅く) で、お好みの -聞き方でお楽しみください
+• 再生速度の調整、チャプターのサポート (MP3、VorbisCommentとPodlove)、再生位置の保存、高度なスリープタイマー (シェイクしてリセット、音量を小さく、再生速度を遅く) で、お好みの聞き方でお楽しみください
• アクセスパスワードで保護されたフィードとエピソード
• ページフィードをご利用ください (www.podlove.org/paged-feeds) 記録、共有 & 感謝
-• エピソードをお気に入りとしてマークして、一番の中の一番を記録してください
+• エピソードをお気に入りとしてマークして、一番の中の一番を保存してください
• 再生履歴から、または検索 (タイトルとショーノート) して目的のエピソードを見つけてください
• 高度なソーシャルメディアとメールオプション、gPodder.netサービス、OPMLエクスポートからエピソードやフィードを共有してください
• 自動Flattrを含むFlattrの統合でコンテンツクリエイターをサポートします @@ -29,13 +28,16 @@ AntennaPodは、独自のポッドキャスターから、BBC、NPR、CNNなど AntennaPod はボランティアによって活発に開発中です。コードやコメントで、あなたもも貢献することができます! GitHubは、機能のリクエスト、バグの報告、コードの貢献のための場所です:
-www.github.com/AntennaPod/AntennaPod +https://www.github.com/AntennaPod/AntennaPod -私たちのGoogleグループは、あなたのアイデア、お気に入りのポッドキャスティングモーメント、感謝を、すべてのボランティアと共有するための場所で:
+私たちのGoogleグループは、あなたのアイデア、お気に入りのポッドキャスティングモーメント、感謝を、すべてのボランティアと共有するための場所です:
https://groups.google.com/forum/#!forum/antennapod +質問や、私たちへのフィードバックがありませんか? +https://twitter.com/@AntennaPod + Transifexは翻訳を支援するための場所です:
-www.transifex.com/antennapod/antennapod +https://www.transifex.com/antennapod/antennapod 私たちのベータテストプログラムをチェックして、最新機能を最初に入手してください:
-www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/ja-JP/listing/title b/app/src/main/play/ja-JP/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/ja-JP/listing/title +++ b/app/src/main/play/ja-JP/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/ja/listing/fulldescription b/app/src/main/play/ja/listing/fulldescription deleted file mode 100644 index b85f6787e..000000000 --- a/app/src/main/play/ja/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPodは、独自のポッドキャスターから、BBC、NPR、CNNなどの大規模な放送まで、数百万の無料や有料ポッドキャストに瞬時にアクセスすることができる、ポッドキャストマネージャーおよびプレーヤーです。フィードは手間のかからないiTunesのPodcastのデータベース、OPMLファイルや簡単なRSSのURLを使用して追加、インポート、エクスポートします。エピソードのダウンロード (時間、間隔およびWiFiネットワークを指定) とエピソードの削除 (お気に入りと遅延設定に基づいて) をするために強力な自動コントロールで、手間、バッテリ消費、モバイルデータ使用量を節約します。
-しかし最も重要なこと: エピソードをダウンロード、ストリーム再生、またはキューに入れて、そして再生速度の調整、チャプターのサポート、スリープタイマーで好きなように楽しんでください。Flattr統合でコンテンツ作成者にあなたの愛を示すことができます。 - -ポッドキャスト愛好家が作成した AntennaPod はすべての意味でフリー自由です: オープンソース、コスト不要、広告はありません。 - -すべての機能:
-インポート、整理、再生
-• iTunesや、gPodder.netディレクトリ、OPMLファイル、RSSまたはAtom経由でフィードを追加およびインポートします
-• 様々な場所で再生を管理します: ホーム画面ウィジェット、システム通知、イヤホン、Bluetoothコントロール
-• 再生速度の調整、チャプターのサポート (MP3、VorbisCommentとPodlove)、再生位置の保存、高度なスリープタイマー (シェイクしてリセット、音量を小さく、再生速度を遅く) で、お好みの聞き方でお楽しみください
-• アクセスパスワードで保護されたフィードとエピソード
-• ページフィードをご利用ください (www.podlove.org/paged-feeds) - -記録、共有 & 感謝
-• エピソードをお気に入りとしてマークして、一番の中の一番を保存してください
-• 再生履歴から、または検索 (タイトルとショーノート) して目的のエピソードを見つけてください
-• 高度なソーシャルメディアとメールオプション、gPodder.netサービス、OPMLエクスポートからエピソードやフィードを共有してください
-• 自動Flattrを含むFlattrの統合でコンテンツクリエイターをサポートします - -システムのコントロール -• 自動ダウンロードの制御: フィードを選択、モバイルネットワークを除外、特定のWiFiネットワークを選択、電話を充電する必要、時間や間隔を設定
-• キャッシュされるエピソードの量の設定、スマート削除 (お気に入りやプレイ状況に基づいて) と、お好みの場所を選択して、ストレージを管理します
-• AntennaPod をあなたの言語でご利用ください (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• ライトとダーク テーマを使用して環境に適応します
-• gPodder.net統合とOPMLのエクスポートで、購読をバックアップします - -AntennaPod のコミュニティに参加してください!
-AntennaPod はボランティアによって活発に開発中です。コードやコメントで、あなたもも貢献することができます! - -GitHubは、機能のリクエスト、バグの報告、コードの貢献のための場所です:
-https://www.github.com/AntennaPod/AntennaPod - -私たちのGoogleグループは、あなたのアイデア、お気に入りのポッドキャスティングモーメント、感謝を、すべてのボランティアと共有するための場所です:
-https://groups.google.com/forum/#!forum/antennapod - -質問や、私たちへのフィードバックがありませんか? -https://twitter.com/@AntennaPod - -Transifexは翻訳を支援するための場所です:
-https://www.transifex.com/antennapod/antennapod - -私たちのベータテストプログラムをチェックして、最新機能を最初に入手してください:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/kn_IN/listing/fulldescription b/app/src/main/play/kn_IN/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/kn_IN/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/ko-KR/listing/fulldescription b/app/src/main/play/ko-KR/listing/fulldescription index 7f04d4e7b..65f20d943 100644 --- a/app/src/main/play/ko-KR/listing/fulldescription +++ b/app/src/main/play/ko-KR/listing/fulldescription @@ -1,20 +1,43 @@ -안테나팟은 오픈소스 팟캐스트 관리 프로그램입니다. 안드로이드 2.2.3 이상에서 동작합니다. 에피소드의 스트리밍 및 다운로드, 자동으로 피드를 새로 확인하고 나중에 들을 수 있게 대기열에 추가하는 등 팟캐스트 프로그램에서 생각할 수 있는 모든 기본 기능을 지원합니다. 또 안테나팟 앱 안에서 팟캐스트에 대해 Flattr 기부 기능을 사용할 수 있습니다. +안테나팟을 사용해 소규모 독립 제작자들부터 BBC, NPR, CNN 등의 대형 언론사까지 수많은 무료 및 유료 팟캐스트에 접근할 수 있습니다. iTunes 팟캐스트 데이터베이스, OPML 파일, RSS 주소를 사용해 팟캐스트 피드를 간편하게 추가하고 내보내고 가져올 수 있습니다. 강력한 자동 다운로드 제어(특정 시간 간격 및 Wi-Fi 네트워크 지정)와 삭제 제어(즐겨찾기 및 지연 설정에 기반한)를 통해 편리하게 배터리와 모바일 데이터 사용량을 줄이세요.
+하지만 가장 중요한 기능은: 에피소드를 다운로드하거나 스트리밍하거나 대기열을 만들고, 재생 속도 조절, 챕터 지원, 취침 타이머를 통해 원하는대로 즐길 수 있다는 점입니다. 내장된 Flattr 지원을 통해 팟캐스트 제작자들에게 호응을 보낼 수도 있습니다. -지금까지 다음 기능이 구현되었습니다: +팟캐스트 애호가에 의해 만들어진, 안테나팟은 모든 면에서 자유롭습니다: 소스 코드가 공개되어 있고, 무료인데다가 광고도 없습니다. -* 에피소드 다운로드 및 스트리밍 -* 여러가지 배속 재생(Presto 사운드 라이브러리 또는 Prestissimo 필요) -* Atom 및 RSS 피드 지원 -* 암호로 보호된 피드와 에피소드 지원 -* iTunes 목록 검색 기능 -* OPML 가져오기 및 내보내기 -* Flattr 통합, 자동으로 Flattr하기 기능 포함 -* 홈스크린 재생 위젯 -* 검색 -* 자동 피드 업데이트 -* 새 에피소드 자동 다운로드 -* 취침 타이머 -* gpodder.net 팟캐스트 디렉터리 찾아보기 -* gpodder.net 서비스와 구독 정보 동기화 -* MP3 챕터, VorbisComment 챕터, Podlove Simple Chapters 기능 -* 페이지 피드 (http://podlove.org/paged-feeds/) 지원 \ No newline at end of file +모든 기능:
+가져오기, 관리하기, 재생하기
+• iTunes, gPodder.net, OPML 파일, RSS 및 Atom 링크를 통해 피드를 추가하거나 가져올 수 있습니다.
+• 재생을 어디에서나 관리할 수 있습니다: 홈스크린 위젯, 시스템 알림, 이어폰 및 블루투스 컨트롤
+• 배속 재생 지원, 챕터 지원(MP3, VorbisComment, Podlove), 마지막 재생 위치 기억, 고급 취침 타이머(흔들어서 초기화, 볼륨 낮추기, 재생 느리게 하기) 등의 기능으로 팟캐스트를 즐기세요
+• 암호로 보호된 피드와 에피소드에 접근
+• 페이지로 구분된 피드 활용 (www.podlove.org/paged-feeds) + +기록하고, 공유하고, 호응하기
+• 가장 좋아하는 팟캐스트 에피소드를 즐겨찾기로 저장
+• 에피소드를 재생 기록 또는 검색(제목 및 노트)으로 찾기
+• 에피소드와 피드를 SNS, 이메일, gPodder.net, OPML 내보내기로 공유
+• 자동으로 Flattr하기 등의 Flattr 기능으로 팟캐스트 제작자 지원 + +시스템 컨트롤 +• 자동 다운로드를 제어하세요: 피드를 고르고, 모바일 네트워크를 제외시키고, 특정 Wi-Fi 네트워크를 선택하고, 기기가 충전중일때만 다운로드하게 하고, 시간과 간격을 정하세요
+• 에피소드 캐시 용량, 똑똑한 삭제(즐겨찾기와 재생 상태에 기반), 선호하는 저장 위치 등으로 저장소를 관리하세요
+• 여러가지 언어로 안테나팟을 사용하세요 (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
+• 밝음 및 어두움 테마로 환경에 맞춰 사용하세요
+• gPodder.net과 OPML 내보내기 기능으로 구독한 팟캐스트를 백업하세요 + +안테나팟 커뮤니티에 참여하세요!
+안테나팟은 지원자들에 의해 활발히 개발되고 있습니다. 당신도 제작을 돕거나 제안을 해서 참여할 수 있습니다! + +GitHub에서 새로운 기능 제안, 버그 보고, 그리고 코드 기여를 할 수 있습니다.:
+https://www.github.com/AntennaPod/AntennaPod + +구글 그룹에서 아이디어와 좋은 팟캐스트를 공유하고 모든 지원자들에게 감사할 수 있습니다:
+https://groups.google.com/forum/#!forum/antennapod + +질문이 있으신가요? 아니면 의견이 있으신가요? +https://twitter.com/@AntennaPod + +Transifex에서 번역을 도울 수 있습니다:
+https://www.transifex.com/antennapod/antennapod + +베타 테스트 프로그램을 통해 최신 기능을 가장 먼저 확인해보세요:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/ko-KR/listing/title b/app/src/main/play/ko-KR/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/ko-KR/listing/title +++ b/app/src/main/play/ko-KR/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/ko/listing/fulldescription b/app/src/main/play/ko/listing/fulldescription deleted file mode 100644 index 65f20d943..000000000 --- a/app/src/main/play/ko/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -안테나팟을 사용해 소규모 독립 제작자들부터 BBC, NPR, CNN 등의 대형 언론사까지 수많은 무료 및 유료 팟캐스트에 접근할 수 있습니다. iTunes 팟캐스트 데이터베이스, OPML 파일, RSS 주소를 사용해 팟캐스트 피드를 간편하게 추가하고 내보내고 가져올 수 있습니다. 강력한 자동 다운로드 제어(특정 시간 간격 및 Wi-Fi 네트워크 지정)와 삭제 제어(즐겨찾기 및 지연 설정에 기반한)를 통해 편리하게 배터리와 모바일 데이터 사용량을 줄이세요.
-하지만 가장 중요한 기능은: 에피소드를 다운로드하거나 스트리밍하거나 대기열을 만들고, 재생 속도 조절, 챕터 지원, 취침 타이머를 통해 원하는대로 즐길 수 있다는 점입니다. 내장된 Flattr 지원을 통해 팟캐스트 제작자들에게 호응을 보낼 수도 있습니다. - -팟캐스트 애호가에 의해 만들어진, 안테나팟은 모든 면에서 자유롭습니다: 소스 코드가 공개되어 있고, 무료인데다가 광고도 없습니다. - -모든 기능:
-가져오기, 관리하기, 재생하기
-• iTunes, gPodder.net, OPML 파일, RSS 및 Atom 링크를 통해 피드를 추가하거나 가져올 수 있습니다.
-• 재생을 어디에서나 관리할 수 있습니다: 홈스크린 위젯, 시스템 알림, 이어폰 및 블루투스 컨트롤
-• 배속 재생 지원, 챕터 지원(MP3, VorbisComment, Podlove), 마지막 재생 위치 기억, 고급 취침 타이머(흔들어서 초기화, 볼륨 낮추기, 재생 느리게 하기) 등의 기능으로 팟캐스트를 즐기세요
-• 암호로 보호된 피드와 에피소드에 접근
-• 페이지로 구분된 피드 활용 (www.podlove.org/paged-feeds) - -기록하고, 공유하고, 호응하기
-• 가장 좋아하는 팟캐스트 에피소드를 즐겨찾기로 저장
-• 에피소드를 재생 기록 또는 검색(제목 및 노트)으로 찾기
-• 에피소드와 피드를 SNS, 이메일, gPodder.net, OPML 내보내기로 공유
-• 자동으로 Flattr하기 등의 Flattr 기능으로 팟캐스트 제작자 지원 - -시스템 컨트롤 -• 자동 다운로드를 제어하세요: 피드를 고르고, 모바일 네트워크를 제외시키고, 특정 Wi-Fi 네트워크를 선택하고, 기기가 충전중일때만 다운로드하게 하고, 시간과 간격을 정하세요
-• 에피소드 캐시 용량, 똑똑한 삭제(즐겨찾기와 재생 상태에 기반), 선호하는 저장 위치 등으로 저장소를 관리하세요
-• 여러가지 언어로 안테나팟을 사용하세요 (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• 밝음 및 어두움 테마로 환경에 맞춰 사용하세요
-• gPodder.net과 OPML 내보내기 기능으로 구독한 팟캐스트를 백업하세요 - -안테나팟 커뮤니티에 참여하세요!
-안테나팟은 지원자들에 의해 활발히 개발되고 있습니다. 당신도 제작을 돕거나 제안을 해서 참여할 수 있습니다! - -GitHub에서 새로운 기능 제안, 버그 보고, 그리고 코드 기여를 할 수 있습니다.:
-https://www.github.com/AntennaPod/AntennaPod - -구글 그룹에서 아이디어와 좋은 팟캐스트를 공유하고 모든 지원자들에게 감사할 수 있습니다:
-https://groups.google.com/forum/#!forum/antennapod - -질문이 있으신가요? 아니면 의견이 있으신가요? -https://twitter.com/@AntennaPod - -Transifex에서 번역을 도울 수 있습니다:
-https://www.transifex.com/antennapod/antennapod - -베타 테스트 프로그램을 통해 최신 기능을 가장 먼저 확인해보세요:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/ko_KR/listing/fulldescription b/app/src/main/play/ko_KR/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/ko_KR/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/lt/listing/fulldescription b/app/src/main/play/lt/listing/fulldescription index 3f9f50a90..c25bce143 100644 --- a/app/src/main/play/lt/listing/fulldescription +++ b/app/src/main/play/lt/listing/fulldescription @@ -1,43 +1,43 @@ -„AntennaPod“ yra tinklalaidžių tvarkytuvė ir leistuvė, įgalinanti momentinę prieigą prie milijonų nemokamų bei mokamų tinklalaidžių, nuo nepriklausomų tinklalaidžių kūrėjų iki didžiųjų leidyklų, tokių kaip „BBC“, „NPR“ ir „CNN“. Be vargo pridėkite, importuokite ir eksportuokite jų sklaidos kanalus naudodamiesi „iTunes“ tinklalaidžių duomenų baze, OPML failais ar tiesiogiai iš RSS kanalo adreso. Sutaupykite laiko, baterijos energijos ir suvartojamų mobiliųjų duomenų išnaudodami galingas automatinio epizodų atsiuntimo priemones (nurodykite atsiuntimo metą, laiko intervalą ir belaidžius tinklus) ir ištrindami epizodus (remiantis mėgiamųjų sąrašu ir laikymo nustatymais).
-Bet svarbiausia: atsisiųskite, klausykitės iš karto ar pridėkite epizodus į eilę ir mėgaukitės jais pasirinkdami atkūrimo spartą, naudodamiesi skyrių palaikymu bei miego laikmačiu. Jūs netgi galite išreikšti savo meilę turinio kūrėjams naudodamiesi mūsų „Flattr“ integracija. +„AntennaPod“ yra tinklalaidžių tvarkytuvė ir leistuvė, įgalinanti prieigą prie milijonų tinklalaidžių, nuo nepriklausomų kūrėjų iki didžiųjų leidyklų, tokių kaip „BBC“, „NPR“ ir „CNN“. Be vargo pridėkite, importuokite ir eksportuokite sklaidos kanalus naudodamiesi „iTunes“ tinklalaidžių duomenų baze, OPML failais ar RSS kanalais. Taupykite laiką, baterijos energiją ir mobilius duomenis naudodami galingas automatinio atsiuntimo priemones (nurodykite atsiuntimo metą, laiko intervalą ir belaidžius tinklus) ir ištrindami epizodus (remiantis mėgiamųjų sąrašu ir laikymo nustatymais).
+Bet svarbiausia: atsisiųskite, klausykitės iš karto ar dėkite epizodus į eilę ir mėgaukitės jais pasirinkę atkūrimo spartą, naudodamiesi skyrių palaikymu bei miego laikmačiu. Be to, galite išreikšti savo meilę turinio kūrėjams naudodamiesi „Flattr“ integracija. -Sukurtas tinklalaidžių entuziasto, „AntennaPod“ yra laisvas visomis šio žodžio prasmėmis: atvirojo kodo, jokių mokesčių, jokių reklamų. +Sukurtas tinklalaidžių entuziasto, „AntennaPod“ yra laisvas visomis prasmėmis: atvirojo kodo, be mokesčių, be reklamų. Visos funkcijos:
IMPORTUOKITE, TVARKYKITE BEI KLAUSYKITĖS
-• Pridėkite bei importuokite sklaidos kanalus iš „iTunes“ bei „gPodder.net“ paslaugų, OPML failų ir RSS ar Atom nuorodų
-• Valdykite atkūrimą bet kur: pradžios ekrano valdyklyje, programos pranešimuose, ausinių ar „Bluetooth“ valdikliu
-• Mėgaukitės klausydamiesi taip, kaip Jums patinka, naudodamiesi derinama atkūrimo sparta, skyrių palaikymu (MP3, „VorbisComment“ ir „Podlove“), išsaugota paskutinio atkūrimo pozicija ir miego laikmačiu (mažinamas garsis bei lėtinama atkūrimo sparta, pakračius nustatomas iš naujo)
-• Pasiekite slaptažodžiu apsaugotus sklaidos kanalus bei epizodus
+• Pridėkite ar importuokite sklaidos kanalus iš „iTunes“ ir „gPodder.net“, OPML failų, RSS ar Atom nuorodų
+• Valdykite atkūrimą bet kur: pradžios ekrane, programų pranešimuose, ausinių ar „Bluetooth“ valdikliu
+• Mėgaukitės klausydamiesi taip, kaip Jums patinka, naudodamiesi derinama atkūrimo sparta, skyrių palaikymu (MP3, „VorbisComment“ ir „Podlove“), išsaugota atkūrimo pozicija ir miego laikmačiu (mažinamas garsis bei lėtinama atkūrimo sparta, pakračius nustatomas iš naujo)
+• Pasiekite slaptažodžiu apsaugotus sklaidos kanalus ir epizodus
• Išnaudokite puslapiuotus sklaidos kanalus (www.podlove.org/paged-feeds) STEBĖKITE, DALINKITĖS IR MĖGAUKITĖS
-• Kaupkite geriausius iš geriausiųjų pažymėdami epizodus kaip mėgstamiausius
-• Raskite tą vienintelį epizodą naudodamiesi atkūrimo istorija arba paieška (pavadinimuose ir laidų užrašuose)
-• Dalinkitės epizodais bei sklaidos kanalais per socialinius tinklus, el. paštu, „gPodder.net“ paslaugą bei eksportuotus OPML failus
-• Remkite turinio kūrėjus naudodamiesi „Flattr“ integracija bei automatiniu rėmimu +• Kaupkite geriausius pažymėję epizodą kaip mėgstamą
+• Raskite norimą epizodą pasinaudoję atkūrimo istorija ir paieška (pavadinimuose ir laidų užrašuose)
+• Dalinkitės epizodais ir sklaidos kanalais per socialinius tinklus, el. paštu, „gPodder.net“ ir OPML failus
+• Remkite turinio kūrėjus pasinaudoję „Flattr“ integracija VALDYKITE SISTEMĄ
-• Valdykite automatinį atsiuntimą: pasirinkite sklaidos kanalus, neleiskite atsiuntimų mobiliuoju duomenų ryšiu, apibrėžkite leidžiamus belaidžio ryšio tinklus, reikalaukite, jog atsiuntimai būtų vykdomi telefono įkrovos metu ir nurodykite atsiuntimų dienos metą ar intervalą
-• Valdykite atmintinės naudojimą nurodydami podėlyje laikomų epizodų kiekį, išmanų ištrynimą (remiantis atkūrimo būsena bei mėgiamųjų sąrašu) ir nurodykite saugojimo vietą
+• Valdykite automatinį atsiuntimą: pasirinkite sklaidos kanalus, neleiskite atsiuntimų mobiliuoju ryšiu, apibrėžkite leistinus belaidžius tinklus, reikalaukite, jog atsiuntimai būtų vykdomi įkrovos metu, nurodykite atsiuntimų dienos metą ar intervalą
+• Valdykite laikmenos naudojimą nurodant podėlyje laikomų epizodų kiekį, išmanų trynimą (remiantis atkūrimo būsena ir mėgiamųjų sąrašu), saugojimo vietą
• Naudokitės „AntennaPod“ savo kalba (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH, LT)
-• Pritaikykite savo aplinkai pasirinkdami šviesią arba tamsią temą
-• Sukurkite savo prenumeratų atsarginę kopiją pasinaudodami „gPodder.net“ integracija arba OPML eksportu +• Pritaikykite savo aplinkai pasirinkę šviesią ar tamsią temą
+• Kurkite prenumeratų atsargines kopijas „gPodder.net“ ar OPML failais Prisijunkite prie AntennaPod bendruomenės!
-„AntennaPod“ aplikaciją aktyviai vysto savanoriai. Jūs taip pat galite prisidėti, nuo atsiliepimų iki programinio kodo! +„AntennaPod“ vysto savanoriai. Ir Jūs galite prisidėti, nuo atsiliepimų iki programinio kodo! -„GitHub“ yra ta vieta, kur galite pageidauti naujų funkcijų, pranešti apie riktą arba prisidėti programiniu kodu:
+Per „GitHub“ galite pageidauti naujų funkcijų, pranešti apie riktą ar prisidėti programiniu kodu:
https://www.github.com/AntennaPod/AntennaPod -Mūsų „Google“ grupė yra puiki vieta pasidalinti idėjomis, mėgstamiausiais tinklalaidžių sklaidos momentais ar išreikšti padėką visiems savanoriams:
+„Google“ grupėje galite dalintis idėjomis, mėgstamais tinklalaidžių sklaidos momentais ar padėkoti savanoriams:
https://groups.google.com/forum/#!forum/antennapod -Turite klausimų ar norite palikti atsiliepimą? +Turite klausimų ar atsiliepimų? https://twitter.com/@AntennaPod -„Transifex“ yra ta vieta, kur galite prisidėti prie aplikacijos vertimo:
+Prie vertimų galite prisidėti per „Transifex“:
https://www.transifex.com/antennapod/antennapod -Išbandykite mūsų Beta Testavimo programą, jei norite pirmieji gauti naujausias funkcijas:
+Jei norite pirmieji gauti naujas funkcijas, išbandykite Beta Testavimo programą:
https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/lt/listing/shortdescription b/app/src/main/play/lt/listing/shortdescription new file mode 100644 index 000000000..0a0752647 --- /dev/null +++ b/app/src/main/play/lt/listing/shortdescription @@ -0,0 +1 @@ +Patogi naudoti, lanksti atvirojo kodo tinklalaidžių tvarkytuvė bei leistuvė \ No newline at end of file diff --git a/app/src/main/play/ms_MY/listing/fulldescription b/app/src/main/play/ms_MY/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/ms_MY/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/nb/listing/fulldescription b/app/src/main/play/nb/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/nb/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/nb_NO/listing/fulldescription b/app/src/main/play/nb_NO/listing/fulldescription deleted file mode 100644 index 460a880fe..000000000 --- a/app/src/main/play/nb_NO/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-Men viktigst av alt: Last ned, strøm eller legg episoder i kø og nyt dem slik du ønsker med regulerbar avspillingshasitghet, kapittelstøtte og en tidtaker for automatisk avslåing. Du kan til og med vise din takknemlighet til innholdets skapere med vår Flattr-integrasjon. - -Laget av podkast-entusiaster er AntennaPod gratis i ordets rette forstand: åpen kildekode, ingen kostnader, ingen reklame. - -
Alle funksjoner: -IMPORTER, ORGANISER OG SPILL AV
-• Legg til og importer strømmer fra mapper fra iTunes og gPodder.net, OPML-filer og linker fra RSS og Atom
-• Behandle avspillinger fra hvor som helst: widget på startskjerm, systemnotifikasjoner og ørepropp- og bluetoothkontroller
-• Nyt det å høre på din måte med regulerbar avspillingshastighet, kapittelstøtte (MP3, VorbisComment og Podlove), husket avspillingsposisjon og en avansert tidtaker for automatisk avslåing (rist for å tilbakestille, senke volumet og sakke ned avspillingen)
-• Støtte for passordbeskyttede strømmer og episoder
-• Støtte for «paged feeds» (www.podlove.org/paged-feeds) - -FØLG MED, DEL OG SETT PRIS PÅ
-• Keep track of the best of the best by marking episodes as favourites
-• Find den ene episoden gjennom avspillingshistorien eller ved å søke (titler og shownotater)
-• Del episoder og strømmer gjennom avanserte sosiale medier- og e-postinstillinger, gPodder.net-tjenester og via OPML-eksportering
-• Støtt innholdsskapere med Flattr-integrasjon gjennom automatisk «flattring» - -KONTROLLER SYSTEMET
-• Ta kontroll over automatiske nedlastninger: velg feeds, ekskluder mobil tilkobling, spesifiser Wifi-nettverk, krev at telefonen er tilkoblet lader, sett tidspunk eller intervaller
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Bruk AntennaPod i ditt språk (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Tilpass appens stil ved å bruke det mørke eller lyse temaet
-• Lag back-up av dine abonnement med gPodder.net-integrasjon og OPML-eksport - -Join the AntennaPod community!
-AntennaPod er under aktiv utvikling av frivillige. Du kan også bidra, med kode eller kommentarer! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Har du spørsmål eller vil du gi oss tilbakemelding? -https://twitter.com/@AntennaPod - -Transifex er stedet for å hjelpe til med oversettinger:
-https://www.transifex.com/antennapod/antennapod - -Sjekk ut vårt program for betatesting for å få de nyeste funksjonene først:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/nl-NL/listing/fulldescription b/app/src/main/play/nl-NL/listing/fulldescription index 52a2d4337..736a3f3a5 100644 --- a/app/src/main/play/nl-NL/listing/fulldescription +++ b/app/src/main/play/nl-NL/listing/fulldescription @@ -1,20 +1,43 @@ -AntennaPod is een open-source podcast manager voor Android 2.3.3 en hoger. Het biedt alle basisfuncties die u verwacht van een podcatcher, zoals streaming en downloaden van episodes, alle feeds automatisch verversen of episodes aan een wachtrij toevoegen om ze later te luisteren. Bovendien laat AntennaPod je podcasts en afleveringen vanuit de app flattr'en. +Met AntennaPod speel en beheer je al je podcasts en krijg je directe toegang tot duizenden gratis en betaalde podcasts - van onafhankelijke makers tot grote merken zoals BBC, CNN en NPO. Via de iTunes database, OPML-bestanden en simpele RSS-linkjes voeg je deze podcasts makkelijk toe. Dankzij simpele maar slimme automatische controle van het downloaden en verwijderen van afleveringen spaar je je batterij, hoef je je favoriete podcast niet meer handmatig te volgen en verbruik je geen onnodig mobiele data.
+Maar belangrijker: Met een handige wachtrij, aanpasbare afspeelsnelheden, ondersteuning van hoofdstukken en een slaap timer luister je naar podcasts op de manier die jij prettig vindt. Je kunt zelfs je liefde voor de makers uiten met onze Flattr-integratie. -So far the following features are implemented: +Gemaakt door podcast-enthousiastelingen, AntennaPod is vrij in de breedste zin van het woord: vrij van advertenties, open source en gratis. -* Episodes downloaden en streamen -* Variabele afspeelsnelheid (vereist Presto Sound Library of Prestissimo) -* Support voor Atom en RSS feeds -* Ondersteuning voor wachtwoord-beveiligde feeds en afleveringen -* Support for searching iTunes listings -* OPML import en export -* Flattr integration including automatic flattring -* Homescreen widget voor de player -* Zoekfunctie -* Automatische feed updates -* Automatisch downloaden van nieuwe episodes -* Sleep timer -* Toegang tot de gpodder.net podcast gids -* Abonnementen synchroniseren met de gpodder.net dienst -* Supports MP3 chapters, VorbisComment chapters and Podlove Simple Chapters -* Supports paged feeds (http://podlove.org/paged-feeds/) \ No newline at end of file +Alle features:
+IMPORTEREN, ORGANISEREN, AFSPELEN
+• Voeg feeds toe via iTunes and gPodder.net database, OPML-bestanden and RSS of Atom linkjes
+• Beheer het afspelen overal: met een homescreen widget, in je Android meldingen en de knoppen op je koptelefoon en bluetooth-apparaat
+• Bepaal zelf hoe je luistert met aanpasbare afspeelsnelheden, ondersteuning van hoofdstukken (MP3, VorbisComment en Podlove), afspeelpositie voor elke aflevering en een handige 'slaap timer' (schudden om te resetten, volume langzaam zachter en herstel naar normale afspeelsnelheid)
+• Toegang tot wachtwoord-beveiligde podcasts en afleveringen
+• Doe je voordeel met 'paged feeds' (www.podlove.org/paged-feeds) + +DEEL & WAARDEER
+• Hou het beste van het beste bij door afleveringen als favoriet te markeren
+• Vindt die ene aflevering terug in de afspeelgeschiedenis of door te zoeken (in titels, shownotes en makers)
+• Deel podcasts en afleveringen via uitgebreide opties voor sociale media, WhatsApp, email en gPodder.net
+• Steun makers met Flattr-integratie, inclusief auto-Flattr + +HOUD DE CONTROLE +• Beheer automatische downloads: kies je podcasts, sluit mobiele netwerken uit, selecteer specifieke WiFi-verbindingen, eis dat de telefoon wordt opgeladen and bepaal tijden of intervals
+• Controleer geheugengebruik: stel een maximumaantal gedownloade afleveringen in, laat afleveringen automatisch verwijderen (maar sluit je favorieten en niet-afgespeelde afleveringen uit) en selecteer zelf je opslaglocatie
+• Gebruik AntennaPod in jouw taal: Nederlands! (Of in het Engels, Zweeds, Frans, Duits, Spaans, enz)
+• Voel je een kameleon: kies voor een licht of donker uiterlijk
+• Back-up je abonnementen via gPodder.net en geëxporteerde OPML-bestanden + +Doe mee met de AntennaPod gemeenschap!
+AntennaPod wordt regelmatig geüpdatet door vrijwilligers. En jij kan ook helpen, met code of commentaar! + +GitHub is de beste plek voor foutmeldingen, verzoekjes voor nieuwe functies en bijdragen aan de code:
+https://www.github.com/AntennaPod/AntennaPod + +Onze Google Group is de beste plek om je ideeën, favoriete podcast-momenten en waardering naar alle vrijwilligers te delen:
+https://groups.google.com/forum/#!forum/antennapod + +Heb je een vraag of wil je feedback geven? +https://twitter.com/@AntennaPod + +Transifex is de beste plek om te helpen met vertalen:
+https://www.transifex.com/antennapod/antennapod + +Check het Beta Testprogramma om de laatste features als eerst te krijgen:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/nl-NL/listing/shortdescription b/app/src/main/play/nl-NL/listing/shortdescription index 4eceefbb7..31c66d634 100644 --- a/app/src/main/play/nl-NL/listing/shortdescription +++ b/app/src/main/play/nl-NL/listing/shortdescription @@ -1 +1 @@ -Easy-to-use, flexible and open-source podcast manager and player \ No newline at end of file +Gemakkelijk te gebruiken, flexibele en open-source podcastbeheerder en -speler \ No newline at end of file diff --git a/app/src/main/play/nl-NL/listing/title b/app/src/main/play/nl-NL/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/nl-NL/listing/title +++ b/app/src/main/play/nl-NL/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/nl/listing/fulldescription b/app/src/main/play/nl/listing/fulldescription deleted file mode 100644 index 736a3f3a5..000000000 --- a/app/src/main/play/nl/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -Met AntennaPod speel en beheer je al je podcasts en krijg je directe toegang tot duizenden gratis en betaalde podcasts - van onafhankelijke makers tot grote merken zoals BBC, CNN en NPO. Via de iTunes database, OPML-bestanden en simpele RSS-linkjes voeg je deze podcasts makkelijk toe. Dankzij simpele maar slimme automatische controle van het downloaden en verwijderen van afleveringen spaar je je batterij, hoef je je favoriete podcast niet meer handmatig te volgen en verbruik je geen onnodig mobiele data.
-Maar belangrijker: Met een handige wachtrij, aanpasbare afspeelsnelheden, ondersteuning van hoofdstukken en een slaap timer luister je naar podcasts op de manier die jij prettig vindt. Je kunt zelfs je liefde voor de makers uiten met onze Flattr-integratie. - -Gemaakt door podcast-enthousiastelingen, AntennaPod is vrij in de breedste zin van het woord: vrij van advertenties, open source en gratis. - -Alle features:
-IMPORTEREN, ORGANISEREN, AFSPELEN
-• Voeg feeds toe via iTunes and gPodder.net database, OPML-bestanden and RSS of Atom linkjes
-• Beheer het afspelen overal: met een homescreen widget, in je Android meldingen en de knoppen op je koptelefoon en bluetooth-apparaat
-• Bepaal zelf hoe je luistert met aanpasbare afspeelsnelheden, ondersteuning van hoofdstukken (MP3, VorbisComment en Podlove), afspeelpositie voor elke aflevering en een handige 'slaap timer' (schudden om te resetten, volume langzaam zachter en herstel naar normale afspeelsnelheid)
-• Toegang tot wachtwoord-beveiligde podcasts en afleveringen
-• Doe je voordeel met 'paged feeds' (www.podlove.org/paged-feeds) - -DEEL & WAARDEER
-• Hou het beste van het beste bij door afleveringen als favoriet te markeren
-• Vindt die ene aflevering terug in de afspeelgeschiedenis of door te zoeken (in titels, shownotes en makers)
-• Deel podcasts en afleveringen via uitgebreide opties voor sociale media, WhatsApp, email en gPodder.net
-• Steun makers met Flattr-integratie, inclusief auto-Flattr - -HOUD DE CONTROLE -• Beheer automatische downloads: kies je podcasts, sluit mobiele netwerken uit, selecteer specifieke WiFi-verbindingen, eis dat de telefoon wordt opgeladen and bepaal tijden of intervals
-• Controleer geheugengebruik: stel een maximumaantal gedownloade afleveringen in, laat afleveringen automatisch verwijderen (maar sluit je favorieten en niet-afgespeelde afleveringen uit) en selecteer zelf je opslaglocatie
-• Gebruik AntennaPod in jouw taal: Nederlands! (Of in het Engels, Zweeds, Frans, Duits, Spaans, enz)
-• Voel je een kameleon: kies voor een licht of donker uiterlijk
-• Back-up je abonnementen via gPodder.net en geëxporteerde OPML-bestanden - -Doe mee met de AntennaPod gemeenschap!
-AntennaPod wordt regelmatig geüpdatet door vrijwilligers. En jij kan ook helpen, met code of commentaar! - -GitHub is de beste plek voor foutmeldingen, verzoekjes voor nieuwe functies en bijdragen aan de code:
-https://www.github.com/AntennaPod/AntennaPod - -Onze Google Group is de beste plek om je ideeën, favoriete podcast-momenten en waardering naar alle vrijwilligers te delen:
-https://groups.google.com/forum/#!forum/antennapod - -Heb je een vraag of wil je feedback geven? -https://twitter.com/@AntennaPod - -Transifex is de beste plek om te helpen met vertalen:
-https://www.transifex.com/antennapod/antennapod - -Check het Beta Testprogramma om de laatste features als eerst te krijgen:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/no/listing/fulldescription b/app/src/main/play/no/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/no/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/pl-PL/listing/fulldescription b/app/src/main/play/pl-PL/listing/fulldescription index 795addbc5..28e75d3cc 100644 --- a/app/src/main/play/pl-PL/listing/fulldescription +++ b/app/src/main/play/pl-PL/listing/fulldescription @@ -1,20 +1,43 @@ -AntennaPod jest menadżerem podcastów dla Androida 2.3.3 i nowszych na otwartej licencji. Oferuje wszystkie podstawowe funkcje których oczekuje się od podcathera, takie jak strumieniowanie oraz pobieranie odcinków, odświeżanie wszystkich wątków automatycznie i dodawanie ich do kolejki do późniejszego odsłuchania. Oprócz tego AntennaPod pozwala na flattr-owanie podcastów i odcinków z poziomu aplikacji. +AntennaPod jest programem katalogującym i odtwarzającym który daje możliwość natychmiastowego dostępu do milionów darmowych i płatnych podcastów. Od niezależych twórców po wielkich producentów takich jak BBC, NPR czy CNN. Dodawaj, importuj, eksportuj wątki bez przeszkód używając bazy iTunes, plików OPML czy po prostu przez linki RSS. Oszczędź wysiłek, baterię oraz pakiety danych mobilnych poprzez zaawansowaną kontrolę automatycznego pobierania (określone godziny, interwały czy sieci WiFi) oraz inteligentne usuwanie odcinków ( na podstawie ulubionych i ustawień opóźnień).
+Najważniejsze: pobieraj , streamuj lub kolejkuj odcinki oraz rozkoszuj się nimi jak tylko chcesz z możliwością zmiany prędkości odtwarzania, wsparciem rozdziałów i wyłącznikiem czasowym. Możesz nawet pokazać jak bardzo doceniach twórców dzięki integracji z Flattr. -Dotychczas zostały wdrożone następujące funkcjonalności: +Stworzone przez entuzjastów podcastów, AntennaPod jest darmowe w każdym słowa znaczeniu: otwarty kod, brak opłat i reklam. -* Pobieranie i strumieniowanie odcinków -* Zmienna prędkość odtwarzania (wymaga Presto Sound Library lub Prestissimo) -* Wsparcie dla wątków Atom i RSS -* Wsparcie dla kanałów i odcinków zabezpieczonych hasłem -* Support for searching iTunes listings -* Import i eksport OPML -Integracja z serwisem Flattr umożliwiająca flattring -* Widget odtwarzacza na home screen -* Wyszukiwanie -* Automatyczne aktualizaje wątków -* Automatyczne pobieranie nowych odcinków -* Timer snu -* Dostęp do katalogu podcastów na gpodder.net -* Synchronizację subskrypcji z gpodder.net -* Obsługuje rodziały MP3, VorbisComment i Podlove Simple. -* Wspiera stronicowane kanały (http://podlove.org/paged-feeds/) \ No newline at end of file +Wszystkie funkcje:
+ZAIMPORTUJ, ZORGANIZUJ I ODTWARZAJ
+• Dodawaj i importuj kanały poprzez iTunes, gPodder.net, z plików OPML, RSS i linków Atom
+• Zarządzaj odtwarzaniem zewsząd: widget na ekranie głównym, powiadomienia systemowe i kontrolery bluetooth
+• Delektuj się słuchaniem po swojemu z: zmienną prędkością odtwarzania, wsparciem rozdziałów (MP3, VorbisComment i Podlove), zapamiętywaniem miejsca zakończenia słuchania i zaawansowanym wyłącznikiem czasowym (potrząśnij aby zrestartować, zmiejszanie głośności i zwalnianie odtwarzania)
+• Dostęp do odcinków i kanałów chroniony hasłem
+• Wykorzystaj zapisane kanały (www.podlove.org/paged-feeds) + +ŚLEDŹ, DZIEL SIĘ I DOCENIAJ
+• Zapamiętywanie najlepszych z najlepszych poprzez dodawania odcinków do ulubionych
+• Wyszukiwanie odcinów w historii odtwarzania lub poprzez tytuł/przypisy
+• Dzial się odcinkami i wątkami poprzez zaawansowane opcje medii społecznych oraz emaila, serwisu gPodder.net lub poprzez eksport do OPML
+• Wsparcie twórców poprzez integrację z Flattr, również poprzez automatyczne flattr-owanie + +Kontroluj system
+• Ustaw automatyczne pobieranie zgodnie z własnymi preferencjami: wybieranie wątków, pobieranie tylko przez WiFi, wybór określonych sieci WiFi, wymaganie ładowania przy pobieraniu oraz ustawienie harmonogramu i interwałów
+• Zarządanie pamięcią poprzez ustawienia liczby pobranych odcinków z pomocą inteligentnego kasowania( na podstawie ulubionych i statusu odtwarzania) oraz wyboru lokalizacji
+• Używaj AntennaPod w swoim języku (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
+• Dostosowanie wyglądu jasną i ciemną skórką
+• Twórz kopie bezpieczeństwa swoich subskrypcji z pomocą zintegrowanego gPoddder.net oraz plików OPML + +Dołącz do społeczności AntennaPod
+AntennaPod jest ciągle rozwijane przez ochotników. Ty też możesz pomóc, kodem lub komentarzem! + +Sugestie ulepszeń, raporty błędów oraz dodatki do kodu prosimy kierować poprzez GitHub
+https://www.github.com/AntennaPod/AntennaPod + +Nasza grupa Google jest miejsce do dzielenia się pomysłami, ulubionymi momentami podcastów oraz miejscem gdzie można podziękować ochotnikom za ich pracę:
+https://groups.google.com/forum/#!forum/antennapod + +Masz pytanie lub chcesz przekazać nam swoją opinię ? +https://twitter.com/@AntennaPod + +Pomoc w tłumaczeniach na Transifex:
+https://www.transifex.com/antennapod/antennapod + +Jeśli chcesz otrzymywać najnowsze ulepszenia wcześniej niż inni rozważ dołączenie do programu beta testów:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod diff --git a/app/src/main/play/pl-PL/listing/title b/app/src/main/play/pl-PL/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/pl-PL/listing/title +++ b/app/src/main/play/pl-PL/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/pl/listing/fulldescription b/app/src/main/play/pl/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/pl/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/pl_PL/listing/fulldescription b/app/src/main/play/pl_PL/listing/fulldescription deleted file mode 100644 index c2c8cc597..000000000 --- a/app/src/main/play/pl_PL/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod jest programem katalogującym i odtwarzającym który daje możliwość natychmiastowego dostępu do milionów darmowych i płatnych podcastów. Od niezależych twórców po wielkich producentów takich jak BBC, NPR czy CNN. Dodawaj, importuj, eksportuj wątki bez przeszkód używając bazy iTunes, plików OPML czy po prostu przez linki RSS. Oszczędź wysiłek, baterię oraz pakiety danych mobilnych poprzez zaawansowaną kontrolę automatycznego pobierania (określone godziny, interwały czy sieci WiFi) oraz inteligentne usuwanie odcinków ( na podstawie ulubionych i ustawień opóźnień).
-Najważniejsze: pobieraj , streamuj lub kolejkuj odcinki oraz rozkoszuj się nimi jak tylko chcesz z możliwością zmiany prędkości odtwarzania, wsparciem rozdziałów i wyłącznikiem czasowym. Możesz nawet pokazać jak bardzo doceniach twórców dzięki integracji z Flattr. - -Stworzone przez entuzjastów podcastów, AntennaPod jest darmowe w każdym słowa znaczeniu: otwarty kod, brak opłat i reklam. - -Wszystkie funkcje:
-ZAIMPORTUJ, ZORGANIZUJ I ODTWARZAJ
-• Dodawaj i importuj kanały poprzez iTunes, gPodder.net, z plików OPML, RSS i linków Atom
-• Zarządzaj odtwarzaniem zewsząd: widget na ekranie głównym, powiadomienia systemowe i kontrolery bluetooth
-• Delektuj się słuchaniem po swojemu z: zmienną prędkością odtwarzania, wsparciem rozdziałów (MP3, VorbisComment i Podlove), zapamiętywaniem miejsca zakończenia słuchania i zaawansowanym wyłącznikiem czasowym (potrząśnij aby zrestartować, zmiejszanie głośności i zwalnianie odtwarzania)
-• Dostęp do odcinków i kanałów chroniony hasłem
-• Wykorzystaj zapisane kanały (www.podlove.org/paged-feeds) - -ŚLEDŹ, DZIEL SIĘ I DOCENIAJ
-• Zapamiętywanie najlepszych z najlepszych poprzez dodawania odcinków do ulubionych
-• Wyszukiwanie odcinów w historii odtwarzania lub poprzez tytuł/przypisy
-• Dzial się odcinkami i wątkami poprzez zaawansowane opcje medii społecznych oraz emaila, serwisu gPodder.net lub poprzez eksport do OPML
-• Wsparcie twórców poprzez integrację z Flattr, również poprzez automatyczne flattr-owanie - -Kontroluj system
-• Ustaw automatyczne pobieranie zgodnie z własnymi preferencjami: wybieranie wątków, pobieranie tylko przez WiFi, wybór określonych sieci WiFi, wymaganie ładowania przy pobieraniu oraz ustawienie harmonogramu i interwałów
-• Zarządanie pamięcią poprzez ustawienia liczby pobranych odcinków z pomocą inteligentnego kasowania( na podstawie ulubionych i statusu odtwarzania) oraz wyboru lokalizacji
-• Używaj AntennaPod w swoim języku (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Dostosowanie wyglądu jasną i ciemną skórką
-• Twórz kopie bezpieczeństwa swoich subskrypcji z pomocą zintegrowanego gPoddder.net oraz plików OPML - -Dołącz do społeczności AntennaPod
-AntennaPod jest ciągle rozwijane przez ochotników. Ty też możesz pomóc, kodem lub komentarzem! - -Sugestie ulepszeń, raporty błędów oraz dodatki do kodu prosimy kierować poprzez GitHub
-https://www.github.com/AntennaPod/AntennaPod - -Nasza grupa Google jest miejsce do dzielenia się pomysłami, ulubionymi momentami podcastów oraz miejscem gdzie można podziękować ochotnikom za ich pracę:
-https://groups.google.com/forum/#!forum/antennapod - -Masz pytanie lub chcesz przekazać nam swoją opinię ? -https://twitter.com/@AntennaPod - -Pomoc w tłumaczeniach na Transifex:
-https://www.transifex.com/antennapod/antennapod - -Jeśli chcesz otrzymywać najnowsze ulepszenia wcześniej niż inni rozważ dołączenie do programu beta testów:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/pt-BR/listing/fulldescription b/app/src/main/play/pt-BR/listing/fulldescription index 735334e0c..e40d3f450 100644 --- a/app/src/main/play/pt-BR/listing/fulldescription +++ b/app/src/main/play/pt-BR/listing/fulldescription @@ -1,40 +1,43 @@ -O AntennaPod é um gestor de podcasts que lhe permite aceder a milhões de podcasts (gratuitos ou pagos), a partir de diversas fontes tais como as estações BBC, NPR e CNN. A adição de fontes é muito fácil através das base de dados iTunes ou gPodder, ficheiros OPML ou fontes RSS. Poupe tempo, economize energia e dados móveis através dos mecanismos de controlo de transferência de episódios (possibilidade de especificar intervalos ou horas para as transferências e redes WiFi) e de eliminação de episódios (de acordo com as suas preferências).
-Mas ainda mais importante: pode transferir, emitir ou colocar episódios na lista de reprodução ao seu gosto, pode utilizar velocidades variáveis de reprodução, tem suporte a capítulos e um temporizador. Pode também mostrar o seu apreço aos disponibilizadores dos episódios através do serviço Flattr. +AntennaPod é um gerenciador e reprodutor de podcasts que te dá acesso instantâneo a milhões de podcasts gratuitos e pagos, desde podcasters independentes até grandes editores como BBC, NPR e CNN. Adicione, importe e exporte seus feeds sem complicações utilizando a base de dados do iTunes, arquivos OPML ou simples URLs RSS. Economize esforços, bateria e uso de dados móveis com poderosos controles de automação para baixar episódios (especifique horários, intervalos e redes WiFi) e excluir episódios (baseado nos seus favoritos e configurações de adiamento).
+Mas o mais importante: Baixe, realize streaming ou enfilere episódios e desfrute deles da maneira que quiser com velocidades de reprodução ajustáveis, suporte para capítulos e cronômetro. Você pode até mostrar o seu apreço aos criadores de conteúdo com a integração com o Flattr. -Criado por entusiastas de podcasts, o AntennaPod é livre em todos os sentidos da palavra: open source, gratuito e sem publicidade. +Desenvolvido por fãs de podcasts, AntennaPod é livre em todos os sentidos da palavra; open source, sem custos, sem propagandas. -Funcionalidades:
-Importação, organização e reprodução
-• Adicione e importe fontes existentes nos diretórios iTunes e gPodder.net, ficheiros OPML e ligações ATOM e RSS
-• Gestão de podcasts através do widget, barra de notificações e controlos de auriculares ou auscultadores
-• Velocidade variável de reprodução, suporte a capítulos (MP3, VorbisComment e Podlove), memorização da posição de reprodução e um temporizador avançado (agite para repor ou baixar e aumentar o volume)
-• Acesso a fontes e episódios protegidos por palavra-passe
-• Possibilidade de subscrever fontes paginadas (www.podlove.org/paged-feeds) +Recursos disponíveis:
+IMPORTE, ORGANIZE E TOQUE
+• Adicione and importe feeds pelo iTunes e diretorios gPodder.net, arquivos OPML e links RSS ou Atom
+• Gerencie suas reproduções de qualquer lugar: widget da tela inicial, notificações de sistema e fone de ouvido e controles bluetooth
+• Ouça do seu jeito com velocidade de reprodução ajustável, suporte a capítulos (MP3, VorbisComment e Podlove), marcador da posição de reprodução e um despertador avançado (chacoalhe para reiniciar, volume reduzido e reprodução desacelerada)
+• Acesse feeds e episódios protegidos por senha +• Faça uso de feeds paginados (www.podlove.org/paged-feeds) -Monitorização, partilha e suporte
-• Monitorize os seus podcasts preferidos marcando-os como favoritos
-• Localize um episódio através do histórico de reprodução ou através de uma pesquisa (títulos e notas)
-• Partilhe episódios e fontes nas redes sociais, por e-mail, no diretório gPodder.net ou através de ficheiros OPML
-• Ajude os criadores de conteúdos através do serviço Flattr +MANTENHA-SE ATUALIZADO, COMPARTILHE E APRECIE
+• Guarde o melhor do melhor marcando episódios como favoritos
+• Encontre aquele episódio específico através do histórico de execução ou pelo sistema de busca (através de títulos e anotações)
+• Compartilhe episódios e feeds através de opções em redes sociais, email, os serviços da gPodder.net e exportação OPML
+• Apoie os criadores de conteúdo com a integração com o Flattr -Controlar o sistema
-• Controle todas as transferÊncias automáticas: escolha as fontes, exclua redes móveis, especifique as redes WiFi, indique se o telefone deve estar a ser carregado e defina as horas ou intervalos das transferências
-• Faça a gestão do armazenamento através da cache de episódios, da eliminação inteligente (de acordo com os seus favoritos e estado de reprodução) e selecionado a localização de armazenamento
-• Utilize o AntennaPod no seu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapte-se ao seu ambiente através dos temas claro ou escuro
-• Salvaguarde as suas subscrições com a integração gPodder.net ou através da exportação OPML +CONTROLE O SISTEMA +• Tenha controle sobre a automação dos downloads: escolha feeds, exclua redes móveis, selecione redes específicas de WiFi, exija que o telefone esteja sendo carregado e defina horários ou intervalos
+• Gerencie o armazenamento configurando a quantidade de episódios em cache, exclusão inteligente dos episódios (baseada nos seus favoritos e status de reprodução)
+• Use o AntennaPod no seu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
+• Adapte-se ao ambiente utilizando os temas claro ou escuro
+• Faça backup das suas inscrições com a integração ao gPodder.net e exportação de OPML -Integre a comunidade do AntennaPod!
-O AntennaPod é desenvolvido por voluntários. Você também pode contribuir na programação ou reportando os erros encontrados! +Junte-se à comunidade AntennaPod!
+O AntennaPod está sob constante desenvolvimento através de voluntários. Você também pode contribuir, com código ou um comentário! -O GitHub é o local certo para os pedidos de funcionalidades, relatórios de erros e contribuições:
-www.github.com/AntennaPod/AntennaPod +Vá ao GitHub para solicitar funcionalidades, reportar bugs e contribuir com código:
+https://www.github.com/AntennaPod/AntennaPod -O nosso grupo Google é o local certo para partilhar ideias e agradecer aos nossos voluntários:
+Nosso grupo no Google é o lugar para compartilhar suas idéias, momentos de podcasts favoritos e agradecer aos voluntários:
https://groups.google.com/forum/#!forum/antennapod -O Transifex é o local no qual pode ajudar a traduzir a aplicação:
-www.transifex.com/antennapod/antennapod +Tem uma dúvida ou um comentário? +https://twitter.com/@AntennaPod -Junte-se ao nosso programa de testes para obter as funcionalidades mais recentes:
-www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file +Transifex é o lugar para ajudar com as traduções:
+https://www.transifex.com/antennapod/antennapod + +Cheque nosso programa de beta testing para receber as atualizações mais recentes primeiro:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/pt-BR/listing/title b/app/src/main/play/pt-BR/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/pt-BR/listing/title +++ b/app/src/main/play/pt-BR/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/pt-PT/listing/title b/app/src/main/play/pt-PT/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/pt-PT/listing/title +++ b/app/src/main/play/pt-PT/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/pt/listing/fulldescription b/app/src/main/play/pt/listing/fulldescription deleted file mode 100644 index 58d88eb24..000000000 --- a/app/src/main/play/pt/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -O AntennaPod é um gestor de podcasts que lhe permite aceder a milhões de podcasts, gratuitos ou pagos, a partir de diversas fontes tais como as estações BBC, NPR e CNN. A adição de fontes é muito fácil através das base de dados iTunes ou gPodder, ficheiros OPML ou fontes RSS. Poupe tempo, economize bateria e dados móveis através dos mecanismos de controlo de descargas de episódios (possibilidade de especificar intervalos ou horas para as descargas e redes WiFi) e de eliminação de episódios (de acordo com as suas preferências).
-Mas ainda mais importante: pode descarregar, emitir ou colocar episódios na lista de reprodução ao seu gosto, pode utilizar velocidades variáveis de reprodução, tem suporte a capítulos e um temporizador. Pode também mostrar o seu apreço aos criadores dos episódios através do serviço Flattr. - -Criado por entusiastas de podcasts, o AntennaPod é livre em todos os sentidos da palavra: open source, gratuito e sem publicidade. - -Funcionalidades:
-Importação, organização e reprodução
-• Adicione e importe fontes existentes nos diretórios iTunes e gPodder.net, ficheiros OPML e ligações ATOM e RSS
-• Gestão de podcasts através do widget, barra de notificações e controlos de auriculares ou auscultadores
-• Velocidade variável de reprodução, suporte a capítulos (MP3, VorbisComment e Podlove), memorização da posição de reprodução e um temporizador avançado (agite para repor, baixar e aumentar o volume)
-• Acesso a fontes e episódios protegidos por palavra-passe
-• Possibilidade de subscrever fontes paginadas (www.podlove.org/paged-feeds) - -Monitorização, partilha e suporte
-• Monitorize os seus podcasts preferidos marcando-os como favoritos
-• Localize um episódio através do histórico de reprodução ou através de uma pesquisa (títulos e notas)
-• Partilhe episódios e fontes nas redes sociais, por e-mail, no diretório gPodder.net ou através de ficheiros OPML
-• Ajude os criadores de conteúdos através do serviço Flattr - -Controlo do sistema
-• Controle todas as descargas automáticas: escolha as fontes, exclua redes móveis, especifique as redes Wi-Fi, indique se o telefone deve estar a ser carregado e defina as horas ou intervalos das descargas
-• Faça a gestão do armazenamento através da cache de episódios, da eliminação inteligente (de acordo com os seus favoritos e estado de reprodução) e selecionado a localização de armazenamento
-• Utilize o AntennaPod no seu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapte-se ao seu ambiente através dos temas claro ou escuro
-• Salvaguarde as suas subscrições com a integração gPodder.net ou através da exportação OPML - -Integre a comunidade do AntennaPod!
-O AntennaPod é desenvolvido por voluntários. Você também pode contribuir na programação ou reportando os erros encontrados! - -O GitHub é o local certo para os pedidos de funcionalidades, relatórios de erros e contributos:
-https://www.github.com/AntennaPod/AntennaPod - -O nosso grupo Google é o local certo para partilhar ideias e agradecer aos nossos voluntários:
-https://groups.google.com/forum/#!forum/antennapod - -Tem alguma questão ou comentário a fazer? -https://twitter.com/@AntennaPod - -O Transifex é o local no qual pode ajudar a traduzir a aplicação:
-https://www.transifex.com/antennapod/antennapod - -Junte-se ao nosso programa Beta para obter as funcionalidades mais recentes:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/pt_BR/listing/fulldescription b/app/src/main/play/pt_BR/listing/fulldescription deleted file mode 100644 index e40d3f450..000000000 --- a/app/src/main/play/pt_BR/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod é um gerenciador e reprodutor de podcasts que te dá acesso instantâneo a milhões de podcasts gratuitos e pagos, desde podcasters independentes até grandes editores como BBC, NPR e CNN. Adicione, importe e exporte seus feeds sem complicações utilizando a base de dados do iTunes, arquivos OPML ou simples URLs RSS. Economize esforços, bateria e uso de dados móveis com poderosos controles de automação para baixar episódios (especifique horários, intervalos e redes WiFi) e excluir episódios (baseado nos seus favoritos e configurações de adiamento).
-Mas o mais importante: Baixe, realize streaming ou enfilere episódios e desfrute deles da maneira que quiser com velocidades de reprodução ajustáveis, suporte para capítulos e cronômetro. Você pode até mostrar o seu apreço aos criadores de conteúdo com a integração com o Flattr. - -Desenvolvido por fãs de podcasts, AntennaPod é livre em todos os sentidos da palavra; open source, sem custos, sem propagandas. - -Recursos disponíveis:
-IMPORTE, ORGANIZE E TOQUE
-• Adicione and importe feeds pelo iTunes e diretorios gPodder.net, arquivos OPML e links RSS ou Atom
-• Gerencie suas reproduções de qualquer lugar: widget da tela inicial, notificações de sistema e fone de ouvido e controles bluetooth
-• Ouça do seu jeito com velocidade de reprodução ajustável, suporte a capítulos (MP3, VorbisComment e Podlove), marcador da posição de reprodução e um despertador avançado (chacoalhe para reiniciar, volume reduzido e reprodução desacelerada)
-• Acesse feeds e episódios protegidos por senha -• Faça uso de feeds paginados (www.podlove.org/paged-feeds) - -MANTENHA-SE ATUALIZADO, COMPARTILHE E APRECIE
-• Guarde o melhor do melhor marcando episódios como favoritos
-• Encontre aquele episódio específico através do histórico de execução ou pelo sistema de busca (através de títulos e anotações)
-• Compartilhe episódios e feeds através de opções em redes sociais, email, os serviços da gPodder.net e exportação OPML
-• Apoie os criadores de conteúdo com a integração com o Flattr - -CONTROLE O SISTEMA -• Tenha controle sobre a automação dos downloads: escolha feeds, exclua redes móveis, selecione redes específicas de WiFi, exija que o telefone esteja sendo carregado e defina horários ou intervalos
-• Gerencie o armazenamento configurando a quantidade de episódios em cache, exclusão inteligente dos episódios (baseada nos seus favoritos e status de reprodução)
-• Use o AntennaPod no seu idioma (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapte-se ao ambiente utilizando os temas claro ou escuro
-• Faça backup das suas inscrições com a integração ao gPodder.net e exportação de OPML - -Junte-se à comunidade AntennaPod!
-O AntennaPod está sob constante desenvolvimento através de voluntários. Você também pode contribuir, com código ou um comentário! - -Vá ao GitHub para solicitar funcionalidades, reportar bugs e contribuir com código:
-https://www.github.com/AntennaPod/AntennaPod - -Nosso grupo no Google é o lugar para compartilhar suas idéias, momentos de podcasts favoritos e agradecer aos voluntários:
-https://groups.google.com/forum/#!forum/antennapod - -Tem uma dúvida ou um comentário? -https://twitter.com/@AntennaPod - -Transifex é o lugar para ajudar com as traduções:
-https://www.transifex.com/antennapod/antennapod - -Cheque nosso programa de beta testing para receber as atualizações mais recentes primeiro:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/ro/listing/shortdescription b/app/src/main/play/ro/listing/shortdescription index 4eceefbb7..7afb5a62d 100644 --- a/app/src/main/play/ro/listing/shortdescription +++ b/app/src/main/play/ro/listing/shortdescription @@ -1 +1 @@ -Easy-to-use, flexible and open-source podcast manager and player \ No newline at end of file +Easy-to-use, flexible and open-source podcast & radio manager and player \ No newline at end of file diff --git a/app/src/main/play/ro/listing/title b/app/src/main/play/ro/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/ro/listing/title +++ b/app/src/main/play/ro/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/ro_RO/listing/fulldescription b/app/src/main/play/ro_RO/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/ro_RO/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/ru-RU/listing/fulldescription b/app/src/main/play/ru-RU/listing/fulldescription index e3e1635ff..9b68a06c0 100644 --- a/app/src/main/play/ru-RU/listing/fulldescription +++ b/app/src/main/play/ru-RU/listing/fulldescription @@ -1,20 +1,43 @@ -AntennaPod — это open-source менеджер подкастов для Android 2.3.3 и выше. Он предлагает все основные функции подкаст-менеджера, такие как воспроизведение из сети, загрузка выпусков, автоматическое обновление каналов и добавление выпусков в очередь. Кроме того, AntennaPod позволяет совершать пожертвования подкаст-каналам, посредством Flattr, прямо из приложения. +AntennaPod — менеджер и проигрыватель подкастов, который обеспечит Вас мгновенным доступом к миллионам бесплатных и платных подкастов, как от независимых подкастеров, так и крупных издательских домов, например, BBC, NPR и CNN. С лёгкостью добавляйте, импортируйте и экспортируйте их каналы используя каталог подкастов iTunes, файлы OPML или адреса каналов RSS. Сберегите усилия, заряд батареи и мобильный трафик при помощи мощных средств автоматизации загрузки выпусков (фильтрация, указание времени и интервалов, а также сетей WiFi) и их удаления (в соответствии с настройками избранного и ожидания).
+Но самое главное: Загружайте, слушайте с эфира или ставьте в очередь и получайте удовольствие от их прослушивания применяя регулируемую скорость воспроизведения, оглавления и таймер сна. Вы даже можете выразить свою благодарность создателям аудио посредством интеграции с Flattr. -Были реализованы следующие возможности: +Созданное поклонниками подкастов, AntennaPod — бесплатное и свободное приложение без рекламы и платежей. -* Загрузка и потоковое воспроизведение выпусков -* Изменение скорости воспроизведения (требует Presto Sound Library или Prestissimo) -* Поддержка каналов в форматах Atom и RSS -* Поддержка защищенных паролем каналов и выпусков -* Поддержка поиска по каталогу iTunes -* Импорт и экспорт OPML -* Интеграция с Flattr, включая автоматическую поддержку через него -* Виджет для домашнего экрана -* Поиск -* Автоматическое обновление каналов -* Автоматическая загрузка новых выпусков -* Таймер сна -* Доступ к каталогу подкастов на gpodder.net -* Синхронизация подписок с сервисом gpodder.net -* Поддержка оглавления MP3, VorbisComment и Podlove Simple Chapters -* Поддержка постраничных лент (http://podlove.org/paged-feeds/) \ No newline at end of file +Все возможности:
+Импортируйте, систематизируйте и прослушивайте
+• Добавление и импорт каналов через каталоги iTunes и gPodder.net, файлы OPML и ссылки на каналы RSS или Atom
+• Всевозможное управление воспроизведением: виджетом, системным уведомлением и кнопками проводных и беспроводных гарнитур
+• Приятное, по вашему вкусу, прослушивание применяя регулировку скорости воспроизведения, оглавления (MP3, VorbisComment и Podlove), запоминание места воспроизведения и продвинутый таймер сна (сброс при встряхивание, снижение громкости и замедление воспроизведения)
+• Доступ к каналам и выпускам защищенным паролем
+• Использует преимущества постраничных лент (www.podlove.org/paged-feeds) + +Отслеживайте, делитесь и благодарите
+• Отслеживайте лучших из лучших, помещая выпуски в избранное
+• Поиск того самого выпуска в истории воспроизведения или по контексту (заголовки и заметки к выпуску)
+• Разнообразные возможности поделиться выпусками и каналами через социальные службы и e-mail, услуги gPodder.net и экспорт в OPML
+• Поддержка создателей аудио при помощи интеграции с Flattr, в том числе и автоматически + +Управляйте системой
+• Управление автоматической загрузкой: выбор отдельных каналов, отбор выпусков на основе ключевых слов, запрет на использование мобильных сетей, выбор отдельных точек доступа WiFi, только во время зарядки телефона и задание времени и интервалов
+• Управление хранением путём задания количества выпусков в кэше, автоудаление (на основании настроек избранного и статуса прослушивания) и выбор предпочитаемого расположения
+• AntennaPod на родном Вам языке (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH, RU)
+• Приспосабливается к Вашему окружению посредством светлой или тёмной темы
+• Резервирование Ваших подписок путём интеграции с gPodder.net и экпорта в OPML + +Присоединяйтесь к сообществу AntennaPod!
+AntennaPod постоянно развивается силами добровольцев. Вы тоже можете сделать свой вклад при помощи кода или комментария! + +Посещайте GitHub для запроса новых возможностей, уведомления об ошибках и внесения кода:
+https://www.github.com/AntennaPod/AntennaPod + +Поделитесь идеями, любимыми мгновениями прослушивания и благодарностью со всеми добровольцами из нашей группы Google:
+https://groups.google.com/forum/#!forum/antennapod + +Появились вопросы и обратная связь? +https://twitter.com/@AntennaPod + +Помогайте с переводом приложения на Transifex:
+https://www.transifex.com/antennapod/antennapod + +Попробуйте себя в программе Бета тестирования и получите доступ к распоследним возможностям в числе первых:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/ru-RU/listing/title b/app/src/main/play/ru-RU/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/ru-RU/listing/title +++ b/app/src/main/play/ru-RU/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/ru_RU/listing/fulldescription b/app/src/main/play/ru_RU/listing/fulldescription deleted file mode 100644 index 9b68a06c0..000000000 --- a/app/src/main/play/ru_RU/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod — менеджер и проигрыватель подкастов, который обеспечит Вас мгновенным доступом к миллионам бесплатных и платных подкастов, как от независимых подкастеров, так и крупных издательских домов, например, BBC, NPR и CNN. С лёгкостью добавляйте, импортируйте и экспортируйте их каналы используя каталог подкастов iTunes, файлы OPML или адреса каналов RSS. Сберегите усилия, заряд батареи и мобильный трафик при помощи мощных средств автоматизации загрузки выпусков (фильтрация, указание времени и интервалов, а также сетей WiFi) и их удаления (в соответствии с настройками избранного и ожидания).
-Но самое главное: Загружайте, слушайте с эфира или ставьте в очередь и получайте удовольствие от их прослушивания применяя регулируемую скорость воспроизведения, оглавления и таймер сна. Вы даже можете выразить свою благодарность создателям аудио посредством интеграции с Flattr. - -Созданное поклонниками подкастов, AntennaPod — бесплатное и свободное приложение без рекламы и платежей. - -Все возможности:
-Импортируйте, систематизируйте и прослушивайте
-• Добавление и импорт каналов через каталоги iTunes и gPodder.net, файлы OPML и ссылки на каналы RSS или Atom
-• Всевозможное управление воспроизведением: виджетом, системным уведомлением и кнопками проводных и беспроводных гарнитур
-• Приятное, по вашему вкусу, прослушивание применяя регулировку скорости воспроизведения, оглавления (MP3, VorbisComment и Podlove), запоминание места воспроизведения и продвинутый таймер сна (сброс при встряхивание, снижение громкости и замедление воспроизведения)
-• Доступ к каналам и выпускам защищенным паролем
-• Использует преимущества постраничных лент (www.podlove.org/paged-feeds) - -Отслеживайте, делитесь и благодарите
-• Отслеживайте лучших из лучших, помещая выпуски в избранное
-• Поиск того самого выпуска в истории воспроизведения или по контексту (заголовки и заметки к выпуску)
-• Разнообразные возможности поделиться выпусками и каналами через социальные службы и e-mail, услуги gPodder.net и экспорт в OPML
-• Поддержка создателей аудио при помощи интеграции с Flattr, в том числе и автоматически - -Управляйте системой
-• Управление автоматической загрузкой: выбор отдельных каналов, отбор выпусков на основе ключевых слов, запрет на использование мобильных сетей, выбор отдельных точек доступа WiFi, только во время зарядки телефона и задание времени и интервалов
-• Управление хранением путём задания количества выпусков в кэше, автоудаление (на основании настроек избранного и статуса прослушивания) и выбор предпочитаемого расположения
-• AntennaPod на родном Вам языке (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH, RU)
-• Приспосабливается к Вашему окружению посредством светлой или тёмной темы
-• Резервирование Ваших подписок путём интеграции с gPodder.net и экпорта в OPML - -Присоединяйтесь к сообществу AntennaPod!
-AntennaPod постоянно развивается силами добровольцев. Вы тоже можете сделать свой вклад при помощи кода или комментария! - -Посещайте GitHub для запроса новых возможностей, уведомления об ошибках и внесения кода:
-https://www.github.com/AntennaPod/AntennaPod - -Поделитесь идеями, любимыми мгновениями прослушивания и благодарностью со всеми добровольцами из нашей группы Google:
-https://groups.google.com/forum/#!forum/antennapod - -Появились вопросы и обратная связь? -https://twitter.com/@AntennaPod - -Помогайте с переводом приложения на Transifex:
-https://www.transifex.com/antennapod/antennapod - -Попробуйте себя в программе Бета тестирования и получите доступ к распоследним возможностям в числе первых:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/sl_SI/listing/fulldescription b/app/src/main/play/sl_SI/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/sl_SI/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/sv-SE/listing/fulldescription b/app/src/main/play/sv-SE/listing/fulldescription index bdf641cf2..84b7d9681 100644 --- a/app/src/main/play/sv-SE/listing/fulldescription +++ b/app/src/main/play/sv-SE/listing/fulldescription @@ -12,14 +12,14 @@ IMPORTERA, ORGANISERA OCH SPELA
• Dra nytta av siduppdelade flöden (www.podlove.ord/paged-feeds) SPÅRA, DELA & UPPSKATTA
-• Spåra det bästa av det bästa med favoritmarkering av episoder
+• Håll ordning på de bästa av de bästa med favoritmarkering av episoder
• Hitta just den där episoden i uppspelningshistoriken eller genom sökning (titel och shownotes)
• Dela episoder och flöden med avancerade vald för social media och och email, tjänsten gPodder.net och via OPML export
• Stöd innehållsskaparna via integrering av Flattr och automatisk flattring KONTROLLERA SYSTEMET
-• Ta kontroll över automatisk nedladdning: välj flöden, exkludera mobilnätverk, välj specifika WiFi nätver, kräv att telefonen är inkopplad för laddning och sätt tider eller intervall
-• Hantera lagringsutrymme genom att välja antalet cachade episoder, smart borttagning (baserat på dina favoriter och uppspelningsstatus) och välj den plats du föredrar
+• Ta kontroll över automatisk nedladdning: välj flöden, exkludera mobilnätverk, välj specifika WiFi nätverk, kräv att telefonen är inkopplad för laddning och sätt tider eller intervall för körning
+• Hantera lagringsutrymme genom att välja antalet cachade episoder, smart borttagning (baserat på dina favoriter och uppspelningsstatus) och välj den lagringsplats du föredrar
• Använd AntennaPod på ditt språk (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
• Anpassa till din omgivning med det ljusa och mörka temat
• Ta backup av dina prenumerationer med integreringen av gPodder.net och OPML exportering @@ -28,13 +28,16 @@ KONTROLLERA SYSTEMET
AntennaPod är under aktiv utveckling av volontärer. Du kan också bidra, med kod eller kommentarer! GitHub är platsen att gå till för att be om funktioner, skapa buggrapporter eller bidra med kod:
-www.github.com/AntennaPod/AntennaPod +https://www.github.com/AntennaPod/AntennaPod Vår Google Group är platsen för att dela idéer, dina favoritögonblick med podcasting och din uppskattning till volontärerna:
https://groups.google.com/forum/#!forum/antennapod +Har du frågor eller vill ge feedback? +https://twitter.com/@AntennaPod + Transifex är platsen att gå till för att hjälpa till med översättningen:
-www.transifex.com/antennapod/antennapod +https://www.transifex.com/antennapod/antennapod Kolla in vårat Beta Testing program för att få de senaste funktionerna först:
-www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file +https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/sv-SE/listing/title b/app/src/main/play/sv-SE/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/sv-SE/listing/title +++ b/app/src/main/play/sv-SE/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/sv_SE/listing/fulldescription b/app/src/main/play/sv_SE/listing/fulldescription deleted file mode 100644 index 84b7d9681..000000000 --- a/app/src/main/play/sv_SE/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod är en podcasthanterare och spelare som ger dig omedelbar tillgång till millioner av gratis och betalda podcasts, allt ifrån oberoende podcasters till publiceringsjättar som BBC, NPR och CNN. Lägg till, importera och exportera enkelt deras flöden med hjälp av iTunes podcastdatabas, OPML filer eller enkla RSS URL:er. Spara tid, batterikraft och mobildata med kraftfull automatisering för nedladdning (specifiera tider, intervall och WiFi-nätverk) och borttagning av episoder (baserat på dina favoriter och fördröjningsinställningar).
-Men viktigast: Ladda ner, strömma eller köa episoder och avnjut dem på ditt sätt med justerbar uppspelningshastighet, kapitelstöd och en sovtimer. Du kan till och med visa din uppskattning av innehållsskaparna med vår integrering av Flattr. - -Gjord av podcastenthusiaster, AntennaPod är fri i alla ordets bemärkelser: öppen källkod, inga kostnader, ingen reklam. - -Alla funktioner:
-IMPORTERA, ORGANISERA OCH SPELA
-• Lägg till och importera flöden via iTunes och gPodder.net, OPML filer och RSS eller Atom länkar
-• Hantera uppspelningen från vartsomhelst: hemskärmswidget, aviseringsfältet och hörlurs/bluetoth-kontroller
-• Njut av att lyssna på ditt sätt med justerbar uppspelningshastighet, kapitelstöd (MP4, VorbisComment och Podlove), ihågkommen uppspelningsposition och en avancerad sömntimer (skaka för återställaning, sänk volymen och sänk hastigheten)
-• Kom åt lösenordsskyddade flöden och episoder
-• Dra nytta av siduppdelade flöden (www.podlove.ord/paged-feeds) - -SPÅRA, DELA & UPPSKATTA
-• Håll ordning på de bästa av de bästa med favoritmarkering av episoder
-• Hitta just den där episoden i uppspelningshistoriken eller genom sökning (titel och shownotes)
-• Dela episoder och flöden med avancerade vald för social media och och email, tjänsten gPodder.net och via OPML export
-• Stöd innehållsskaparna via integrering av Flattr och automatisk flattring - -KONTROLLERA SYSTEMET
-• Ta kontroll över automatisk nedladdning: välj flöden, exkludera mobilnätverk, välj specifika WiFi nätverk, kräv att telefonen är inkopplad för laddning och sätt tider eller intervall för körning
-• Hantera lagringsutrymme genom att välja antalet cachade episoder, smart borttagning (baserat på dina favoriter och uppspelningsstatus) och välj den lagringsplats du föredrar
-• Använd AntennaPod på ditt språk (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Anpassa till din omgivning med det ljusa och mörka temat
-• Ta backup av dina prenumerationer med integreringen av gPodder.net och OPML exportering - -Gå med i AntennaPods gemenskap!
-AntennaPod är under aktiv utveckling av volontärer. Du kan också bidra, med kod eller kommentarer! - -GitHub är platsen att gå till för att be om funktioner, skapa buggrapporter eller bidra med kod:
-https://www.github.com/AntennaPod/AntennaPod - -Vår Google Group är platsen för att dela idéer, dina favoritögonblick med podcasting och din uppskattning till volontärerna:
-https://groups.google.com/forum/#!forum/antennapod - -Har du frågor eller vill ge feedback? -https://twitter.com/@AntennaPod - -Transifex är platsen att gå till för att hjälpa till med översättningen:
-https://www.transifex.com/antennapod/antennapod - -Kolla in vårat Beta Testing program för att få de senaste funktionerna först:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/sw_KE/listing/fulldescription b/app/src/main/play/sw_KE/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/sw_KE/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/te/listing/fulldescription b/app/src/main/play/te/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/te/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/tr-TR/listing/fulldescription b/app/src/main/play/tr-TR/listing/fulldescription index 7ea4d906d..90bda48af 100644 --- a/app/src/main/play/tr-TR/listing/fulldescription +++ b/app/src/main/play/tr-TR/listing/fulldescription @@ -1,20 +1,43 @@ -AntennaPod, Android 2.3.3 ve üzeri için açık kaynak kodlu cepyayını yöneticisidir. Bölümleri yayınlama ve indirme, beslemelerin otomatik olarak yenilenmesi veya daha sonra dinlemek için sıraya konması gibi bir cepyayını yakalayıcısından beklediğiniz tüm temel özellikleri içerir. Hatta cepyayınlarını ve bölümleri uygulama içinden flattr aracılığıyla desteklemenize olanak verir. +AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
+But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. -Şimdiye kadar aşağıdaki özellikler eklenmiştir: +Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. -* Bölümlerin indirilmesi ve yayınlanması -* Değişken çalma hızı (Presto Sound Library veya Prestissimo gerekir) -* Atom ve RSS besleme desteği -* Şifre korumalı besleme ve bölüm desteği -* iTunes listelerinde arama yapma desteği -* OPML içe aktarma ve dışa aktarma -* Otomatik flatter içeren Flattr entegrasyonu -* Ev ekranı oynatıcı widget'ı -* Arama -* Otomatik besleme güncellemeleri -* Yeni bölümlerin otomatik indirilmesi -*Uyku zamanlayıcı -* gpodder.net cepyayını dizinine erişim -* gpodder.net servisi ile üyelik senkronizasyonu -* MP3 kısımları, VorbisComment kısımlar ve Podlove Simple Chapter desteği -* Sayfalanmış beslemeler desteği (http://podlove.org/paged-feeds/) \ No newline at end of file +Tüm özellikler:
+IMPORT, ORGANIZE AND PLAY
+• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
+• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
+• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
+• Access password-protected feeds and episodes
+• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE
+• Keep track of the best of the best by marking episodes as favourites
+• Find that one episode through the playback history or by searching (titles and shownotes)
+• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
+• Support content creators with Flattr integration including automatic flattring + +SİSTEMİ KONTROL ET
+• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
+• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
+• AntennaPod'u kendi dilinizde kullanın (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
+• Adapt to your environment using the light and dark theme
+• Back-up your subscriptions with the gPodder.net integration and OPML export + +AntennaPod topluluğuna katılın!
+AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:
+https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
+https://groups.google.com/forum/#!forum/antennapod + +Bir sorunuz mu var veya bize geri bildirim bırakmak mı istiyorsunuz? +https://twitter.com/@AntennaPod + +Tercümelere yardım etmenin yeri Transifex:
+https://www.transifex.com/antennapod/antennapod + +En son özellikleri ilk önce almak isterseniz Beta Testing programımıza katılın:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/tr-TR/listing/title b/app/src/main/play/tr-TR/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/tr-TR/listing/title +++ b/app/src/main/play/tr-TR/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/tr/listing/fulldescription b/app/src/main/play/tr/listing/fulldescription deleted file mode 100644 index 90bda48af..000000000 --- a/app/src/main/play/tr/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -Tüm özellikler:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -SİSTEMİ KONTROL ET
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• AntennaPod'u kendi dilinizde kullanın (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -AntennaPod topluluğuna katılın!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Bir sorunuz mu var veya bize geri bildirim bırakmak mı istiyorsunuz? -https://twitter.com/@AntennaPod - -Tercümelere yardım etmenin yeri Transifex:
-https://www.transifex.com/antennapod/antennapod - -En son özellikleri ilk önce almak isterseniz Beta Testing programımıza katılın:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/uk/listing/shortdescription b/app/src/main/play/uk/listing/shortdescription index ac638de72..a5636500d 100644 --- a/app/src/main/play/uk/listing/shortdescription +++ b/app/src/main/play/uk/listing/shortdescription @@ -1 +1 @@ -Менеджер подкастів для Android з відкритими вихідними текстами. \ No newline at end of file +Легкий у використанні, гнучкий плеєр і менеджер подкастів з відкритим кодом. \ No newline at end of file diff --git a/app/src/main/play/uk/listing/title b/app/src/main/play/uk/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/uk/listing/title +++ b/app/src/main/play/uk/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/uk_UA/listing/fulldescription b/app/src/main/play/uk_UA/listing/fulldescription deleted file mode 100644 index ae8ac2c20..000000000 --- a/app/src/main/play/uk_UA/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod це менеджер подкастів та плейер що дає доступ до мільйонів безкоштовних та комерційних подкастів від незалежних подкастерів та великих корпорацій таких як BBC, NPR та CNN. Є можливість додавати, імпортувати та експортувати канали за допомогою бази даних подкастів iTunes, файлів OPML або простих посилань на RSS. Зберігайте зусилля, живлення та мобільний трафік за допомогою автоматичного завантаження епізодів (зазначивши час, інтервали та мережі WiFi) та видалення епізодів (з урахуванням ваших побажань та налаштувань).
-Але найважливіше: завантажуйте, слухайте або додавайте до черги епізоди так, як вам подобається з налаштуванням швидкості програвання, підтримкою розділів та таймера сну. Можливо навіть фінансово заохочувати авторів за допомогою інтергації з сервісом Flattr. - -Зроблений ентузіастом подкастів, AntennaPod є вільним в усіх сенсах цього слова: відкриті вихідні тексти, безкоштовний, без реклами. - -Всі можливості:
-ІМПОРТУЙТЕ, ВПОРЯДКОВУЙТЕ ТА СЛУХАЙТЕ
-• Додавайте та імпортуйте канали з каталогів iTunes та gPodder.net, файлів OPML та з посилань на RSS або Atom
-• Керуйте програванням будь-де: з віджета, нотифікації, кнопками навушників або через блютус
-• Слухайте так як вам подобається з налаштуванням швидкості програвання, підтримкой розділів (в форматах MP3, VorbisComment та Podlove), зберіганням момента програвання та таймером сну (перезапуск струсом, зниження гучності та уповільнення програвання)
-• Доступ до каналів та епізодів що захищені паролем
-• Використовуйте посторінкові канали (www.podlove.org/paged-feeds) - -ВІДСТЕЖУЙТЕ, ДІЛІТЬСЯ ТА ОЦІНЮЙТЕ
-• Зберігайте найкраще в улюблених епізодах
-• Відшукайте той самий епізод в історії програвання або пошуком (в назвах і нотатках)
-• Діліться епізодами та каналами за допомогою соцмереж та пошти, сервісів gPodder.net та через експорт OPML файлів
-• Підтримуйте авторів за допомогою інтегрованого сервіса Flattr з можливістю автоматичной підтримки - -КЕРУЙТЕ СИСТЕМОЙ
-• Керуйте автоматичним завантаженням: вибирайте канали, мобільні мережі, мережі WiFi, завантажуйте тільки під час зарядки або у встановлений час і інтервали
-• Керуйте збереженням, встановлюйте ліміт на кеш епізодів, налагоджуйте розумне видалення (з урахуванням улюблених епізодів і статуса програвання) та вибирайте місце зберігання
-• Користуйтесь AntennaPod вашою мовою (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Пристосовуйтесь до ваших умов, користуйтесь світлой або темной темами
-• Зберігайте ваші підписки на gPodder.net або експортуйте в файл OPML - -Долучайтесь до спільноти AntennaPod!
-AntennaPod швидко розвивається волонтерами. Ви також маєте змогу допомогти, кодом або зауваженнями! - -Долучитись до проекта, повідомити про ваші побажання та про помилки можна на GitHub:
-https://www.github.com/AntennaPod/AntennaPod - -В нашій групі на Google можна поділитись ідеями, улюбленими моментами з подкастінга та добрими побажаннями волонтерам:
-https://groups.google.com/forum/#!forum/antennapod - -Маєте питання або повідомлення для нас? -https://twitter.com/@AntennaPod - -Допомагайте з перекладом на Transifex:
-https://www.transifex.com/antennapod/antennapod - -Зверніть увагу на нашу програму для бета тестування якщо бажаєте получати найновіші версії в першу чергу:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/vi/listing/fulldescription b/app/src/main/play/vi/listing/fulldescription index 87b477fdc..9519b5da1 100644 --- a/app/src/main/play/vi/listing/fulldescription +++ b/app/src/main/play/vi/listing/fulldescription @@ -3,7 +3,7 @@ But most importantly: Download, stream or queue episodes and enjoy them the way Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. -All features:
+Mọi tính năng: IMPORT, ORGANIZE AND PLAY
• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
@@ -17,14 +17,14 @@ KEEP TRACK, SHARE & APPRECIATE
• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
• Support content creators with Flattr integration including automatic flattring -CONTROL THE SYSTEM
+ĐIỀU KHIỂN HỆ THỐNG • Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
• Adapt to your environment using the light and dark theme
• Back-up your subscriptions with the gPodder.net integration and OPML export -Join the AntennaPod community!
+Tham gia cộng đồng AntennaPod! AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! GitHub is the place to go for feature requests, bug reports and code contributions:
@@ -33,7 +33,7 @@ https://www.github.com/AntennaPod/AntennaPod Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
https://groups.google.com/forum/#!forum/antennapod -Have a question or want to give us feedback? +Có một thắc mắc hay muốn phản hồi cho chúng tôi? https://twitter.com/@AntennaPod Transifex is the place to help with translations:
diff --git a/app/src/main/play/vi/listing/shortdescription b/app/src/main/play/vi/listing/shortdescription new file mode 100644 index 000000000..7afb5a62d --- /dev/null +++ b/app/src/main/play/vi/listing/shortdescription @@ -0,0 +1 @@ +Easy-to-use, flexible and open-source podcast & radio manager and player \ No newline at end of file diff --git a/app/src/main/play/vi/listing/title b/app/src/main/play/vi/listing/title new file mode 100644 index 000000000..6c7c64cfc --- /dev/null +++ b/app/src/main/play/vi/listing/title @@ -0,0 +1 @@ +AntennaPod diff --git a/app/src/main/play/vi_VN/listing/fulldescription b/app/src/main/play/vi_VN/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/vi_VN/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/zh-CN/listing/fulldescription b/app/src/main/play/zh-CN/listing/fulldescription index 932b5ba3a..6f2a6209e 100644 --- a/app/src/main/play/zh-CN/listing/fulldescription +++ b/app/src/main/play/zh-CN/listing/fulldescription @@ -1,20 +1,43 @@ -AntennaPod 是一款开源播客管理软件, 提供 Android 2.3.3 及以上平台运行. 它提供了所有你所期望的播客基本功能, 例如在线流媒体和下载收听曲目, 以及自动刷新所有订阅和添加到播放列表. 此外, AntennaPod 支持应用内 Flattr 播客和节目表. +AntennaPod 是播客管理和播放工具,使得你即刻收听到数百万来自从个人播客制作者到类似BBC、NPR和CNN等大型出版机构的免费或付费播客。通过 iTunes 数据库、OPML 文件或简单的 RSS 地址,你可以自由地添加、导入和导出播客订阅流。通过指定次数、间隔时间和 WIFI 网络的下载以及基于个人喜好和延迟删除的设置,功能强大的智能控制做到了省力、省电和省流量。
+但最重要的在于,你可以选择下载、串流或加入队列等方式收听节目,并使用调节回放速度、章节跳转和定时睡眠的辅助功能。你甚至可以通过 Flattr 集成功能向内容创作者表达你衷心的感谢。 -So far the following features are implemented: +AntennaPod 是一个由播客爱好者开发,在多种意义下“自由”的软件——开源、免费并且没有广告。 -* 在线流媒体和下载收听曲目 -* 变速播放 (需要 Presto 声音库或者 Prestissimo) -* 支持 Atom 和 RSS 订阅 -* 支持加密的订阅 -* Support for searching iTunes listings -* OPML 文件导入导出 -* Flattr integration including automatic flattring -* 播放器主屏幕窗口小部件 (Widget) -* 搜索 -* 自动订阅更新 -* 自动下载新曲目 -* 睡眠计时器 -* 访问 gpodder.net 播客目录 -* 同步 gpodder.net 订阅服务 -* Supports MP3 chapters, VorbisComment chapters and Podlove Simple Chapters -* Supports paged feeds (http://podlove.org/paged-feeds/) \ No newline at end of file +特性包括:
+导入,组织和播放
+• 通过 iTunes,gPodder.net,OPML文件,RSS或Atom链接添加和导入订阅 +• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
+• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
+• Access password-protected feeds and episodes
+• Take advantage of paged feeds (www.podlove.org/paged-feeds) + +KEEP TRACK, SHARE & APPRECIATE
+• Keep track of the best of the best by marking episodes as favourites
+• Find that one episode through the playback history or by searching (titles and shownotes)
+• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
+• Support content creators with Flattr integration including automatic flattring + +CONTROL THE SYSTEM
+• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
+• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
+• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
+• Adapt to your environment using the light and dark theme
+• Back-up your subscriptions with the gPodder.net integration and OPML export + +Join the AntennaPod community!
+AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! + +GitHub is the place to go for feature requests, bug reports and code contributions:
+https://www.github.com/AntennaPod/AntennaPod + +Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
+https://groups.google.com/forum/#!forum/antennapod + +Have a question or want to give us feedback? +https://twitter.com/@AntennaPod + +Transifex is the place to help with translations:
+https://www.transifex.com/antennapod/antennapod + +Check out our Beta Testing programme to get the latest features first:
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/zh-CN/listing/title b/app/src/main/play/zh-CN/listing/title index 31552f353..6c7c64cfc 100644 --- a/app/src/main/play/zh-CN/listing/title +++ b/app/src/main/play/zh-CN/listing/title @@ -1 +1 @@ -AntennaPod \ No newline at end of file +AntennaPod diff --git a/app/src/main/play/zh/listing/fulldescription b/app/src/main/play/zh/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/zh/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/zh_CN/listing/fulldescription b/app/src/main/play/zh_CN/listing/fulldescription deleted file mode 100644 index 6f2a6209e..000000000 --- a/app/src/main/play/zh_CN/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod 是播客管理和播放工具,使得你即刻收听到数百万来自从个人播客制作者到类似BBC、NPR和CNN等大型出版机构的免费或付费播客。通过 iTunes 数据库、OPML 文件或简单的 RSS 地址,你可以自由地添加、导入和导出播客订阅流。通过指定次数、间隔时间和 WIFI 网络的下载以及基于个人喜好和延迟删除的设置,功能强大的智能控制做到了省力、省电和省流量。
-但最重要的在于,你可以选择下载、串流或加入队列等方式收听节目,并使用调节回放速度、章节跳转和定时睡眠的辅助功能。你甚至可以通过 Flattr 集成功能向内容创作者表达你衷心的感谢。 - -AntennaPod 是一个由播客爱好者开发,在多种意义下“自由”的软件——开源、免费并且没有广告。 - -特性包括:
-导入,组织和播放
-• 通过 iTunes,gPodder.net,OPML文件,RSS或Atom链接添加和导入订阅 -• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/zh_HK/listing/fulldescription b/app/src/main/play/zh_HK/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/zh_HK/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/play/zh_TW/listing/fulldescription b/app/src/main/play/zh_TW/listing/fulldescription deleted file mode 100644 index 87b477fdc..000000000 --- a/app/src/main/play/zh_TW/listing/fulldescription +++ /dev/null @@ -1,43 +0,0 @@ -AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration. - -Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads. - -All features:
-IMPORT, ORGANIZE AND PLAY
-• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links
-• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls
-• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)
-• Access password-protected feeds and episodes
-• Take advantage of paged feeds (www.podlove.org/paged-feeds) - -KEEP TRACK, SHARE & APPRECIATE
-• Keep track of the best of the best by marking episodes as favourites
-• Find that one episode through the playback history or by searching (titles and shownotes)
-• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export
-• Support content creators with Flattr integration including automatic flattring - -CONTROL THE SYSTEM
-• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals
-• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location
-• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)
-• Adapt to your environment using the light and dark theme
-• Back-up your subscriptions with the gPodder.net integration and OPML export - -Join the AntennaPod community!
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment! - -GitHub is the place to go for feature requests, bug reports and code contributions:
-https://www.github.com/AntennaPod/AntennaPod - -Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:
-https://groups.google.com/forum/#!forum/antennapod - -Have a question or want to give us feedback? -https://twitter.com/@AntennaPod - -Transifex is the place to help with translations:
-https://www.transifex.com/antennapod/antennapod - -Check out our Beta Testing programme to get the latest features first:
-https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file diff --git a/app/src/main/res/layout/all_episodes_fragment.xml b/app/src/main/res/layout/all_episodes_fragment.xml index 5336fb8ce..099216007 100644 --- a/app/src/main/res/layout/all_episodes_fragment.xml +++ b/app/src/main/res/layout/all_episodes_fragment.xml @@ -10,10 +10,16 @@ android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" - android:scrollbarStyle="outsideOverlay" + android:clipToPadding="false" android:paddingTop="@dimen/list_vertical_padding" android:paddingBottom="@dimen/list_vertical_padding" - android:clipToPadding="false"/> + android:scrollbarStyle="outsideOverlay" + tools:itemCount="13" + tools:listitem="@layout/new_episodes_listitem" /> + + diff --git a/app/src/main/res/layout/audio_controls.xml b/app/src/main/res/layout/audio_controls.xml index 852b6e922..090aec47f 100644 --- a/app/src/main/res/layout/audio_controls.xml +++ b/app/src/main/res/layout/audio_controls.xml @@ -21,6 +21,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" + android:layout_marginStart="16dp" android:text="1.00x"/> @@ -35,6 +36,7 @@ android:layout_width="32dp" android:layout_height="32dp" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:gravity="center" android:text="-" android:textStyle="bold" @@ -48,6 +50,7 @@ android:layout_height="32dp" android:minWidth="0dp" android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" android:gravity="center" android:text="+" android:textStyle="bold" @@ -60,12 +63,21 @@ android:layout_width="match_parent" android:layout_height="32dp" android:layout_toRightOf="@id/butDecSpeed" + android:layout_toEndOf="@id/butDecSpeed" android:layout_toLeftOf="@id/butIncSpeed" + android:layout_toStartOf="@id/butIncSpeed" android:layout_centerVertical="true" android:max="40"/> + + @@ -101,6 +114,7 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginLeft="8dp" + android:layout_marginStart="8dp" android:orientation="horizontal" android:gravity="center"> diff --git a/app/src/main/res/layout/authentication_dialog.xml b/app/src/main/res/layout/authentication_dialog.xml index 00e74c9e1..187045c63 100644 --- a/app/src/main/res/layout/authentication_dialog.xml +++ b/app/src/main/res/layout/authentication_dialog.xml @@ -67,8 +67,10 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:layout_toLeftOf="@id/horizontal_divider" + android:layout_toStartOf="@id/horizontal_divider" android:background="?android:attr/selectableItemBackground" android:text="@string/cancel_label" /> @@ -78,8 +80,10 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" android:layout_alignParentTop="true" android:layout_toRightOf="@id/horizontal_divider" + android:layout_toEndOf="@id/horizontal_divider" android:background="?android:attr/selectableItemBackground" android:text="@string/confirm_label" /> diff --git a/app/src/main/res/layout/directory_chooser.xml b/app/src/main/res/layout/directory_chooser.xml index 14e2f6a38..5b9269607 100644 --- a/app/src/main/res/layout/directory_chooser.xml +++ b/app/src/main/res/layout/directory_chooser.xml @@ -33,8 +33,10 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:layout_toLeftOf="@id/horizontal_divider" + android:layout_toStartOf="@id/horizontal_divider" android:background="?android:attr/selectableItemBackground" android:text="@string/cancel_label" /> @@ -44,8 +46,10 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" android:layout_alignParentTop="true" android:layout_toRightOf="@id/horizontal_divider" + android:layout_toEndOf="@id/horizontal_divider" android:background="?android:attr/selectableItemBackground" android:text="@string/confirm_label" /> @@ -62,6 +66,7 @@ android:layout_width="60dp" android:layout_height="60dp" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:background="?attr/selectableItemBackground" android:src="?attr/navigation_up" @@ -77,6 +82,7 @@ android:layout_marginRight="8dp" android:layout_marginTop="8dp" android:layout_toRightOf="@id/butNavUp" + android:layout_toEndOf="@id/butNavUp" android:text="@string/selected_folder_label" android:textStyle="bold" tools:background="@android:color/holo_green_dark"> @@ -87,9 +93,11 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" android:layout_below="@id/txtvSelectedFolderLabel" android:layout_margin="8dp" android:layout_toRightOf="@id/butNavUp" + android:layout_toEndOf="@id/butNavUp" android:ellipsize="start" android:scrollHorizontally="true" android:singleLine="true" diff --git a/app/src/main/res/layout/download_authentication_activity.xml b/app/src/main/res/layout/download_authentication_activity.xml index f6925dc3a..3414a5e00 100644 --- a/app/src/main/res/layout/download_authentication_activity.xml +++ b/app/src/main/res/layout/download_authentication_activity.xml @@ -77,8 +77,10 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:layout_toLeftOf="@id/horizontal_divider" + android:layout_toStartOf="@id/horizontal_divider" android:background="?android:attr/selectableItemBackground" android:text="@string/cancel_label"/> @@ -88,8 +90,10 @@ android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" android:layout_alignParentTop="true" android:layout_toRightOf="@id/horizontal_divider" + android:layout_toEndOf="@id/horizontal_divider" android:background="?android:attr/selectableItemBackground" android:text="@string/confirm_label"/> diff --git a/app/src/main/res/layout/downloaded_episodeslist_item.xml b/app/src/main/res/layout/downloaded_episodeslist_item.xml index 770b88c7e..65a08251f 100644 --- a/app/src/main/res/layout/downloaded_episodeslist_item.xml +++ b/app/src/main/res/layout/downloaded_episodeslist_item.xml @@ -13,6 +13,7 @@ android:layout_gravity="center_vertical" android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" + android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding" android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" android:contentDescription="@string/cover_label" android:scaleType="centerCrop" @@ -24,7 +25,9 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding" + android:layout_marginStart="@dimen/listitem_threeline_textleftpadding" android:layout_marginRight="@dimen/listitem_threeline_textrightpadding" + android:layout_marginEnd="@dimen/listitem_threeline_textrightpadding" android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding" android:layout_weight="1" @@ -74,6 +77,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8dp" + android:layout_marginStart="8dp" tools:text="Jan 23" tools:background="@android:color/holo_green_dark"/> @@ -88,7 +92,7 @@ android:layout_height="match_parent" android:background="?attr/selectableItemBackground" android:clickable="false" - android:contentDescription="@string/remove_episode_lable" + android:contentDescription="@string/delete_episode_label" android:focusable="false" android:focusableInTouchMode="false" android:src="?attr/content_discard" diff --git a/app/src/main/res/layout/downloadlist_item.xml b/app/src/main/res/layout/downloadlist_item.xml index 97f3ac1a1..668ec817a 100644 --- a/app/src/main/res/layout/downloadlist_item.xml +++ b/app/src/main/res/layout/downloadlist_item.xml @@ -17,6 +17,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding" + android:layout_marginStart="@dimen/listitem_threeline_horizontalpadding" android:layout_marginTop="@dimen/listitem_threeline_verticalpadding" android:ellipsize="end" android:lines="1" @@ -48,6 +49,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:ellipsize="end" android:lines="1" android:textColor="?android:attr/textColorPrimary" @@ -60,6 +62,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" android:ellipsize="end" android:lines="1" android:textColor="?android:attr/textColorPrimary" diff --git a/app/src/main/res/layout/downloadlog_item.xml b/app/src/main/res/layout/downloadlog_item.xml index 712dda63e..505102ea4 100644 --- a/app/src/main/res/layout/downloadlog_item.xml +++ b/app/src/main/res/layout/downloadlog_item.xml @@ -17,6 +17,7 @@ android:layout_height="48sp" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:textSize="48sp" android:gravity="center" /> @@ -26,7 +27,9 @@ android:layout_height="wrap_content" android:layout_below="@id/txtvIcon" android:layout_alignLeft="@id/txtvIcon" + android:layout_alignStart="@id/txtvIcon" android:layout_alignRight="@id/txtvIcon" + android:layout_alignEnd="@id/txtvIcon" android:layout_marginTop="8dp" android:text="{fa-repeat}" tools:text="↻" /> @@ -38,7 +41,9 @@ android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" android:layout_marginLeft="8dp" + android:layout_marginStart="8dp" android:layout_marginBottom="8dp" tools:text="Media file" tools:background="@android:color/holo_green_dark" /> @@ -50,8 +55,11 @@ android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_toRightOf="@id/txtvIcon" + android:layout_toEndOf="@id/txtvIcon" android:layout_toLeftOf="@id/txtvType" + android:layout_toStartOf="@id/txtvType" android:layout_marginLeft="8dp" + android:layout_marginStart="8dp" android:layout_marginBottom="8dp" android:minLines="1" android:maxLines="2" @@ -64,8 +72,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/txtvIcon" + android:layout_toEndOf="@id/txtvIcon" android:layout_below="@id/txtvTitle" android:layout_marginLeft="8dp" + android:layout_marginStart="8dp" android:layout_marginBottom="8dp" tools:text="January 23" tools:background="@android:color/holo_green_dark" /> @@ -76,7 +86,9 @@ android:layout_height="wrap_content" android:layout_below="@id/txtvDate" android:layout_toRightOf="@id/txtvIcon" + android:layout_toEndOf="@id/txtvIcon" android:layout_marginLeft="8dp" + android:layout_marginStart="8dp" android:textColor="?android:attr/textColorTertiary" android:textSize="@dimen/text_size_micro" tools:text="@string/design_time_downloaded_log_failure_reason" diff --git a/app/src/main/res/layout/ellipsize_start_listitem.xml b/app/src/main/res/layout/ellipsize_start_listitem.xml index 4a70ff982..1b6c48152 100644 --- a/app/src/main/res/layout/ellipsize_start_listitem.xml +++ b/app/src/main/res/layout/ellipsize_start_listitem.xml @@ -1,22 +1,22 @@ + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + tools:background="@android:color/darker_gray"> + android:singleLine="true" + android:textColor="?android:attr/textColorPrimary" + android:textSize="@dimen/text_size_small" + tools:background="@android:color/holo_green_dark" + tools:text="List item title" /> \ No newline at end of file diff --git a/app/src/main/res/layout/empty_view_layout.xml b/app/src/main/res/layout/empty_view_layout.xml new file mode 100644 index 000000000..051773e51 --- /dev/null +++ b/app/src/main/res/layout/empty_view_layout.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/episodes_apply_action_fragment.xml b/app/src/main/res/layout/episodes_apply_action_fragment.xml index e9a2e2e23..984e960d8 100644 --- a/app/src/main/res/layout/episodes_apply_action_fragment.xml +++ b/app/src/main/res/layout/episodes_apply_action_fragment.xml @@ -1,115 +1,50 @@ - - - -