From b1881f0cf4243e230fe2bd5f391deddf09711342 Mon Sep 17 00:00:00 2001 From: Eric Kok Date: Mon, 14 Oct 2013 08:41:42 +0200 Subject: [PATCH 1/5] Only check for app (and search module) updates once a day. That should be enough, right? --- .../core/app/settings/SystemSettings.java | 24 +++++++++++++++++-- .../core/service/AppUpdateService.java | 19 +++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/core/src/org/transdroid/core/app/settings/SystemSettings.java b/core/src/org/transdroid/core/app/settings/SystemSettings.java index 0ef58d0d..3264d375 100644 --- a/core/src/org/transdroid/core/app/settings/SystemSettings.java +++ b/core/src/org/transdroid/core/app/settings/SystemSettings.java @@ -16,9 +16,12 @@ */ package org.transdroid.core.app.settings; +import java.util.Date; + import org.androidannotations.annotations.EBean; import org.androidannotations.annotations.RootContext; import org.androidannotations.annotations.EBean.Scope; +import org.transdroid.core.service.AppUpdateService; import android.content.Context; import android.content.SharedPreferences; @@ -34,7 +37,7 @@ public class SystemSettings { @RootContext protected Context context; private SharedPreferences prefs; - + protected SystemSettings(Context context) { prefs = PreferenceManager.getDefaultSharedPreferences(context); } @@ -46,5 +49,22 @@ public class SystemSettings { public boolean useDarkTheme() { return prefs.getBoolean("system_usedarktheme", false); } - + + /** + * Returns the date when we last checked transdroid.org for the latest app version. + * @return The date/time when the {@link AppUpdateService} checked on the server for updates + */ + public Date getLastCheckedForAppUpdates() { + long lastChecked = prefs.getLong("system_lastappupdatecheck", -1L); + return lastChecked == -1 ? null : new Date(lastChecked); + } + + /** + * Stores the date at which was last successfully, fully checked for new updates to the app. + * @param lastChecked The date/time at which the {@link AppUpdateService} last checked the server for updates + */ + public void setLastCheckedForAppUpdates(Date lastChecked) { + prefs.edit().putLong("system_lastappupdatecheck", lastChecked == null ? -1L : lastChecked.getTime()).commit(); + } + } diff --git a/core/src/org/transdroid/core/service/AppUpdateService.java b/core/src/org/transdroid/core/service/AppUpdateService.java index 4296e450..7cdf6975 100644 --- a/core/src/org/transdroid/core/service/AppUpdateService.java +++ b/core/src/org/transdroid/core/service/AppUpdateService.java @@ -18,6 +18,8 @@ package org.transdroid.core.service; import java.io.IOException; import java.io.InputStream; +import java.util.Calendar; +import java.util.Date; import java.util.Random; import org.androidannotations.annotations.Bean; @@ -74,6 +76,15 @@ public class AppUpdateService extends IntentService { return; } + Date lastChecked = systemSettings.getLastCheckedForAppUpdates(); + Calendar lastDay = Calendar.getInstance(); + lastDay.add(Calendar.DAY_OF_MONTH, -1); + if (lastChecked == null || lastChecked.after(lastDay.getTime())) { + Log.d(this, "Ship the update service, as we already checked the last 24 hours (or to be exact at " + + lastChecked.toString() + ")."); + return; + } + DefaultHttpClient httpclient = new DefaultHttpClient(); Random random = new Random(); @@ -88,6 +99,8 @@ public class AppUpdateService extends IntentService { // New version of the app? try { PackageInfo appPackage = getPackageManager().getPackageInfo(getPackageName(), 0); + Log.d(this, "Local Transdroid is at " + appPackage.versionCode + " and the reported latest version is " + + appVersion); if (appPackage.versionCode < appVersion) { // New version available! Notify the user. newNotification(getString(R.string.update_app_newversion), @@ -102,6 +115,8 @@ public class AppUpdateService extends IntentService { // New version of the search module? try { PackageInfo searchPackage = getPackageManager().getPackageInfo("org.transdroid.search", 0); + Log.d(this, "Local Transdroid Seach is at " + searchPackage.versionCode + + " and the reported latest version is " + searchVersion); if (searchPackage.versionCode < searchVersion) { // New version available! Notify the user. newNotification(getString(R.string.update_search_newversion), @@ -114,6 +129,10 @@ public class AppUpdateService extends IntentService { // install it (when the first search is initiated) } + // Save that we successfully checked for app updates (and notified the user) + // This prevents checking again for 1 day + systemSettings.setLastCheckedForAppUpdates(new Date()); + } catch (Exception e) { // Cannot check right now for some reason; log and ignore Log.d(this, "Cannot retrieve latest app or search module version code from the site: " + e.toString()); From c9e1609da3c1771b1f4b3cdbe3b49460185610ac Mon Sep 17 00:00:00 2001 From: Eric Kok Date: Mon, 14 Oct 2013 08:43:22 +0200 Subject: [PATCH 2/5] Fix typo in turtle mode. --- core/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/res/values/strings.xml b/core/res/values/strings.xml index 0d90b8cb..0218ba37 100644 --- a/core/res/values/strings.xml +++ b/core/res/values/strings.xml @@ -25,8 +25,8 @@ Search Refresh RSS - Enable turle mode - Disable turle mode + Enable turtle mode + Disable turtle mode Sort list Name Status From f8f0fa42b628464d2d93673b5c89e48959eedbad Mon Sep 17 00:00:00 2001 From: Eric Kok Date: Mon, 14 Oct 2013 21:40:35 +0200 Subject: [PATCH 3/5] Modifications for the lite version of Transdroid (now called Transdrone :). --- core/AndroidManifest.xml | 4 ++-- core/res/layout/fragment_torrents.xml | 1 - core/res/values/changelog.xml | 4 ++++ core/res/values/strings.xml | 11 +++++------ core/res/xml/pref_system.xml | 3 +-- .../core/app/settings/SystemSettings.java | 9 +++++++++ .../org/transdroid/core/gui/TorrentsFragment.java | 1 + .../core/gui/navigation/NavigationHelper.java | 10 +++++----- .../core/gui/settings/SystemSettingsActivity.java | 15 +++++++++++---- .../org/transdroid/core/service/BootReceiver.java | 2 +- full/AndroidManifest.xml | 6 +++--- lite/AndroidManifest.xml | 12 +++--------- lite/res/values/strings.xml | 2 +- 13 files changed, 46 insertions(+), 34 deletions(-) diff --git a/core/AndroidManifest.xml b/core/AndroidManifest.xml index 80c57969..742ead80 100644 --- a/core/AndroidManifest.xml +++ b/core/AndroidManifest.xml @@ -17,8 +17,8 @@ --> + android:versionCode="7" + android:versionName="2.0.1" > diff --git a/core/res/values/changelog.xml b/core/res/values/changelog.xml index b4483df1..a12c9d53 100644 --- a/core/res/values/changelog.xml +++ b/core/res/values/changelog.xml @@ -17,6 +17,10 @@ --> +Transdroid 2.0.1\n +- First Google Play release of the lite version as Transdrone\n +- First release as auto-update (now checked only once a day)\n +\n Transdroid 2.0.0\n - Scrollable home screen widget (Android 3+)\n - Allow changing of storage location (Deluge and Transmission)\n diff --git a/core/res/values/strings.xml b/core/res/values/strings.xml index 0218ba37..af4e4c31 100644 --- a/core/res/values/strings.xml +++ b/core/res/values/strings.xml @@ -59,7 +59,7 @@ Remove settings Visit transdroid.org - Transdroid allows you to monitor and manage the torrent client you run at home or on your seedbox. Setting things up can be a bit tricky, but we offer step-by-step guides and promise it\'ll be worth it! + %1$s allows you to monitor and manage the torrent client you run at home or on your seedbox. Setting things up can be a bit tricky, but we offer step-by-step guides and promise it\'ll be worth it! Connected, but no torrent are active within the current filter Select a torrent to view its details SERVERS @@ -270,17 +270,17 @@ Use dark UI theme Requires a restart to take effect Import settings - Transdroid will try to import server, web search, RSS and system settings from: %1$s + %1$s will try to import server, web search, RSS and system settings from: %2$s Settings successfully imported Export settings - Transdroid will export server (including passwords), web search, RSS and system settings to the following plain text JSON file: %1$s + %1$s will export server (including passwords), web search, RSS and system settings to the following plain text JSON file: %2$s Settings successfully exported Send error log Get support or report a bug View install guides Available at transdroid.org/download Recent changes - About Transdroid + About %1$s BitComet Bitflu 1.2+ @@ -359,7 +359,7 @@ The RSS feed item does not provide a link to browse to URL is not a (valid) RSS feed SD card not available to read/write - File does not seem to contain Transdroid settings + File does not seem to contain %1$s settings The settings file could not be found Can\'t write to the settings file Please enter a positive number @@ -371,7 +371,6 @@ New Transdroid search module available You can now update to %1$s - Transdroid \u00A9 Eric Kok, 2312 development Published under GNU General Public License v3 Some code/libraries are used in the project: diff --git a/core/res/xml/pref_system.xml b/core/res/xml/pref_system.xml index edf5cb54..d46c8d94 100644 --- a/core/res/xml/pref_system.xml +++ b/core/res/xml/pref_system.xml @@ -52,7 +52,6 @@ android:title="@string/pref_changelog" /> + android:key="system_about" /> diff --git a/core/src/org/transdroid/core/app/settings/SystemSettings.java b/core/src/org/transdroid/core/app/settings/SystemSettings.java index 3264d375..f5762d80 100644 --- a/core/src/org/transdroid/core/app/settings/SystemSettings.java +++ b/core/src/org/transdroid/core/app/settings/SystemSettings.java @@ -67,4 +67,13 @@ public class SystemSettings { prefs.edit().putLong("system_lastappupdatecheck", lastChecked == null ? -1L : lastChecked.getTime()).commit(); } + /** + * Whether the custom app update checker should be used to check for new app and search module versions. + * @return True if it should be checked against transdroid.org if there are app updates (as opposed to using the + * Play Store for updates), false otherwise + */ + public static boolean enableUpdateChecker(Context context) { + return !context.getPackageName().equals("org.transdroid.lite"); + } + } diff --git a/core/src/org/transdroid/core/gui/TorrentsFragment.java b/core/src/org/transdroid/core/gui/TorrentsFragment.java index de78df42..5a9333a0 100644 --- a/core/src/org/transdroid/core/gui/TorrentsFragment.java +++ b/core/src/org/transdroid/core/gui/TorrentsFragment.java @@ -114,6 +114,7 @@ public class TorrentsFragment extends SherlockFragment implements OnLabelPickedL torrentsList.setFastScrollEnabled(true); if (torrents != null) updateTorrents(torrents, currentLabels); + nosettingsText.setText(getString(R.string.navigation_nosettings, getString(R.string.app_name))); } diff --git a/core/src/org/transdroid/core/gui/navigation/NavigationHelper.java b/core/src/org/transdroid/core/gui/navigation/NavigationHelper.java index 6c3736ae..a36221bf 100644 --- a/core/src/org/transdroid/core/gui/navigation/NavigationHelper.java +++ b/core/src/org/transdroid/core/gui/navigation/NavigationHelper.java @@ -173,12 +173,12 @@ public class NavigationHelper { * @return A best-guess, reasonably long name for the linked torrent */ public static String extractNameFromUri(Uri rawTorrentUri) { - + if (rawTorrentUri.getScheme() == null) { // Probably an incorrect URI; just return the whole thing return rawTorrentUri.toString(); } - + if (rawTorrentUri.getScheme().equals("magnet")) { // Magnet links might have a dn (display name) parameter String dn = getQueryParameter(rawTorrentUri, "dn"); @@ -198,7 +198,7 @@ public class NavigationHelper { return path; } } - + // No idea what to do with this; return as is return rawTorrentUri.toString(); } @@ -208,9 +208,9 @@ public class NavigationHelper { if (start >= 0) { int begin = start + (parameter + "=").length(); int end = uri.toString().indexOf("&", begin); - return uri.toString().substring(begin, end >= 0? end: uri.toString().length()); + return uri.toString().substring(begin, end >= 0 ? end : uri.toString().length()); } return null; } - + } diff --git a/core/src/org/transdroid/core/gui/settings/SystemSettingsActivity.java b/core/src/org/transdroid/core/gui/settings/SystemSettingsActivity.java index 2ed02f2a..30aae1f1 100644 --- a/core/src/org/transdroid/core/gui/settings/SystemSettingsActivity.java +++ b/core/src/org/transdroid/core/gui/settings/SystemSettingsActivity.java @@ -26,6 +26,7 @@ import org.json.JSONException; import org.transdroid.core.R; import org.transdroid.core.app.settings.ApplicationSettings; import org.transdroid.core.app.settings.SettingsPersistence; +import org.transdroid.core.app.settings.SystemSettings; import org.transdroid.core.gui.log.ErrorLogSender; import org.transdroid.core.gui.navigation.DialogHelper; import org.transdroid.core.gui.navigation.NavigationHelper; @@ -77,12 +78,17 @@ public class SystemSettingsActivity extends SherlockPreferenceActivity { addPreferencesFromResource(R.xml.pref_system); // Handle outgoing links and preference changes - findPreference("system_checkupdates").setOnPreferenceClickListener(onCheckUpdatesClick); + if (SystemSettings.enableUpdateChecker(this)) { + findPreference("system_checkupdates").setOnPreferenceClickListener(onCheckUpdatesClick); + } else { + getPreferenceScreen().removePreference(findPreference("system_checkupdates")); + } findPreference("system_sendlog").setOnPreferenceClickListener(onSendLogClick); findPreference("system_installhelp").setOnPreferenceClickListener(onInstallHelpClick); findPreference("system_changelog").setOnPreferenceClickListener(onChangeLogClick); findPreference("system_importsettings").setOnPreferenceClickListener(onImportSettingsClick); findPreference("system_exportsettings").setOnPreferenceClickListener(onExportSettingsClick); + findPreference("system_about").setTitle(getString(R.string.pref_about, getString(R.string.app_name))); findPreference("system_about").setOnPreferenceClickListener(onAboutClick); } @@ -165,7 +171,7 @@ public class SystemSettingsActivity extends SherlockPreferenceActivity { // @formatter:off return new AlertDialog.Builder(this) .setMessage( - getString(R.string.pref_import_dialog, SettingsPersistence.DEFAULT_SETTINGS_FILE.toString())) + getString(R.string.pref_import_dialog, getString(R.string.app_name), SettingsPersistence.DEFAULT_SETTINGS_FILE.toString())) .setPositiveButton(android.R.string.ok, importSettings) .setNegativeButton(android.R.string.cancel, null).create(); // @formatter:on @@ -173,7 +179,7 @@ public class SystemSettingsActivity extends SherlockPreferenceActivity { // @formatter:off return new AlertDialog.Builder(this) .setMessage( - getString(R.string.pref_export_dialog, SettingsPersistence.DEFAULT_SETTINGS_FILE.toString())) + getString(R.string.pref_export_dialog, getString(R.string.app_name), SettingsPersistence.DEFAULT_SETTINGS_FILE.toString())) .setPositiveButton(android.R.string.ok, exportSettings) .setNegativeButton(android.R.string.cancel, null).create(); // @formatter:on @@ -193,7 +199,8 @@ public class SystemSettingsActivity extends SherlockPreferenceActivity { Crouton.showText(SystemSettingsActivity.this, R.string.error_file_not_found, NavigationHelper.CROUTON_ERROR_STYLE); } catch (JSONException e) { - Crouton.showText(SystemSettingsActivity.this, R.string.error_no_valid_settings_file, + Crouton.showText(SystemSettingsActivity.this, + getString(R.string.error_no_valid_settings_file, getString(R.string.app_name)), NavigationHelper.CROUTON_ERROR_STYLE); } } diff --git a/core/src/org/transdroid/core/service/BootReceiver.java b/core/src/org/transdroid/core/service/BootReceiver.java index 4b40f795..1cfa6b1e 100644 --- a/core/src/org/transdroid/core/service/BootReceiver.java +++ b/core/src/org/transdroid/core/service/BootReceiver.java @@ -69,7 +69,7 @@ public class BootReceiver extends BroadcastReceiver { public static void startAppUpdatesService(Context context) { SystemSettings systemSettings = SystemSettings_.getInstance_(context); AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - if (systemSettings.checkForUpdates() && piAppUpdates == null) { + if (SystemSettings.enableUpdateChecker(context) && systemSettings.checkForUpdates() && piAppUpdates == null) { Log.d(context, "Boot signal received, starting app update checker service"); // Schedule a daily, with the first being (somewhat) in 1 second from now diff --git a/full/AndroidManifest.xml b/full/AndroidManifest.xml index a777240f..e5dcf51a 100644 --- a/full/AndroidManifest.xml +++ b/full/AndroidManifest.xml @@ -17,8 +17,8 @@ --> + android:versionCode="7" + android:versionName="2.0.1" > diff --git a/lite/AndroidManifest.xml b/lite/AndroidManifest.xml index 18fa9c1a..cb255547 100644 --- a/lite/AndroidManifest.xml +++ b/lite/AndroidManifest.xml @@ -17,8 +17,8 @@ --> + android:versionCode="7" + android:versionName="2.0.1" > @@ -61,9 +61,6 @@ - - - @@ -180,15 +177,12 @@ - - - diff --git a/lite/res/values/strings.xml b/lite/res/values/strings.xml index ac9d60da..59d4806e 100644 --- a/lite/res/values/strings.xml +++ b/lite/res/values/strings.xml @@ -16,6 +16,6 @@ --> - Transdroid Lite + Transdrone From 94fe30bbb41e848a9dbb662adffadd74b16a836f Mon Sep 17 00:00:00 2001 From: Eric Kok Date: Mon, 14 Oct 2013 21:40:49 +0200 Subject: [PATCH 4/5] Added Dutch translation. --- core/res/values-nl/strings.xml | 323 +++++++++++++++++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 core/res/values-nl/strings.xml diff --git a/core/res/values-nl/strings.xml b/core/res/values-nl/strings.xml new file mode 100644 index 00000000..8d3bfc05 --- /dev/null +++ b/core/res/values-nl/strings.xml @@ -0,0 +1,323 @@ + + + + +Toevoegen +Allen toevoegen +Met een bestand +Met een URL +Barcode scanner +Zoeken +Verversen +RSS +Turtle mode aanzetten +Turtle mode uitzetten +Lijst sorteren +Naam +Status +Datum gereed +Datum toegevoegd +Uploadsnelheid +Ratio +Lijst filteren +Instellingen +Help +Start +Normaal starten +Geforceerd starten +Stoppen +Hervatten +Pauzeren +Verwijderen +Verwijder torrent +Verwijder en wis bestanden +Label toewijzen +Trackers updaten +Opslaglocatie wijzigen +Uit +Laag +Normaal +Hoog +Afspelen op server met VLC +Downloaden met (S)FTP +Toon details +Verwijder instellingen +Bezoek transdroid.org + +Met %1$s kun je je torrents beheren die op je torrent client thuis of op je seedbox draaien. Het opzetten van een verbinding is soms wat lastig, maar er zijn stap voor stap-instructies beschikbaar en we beloven dat het de moeite waard is! +Verbonden, maar geen torrents actief in het huidige filter +Selecteer een torrent op details te bekijken +SERVERS +STATUS +LABELS +Alles +Downloads +Uploads +Actief +Inactief + +%1$d torrent geselecteerd +%1$d torrents geselecteerd + + +%1$d bestand geselecteerd +%1$d bestanden geselecteerd + +Alles selecteren +Selectie omdraaien + +STATUS: %1$s +Zal worden gecontroleerd… +Locale data verifiëren… +Zal worden gedownload… +Fout… +%1$s VAN %2$s (%3$s) +%1$s, %2$s GEÜPLOAD +SINDS %1$s +~ %1$s +ETA %1$s +VAN %1$s +ONBEKENDE ETA +RATIO %1$s +%1$s VAN %2$s PEERS +Downloaden +Seeden +Gepauzeerd +In de wachtrij +Gestopt +Onbekende status +Niet gedownload +Lage prioriteit +Normale prioriteit +Hoge prioriteit +TRACKERS +FOUTEN +BESTANDEN +Maximale snelheden +NAX DOWNLOAD +MAX UPLOAD +KB/S +Resetten +Updaten + +Nieuwe torrent toegevoegd +%1$s nieuwe torrents toegevoegd + + +Torrent is gereed +%1$s torrents zijn gereed + + +%1$s torrent toegevoed, %2$s gereed +%1$s torrents toegevoed, %2$s gereed + +%1$s and anderen + +Alle labels +Ongelabeld +Nieuw label +Labels worden niet ondersteund door je torrent client +KIES EEN LABEL +NIEUW LABEL +Verwijder label +Bijv. films of linux + +%1$s toegevoegd (nu verversen) +%1$s verwijderd +%1$s verwijderd en bestanden gewist +%1$s hervat (nu versersen) +%1$s gestopt (nu verversen) +%1$s gestart (nu verversen) +%1$s gepauzeerd (nu verversen) +Torrents gepauseerd (nu verversen) +Torrents hervat (nu verversen) +Torrents gestopt (nu verversen) +Torrents gestart (nu verversen) +Trackers geüpdatet +Label \'%1$s\' toegewezen +Label verwijderd +Torrent verplaatst naar \'%1$s\' +Bestandsprioriteiten geüpdatet +Maximale snelheden ingesteld + +Torrents zoeken +\'%1$s\' op %2$s +Zoeken naar torrents +Geen resultaten voor je zoekopdracht +S: %1$s +L: %1$s +Deze functie vereist een eenmalige installatie van de Torrent Search-module. Kies download om het installatiepakket (apk) te installeren van transdroid.org en herstart je zoekopdracht. +Module downloaden +Details voor %1$s worden geopend +De Barcode Scanner-app kan niet worden gevonden. Wil je deze installeren via de Play Store? +Geen ondersteunde bestandsbeheer-app gevonden. WIl je IO File Manager installeren via de Play Store? + +%1$d resultaat geselecteerd +%1$d resutaten geselecteerd + + +RSS feeds +Je monitort nog geen RSS feeds. Torrent-specifieke RSS feeds bieden de laatste nieuwe torrents en je krijgt meldingen als er nieuwe torrents beschikbaar zijn. +Selecteer een RSS feed om de nieuwe items te beijken +De RSS feed is niet beschikbaar of bevat geen items +Sorry, nog even wachten tot de RSS feed is geladen +Sorry, deze RSS feed kon momenteel niet worden geladen + +%1$d item geselecteerd +%1$d items geselecteerd + + +Nieuwe RSS-feedtorrent beschikbaar +%1$s nieuwe RSS-feedtorrents + +Nieuwe torrent voor %1$s + +Laden… +Transdroid openen +SERVERSELECTIE +UITERLIJK +SORTEERVOLGORDE +Omgekeerde sorteervolgorde +Gebruik donker kleurenschema (geen preview) +KLAAR + +Servers +Nieuwe server toevoegen +Zoeksites +Stel standaardsite in +Nieuwe webgebaseerde site toevoegen +RSS feeds +Nieuwe RSS feed +Andere instellingen + +Naam +Optionele persoonlijke naam +URL van zoekpagina +%s zal worden vervangen door de zoekopdracht +Cookies +Optioneel; gebruik key1=value1;key2=value2 als formaat +URL van de feed +Inloggen vereist +Links zullen in de browser worden geopend op in te loggen + +Servertype +IP of domeinnaam +Poortnummer +Gebruikersnaam +Wachtwoord +Deluge webwachtwoord +Geavanceerde instellingen +Loale IP of hostnaam +Mits verbonden met het opgegeven lokale netwerk +Lokale netwerk +De SSID van het lokale netwerk +Relatieve directory +Normaal gesproken leeg +SCGI mountpunt +Optionele instellingen +Voltooidmelding +Meld als een torrent is voltooid +Nieuwetorrentmelding +Meld al een torrent is toegevoegd +Besturingssysteem +Downloaddirectory +Handmatig de absolute directory instellen voor commando\'s naar de server +Verbindingstimeout +Aantal seconden voordat een poging wordt afgebroken +Basis-URL voor (S)FTP +Bijvoorbeeld ftp://me@server/downloads/ +(S)FTP-wachtwoord +Gebruik SSL +Via https verbinden +Handmatige SSL-vingerafdruk (SHA-1) +Alleen verbindingen met dit certificaat toestaan +Alle SSL-certificaten toestaan +Verbindingen met alle SSL-vingerafdrukken toestaan + +Meldingen op achtergrond +Meldingen aanzetten +Meldingen op de achtergrond toestaan +Interval +Hoe vaak de server gecontroleerd moet worden +Geluid +Trillen +LED-kleur +Mits ondersteund door je apparaat +ADW-meldingen ondersteunen +Toon het aantal torrents in ADW Launcher + +Systeem +Controleren op updates +Controleer transdroid.org voor de meest recente versie +Gebruik donker kleurenschema +Vereist een herstart om toe te passen +Importeer instellingen +%1$s zal proberen server-, zoeksite-, RSS- en systeeminstellingen te laden uit: %2$s +Instellingen succesvol geïmporteerd +Exporteer instellingen +%1$s zal server- (inclusief wachtwoorden), zoeksite-, RSS- en systeeminstellingen exporten naar het JSON-tekstbestand: %2$s +Instellingen succesvol geëxporteerd +Foutrapport verzenden +Hulp vragen of een bug melden +Bekijk installatieinstructies +Beschikbaar op transdroid.org/download +Recente wijzigingen +Over %1$s + +1 minuut +10 minuten +30 minuten +1 uur +3 uur +12 uur +1 dag + + +Verbindingsfout; controleer je internetverbinding +Interne fout bij het opzetten van de verbinding +Fout bij het verwerken van de serverreactie (controleer je instellingen) +De webinterface is niet verbonden met een actieve daemon +Toegang geweiged (controleer je instellingen) +Kan het .torrent-bestand niet lezen +Fout bij het verwerken van de RSS-feed +Dit is geen geldige URL +De URL van je zoeksite is ongeldig: +Geen geldige IP of domeinnaam ingevoerd +Het poortnummer is altijd numeriek +Een directory eindigd altijd op een / of \ +De timeout kan niet leeg zijn en is een positief getal +Het RSS-feeditem bevat geen URL-enclosure of -link naar een .torrent-file +Het RSS-feeditem bevat geen link om te bezoeken +De URL is geen (geldige) RSS-feed +De SD-kaart is niet beschikbaar +Het bestand lijkt geen %1$s-instellingen te bevatten +Het bestand met instellingen kon niet worden gevonden +Kan niet naar het bestand met instellingen schrijven +Kies een positief getal +Geen een geldige labelnaam op of kies uit de lijst +Even wachten tot de torrentdetails zijn geladen +Geen app gevonden die %1$s kan downloaden + +Nieuwe versie van Transdroid beschikbaar +Nieuwe versie van de Transdroid zoekmodule beschikbaar +Je kunt nu updaten naar %1$s + +Enkele libraries die in het project zijn gebruikt: +Beheer je torrents vanaf je Androidapparaat + + From 1ed644e42ce3b00b62075f6fc41d1cd163d87a4c Mon Sep 17 00:00:00 2001 From: Eric Kok Date: Wed, 16 Oct 2013 08:28:26 +0200 Subject: [PATCH 5/5] Added support for pull to refresh in main and details screen (via ActionBar-PullToRefresh library). Fixes #19. --- README.md | 3 + core/project.properties | 2 + core/res/values/changelog.xml | 1 + core/res/values/strings.xml | 2 +- .../transdroid/core/gui/DetailsActivity.java | 31 +- .../transdroid/core/gui/DetailsFragment.java | 5 + .../transdroid/core/gui/TorrentsActivity.java | 28 + .../transdroid/core/gui/TorrentsFragment.java | 4 + .../lists/NoProgressHeaderTransformer.java | 17 + .../gui/navigation/RefreshableActivity.java | 4 + .../core/service/AppUpdateService.java | 2 +- .../AndroidManifest.xml | 7 + .../build.gradle | 25 + .../build.xml | 92 ++ .../gradle.properties | 3 + .../proguard-project.txt | 20 + .../project.properties | 17 + .../res/anim/fade_in.xml | 22 + .../res/anim/fade_out.xml | 22 + .../AbsDefaultHeaderTransformer.java | 187 ++++ .../PullToRefreshAttacher.java | 75 ++ .../AndroidManifest.xml | 7 + external/ActionBar-PullToRefresh/build.gradle | 16 + external/ActionBar-PullToRefresh/build.xml | 92 ++ .../ActionBar-PullToRefresh/gradle.properties | 3 + .../proguard-project.txt | 20 + .../project.properties | 15 + .../ptr_progress_primary_holo.9.png | Bin 0 -> 257 bytes .../ptr_progressbar_indeterminate_holo1.png | Bin 0 -> 603 bytes .../ptr_progressbar_indeterminate_holo2.png | Bin 0 -> 725 bytes .../ptr_progressbar_indeterminate_holo3.png | Bin 0 -> 716 bytes .../ptr_progressbar_indeterminate_holo4.png | Bin 0 -> 761 bytes .../ptr_progressbar_indeterminate_holo5.png | Bin 0 -> 675 bytes .../ptr_progressbar_indeterminate_holo6.png | Bin 0 -> 761 bytes .../ptr_progressbar_indeterminate_holo7.png | Bin 0 -> 647 bytes .../ptr_progressbar_indeterminate_holo8.png | Bin 0 -> 692 bytes .../ptr_progress_primary_holo.9.png | Bin 0 -> 272 bytes .../ptr_progressbar_indeterminate_holo1.png | Bin 0 -> 602 bytes .../ptr_progressbar_indeterminate_holo2.png | Bin 0 -> 716 bytes .../ptr_progressbar_indeterminate_holo3.png | Bin 0 -> 778 bytes .../ptr_progressbar_indeterminate_holo4.png | Bin 0 -> 771 bytes .../ptr_progressbar_indeterminate_holo5.png | Bin 0 -> 722 bytes .../ptr_progressbar_indeterminate_holo6.png | Bin 0 -> 824 bytes .../ptr_progressbar_indeterminate_holo7.png | Bin 0 -> 721 bytes .../ptr_progressbar_indeterminate_holo8.png | Bin 0 -> 741 bytes .../ptr_progress_horizontal_holo_center.xml | 27 + ...progress_indeterminate_horizontal_holo.xml | 45 + .../res/layout/default_header.xml | 45 + .../res/values-ar/pull_refresh_strings.xml | 21 + .../res/values-cs/pull_refresh_strings.xml | 21 + .../res/values-de/pull_refresh_strings.xml | 21 + .../res/values-es/pull_refresh_strings.xml | 22 + .../res/values-fi/pull_refresh_strings.xml | 21 + .../res/values-fr/pull_refresh_strings.xml | 21 + .../res/values-he/pull_refresh_strings.xml | 22 + .../res/values-it/pull_refresh_strings.xml | 21 + .../res/values-iw/pull_refresh_strings.xml | 21 + .../res/values-ja/pull_refresh_strings.xml | 22 + .../res/values-ko/pull_refresh_strings.xml | 22 + .../res/values-nl/pull_refresh_strings.xml | 21 + .../res/values-pl/pull_refresh_strings.xml | 21 + .../values-pt-rBR/pull_refresh_strings.xml | 22 + .../res/values-pt/pull_refresh_strings.xml | 21 + .../res/values-ro/pull_refresh_strings.xml | 21 + .../res/values-ru/pull_refresh_strings.xml | 21 + .../res/values-sv/pull_refresh_strings.xml | 23 + .../res/values-zh/pull_refresh_strings.xml | 22 + .../res/values/attrs.xml | 48 + .../res/values/ids.xml | 24 + .../res/values/pull_refresh_strings.xml | 23 + .../res/values/styles.xml | 29 + .../library/DefaultHeaderTransformer.java | 397 ++++++++ .../library/InstanceCreationUtils.java | 91 ++ .../library/PullToRefreshAttacher.java | 948 ++++++++++++++++++ .../library/PullToRefreshLayout.java | 133 +++ .../library/platform/SDK11.java | 27 + .../viewdelegates/AbsListViewDelegate.java | 93 ++ .../viewdelegates/ScrollYDelegate.java | 32 + .../viewdelegates/WebViewDelegate.java | 35 + external/ColorPickerPreference/build.xml | 2 +- lite/ant.properties | 2 + lite/build.xml | 92 ++ 82 files changed, 3218 insertions(+), 4 deletions(-) create mode 100644 core/src/org/transdroid/core/gui/lists/NoProgressHeaderTransformer.java create mode 100644 external/ActionBar-PullToRefresh-actionbarsherlock/AndroidManifest.xml create mode 100644 external/ActionBar-PullToRefresh-actionbarsherlock/build.gradle create mode 100644 external/ActionBar-PullToRefresh-actionbarsherlock/build.xml create mode 100644 external/ActionBar-PullToRefresh-actionbarsherlock/gradle.properties create mode 100644 external/ActionBar-PullToRefresh-actionbarsherlock/proguard-project.txt create mode 100644 external/ActionBar-PullToRefresh-actionbarsherlock/project.properties create mode 100644 external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_in.xml create mode 100644 external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_out.xml create mode 100644 external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/AbsDefaultHeaderTransformer.java create mode 100644 external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/PullToRefreshAttacher.java create mode 100644 external/ActionBar-PullToRefresh/AndroidManifest.xml create mode 100644 external/ActionBar-PullToRefresh/build.gradle create mode 100644 external/ActionBar-PullToRefresh/build.xml create mode 100644 external/ActionBar-PullToRefresh/gradle.properties create mode 100644 external/ActionBar-PullToRefresh/proguard-project.txt create mode 100644 external/ActionBar-PullToRefresh/project.properties create mode 100644 external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progress_primary_holo.9.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo1.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo2.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo3.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo4.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo5.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo6.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo7.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo8.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progress_primary_holo.9.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo1.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo2.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo3.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo4.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo5.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo6.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo7.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo8.png create mode 100644 external/ActionBar-PullToRefresh/res/drawable/ptr_progress_horizontal_holo_center.xml create mode 100644 external/ActionBar-PullToRefresh/res/drawable/ptr_progress_indeterminate_horizontal_holo.xml create mode 100644 external/ActionBar-PullToRefresh/res/layout/default_header.xml create mode 100644 external/ActionBar-PullToRefresh/res/values-ar/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-cs/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-de/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-es/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-fi/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-fr/pull_refresh_strings.xml create mode 100644 external/ActionBar-PullToRefresh/res/values-he/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-it/pull_refresh_strings.xml create mode 100644 external/ActionBar-PullToRefresh/res/values-iw/pull_refresh_strings.xml create mode 100644 external/ActionBar-PullToRefresh/res/values-ja/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-ko/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-nl/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-pl/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-pt-rBR/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-pt/pull_refresh_strings.xml create mode 100644 external/ActionBar-PullToRefresh/res/values-ro/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-ru/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-sv/pull_refresh_strings.xml create mode 100755 external/ActionBar-PullToRefresh/res/values-zh/pull_refresh_strings.xml create mode 100644 external/ActionBar-PullToRefresh/res/values/attrs.xml create mode 100644 external/ActionBar-PullToRefresh/res/values/ids.xml create mode 100755 external/ActionBar-PullToRefresh/res/values/pull_refresh_strings.xml create mode 100644 external/ActionBar-PullToRefresh/res/values/styles.xml create mode 100644 external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/DefaultHeaderTransformer.java create mode 100644 external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/InstanceCreationUtils.java create mode 100644 external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshAttacher.java create mode 100644 external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshLayout.java create mode 100644 external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/platform/SDK11.java create mode 100644 external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/AbsListViewDelegate.java create mode 100644 external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/ScrollYDelegate.java create mode 100644 external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/WebViewDelegate.java create mode 100644 lite/ant.properties create mode 100644 lite/build.xml diff --git a/README.md b/README.md index e52a4f8a..69f4a51c 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,9 @@ Some code/libraries/resources are used in the project: * [AndroidAnnotations](http://androidannotations.org/) Pierre-Yves Ricau (eBusinessInformations) et al. Apache License, Version 2.0 +* [ActionBar-PullToRefresh](https://github.com/chrisbanes/ActionBar-PullToRefresh) + Chris Banes + Apache License, Version 2.0 * [Crouton](https://github.com/keyboardsurfer/Crouton) Code: Benjamin Weiss (Neofonie Mobile Gmbh) et al. Idea: Cyril Mottier diff --git a/core/project.properties b/core/project.properties index 0ca2ebd5..054f960b 100644 --- a/core/project.properties +++ b/core/project.properties @@ -16,3 +16,5 @@ android.library.reference.1=../external/JakeWharton-ActionBarSherlock/library android.library.reference.2=../external/ColorPickerPreference android.library=true android.library.reference.3=../external/Crouton/library +android.library.reference.4=../external/ActionBar-PullToRefresh-actionbarsherlock +android.library.reference.5=../external/ActionBar-PullToRefresh diff --git a/core/res/values/changelog.xml b/core/res/values/changelog.xml index a12c9d53..82213298 100644 --- a/core/res/values/changelog.xml +++ b/core/res/values/changelog.xml @@ -18,6 +18,7 @@ Transdroid 2.0.1\n +- Support for pull to refresh\n - First Google Play release of the lite version as Transdrone\n - First release as auto-update (now checked only once a day)\n \n diff --git a/core/res/values/strings.xml b/core/res/values/strings.xml index af4e4c31..6d9e7a67 100644 --- a/core/res/values/strings.xml +++ b/core/res/values/strings.xml @@ -374,7 +374,7 @@ \u00A9 Eric Kok, 2312 development Published under GNU General Public License v3 Some code/libraries are used in the project: - ActionBarSherlock\n \u00A0 http://actionbarsherlock.com/\n \u00A0 Jake Wharton \n \u00A0 Apache License, Version 2.0\nAndroidAnnotations\n \u00A0 http://androidannotations.org/\n \u00A0 Pierre-Yves Ricau (eBusinessInformations) et al. \n \u00A0 Apache License, Version 2.0\nCrouton\n \u00A0 https://github.com/keyboardsurfer/Crouton\n \u00A0 Code: Benjamin Weiss (Neofonie Mobile Gmbh) et al. \n \u00A0 Idea: Cyril Mottier \n \u00A0 Apache License, Version 2.0\nBase16Encoder\n \u00A0 http://openjpa.apache.org/\n \u00A0 Marc Prud\'hommeaux \n \u00A0 Apache OpenJPA\n MultipartEntity \n \u00A0 Apache Software Foundation \n \u00A0 Apache License, Version 2.0\nRssParser (learning-android)\n \u00A0 http://github.com/digitalspaghetti/learning-android\n \u00A0 Tane Piper \n \u00A0 Public Domain\nBase64\n \u00A0 http://iharder.net/base64\n \u00A0 Robert Harder \n \u00A0 Public Domain\nandroid-xmlrpc\n \u00A0 http://code.google.com/p/android-xmlrpc/\n \u00A0 pskink et al. \n \u00A0 Apache License, Version 2.0\nandroid-ColorPickerPreference\n \u00A0 https://github.com/attenzione/android-ColorPickerPreference\n \u00A0 Daniel Nilsson and Sergey Margaritov \n \u00A0 Apache License, Version 2.0\nCheckableRelativeLayout\n \u00A0 http://www.marvinlabs.com/2010/10/custom-listview-ability-check-items/\n \u00A0 Cédric Caron (MarvinLabs)\n \u00A0 Public Domain\nFunnel icon\n \u00A0 http://thenounproject.com/noun/funnel/#icon-No5608\n \u00A0 Naomi Atkinson from The Noun Project\n \u00A0 Creative Commons Attribution 3.0 + ActionBarSherlock\n \u00A0 http://actionbarsherlock.com/\n \u00A0 Jake Wharton \n \u00A0 Apache License, Version 2.0\nAndroidAnnotations\n \u00A0 http://androidannotations.org/\n \u00A0 Pierre-Yves Ricau (eBusinessInformations) et al. \n \u00A0 Apache License, Version 2.0\nActionBar-PullToRefresh\n \u00A0 https://github.com/chrisbanes/ActionBar-PullToRefresh\n \u00A0 Chris Banes \n \u00A0 Apache License, Version 2.0\nCrouton\n \u00A0 https://github.com/keyboardsurfer/Crouton\n \u00A0 Code: Benjamin Weiss (Neofonie Mobile Gmbh) et al. \n \u00A0 Idea: Cyril Mottier \n \u00A0 Apache License, Version 2.0\nBase16Encoder\n \u00A0 http://openjpa.apache.org/\n \u00A0 Marc Prud\'hommeaux \n \u00A0 Apache OpenJPA\n MultipartEntity \n \u00A0 Apache Software Foundation \n \u00A0 Apache License, Version 2.0\nRssParser (learning-android)\n \u00A0 http://github.com/digitalspaghetti/learning-android\n \u00A0 Tane Piper \n \u00A0 Public Domain\nBase64\n \u00A0 http://iharder.net/base64\n \u00A0 Robert Harder \n \u00A0 Public Domain\nandroid-xmlrpc\n \u00A0 http://code.google.com/p/android-xmlrpc/\n \u00A0 pskink et al. \n \u00A0 Apache License, Version 2.0\nandroid-ColorPickerPreference\n \u00A0 https://github.com/attenzione/android-ColorPickerPreference\n \u00A0 Daniel Nilsson and Sergey Margaritov \n \u00A0 Apache License, Version 2.0\nCheckableRelativeLayout\n \u00A0 http://www.marvinlabs.com/2010/10/custom-listview-ability-check-items/\n \u00A0 Cédric Caron (MarvinLabs)\n \u00A0 Public Domain\nFunnel icon\n \u00A0 http://thenounproject.com/noun/funnel/#icon-No5608\n \u00A0 Naomi Atkinson from The Noun Project\n \u00A0 Creative Commons Attribution 3.0 Manage your torrents from your Android device diff --git a/core/src/org/transdroid/core/gui/DetailsActivity.java b/core/src/org/transdroid/core/gui/DetailsActivity.java index 0f3c816d..50a5dcde 100644 --- a/core/src/org/transdroid/core/gui/DetailsActivity.java +++ b/core/src/org/transdroid/core/gui/DetailsActivity.java @@ -32,6 +32,7 @@ import org.androidannotations.annotations.UiThread; import org.transdroid.core.R; import org.transdroid.core.app.settings.*; import org.transdroid.core.gui.lists.LocalTorrent; +import org.transdroid.core.gui.lists.NoProgressHeaderTransformer; import org.transdroid.core.gui.log.Log; import org.transdroid.core.gui.navigation.Label; import org.transdroid.core.gui.navigation.NavigationHelper; @@ -62,10 +63,15 @@ import org.transdroid.daemon.task.SetTrackersTask; import org.transdroid.daemon.task.StartTask; import org.transdroid.daemon.task.StopTask; +import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher; +import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher.OnRefreshListener; +import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher.Options; + import android.annotation.TargetApi; import android.content.Intent; import android.os.Build; import android.os.Bundle; +import android.view.View; import android.widget.Toast; import com.actionbarsherlock.app.SherlockFragmentActivity; @@ -97,6 +103,7 @@ public class DetailsActivity extends SherlockFragmentActivity implements Torrent @Bean protected ApplicationSettings applicationSettings; private IDaemonAdapter currentConnection = null; + private PullToRefreshAttacher pullToRefreshAttacher = null; // Details view components @FragmentById(resName = "torrent_details") @@ -148,6 +155,28 @@ public class DetailsActivity extends SherlockFragmentActivity implements Torrent TorrentsActivity_.intent(this).flags(Intent.FLAG_ACTIVITY_CLEAR_TOP).start(); } + /** + * Attaches some view (perhaps contained in a fragment) to this activity's pull to refresh support + * @param view The view to attach + */ + @Override + public void addRefreshableView(View view) { + if (pullToRefreshAttacher == null) { + // Still need to initialise the PullToRefreshAttacher + Options options = new PullToRefreshAttacher.Options(); + options.headerTransformer = new NoProgressHeaderTransformer(); + pullToRefreshAttacher = PullToRefreshAttacher.get(this, options); + } + pullToRefreshAttacher.addRefreshableView(view, new OnRefreshListener() { + @Override + public void onRefreshStarted(View view) { + // Just refresh the full screen, now that the user has pulled to refresh + pullToRefreshAttacher.setRefreshComplete(); + refreshScreen(); + } + }); + } + @OptionsItem(resName = "action_refresh") public void refreshScreen() { fragmentDetails.updateIsLoading(true, null); @@ -330,7 +359,7 @@ public class DetailsActivity extends SherlockFragmentActivity implements Torrent protected void onCommunicationError(DaemonTaskFailureResult result, boolean isCritical) { Log.i(this, result.getException().toString()); String error = getString(LocalTorrent.getResourceForDaemonException(result.getException())); - fragmentDetails.updateIsLoading(false, isCritical? error: null); + fragmentDetails.updateIsLoading(false, isCritical ? error : null); Crouton.showText(this, getString(LocalTorrent.getResourceForDaemonException(result.getException())), NavigationHelper.CROUTON_ERROR_STYLE); } diff --git a/core/src/org/transdroid/core/gui/DetailsFragment.java b/core/src/org/transdroid/core/gui/DetailsFragment.java index d38c26d2..29de8d05 100644 --- a/core/src/org/transdroid/core/gui/DetailsFragment.java +++ b/core/src/org/transdroid/core/gui/DetailsFragment.java @@ -119,6 +119,11 @@ public class DetailsFragment extends SherlockFragment implements OnTrackersUpdat detailsList.setAdapter(new DetailsAdapter(getActivity())); detailsList.setMultiChoiceModeListener(onDetailsSelected); detailsList.setFastScrollEnabled(true); + if (getActivity() != null && getActivity() instanceof RefreshableActivity) { + ((RefreshableActivity) getActivity()).addRefreshableView(detailsList); + } + + // Restore the fragment state (on orientation changes et al.) if (torrent != null) updateTorrent(torrent); if (torrentDetails != null) diff --git a/core/src/org/transdroid/core/gui/TorrentsActivity.java b/core/src/org/transdroid/core/gui/TorrentsActivity.java index 11499432..01cc2eee 100644 --- a/core/src/org/transdroid/core/gui/TorrentsActivity.java +++ b/core/src/org/transdroid/core/gui/TorrentsActivity.java @@ -46,6 +46,7 @@ import org.apache.http.impl.cookie.BasicClientCookie; import org.transdroid.core.R; import org.transdroid.core.app.settings.*; import org.transdroid.core.gui.lists.LocalTorrent; +import org.transdroid.core.gui.lists.NoProgressHeaderTransformer; import org.transdroid.core.gui.lists.SimpleListItem; import org.transdroid.core.gui.log.*; import org.transdroid.core.gui.navigation.*; @@ -92,6 +93,10 @@ import org.transdroid.daemon.task.StopTask; import org.transdroid.daemon.util.DLog; import org.transdroid.daemon.util.HttpHelper; +import uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefreshAttacher; +import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher.OnRefreshListener; +import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher.Options; + import android.annotation.TargetApi; import android.app.SearchManager; import android.content.ContentResolver; @@ -138,6 +143,7 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi @SystemService protected SearchManager searchManager; private MenuItem searchMenu = null; + private PullToRefreshAttacher pullToRefreshAttacher = null; // Settings @Bean @@ -571,6 +577,28 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi startSearch(query, false, null, false); } + /** + * Attaches some view (perhaps contained in a fragment) to this activity's pull to refresh support + * @param view The view to attach + */ + @Override + public void addRefreshableView(View view) { + if (pullToRefreshAttacher == null) { + // Still need to initialise the PullToRefreshAttacher + Options options = new PullToRefreshAttacher.Options(); + options.headerTransformer = new NoProgressHeaderTransformer(); + pullToRefreshAttacher = PullToRefreshAttacher.get(this, options); + } + pullToRefreshAttacher.addRefreshableView(view, new OnRefreshListener() { + @Override + public void onRefreshStarted(View view) { + // Just refresh the full screen, now that the user has pulled to refresh + pullToRefreshAttacher.setRefreshComplete(); + refreshScreen(); + } + }); + } + @OptionsItem(resName = "action_refresh") public void refreshScreen() { fragmentTorrents.updateIsLoading(true); diff --git a/core/src/org/transdroid/core/gui/TorrentsFragment.java b/core/src/org/transdroid/core/gui/TorrentsFragment.java index 5a9333a0..680b4068 100644 --- a/core/src/org/transdroid/core/gui/TorrentsFragment.java +++ b/core/src/org/transdroid/core/gui/TorrentsFragment.java @@ -114,6 +114,10 @@ public class TorrentsFragment extends SherlockFragment implements OnLabelPickedL torrentsList.setFastScrollEnabled(true); if (torrents != null) updateTorrents(torrents, currentLabels); + // Allow pulls on the list view to refresh the torrents + if (getActivity() != null && getActivity() instanceof RefreshableActivity) { + ((RefreshableActivity) getActivity()).addRefreshableView(torrentsList); + } nosettingsText.setText(getString(R.string.navigation_nosettings, getString(R.string.app_name))); } diff --git a/core/src/org/transdroid/core/gui/lists/NoProgressHeaderTransformer.java b/core/src/org/transdroid/core/gui/lists/NoProgressHeaderTransformer.java new file mode 100644 index 00000000..a9abcee2 --- /dev/null +++ b/core/src/org/transdroid/core/gui/lists/NoProgressHeaderTransformer.java @@ -0,0 +1,17 @@ +package org.transdroid.core.gui.lists; + +import org.transdroid.core.R; + +import android.app.Activity; +import android.view.View; +import uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.AbsDefaultHeaderTransformer; + +public class NoProgressHeaderTransformer extends AbsDefaultHeaderTransformer { + + @Override + public void onViewCreated(Activity activity, View headerView) { + super.onViewCreated(activity, headerView); + setProgressBarColor(activity.getResources().getColor(R.color.green)); + } + +} diff --git a/core/src/org/transdroid/core/gui/navigation/RefreshableActivity.java b/core/src/org/transdroid/core/gui/navigation/RefreshableActivity.java index b5df126a..37ab45af 100644 --- a/core/src/org/transdroid/core/gui/navigation/RefreshableActivity.java +++ b/core/src/org/transdroid/core/gui/navigation/RefreshableActivity.java @@ -16,6 +16,8 @@ */ package org.transdroid.core.gui.navigation; +import android.view.View; + /** * Interface to be implemented by any activity that allows its content to be refreshed; fragments can ask for * user-initiated refreshes. @@ -25,4 +27,6 @@ public interface RefreshableActivity { public void refreshScreen(); + public void addRefreshableView(View view); + } diff --git a/core/src/org/transdroid/core/service/AppUpdateService.java b/core/src/org/transdroid/core/service/AppUpdateService.java index 7cdf6975..ef7a29e1 100644 --- a/core/src/org/transdroid/core/service/AppUpdateService.java +++ b/core/src/org/transdroid/core/service/AppUpdateService.java @@ -79,7 +79,7 @@ public class AppUpdateService extends IntentService { Date lastChecked = systemSettings.getLastCheckedForAppUpdates(); Calendar lastDay = Calendar.getInstance(); lastDay.add(Calendar.DAY_OF_MONTH, -1); - if (lastChecked == null || lastChecked.after(lastDay.getTime())) { + if (lastChecked != null && lastChecked.after(lastDay.getTime())) { Log.d(this, "Ship the update service, as we already checked the last 24 hours (or to be exact at " + lastChecked.toString() + ")."); return; diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/AndroidManifest.xml b/external/ActionBar-PullToRefresh-actionbarsherlock/AndroidManifest.xml new file mode 100644 index 00000000..ae76ec35 --- /dev/null +++ b/external/ActionBar-PullToRefresh-actionbarsherlock/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/build.gradle b/external/ActionBar-PullToRefresh-actionbarsherlock/build.gradle new file mode 100644 index 00000000..2ca4be69 --- /dev/null +++ b/external/ActionBar-PullToRefresh-actionbarsherlock/build.gradle @@ -0,0 +1,25 @@ +apply plugin: 'android-library' + +dependencies { + compile project(':library') + compile "com.android.support:support-v4:[18.0,)" + compile ("com.actionbarsherlock:actionbarsherlock:[4.4,)@aar") { + // Need to specifically exclude this as it is specified in ActionBarSherlock pom + exclude group: 'com.google.android', module: 'support-v4' + } +} + +android { + compileSdkVersion 18 + buildToolsVersion '17.0.0' + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + res.srcDirs = ['res'] + } + } +} + +apply from: '../../maven_push.gradle' diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/build.xml b/external/ActionBar-PullToRefresh-actionbarsherlock/build.xml new file mode 100644 index 00000000..390ff5f3 --- /dev/null +++ b/external/ActionBar-PullToRefresh-actionbarsherlock/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/gradle.properties b/external/ActionBar-PullToRefresh-actionbarsherlock/gradle.properties new file mode 100644 index 00000000..3a29e9ee --- /dev/null +++ b/external/ActionBar-PullToRefresh-actionbarsherlock/gradle.properties @@ -0,0 +1,3 @@ +POM_NAME=ActionBar-PullToRefresh Extras: ActionBarSherlock +POM_ARTIFACT_ID=extra-abs +POM_PACKAGING=aar diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/proguard-project.txt b/external/ActionBar-PullToRefresh-actionbarsherlock/proguard-project.txt new file mode 100644 index 00000000..f2fe1559 --- /dev/null +++ b/external/ActionBar-PullToRefresh-actionbarsherlock/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/project.properties b/external/ActionBar-PullToRefresh-actionbarsherlock/project.properties new file mode 100644 index 00000000..367cb5d5 --- /dev/null +++ b/external/ActionBar-PullToRefresh-actionbarsherlock/project.properties @@ -0,0 +1,17 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-18 +android.library=true +android.library.reference.1=../ActionBar-PullToRefresh +android.library.reference.2=../JakeWharton-ActionBarSherlock/library diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_in.xml b/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_in.xml new file mode 100644 index 00000000..fd820b3a --- /dev/null +++ b/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_in.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_out.xml b/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_out.xml new file mode 100644 index 00000000..aad49484 --- /dev/null +++ b/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_out.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/AbsDefaultHeaderTransformer.java b/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/AbsDefaultHeaderTransformer.java new file mode 100644 index 00000000..3fd83be8 --- /dev/null +++ b/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/AbsDefaultHeaderTransformer.java @@ -0,0 +1,187 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock; + +import android.app.Activity; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; + +import uk.co.senab.actionbarpulltorefresh.library.DefaultHeaderTransformer; + +public class AbsDefaultHeaderTransformer extends DefaultHeaderTransformer { + + private Animation mHeaderInAnimation, mHeaderOutAnimation; + + @Override + public void onViewCreated(Activity activity, View headerView) { + super.onViewCreated(activity, headerView); + + // Create animations for use later + mHeaderInAnimation = AnimationUtils.loadAnimation(activity, R.anim.fade_in); + mHeaderOutAnimation = AnimationUtils.loadAnimation(activity, R.anim.fade_out); + + if (mHeaderOutAnimation != null || mHeaderInAnimation != null) { + final AnimationCallback callback = new AnimationCallback(); + if (mHeaderOutAnimation != null) { + mHeaderOutAnimation.setAnimationListener(callback); + } + } + } + + @Override + protected Drawable getActionBarBackground(Context context) { + // Super handles ICS+ anyway... + if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) { + return super.getActionBarBackground(context); + } + + // Get action bar style values... + TypedArray abStyle = obtainStyledAttrsFromThemeAttr(context, R.attr.actionBarStyle, + R.styleable.SherlockActionBar); + try { + return abStyle.getDrawable(R.styleable.SherlockActionBar_background); + } finally { + abStyle.recycle(); + } + } + + @Override + protected int getActionBarSize(Context context) { + // Super handles ICS+ anyway... + if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) { + return super.getActionBarSize(context); + } + + TypedArray values = context.obtainStyledAttributes(R.styleable.SherlockTheme); + try { + return values.getDimensionPixelSize(R.styleable.SherlockTheme_actionBarSize, 0); + } finally { + values.recycle(); + } + } + + @Override + protected int getActionBarTitleStyle(Context context) { + // Super handles ICS+ anyway... + if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) { + return super.getActionBarTitleStyle(context); + } + + // Get action bar style values... + TypedArray abStyle = obtainStyledAttrsFromThemeAttr(context, R.attr.actionBarStyle, + R.styleable.SherlockActionBar); + try { + return abStyle.getResourceId(R.styleable.SherlockActionBar_titleTextStyle, 0); + } finally { + abStyle.recycle(); + } + } + + @Override + public boolean showHeaderView() { + // Super handles ICS+ anyway... + if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) { + return super.showHeaderView(); + } + + final View headerView = getHeaderView(); + final boolean changeVis = headerView != null && headerView.getVisibility() != View.VISIBLE; + if (changeVis) { + // Show Header + if (mHeaderInAnimation != null) { + // AnimationListener will call HeaderViewListener + headerView.startAnimation(mHeaderInAnimation); + } + headerView.setVisibility(View.VISIBLE); + } + return changeVis; + } + + @Override + public boolean hideHeaderView() { + // Super handles ICS+ anyway... + if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) { + return super.hideHeaderView(); + } + + final View headerView = getHeaderView(); + final boolean changeVis = headerView != null && headerView.getVisibility() != View.GONE; + if (changeVis) { + // Hide Header + if (mHeaderOutAnimation != null) { + // AnimationListener will call HeaderTransformer and + // HeaderViewListener + headerView.startAnimation(mHeaderOutAnimation); + } else { + // As we're not animating, hide the header + call the header + // transformer now + headerView.setVisibility(View.GONE); + onReset(); + } + } + return changeVis; + } + + @Override + public void onRefreshMinimized() { + // Super handles ICS+ anyway... + if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) { + super.onRefreshMinimized(); + return; + } + + // Here we fade out most of the header, leaving just the progress bar + View contentLayout = getHeaderView().findViewById(R.id.ptr_content); + if (contentLayout != null) { + contentLayout.startAnimation(AnimationUtils + .loadAnimation(contentLayout.getContext(), R.anim.fade_out)); + contentLayout.setVisibility(View.INVISIBLE); + } + } + + @Override + protected int getMinimumApiLevel() { + return Build.VERSION_CODES.ECLAIR_MR1; + } + + class AnimationCallback implements Animation.AnimationListener { + + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + if (animation == mHeaderOutAnimation) { + View headerView = getHeaderView(); + if (headerView != null) { + headerView.setVisibility(View.GONE); + } + onReset(); + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + } +} diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/PullToRefreshAttacher.java b/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/PullToRefreshAttacher.java new file mode 100644 index 00000000..aad995c5 --- /dev/null +++ b/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/PullToRefreshAttacher.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock; + +import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.app.SherlockExpandableListActivity; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import com.actionbarsherlock.app.SherlockListActivity; +import com.actionbarsherlock.app.SherlockPreferenceActivity; + +import android.app.Activity; +import android.content.Context; + +public class PullToRefreshAttacher extends + uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher { + + public static PullToRefreshAttacher get(Activity activity) { + return get(activity, new Options()); + } + + public static PullToRefreshAttacher get(Activity activity, Options options) { + return new PullToRefreshAttacher(activity, options); + } + + protected PullToRefreshAttacher(Activity activity, Options options) { + super(activity, options); + } + + @Override + protected EnvironmentDelegate createDefaultEnvironmentDelegate() { + return new AbsEnvironmentDelegate(); + } + + @Override + protected HeaderTransformer createDefaultHeaderTransformer() { + return new AbsDefaultHeaderTransformer(); + } + + public static class AbsEnvironmentDelegate extends EnvironmentDelegate { + /** + * @return Context which should be used for inflating the header layout + */ + public Context getContextForInflater(Activity activity) { + if (activity instanceof SherlockActivity) { + return ((SherlockActivity) activity).getSupportActionBar().getThemedContext(); + } else if (activity instanceof SherlockListActivity) { + return ((SherlockListActivity) activity).getSupportActionBar().getThemedContext(); + } else if (activity instanceof SherlockFragmentActivity) { + return ((SherlockFragmentActivity) activity).getSupportActionBar() + .getThemedContext(); + } else if (activity instanceof SherlockExpandableListActivity) { + return ((SherlockExpandableListActivity) activity).getSupportActionBar() + .getThemedContext(); + } else if (activity instanceof SherlockPreferenceActivity) { + return ((SherlockPreferenceActivity) activity).getSupportActionBar() + .getThemedContext(); + } + return super.getContextForInflater(activity); + } + } +} diff --git a/external/ActionBar-PullToRefresh/AndroidManifest.xml b/external/ActionBar-PullToRefresh/AndroidManifest.xml new file mode 100644 index 00000000..fc808f4f --- /dev/null +++ b/external/ActionBar-PullToRefresh/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/external/ActionBar-PullToRefresh/build.gradle b/external/ActionBar-PullToRefresh/build.gradle new file mode 100644 index 00000000..625d8f23 --- /dev/null +++ b/external/ActionBar-PullToRefresh/build.gradle @@ -0,0 +1,16 @@ +apply plugin: 'android-library' + +android { + compileSdkVersion 18 + buildToolsVersion '17.0.0' + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + res.srcDirs = ['res'] + } + } +} + +apply from: '../maven_push.gradle' \ No newline at end of file diff --git a/external/ActionBar-PullToRefresh/build.xml b/external/ActionBar-PullToRefresh/build.xml new file mode 100644 index 00000000..1b4d11f9 --- /dev/null +++ b/external/ActionBar-PullToRefresh/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/ActionBar-PullToRefresh/gradle.properties b/external/ActionBar-PullToRefresh/gradle.properties new file mode 100644 index 00000000..7d783d1a --- /dev/null +++ b/external/ActionBar-PullToRefresh/gradle.properties @@ -0,0 +1,3 @@ +POM_NAME=ActionBar-PullToRefresh Library +POM_ARTIFACT_ID=library +POM_PACKAGING=aar diff --git a/external/ActionBar-PullToRefresh/proguard-project.txt b/external/ActionBar-PullToRefresh/proguard-project.txt new file mode 100644 index 00000000..f2fe1559 --- /dev/null +++ b/external/ActionBar-PullToRefresh/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/external/ActionBar-PullToRefresh/project.properties b/external/ActionBar-PullToRefresh/project.properties new file mode 100644 index 00000000..1b8c5a34 --- /dev/null +++ b/external/ActionBar-PullToRefresh/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-18 +android.library=true diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progress_primary_holo.9.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progress_primary_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..cc5478848e36c014db6043719359f70559f47d55 GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^%0SG)!3HFYH@U3=QY^(zo*^7SP{WbZ0pxQQctjR6 zFmMZjFyp1Wb$@_@G9|7NCBgY=CFO}lsSJ)O`AMk?Zka`?<@rU~#R|^BW-s<^>H(^& z_H=O!vFJT}`5|U}oXkrgM&cQ_!uOn_sReTdpunn zLn02popG19K|!F|GC)93M6~|<{mYU9avWcz7kFOIF49as;yS(K!I7$!Q{EJ>5cO6z zdo1xKL+y21y1MZzM$P|M#pj59OFI<(d`*4!a>3b!GeYx(5_1Rxsze;41q) zZaK#sum8OxuK3iYc8j3d#bdv2b@+?U*9!9c8?y1y0kyC>PGNKSjTxsusr9H`19X>a ziEBhjN@7W>RdP`(kYX@0Ff`URFw-?M3o$gZGBUCU}oXkrgMJV;kvZ4=O8dL==A!4sy=m^Eki^vMY#Tfra1VG*EDtr;B4q#NoFQxA~e3M5KERX9`<9kZm(}ak%@xe%|^+v)d#k zm&;#R;yc?!^+@4La}|lNKXn9(6~*uH&rG+BkeDbji6u$s=K62K{+C3iH7|d?+^9!& zX5jqwDbr`}IyWmr_(o1S)3+FZmdJG>^D>X@R(A|Mari~*4DU}LS!$nco@o|$YW1qT zb0L$$%^7@qdEZoB+V=f8Sbp=GUuSN(1(9xw`-e0?ycIor&v-t7o&&lr3 zOkxujmrk#L-3j!CYKdz^NlIc#s#S7PDv)9@GB7mOH89gPG7B*@vNANaGBDIOFtjo- znCq`|9YsTKeoAIqC2kFGgr;NzHAsSN2+mI{DNig)WpGT%PfAtr%uP&B4N6T+sVqF1 Q3QArKp00i_>zopr0AY?4>;M1& literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo3.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo3.png new file mode 100644 index 0000000000000000000000000000000000000000..d2c6e88d2ef5e7e1c699a04d7d07cbad05546c86 GIT binary patch literal 716 zcmeAS@N?(olHy`uVBq!ia0y~yVD1I7**KViWPoTlh{KZZ=U}oXkrgMK=f4d%3PpJG)sc~f+tL!A<4%vYtHPM(^NR8PmU4hVh`n&=v6Wo+YTgHR^XTp z4N3_H7JiG`&XD-N+i%XC9Twbmo{#3I zU%Oc|J#O>P1Da=U?9h1b^r0qX?V>50blftW3Ri3KS}}20@3Qx}U~D;K@2_?D7F87| zU-r6bcFOy8)uMgPqT(W%s~mwQy08DP(B5BYQ2j0T=7C-b7l#X1dvAnnT*BD&%U3j9 zM#g}_akBO~@%+tsJ9kP5IsiSSTH+c}l9E`GYL#4+3Zxi}3=EBR4a{_n%t8!}tPD-9 z42-o646O_dxGvcKL(!0%pOTqYiCaT;Z>tkfgCxj?;QX|b^2DN42FH~Aq*MjZ+{EFVdQ&MBb@0O%_XaR2}S literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo4.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo4.png new file mode 100644 index 0000000000000000000000000000000000000000..06204753de0f80fd2873ec3cd8673bc1bb91bb11 GIT binary patch literal 761 zcmeAS@N?(olHy`uVBq!ia0y~yVD1I7**KViWPoTlh{KZZ=U}oXkrgM6Ai~WtO@&V~hF79jigTF^ zzq!%^>7Q}}E9C`wti{FD7l~$^&|C)8%9-!xRt%&;fRlmy1#dfuQQ#2?67&FLx0Bg+ zAi=T%$8=~AOE9qTTbu?8-tu&D42d}WHsUm2lYu}^<+L!3C>H^Nr)wAd`G0>UrCP~3Zmv#A;u3grp&9}~C$0LTw!g-tr)_pu>YSIeyrD}<5 zL`h0wNvc(HQ7VvPFfuSS)-^EGH8Kk^G_o=@wKA~KHZZg@FyOeJ$%3LGH$NpatrE9} z%C3t$fEpx0HU#IVm6RtIr7}3C zcvi{_@(Rc;;!`QE1!~~TcXKNS(jdUe!2N<36f&Fz9+4nH4={E+nQaFWEGuwK2L@d) zkS)Q$!f$aJ$XMg);usQf`0b37d`$)tEzw+e8-k{~rfM##{U842Nuz{M)kfPh|6H_V+Po{zr3xlVtpUXO@geCxB68J#? literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo6.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo6.png new file mode 100644 index 0000000000000000000000000000000000000000..48ba1b4dbbf4d3929deb8d523fb812340e99e334 GIT binary patch literal 761 zcmeAS@N?(olHy`uVBq!ia0y~yVD194**KVihMuXm0W7BRDJ=nE+lM+h^#|nXf<$NmwZad^MZ#`>&#Z3M&*Iv$!t`DF@qgvt` zQIe8al4_M)lnSI6j0_Bobq&mPjm$y}jjRk!tqhH{4GgUe3=(+FuApeh%}>cptHiBA zFrY63s6i5BLvVgtNqJ&XDuZK6ep0G}XKrG8YEWuoN@d~6R8SIR@O1TaS?83{1ORf# B9{>OV literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo7.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo7.png new file mode 100644 index 0000000000000000000000000000000000000000..34f15ce4ecfad2111782acff520f7a549b37652a GIT binary patch literal 647 zcmeAS@N?(olHy`uVBq!ia0y~yVD163**KViov} zi}RX3o^xa!P%US^n_DrE1_4e6?ial6AVz^lBuLN$jNMLV+kphj3LMjc!PE<6OE9qT zTbu?mmUy~2hD02GJL5KAlLL>-?wC`03r^&^uKWEz{^f3|M)t|K&Q#{ldYLjQt;0t| z-MvHESu8j#WtYj;)O?>WP1DW_Fmm-&^P(}0k|4uNC) zd6e&k>{)r?$8K{`Rz5Bn5ep-(IqLSM_XQTm2OC7#SEE z>l&Ep8kvO{8d({dS{a&X8yH#{7%<;ueuttVH$NpatrE9}qK4hTRKy?&vLQG>t)x7$ mD3!r6B|j-u!8128JvAsbF{QHbWGW~@FnGH9xvXU}oXkrgMD6}_RXgbgt8YMw~!4sy=m^Eki%;}Rug}Ka4Rj4 z{wXJ5EzT>ZzDPdoK+q+i9?pC>w_+d-0-OxoFL>KQi~^5Hke~+`yPeFo0|}NDIHp5` zQG$Vm-{Le-aHFS-V@Sl|w=*JznhXS7gq;*v5*<=y60|d2&dq)%_<{!I?^r7fkRx=(S2qD^f6Oo2g##^(|kkXWO4wbzN1am+f-o z`_kQ=art7C=+8pI4o}PSpX3=!h>H0ZO7E7Kvarn>9Oto3+JHEd& zI$g9^ak~2V_Ls5O4!GUmkapf6=qu_gy7OA@s))i3j}ngloGAL7bGL>6%&4ZD7l4je zEpd$~Nl7e8wMs5Z1yT$~28PDE24=cOW+8?~R)(flhGyCZhE@g!Q=Ej3qiD#@PsvQH z#I50}{Hki821$?&!TD(=<%vb942~)JNvR5+xryniL8*x;m4zo$L8*tq)78&qol`;+ E00{m93jhEB literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progress_primary_holo.9.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progress_primary_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..0f542a325818b4ed01a0e15d97107ff7f784a45d GIT binary patch literal 272 zcmeAS@N?(olHy`uVBq!ia0vp^dO*y@!3HExx8#TeDVAa<&kznEsNqQI0P;BtJR*x3 z7`TN%nDNrxx<5ccnG)BClHmNblJdl&R0hYC{G?O`x6Go{^8BLgVg=`5vln|d^#Ij% zdAc};SoB`KvXS?YgMiCLdod@cMNHER6iauo8^ugsdALYAMeksdABz*u!NiGj7c=X( zN$<@#qA#p`Gi`fpX3RQM)1_x)xj(e}ziy~q$*J}7!S}hDtS_VwXfjA0cvSJ}HP3}B z$NtR!CLlDAn_axlp)GrwlMdGp%|hl2-@G0hU16STUY?t8-CudcuGLp#(E_jHr9f9P Nc)I$ztaD0e0suwUU&;Ug literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo1.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo1.png new file mode 100644 index 0000000000000000000000000000000000000000..c59fb19baed103e0576137b6c5cdd40d826d9c00 GIT binary patch literal 602 zcmeAS@N?(olHy`uVBq!ia0y~yVA%s?b8s*N$s?j-6+nt5-O<;Pfnj4m_n$;oAfK@~ z$lZxy-8q?;K#oGPN02WALzNl>LqiJ#!!Mvv!wUw6QUeBtR|yOZRx=nF#0%!^3bX-A zcnA1|xEgPLN-cCmt>-?_Sc#G#zu*azr_Y={M^c!JV@9u>I1lF!Rat)SpXvhIcC#J; z)o|v!xfKIx5a3}boB#6=kil8t5eX9X0Ash4*>)hovI56+XfP-+NDAg{0}4*}ba4#H zxcBx}G+%=PkIO}-&_KbO*Z;y_3H@0pKg(Kr#*-zP4uXYtE6msedGC4NKDw_zHv9VL zP<;QrM9x|>~V63{TVznedVG{s-(Q2uvxxe)*T@{5!I zExvOE=tR{L*NBpo#FA92LqiJ#!!Mvv!wUw6QUeBtR|yOZRx=nF#0%!^3bX-A zlm_^OxEgPLN`JKI^~8Rl1Jp`_{DLP;o<4K-oQWzTTpYrZ+?)zCdW|J`dBo*(epm_c z%c}mgmKRj#GZoonmkiXwneXOS45UGThoNl#&qF{4XMsl~NYDd}-A-oPfdtD69Mhq} zr@$a7n70imc+u0vF(l*O+gZ2ynhXS7c807I6YUChV0HQTU%1!MuG21oY2v(}jh=qX zCcjJ5JzW-~7&h61R^s?Q&`%{53*GqGQotw7Ia(r}c%He%e#Gkf$Xg@vbK4;^^L{1@ZIqAs8e;)m< zwwb0KN2a&hE*F~PrEuw2|8k-77rUeEC+k|B26|4l#5JNMC9x#cD!C{XNHG{07#iyu znCTjsg%}!H8Jb!d7-}0BS{WG3_1C$Mq9HdwB{QuOw}v-DQ?h{?BtbR==ckpFCl;kL jIHu$$r7C#lCZ?wbr6#6S7M@H6r78wbS3j3^P6LqiJ#!!Mvv!wUw6QUeBtR|yOZRx=nF#0%!^3bX-A zR0sHkxEgPLI#6hDxX^T^T!vM7TK>Bzon>b;$^2BemKQX2O`iV^sE0G(&8-+ng8&ah+5De}fDFz8k4TW92N=7Z%(epwmK8Xr zLxWL)K~gYp8!*J!JzX3_GVZ;db(*iqK*06(q7y$foK}XibSs_uU%!xBeof4b28(C& zQp4v?o;iDqq~a1TCe@=UQs>ehmMAUh>Ud_)7r5j}(#}hTYr;>nc3T%eemNsJ{=nP( zkZtb_eLEKE&7Tyqs-Z(8z)18h^W>Wr+h%4;ZuFdUP4DKG1drp1C)VgcD9hQlH@xip z^4NXv`@XIJp!F%}wUNGsrj^9|Ip*v=2N(3MO}!>wU|pp%d(-n%U3;$VvJzYV?!_0b z^|var_pY?mv@)N*YL`hmNafsQkV>=b$G*oz*7hHkddO;!Q1ILSVQaebfz5(>k#^D_ z6Z!919Ba3|Q+Hyz-J6YCj2pBVx66d9<~=Cgxpt1>gA8Cesg}4#l%yn~>+BeM`gBP&BwD+6O~14AnV1Fj3U|4=mK=BH$)RpQoA-P`H})F276Aviy+ pq&%@GmBBG3KPgqgGdD3kH7GSPrLyp3Dkx1dc)I$ztaD0e0s#1JFBSj* literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo4.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo4.png new file mode 100644 index 0000000000000000000000000000000000000000..143d63c41d73b1b724d795673004f31ed997846a GIT binary patch literal 771 zcmeAS@N?(olHy`uVBq!ia0y~yVA%s?b8s*N$s?j-6+nt5-O<;Pfnj4m_n$;oAfK@~ z$lZxy-8q?;K#oGPN02WALzNl>LqiJ#!!Mvv!wUw6QUeBtR|yOZRx=nF#0%!^3bX-A zR0sHkxEgPLI#6hDxX^T>b;$^2BemKQXA@HN;FsE0G(&8-+ng8&ah+5De}fDFz8k4TW92N=7Z%(epwmK8Xr zLxWL)K~gYp8!*HeJY5_^GVZ;db&{{yfXC(LDLJl|rK$Rir~cO`vU*I7I=E2Ca>uNl zu5+H9oOeR4Yf;v&#F%?VJh8!|mp92C-*)ExdXp_x1-A2989&=jU&8J+NAo(@ic@7p zwu;_%L7F`wx_zdmLC<18s_-_MJTy*BO*|JNmu9RodvmVvdeMNX%Wr4;Z422Y{pDHy&N!P~n(i9Psz}heJ0w5_4EWCnYP3eY?Ov zXX6I;tInP=Hy*EKX_^0Pf!D{CN4Se8^iB1B!@Cw3K&mCK5hW>!C8<`)MX5lF!N|bS zSl7Tz*T^iy(8$Wr)XKm@+rZGuz<}d=CJTy&-29Zxv`X9>D!VT30BVo~*$|wcR#Ki= ml*-_klAn~S;F+74o*I;zm{M7IG8L2<89ZJ6T-G@yGywn}zb5Sf literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo5.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo5.png new file mode 100644 index 0000000000000000000000000000000000000000..8db70e7428b983ed043a0a2d9cdee3b064f31b64 GIT binary patch literal 722 zcmeAS@N?(olHy`uVBq!ia0y~yVA%p>b8s*N$?J#0dVmy5x}&cn1H;CC?mvmFKt5w} zkh>GZx^prwfgFWok04(LhAK4%hK3dfhF?ITh8GMBr3MTPuM!v-tY$DUh!@P+6=(yL z$PDlaaW&rhls-smW!_<+rAj41e!&waPoFt^j-)Ub$3ztoZcYU`aUNp{UL93gek%cW zYk5IF)5BBr@_?#2^WEHvfiwv4FqF;zc?ihhEbxc~33`CB+sSM@kYHJXV>&Q!_5j%m z43dI*+klMco-U3d8Ta1KIw{nwAm9?{d4#n|qwt{azyI#be9n1JJhVxvY`!f||IB4+ zGEPkfi@tnvoZ^<~u+Gq1NGyJTeYMVBziDZf;!V#ZUtK);Z}#^3nJm-xAFVAen7mzn z;!&qf0ZuEN^zN-(WAc2LmUxE#y`IXMo(Y+&cNgCYTNY}r`#d-JclpP;CQ;Hi7qXN+ zUOQzvQ2(_w?dan>*7~fD|0r=2D1F%C>}L}`jmEnb>-$~!g`TJWl;};qW1u@jjEh(2 zud(iyc7a>Y8*D}V4vx8YO6{VxfXOQyD~uQPwl6m>PL0qAAb z64!{5l*E!$tK_0oAjM#0U}&ssV5Vzi7Gh{*WoT+;XrOIiXk}pVeUkcL6b-rgDVb@N zxHYt$pASrT43Z!lg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4hg3=a)r>mdKI;Vst E0MNS+&Hw-a literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo6.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo6.png new file mode 100644 index 0000000000000000000000000000000000000000..fab55fa546d8b280a13338e1f433f0b34b34e3a2 GIT binary patch literal 824 zcmeAS@N?(olHy`uVBq!ia0y~yVA%m=b8s*N$+Q2qF##!-bVpxD28NCO+O+%m>@fksM!=b zabpSIOVWH&p{la{RsvU)gcPIIt>v#O$EfH0$pjj}neXOS45UGThoNl#&qF{4XMsl~ zNYDd}-A-oPfdtD69MgdTy$8rvV2~8d+Xf6}Mo$;Vkc@k8XT9V*q#)2zz2Ionhczo! zXl&KG7k>Z$)jtopBZQ@A&;9Ao6rZMkGu8Gyztb@(`Ob|7ANHmliPn`fJw0d5dI@f3 z`#g0guZdfdh4TOLKbjKbHd*0yN%h}@22+(+9-CZo>+g$s??pa!UAknfx^&jdrU}ou zm0KduaIdg>G)K5t(zEGwsFKR|o4f98)Nj(hpVN9HugFX7MrL}?W$P)V@Y`XZc^MO;r!Z!*m z;!&a>QWZRN6Vp?JQWH}u3s0tkQZR$3tDnm{r-UW| D@R3HU literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo7.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo7.png new file mode 100644 index 0000000000000000000000000000000000000000..feec26b94865391c0a43c17ee74d7dab4bb63569 GIT binary patch literal 721 zcmeAS@N?(olHy`uVBq!ia0y~yVA%y^b8s*N$&=h^_CSgy-O<;Pfnj4m_n$;oAfK@~ z$lZxy-8q?;K#oGPN02WALzNl>LqiJ#!!Mvv!wUw6QUeBtR|yOZRx=nF#0%!^3bX-A zWCr+zxEgPLN*^S(GVd_ZQl*k0zu*azr_Y={M^c!JW1@-(H>ZM}IFGReua2rLzmES7Qc|g^i`EG8-KpF&i7|Q1VJOpHL7I;L01U`$0&nG@*eLP3BvaC{W-Oj`9b)St&ZTFoKo@{rp z%3;xzIj4ixTv)d%tY_seCeG(~G+X)iKL5I9)$4!~)7;|`*Ub!?1NFBAMSW3tIA`~i z4-3EV(YhFUrBq{A8*if+^O*z_zt5Y_T;>ouw=>_Lt>%U0`s+({UpbX1?kW&H_&V!i zYnvdivXsJyPa6`C%=pJ_d+f{qM}3BWIV&RjUT&0We9BStt$BL=X~BHHk{4{6O!;4d zK2|MpjVMV;EJ?LWE=mPb3`Pcq#<~V(x<+OphDKI~rdEa~+6IPJ1_sP`nctyk$jwj5 zOsmALp{QXuFg-Fzf@}!RPb(=;EJ|f?Ovz75Rq)JBOiv9;O-!jQJedkgS`419elF{r G5}E+E7!r2? literal 0 HcmV?d00001 diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo8.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo8.png new file mode 100644 index 0000000000000000000000000000000000000000..8843242888dbf3358681e3e112fd8f35a4c2d4a4 GIT binary patch literal 741 zcmeAS@N?(olHy`uVBq!ia0y~yVA%s?b8s*N$s?j-6+nt5-O<;Pfnj4m_n$;oAfK@~ z$lZxy-8q?;K#oGPN02WALzNl>LqiJ#!!Mvv!wUw6QUeBtR|yOZRx=nF#0%!^3bX-A zlm_^OxEgPLN`JKI^~8Rl1Jp`_{DLP;o<4K-97$m=j)^KF+?)zCdga7%l!VD@6|l&dCDR^Q>gjUxjPTfE&lv7q$uvBpqKu- zV%5okojyf+#)gjEr?`*K&?=g6V{Wy?p}ArocIK{pl4r5!)T*>K>%1fqJ$o;BWnOGJ z^6t*k7Hi!Hle??-PHKPnA?x}1>x)_ir(OAa*n+Q?U1)dl{CcT^=MR6{RPT-BJjDI5 z^*E>Eo(pD+a$TZX?6z&|mAH|=ON!@B{ZU!wYV996GB=V#nN|x$urkO?hpWal*G4{f zxZ1G;=xfyy*NBpo#FA92rfpzoWneJHN$5C= zhTQy=%(P0}8lK9pss?J11lbUrpH@ + + + + + + + + + \ No newline at end of file diff --git a/external/ActionBar-PullToRefresh/res/drawable/ptr_progress_indeterminate_horizontal_holo.xml b/external/ActionBar-PullToRefresh/res/drawable/ptr_progress_indeterminate_horizontal_holo.xml new file mode 100644 index 00000000..b55003e6 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/drawable/ptr_progress_indeterminate_horizontal_holo.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + diff --git a/external/ActionBar-PullToRefresh/res/layout/default_header.xml b/external/ActionBar-PullToRefresh/res/layout/default_header.xml new file mode 100644 index 00000000..4a3619e2 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/layout/default_header.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + diff --git a/external/ActionBar-PullToRefresh/res/values-ar/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-ar/pull_refresh_strings.xml new file mode 100644 index 00000000..c7de7f8c --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-ar/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + اسحب للتحديث… + اترك للتحديث… + تحميل… + diff --git a/external/ActionBar-PullToRefresh/res/values-cs/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-cs/pull_refresh_strings.xml new file mode 100755 index 00000000..97240bec --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-cs/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + Tažením aktualizujete… + Uvolněním aktualizujete… + Načítání… + diff --git a/external/ActionBar-PullToRefresh/res/values-de/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-de/pull_refresh_strings.xml new file mode 100755 index 00000000..c5ac00bc --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-de/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + Ziehen zum Aktualisieren… + Loslassen zum Aktualisieren… + Laden… + diff --git a/external/ActionBar-PullToRefresh/res/values-es/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-es/pull_refresh_strings.xml new file mode 100755 index 00000000..04894df2 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-es/pull_refresh_strings.xml @@ -0,0 +1,22 @@ + + + + + Desliza el dedo hacia abajo para actualizar. + Soltar para actualizar… + Cargando… + diff --git a/external/ActionBar-PullToRefresh/res/values-fi/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-fi/pull_refresh_strings.xml new file mode 100755 index 00000000..bc8d32a5 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-fi/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + Päivitä vetämällä alas… + Päivitä vapauttamalla… + Päivitetään… + \ No newline at end of file diff --git a/external/ActionBar-PullToRefresh/res/values-fr/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-fr/pull_refresh_strings.xml new file mode 100755 index 00000000..0005f8cf --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-fr/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + Tirez pour rafraîchir… + Relâcher pour rafraîchir… + Chargement… + diff --git a/external/ActionBar-PullToRefresh/res/values-he/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-he/pull_refresh_strings.xml new file mode 100644 index 00000000..a6a13281 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-he/pull_refresh_strings.xml @@ -0,0 +1,22 @@ + + + + + משוך לרענון… + שחרר לרענון… + טוען… + diff --git a/external/ActionBar-PullToRefresh/res/values-it/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-it/pull_refresh_strings.xml new file mode 100755 index 00000000..9476c787 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-it/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + Tira per aggiornare… + Rilascia per aggionare… + Caricamento… + diff --git a/external/ActionBar-PullToRefresh/res/values-iw/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-iw/pull_refresh_strings.xml new file mode 100644 index 00000000..539b7aaa --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-iw/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + משוך לרענון… + שחרר לרענון… + טוען… + diff --git a/external/ActionBar-PullToRefresh/res/values-ja/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-ja/pull_refresh_strings.xml new file mode 100644 index 00000000..5c400234 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-ja/pull_refresh_strings.xml @@ -0,0 +1,22 @@ + + + + + 画面を引っ張って… + 指を離して更新… + 読み込み中… + diff --git a/external/ActionBar-PullToRefresh/res/values-ko/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-ko/pull_refresh_strings.xml new file mode 100755 index 00000000..7f642cb4 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-ko/pull_refresh_strings.xml @@ -0,0 +1,22 @@ + + + + + 당겨서 새로 고침… + 놓아서 새로 고침… + 로드 중… + diff --git a/external/ActionBar-PullToRefresh/res/values-nl/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-nl/pull_refresh_strings.xml new file mode 100755 index 00000000..016e7bd4 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-nl/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + Sleep om te vernieuwen… + Loslaten om te vernieuwen… + Laden… + diff --git a/external/ActionBar-PullToRefresh/res/values-pl/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-pl/pull_refresh_strings.xml new file mode 100755 index 00000000..be33a27e --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-pl/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + Pociągnij, aby odświeżyć… + Puść, aby odświeżyć… + Wczytywanie… + diff --git a/external/ActionBar-PullToRefresh/res/values-pt-rBR/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-pt-rBR/pull_refresh_strings.xml new file mode 100755 index 00000000..d12ab0c8 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-pt-rBR/pull_refresh_strings.xml @@ -0,0 +1,22 @@ + + + + + Puxe para atualizar… + Libere para atualizar… + Carregando… + diff --git a/external/ActionBar-PullToRefresh/res/values-pt/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-pt/pull_refresh_strings.xml new file mode 100755 index 00000000..a49e011f --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-pt/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + Puxe para atualizar… + Liberação para atualizar… + A carregar… + diff --git a/external/ActionBar-PullToRefresh/res/values-ro/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-ro/pull_refresh_strings.xml new file mode 100644 index 00000000..7bc25483 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-ro/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + Trage pentru a reîmprospăta… + Eliberează pentru a reîmprospăta… + Încărcare… + diff --git a/external/ActionBar-PullToRefresh/res/values-ru/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-ru/pull_refresh_strings.xml new file mode 100755 index 00000000..7e433f66 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-ru/pull_refresh_strings.xml @@ -0,0 +1,21 @@ + + + + потяните + отпустите + обновление + diff --git a/external/ActionBar-PullToRefresh/res/values-sv/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-sv/pull_refresh_strings.xml new file mode 100755 index 00000000..14d6def5 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-sv/pull_refresh_strings.xml @@ -0,0 +1,23 @@ + + + + + Dra nedåt om du vill uppdatera + Släpp om du vill uppdatera + Uppdaterar… + + diff --git a/external/ActionBar-PullToRefresh/res/values-zh/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-zh/pull_refresh_strings.xml new file mode 100755 index 00000000..73d787a5 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values-zh/pull_refresh_strings.xml @@ -0,0 +1,22 @@ + + + + + 下拉刷新… + 放开以刷新… + 正在载入… + diff --git a/external/ActionBar-PullToRefresh/res/values/attrs.xml b/external/ActionBar-PullToRefresh/res/values/attrs.xml new file mode 100644 index 00000000..83cc026d --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values/attrs.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/external/ActionBar-PullToRefresh/res/values/ids.xml b/external/ActionBar-PullToRefresh/res/values/ids.xml new file mode 100644 index 00000000..df504085 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values/ids.xml @@ -0,0 +1,24 @@ + + + + + + + + + + \ No newline at end of file diff --git a/external/ActionBar-PullToRefresh/res/values/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values/pull_refresh_strings.xml new file mode 100755 index 00000000..d5f8714c --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values/pull_refresh_strings.xml @@ -0,0 +1,23 @@ + + + + + Pull to refresh… + Release to refresh… + Loading… + + diff --git a/external/ActionBar-PullToRefresh/res/values/styles.xml b/external/ActionBar-PullToRefresh/res/values/styles.xml new file mode 100644 index 00000000..35d7cbb4 --- /dev/null +++ b/external/ActionBar-PullToRefresh/res/values/styles.xml @@ -0,0 +1,29 @@ + + + + + + + \ No newline at end of file diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/DefaultHeaderTransformer.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/DefaultHeaderTransformer.java new file mode 100644 index 00000000..d5989de4 --- /dev/null +++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/DefaultHeaderTransformer.java @@ -0,0 +1,397 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.senab.actionbarpulltorefresh.library; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.Interpolator; +import android.widget.ProgressBar; +import android.widget.TextView; + +import uk.co.senab.actionbarpulltorefresh.library.platform.SDK11; + +/** + * Default Header Transformer. + */ +public class DefaultHeaderTransformer extends PullToRefreshAttacher.HeaderTransformer { + + private View mHeaderView; + private ViewGroup mContentLayout; + private TextView mHeaderTextView; + private ProgressBar mHeaderProgressBar; + + private CharSequence mPullRefreshLabel, mRefreshingLabel, mReleaseLabel; + + private boolean mUseCustomProgressColor = false; + private int mProgressDrawableColor; + private long mAnimationDuration; + + private final Interpolator mInterpolator = new AccelerateInterpolator(); + + protected DefaultHeaderTransformer() { + final int min = getMinimumApiLevel(); + if (Build.VERSION.SDK_INT < min) { + throw new IllegalStateException("This HeaderTransformer is designed to run on SDK " + + min + + "+. If using ActionBarSherlock or ActionBarCompat you should use the appropriate provided extra."); + } + } + + @Override + public void onViewCreated(Activity activity, View headerView) { + mHeaderView = headerView; + + // Get ProgressBar and TextView + mHeaderProgressBar = (ProgressBar) headerView.findViewById(R.id.ptr_progress); + mHeaderTextView = (TextView) headerView.findViewById(R.id.ptr_text); + mContentLayout = (ViewGroup) headerView.findViewById(R.id.ptr_content); + + // Default Labels to display + mPullRefreshLabel = activity.getString(R.string.pull_to_refresh_pull_label); + mRefreshingLabel = activity.getString(R.string.pull_to_refresh_refreshing_label); + mReleaseLabel = activity.getString(R.string.pull_to_refresh_release_label); + + mAnimationDuration = activity.getResources() + .getInteger(android.R.integer.config_shortAnimTime); + + // Setup the View styles + setupViewsFromStyles(activity, headerView); + + // Apply any custom ProgressBar colors + applyProgressBarColor(); + + // FIXME: I do not like this call here + onReset(); + } + + @Override + public void onConfigurationChanged(Activity activity, Configuration newConfig) { + setupViewsFromStyles(activity, getHeaderView()); + } + + @Override + public void onReset() { + // Reset Progress Bar + if (mHeaderProgressBar != null) { + mHeaderProgressBar.setVisibility(View.GONE); + mHeaderProgressBar.setProgress(0); + mHeaderProgressBar.setIndeterminate(false); + } + + // Reset Text View + if (mHeaderTextView != null) { + mHeaderTextView.setVisibility(View.VISIBLE); + mHeaderTextView.setText(mPullRefreshLabel); + } + + // Reset the Content Layout + if (mContentLayout != null) { + mContentLayout.setVisibility(View.VISIBLE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + SDK11.setAlpha(mContentLayout, 1f); + } + } + } + + @Override + public void onPulled(float percentagePulled) { + if (mHeaderProgressBar != null) { + mHeaderProgressBar.setVisibility(View.VISIBLE); + final float progress = mInterpolator.getInterpolation(percentagePulled); + mHeaderProgressBar.setProgress(Math.round(mHeaderProgressBar.getMax() * progress)); + } + } + + @Override + public void onRefreshStarted() { + if (mHeaderTextView != null) { + mHeaderTextView.setText(mRefreshingLabel); + } + if (mHeaderProgressBar != null) { + mHeaderProgressBar.setVisibility(View.VISIBLE); + mHeaderProgressBar.setIndeterminate(true); + } + } + + @Override + public void onReleaseToRefresh() { + if (mHeaderTextView != null) { + mHeaderTextView.setText(mReleaseLabel); + } + if (mHeaderProgressBar != null) { + mHeaderProgressBar.setProgress(mHeaderProgressBar.getMax()); + } + } + + @Override + public void onRefreshMinimized() { + // Here we fade out most of the header, leaving just the progress bar + if (mContentLayout != null) { + ObjectAnimator.ofFloat(mContentLayout, "alpha", 1f, 0f).start(); + } + } + + public View getHeaderView() { + return mHeaderView; + } + + @Override + public boolean showHeaderView() { + final boolean changeVis = mHeaderView.getVisibility() != View.VISIBLE; + + if (changeVis) { + mHeaderView.setVisibility(View.VISIBLE); + AnimatorSet animSet = new AnimatorSet(); + ObjectAnimator transAnim = ObjectAnimator.ofFloat(mContentLayout, "translationY", + -mContentLayout.getHeight(), 0f); + ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mHeaderView, "alpha", 0f, 1f); + animSet.playTogether(transAnim, alphaAnim); + animSet.setDuration(mAnimationDuration); + animSet.start(); + } + + return changeVis; + } + + @Override + public boolean hideHeaderView() { + final boolean changeVis = mHeaderView.getVisibility() != View.GONE; + + if (changeVis) { + Animator animator; + if (mContentLayout.getAlpha() >= 0.5f) { + // If the content layout is showing, translate and fade out + animator = new AnimatorSet(); + ObjectAnimator transAnim = ObjectAnimator.ofFloat(mContentLayout, "translationY", + 0f, -mContentLayout.getHeight()); + ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mHeaderView, "alpha", 1f, 0f); + ((AnimatorSet) animator).playTogether(transAnim, alphaAnim); + } else { + // If the content layout isn't showing (minimized), just fade out + animator = ObjectAnimator.ofFloat(mHeaderView, "alpha", 1f, 0f); + } + animator.setDuration(mAnimationDuration); + animator.addListener(new HideAnimationCallback()); + animator.start(); + } + + return changeVis; + } + + /** + * Set color to apply to the progress bar. Automatically enables usage of the custom color. Use + * {@link #setProgressBarColorEnabled(boolean)} to disable and re-enable the custom color usage. + *

+ * The best way to apply a color is to load the color from resources: {@code + * setProgressBarColor(getResources().getColor(R.color.your_color_name))}. + * + * @param color The color to use. + */ + public void setProgressBarColor(int color) { + mProgressDrawableColor = color; + setProgressBarColorEnabled(true); + } + + /** + * Enable or disable the use of a custom progress bar color. You can set what color to use with + * {@link #setProgressBarColor(int)}, which also automatically enables custom color usage. + */ + public void setProgressBarColorEnabled(boolean enabled) { + mUseCustomProgressColor = enabled; + applyProgressBarColor(); + } + + + /** + * Set Text to show to prompt the user is pull (or keep pulling). + * + * @param pullText - Text to display. + */ + public void setPullText(CharSequence pullText) { + mPullRefreshLabel = pullText; + if (mHeaderTextView != null) { + mHeaderTextView.setText(mPullRefreshLabel); + } + } + + /** + * Set Text to show to tell the user that a refresh is currently in progress. + * + * @param refreshingText - Text to display. + */ + public void setRefreshingText(CharSequence refreshingText) { + mRefreshingLabel = refreshingText; + } + + /** + * Set Text to show to tell the user has scrolled enough to refresh. + * + * @param releaseText - Text to display. + */ + public void setReleaseText(CharSequence releaseText) { + mReleaseLabel = releaseText; + } + + private void setupViewsFromStyles(Activity activity, View headerView) { + final TypedArray styleAttrs = obtainStyledAttrsFromThemeAttr(activity, + R.attr.ptrHeaderStyle, R.styleable.PullToRefreshHeader); + + // Retrieve the Action Bar size from the app theme or the Action Bar's style + if (mContentLayout != null) { + final int height = styleAttrs + .getDimensionPixelSize(R.styleable.PullToRefreshHeader_ptrHeaderHeight, + getActionBarSize(activity)); + mContentLayout.getLayoutParams().height = height; + mContentLayout.requestLayout(); + } + + // Retrieve the Action Bar background from the app theme or the Action Bar's style (see #93) + Drawable bg = styleAttrs.hasValue(R.styleable.PullToRefreshHeader_ptrHeaderBackground) + ? styleAttrs.getDrawable(R.styleable.PullToRefreshHeader_ptrHeaderBackground) + : getActionBarBackground(activity); + if (bg != null) { + mHeaderTextView.setBackgroundDrawable(bg); + + // If we have an opaque background we can remove the background from the content layout + if (mContentLayout != null && bg.getOpacity() == PixelFormat.OPAQUE) { + mContentLayout.setBackgroundResource(0); + } + } + + // Retrieve the Action Bar Title Style from the app theme or the Action Bar's style + Context abContext = headerView.getContext(); + final int titleTextStyle = styleAttrs + .getResourceId(R.styleable.PullToRefreshHeader_ptrHeaderTitleTextAppearance, + getActionBarTitleStyle(abContext)); + if (titleTextStyle != 0) { + mHeaderTextView.setTextAppearance(abContext, titleTextStyle); + } + + // Retrieve the Progress Bar Color the style + if (styleAttrs.hasValue(R.styleable.PullToRefreshHeader_ptrProgressBarColor)) { + mUseCustomProgressColor = true; + mProgressDrawableColor = styleAttrs + .getColor(R.styleable.PullToRefreshHeader_ptrProgressBarColor, 0); + } + + // Retrieve the text strings from the style (if they're set) + if (styleAttrs.hasValue(R.styleable.PullToRefreshHeader_ptrPullText)) { + mPullRefreshLabel = styleAttrs.getString(R.styleable.PullToRefreshHeader_ptrPullText); + } + if (styleAttrs.hasValue(R.styleable.PullToRefreshHeader_ptrRefreshingText)) { + mRefreshingLabel = styleAttrs + .getString(R.styleable.PullToRefreshHeader_ptrRefreshingText); + } + if (styleAttrs.hasValue(R.styleable.PullToRefreshHeader_ptrReleaseText)) { + mReleaseLabel = styleAttrs.getString(R.styleable.PullToRefreshHeader_ptrReleaseText); + } + + styleAttrs.recycle(); + } + + private void applyProgressBarColor() { + if (mHeaderProgressBar != null) { + if (mUseCustomProgressColor) { + mHeaderProgressBar.getProgressDrawable() + .setColorFilter(mProgressDrawableColor, PorterDuff.Mode.SRC_ATOP); + mHeaderProgressBar.getIndeterminateDrawable() + .setColorFilter(mProgressDrawableColor, PorterDuff.Mode.SRC_ATOP); + } else { + mHeaderProgressBar.getProgressDrawable().clearColorFilter(); + mHeaderProgressBar.getIndeterminateDrawable().clearColorFilter(); + } + } + } + + protected Drawable getActionBarBackground(Context context) { + int[] android_styleable_ActionBar = {android.R.attr.background}; + + // Now get the action bar style values... + TypedArray abStyle = obtainStyledAttrsFromThemeAttr(context, android.R.attr.actionBarStyle, + android_styleable_ActionBar); + try { + // background is the first attr in the array above so it's index is 0. + return abStyle.getDrawable(0); + } finally { + abStyle.recycle(); + } + } + + protected int getActionBarSize(Context context) { + int[] attrs = {android.R.attr.actionBarSize}; + TypedArray values = context.getTheme().obtainStyledAttributes(attrs); + try { + return values.getDimensionPixelSize(0, 0); + } finally { + values.recycle(); + } + } + + protected int getActionBarTitleStyle(Context context) { + int[] android_styleable_ActionBar = {android.R.attr.titleTextStyle}; + + // Now get the action bar style values... + TypedArray abStyle = obtainStyledAttrsFromThemeAttr(context, android.R.attr.actionBarStyle, + android_styleable_ActionBar); + try { + // titleTextStyle is the first attr in the array above so it's index is 0. + return abStyle.getResourceId(0, 0); + } finally { + abStyle.recycle(); + } + } + + protected int getMinimumApiLevel() { + return Build.VERSION_CODES.ICE_CREAM_SANDWICH; + } + + class HideAnimationCallback extends AnimatorListenerAdapter { + @Override + public void onAnimationEnd(Animator animation) { + View headerView = getHeaderView(); + if (headerView != null) { + headerView.setVisibility(View.GONE); + } + onReset(); + } + } + + protected static TypedArray obtainStyledAttrsFromThemeAttr(Context context, int themeAttr, + int[] styleAttrs) { + // Need to get resource id of style pointed to from the theme attr + TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(themeAttr, outValue, true); + final int styleResId = outValue.resourceId; + + // Now return the values (from styleAttrs) from the style + return context.obtainStyledAttributes(styleResId, styleAttrs); + } +} diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/InstanceCreationUtils.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/InstanceCreationUtils.java new file mode 100644 index 00000000..77766f8a --- /dev/null +++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/InstanceCreationUtils.java @@ -0,0 +1,91 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.senab.actionbarpulltorefresh.library; + +import android.content.Context; +import android.util.Log; +import android.view.View; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import uk.co.senab.actionbarpulltorefresh.library.viewdelegates.AbsListViewDelegate; +import uk.co.senab.actionbarpulltorefresh.library.viewdelegates.ScrollYDelegate; +import uk.co.senab.actionbarpulltorefresh.library.viewdelegates.WebViewDelegate; + +class InstanceCreationUtils { + + private static final String LOG_TAG = "InstanceCreationUtils"; + + private static final Class[] VIEW_DELEGATE_CONSTRUCTOR_SIGNATURE = new Class[]{}; + private static final Class[] TRANSFORMER_CONSTRUCTOR_SIGNATURE = new Class[]{}; + + private static final HashMap BUILT_IN_DELEGATES; + static { + BUILT_IN_DELEGATES = new HashMap(); + BUILT_IN_DELEGATES.put(AbsListViewDelegate.SUPPORTED_VIEW_CLASS, AbsListViewDelegate.class); + BUILT_IN_DELEGATES.put(WebViewDelegate.SUPPORTED_VIEW_CLASS, WebViewDelegate.class); + } + + static PullToRefreshAttacher.ViewDelegate getBuiltInViewDelegate(final View view) { + final Set> entries = BUILT_IN_DELEGATES.entrySet(); + for (final Map.Entry entry : entries) { + if (entry.getKey().isInstance(view)) { + return InstanceCreationUtils.newInstance(view.getContext(), + entry.getValue(), VIEW_DELEGATE_CONSTRUCTOR_SIGNATURE, null); + } + } + + // Default is the ScrollYDelegate + return InstanceCreationUtils.newInstance(view.getContext(), + ScrollYDelegate.class, VIEW_DELEGATE_CONSTRUCTOR_SIGNATURE, null); + } + + static T instantiateViewDelegate(Context context, String className, Object[] arguments) { + try { + Class clazz = context.getClassLoader().loadClass(className); + return newInstance(context, clazz, VIEW_DELEGATE_CONSTRUCTOR_SIGNATURE, arguments); + } catch (Exception e) { + Log.w(LOG_TAG, "Cannot instantiate class: " + className, e); + } + return null; + } + + static T instantiateTransformer(Context context, String className, Object[] arguments) { + try { + Class clazz = context.getClassLoader().loadClass(className); + return newInstance(context, clazz, TRANSFORMER_CONSTRUCTOR_SIGNATURE, arguments); + } catch (Exception e) { + Log.w(LOG_TAG, "Cannot instantiate class: " + className, e); + } + return null; + } + + private static T newInstance(Context context, Class clazz, Class[] constructorSig, + Object[] arguments) { + try { + Constructor constructor = clazz.getConstructor(constructorSig); + return (T) constructor.newInstance(arguments); + } catch (Exception e) { + Log.w(LOG_TAG, "Cannot instantiate class: " + clazz.getName(), e); + } + return null; + } + +} diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshAttacher.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshAttacher.java new file mode 100644 index 00000000..5b344be1 --- /dev/null +++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshAttacher.java @@ -0,0 +1,948 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.senab.actionbarpulltorefresh.library; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.os.Build; +import android.os.Handler; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import java.util.Set; +import java.util.WeakHashMap; + +/** + * FIXME + */ +public class PullToRefreshAttacher implements View.OnTouchListener { + + /* Default configuration values */ + private static final int DEFAULT_HEADER_LAYOUT = R.layout.default_header; + private static final float DEFAULT_REFRESH_SCROLL_DISTANCE = 0.5f; + private static final boolean DEFAULT_REFRESH_ON_UP = false; + private static final int DEFAULT_REFRESH_MINIMIZED_DELAY = 1 * 1000; + private static final boolean DEFAULT_REFRESH_MINIMIZE = true; + + private static final boolean DEBUG = false; + private static final String LOG_TAG = "PullToRefreshAttacher"; + + /* Member Variables */ + + private final EnvironmentDelegate mEnvironmentDelegate; + private final HeaderTransformer mHeaderTransformer; + + private final Activity mActivity; + private final View mHeaderView; + private HeaderViewListener mHeaderViewListener; + + private final int mTouchSlop; + private final float mRefreshScrollDistance; + + private int mInitialMotionY, mLastMotionY, mPullBeginY; + private boolean mIsBeingDragged, mIsRefreshing, mHandlingTouchEventFromDown; + + private final WeakHashMap mRefreshableViews; + + private boolean mEnabled = true; + private final boolean mRefreshOnUp; + private final int mRefreshMinimizeDelay; + private final boolean mRefreshMinimize; + + private final Handler mHandler = new Handler(); + + /** + * Get a PullToRefreshAttacher for this Activity. If there is already a + * PullToRefreshAttacher attached to the Activity, the existing one is + * returned, otherwise a new instance is created. This version of the method + * will use default configuration options for everything. + * + * @param activity + * Activity to attach to. + * @return PullToRefresh attached to the Activity. + */ + public static PullToRefreshAttacher get(Activity activity) { + return get(activity, new Options()); + } + + /** + * Get a PullToRefreshAttacher for this Activity. If there is already a + * PullToRefreshAttacher attached to the Activity, the existing one is + * returned, otherwise a new instance is created. + * + * @param activity + * Activity to attach to. + * @param options + * Options used when creating the PullToRefreshAttacher. + * @return PullToRefresh attached to the Activity. + */ + public static PullToRefreshAttacher get(Activity activity, Options options) { + return new PullToRefreshAttacher(activity, options); + } + + protected PullToRefreshAttacher(Activity activity, Options options) { + if (options == null) { + Log.i(LOG_TAG, "Given null options so using default options."); + options = new Options(); + } + + mActivity = activity; + mRefreshableViews = new WeakHashMap(); + + // Copy necessary values from options + mRefreshScrollDistance = options.refreshScrollDistance; + mRefreshOnUp = options.refreshOnUp; + mRefreshMinimizeDelay = options.refreshMinimizeDelay; + mRefreshMinimize = options.refreshMinimize; + + // EnvironmentDelegate + mEnvironmentDelegate = options.environmentDelegate != null ? options.environmentDelegate + : createDefaultEnvironmentDelegate(); + + // Header Transformer + mHeaderTransformer = options.headerTransformer != null ? options.headerTransformer + : createDefaultHeaderTransformer(); + + // Get touch slop for use later + mTouchSlop = ViewConfiguration.get(activity).getScaledTouchSlop(); + + // Get Window Decor View + final ViewGroup decorView = (ViewGroup) activity.getWindow() + .getDecorView(); + + // Check to see if there is already a Attacher view installed + if (decorView.getChildCount() == 1 + && decorView.getChildAt(0) instanceof DecorChildLayout) { + throw new IllegalStateException( + "You should only create one PullToRefreshAttacher per Activity"); + } + + // Create Header view and then add to Decor View + mHeaderView = LayoutInflater.from( + mEnvironmentDelegate.getContextForInflater(activity)).inflate( + options.headerLayout, decorView, false); + if (mHeaderView == null) { + throw new IllegalArgumentException( + "Must supply valid layout id for header."); + } + // Make Header View invisible so it still gets a layout pass + mHeaderView.setVisibility(View.INVISIBLE); + + // Create DecorChildLayout which will move all of the system's decor + // view's children + the + // Header View to itself. See DecorChildLayout for more info. + DecorChildLayout decorContents = new DecorChildLayout(activity, + decorView, mHeaderView); + + // Now add the DecorChildLayout to the decor view + decorView.addView(decorContents, ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT); + + // Notify transformer + mHeaderTransformer.onViewCreated(activity, mHeaderView); + // TODO Remove the follow deprecated method call before v1.0 + mHeaderTransformer.onViewCreated(mHeaderView); + } + + /** + * Add a view which will be used to initiate refresh requests and a listener + * to be invoked when a refresh is started. This version of the method will + * try to find a handler for the view from the built-in view delegates. + * + * @param view + * View which will be used to initiate refresh requests. + * @param refreshListener + * Listener to be invoked when a refresh is started. + */ + public void addRefreshableView(View view, OnRefreshListener refreshListener) { + addRefreshableView(view, null, refreshListener); + } + + /** + * Add a view which will be used to initiate refresh requests, along with a + * delegate which knows how to handle the given view, and a listener to be + * invoked when a refresh is started. + * + * @param view + * View which will be used to initiate refresh requests. + * @param viewDelegate + * delegate which knows how to handle view. + * @param refreshListener + * Listener to be invoked when a refresh is started. + */ + public void addRefreshableView(View view, ViewDelegate viewDelegate, + OnRefreshListener refreshListener) { + addRefreshableView(view, viewDelegate, refreshListener, true); + } + + /** + * Add a view which will be used to initiate refresh requests, along with a + * delegate which knows how to handle the given view, and a listener to be + * invoked when a refresh is started. + * + * @param view + * View which will be used to initiate refresh requests. + * @param viewDelegate + * delegate which knows how to handle view. + * @param refreshListener + * Listener to be invoked when a refresh is started. + * @param setTouchListener + * Whether to set this as the + * {@link android.view.View.OnTouchListener}. + */ + void addRefreshableView(View view, ViewDelegate viewDelegate, + OnRefreshListener refreshListener, final boolean setTouchListener) { + // Check to see if view is null + if (view == null) { + Log.i(LOG_TAG, "Refreshable View is null."); + return; + } + + if (refreshListener == null) { + throw new IllegalArgumentException( + "OnRefreshListener not given. Please provide one."); + } + + // ViewDelegate + if (viewDelegate == null) { + viewDelegate = InstanceCreationUtils.getBuiltInViewDelegate(view); + if (viewDelegate == null) { + throw new IllegalArgumentException( + "No view handler found. Please provide one."); + } + } + + // View to detect refreshes for + mRefreshableViews.put(view, new ViewParams(viewDelegate, refreshListener)); + if (setTouchListener) { + view.setOnTouchListener(this); + } + } + + /** + * Remove a view which was previously used to initiate refresh requests. + * + * @param view + * - View which will be used to initiate refresh requests. + */ + public void removeRefreshableView(View view) { + if (mRefreshableViews.containsKey(view)) { + mRefreshableViews.remove(view); + view.setOnTouchListener(null); + } + } + + /** + * Clear all views which were previously used to initiate refresh requests. + */ + public void clearRefreshableViews() { + Set views = mRefreshableViews.keySet(); + for (View view : views) { + view.setOnTouchListener(null); + } + mRefreshableViews.clear(); + } + + /** + * This method should be called by your Activity's or Fragment's + * onConfigurationChanged method. + * + * @param newConfig The new configuration + */ + public void onConfigurationChanged(Configuration newConfig) { + mHeaderTransformer.onConfigurationChanged(mActivity, newConfig); + } + + /** + * Manually set this Attacher's refreshing state. The header will be + * displayed or hidden as requested. + * + * @param refreshing + * - Whether the attacher should be in a refreshing state, + */ + public final void setRefreshing(boolean refreshing) { + setRefreshingInt(null, refreshing, false); + } + + /** + * @return true if this Attacher is currently in a refreshing state. + */ + public final boolean isRefreshing() { + return mIsRefreshing; + } + + /** + * @return true if this PullToRefresh is currently enabled (defaults to + * true) + */ + public boolean isEnabled() { + return mEnabled; + } + + /** + * Allows the enable/disable of this PullToRefreshAttacher. If disabled when + * refreshing then the UI is automatically reset. + * + * @param enabled + * - Whether this PullToRefreshAttacher is enabled. + */ + public void setEnabled(boolean enabled) { + mEnabled = enabled; + + if (!enabled) { + // If we're not enabled, reset any touch handling + resetTouch(); + + // If we're currently refreshing, reset the ptr UI + if (mIsRefreshing) { + reset(false); + } + } + } + + /** + * Call this when your refresh is complete and this view should reset itself + * (header view will be hidden). + * + * This is the equivalent of calling setRefreshing(false). + */ + public final void setRefreshComplete() { + setRefreshingInt(null, false, false); + } + + /** + * Set a {@link HeaderViewListener} which is called when the visibility + * state of the Header View has changed. + * + * @param listener + */ + public final void setHeaderViewListener(HeaderViewListener listener) { + mHeaderViewListener = listener; + } + + /** + * @return The Header View which is displayed when the user is pulling, or + * we are refreshing. + */ + public final View getHeaderView() { + return mHeaderView; + } + + /** + * @return The HeaderTransformer currently used by this Attacher. + */ + public HeaderTransformer getHeaderTransformer() { + return mHeaderTransformer; + } + + @Override + public final boolean onTouch(final View view, final MotionEvent event) { + // Just call onTouchEvent. It now handles the proper calling of onInterceptTouchEvent + onTouchEvent(view, event); + // Always return false as we only want to observe events + return false; + } + + final boolean onInterceptTouchEvent(View view, MotionEvent event) { + if (DEBUG) { + Log.d(LOG_TAG, "onInterceptTouchEvent: " + event.toString()); + } + + // If we're not enabled or currently refreshing don't handle any touch + // events + if (!isEnabled() || isRefreshing()) { + return false; + } + + final ViewParams params = mRefreshableViews.get(view); + if (params == null) { + return false; + } + + if (DEBUG) Log.d(LOG_TAG, "onInterceptTouchEvent. Got ViewParams. " + view.toString()); + + switch (event.getAction()) { + case MotionEvent.ACTION_MOVE: { + // We're not currently being dragged so check to see if the user has + // scrolled enough + if (!mIsBeingDragged && mInitialMotionY > 0) { + final int y = (int) event.getY(); + final int yDiff = y - mInitialMotionY; + + if (yDiff > mTouchSlop) { + mIsBeingDragged = true; + onPullStarted(y); + } else if (yDiff < -mTouchSlop) { + resetTouch(); + } + } + break; + } + + case MotionEvent.ACTION_DOWN: { + // If we're already refreshing, ignore + if (canRefresh(true, params.onRefreshListener) + && params.viewDelegate.isReadyForPull(view, event.getX(), event.getY())) { + mInitialMotionY = (int) event.getY(); + } + break; + } + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: { + resetTouch(); + break; + } + } + + if (DEBUG) Log.d(LOG_TAG, "onInterceptTouchEvent. Returning " + mIsBeingDragged); + + return mIsBeingDragged; + } + + final boolean onTouchEvent(View view, MotionEvent event) { + if (DEBUG) { + Log.d(LOG_TAG, "onTouchEvent: " + event.toString()); + } + + // If we're not enabled or currently refreshing don't handle any touch + // events + if (!isEnabled()) { + return false; + } + + final ViewParams params = mRefreshableViews.get(view); + if (params == null) { + Log.i(LOG_TAG, "View does not have ViewParams"); + return false; + } + + // Record whether our handling is started from ACTION_DOWN + if (event.getAction() == MotionEvent.ACTION_DOWN) { + mHandlingTouchEventFromDown = true; + } + + // If we're being called from ACTION_DOWN then we must call through to + // onInterceptTouchEvent until it sets mIsBeingDragged + if (mHandlingTouchEventFromDown && !mIsBeingDragged) { + onInterceptTouchEvent(view, event); + return true; + } + + switch (event.getAction()) { + case MotionEvent.ACTION_MOVE: { + // If we're already refreshing ignore it + if (isRefreshing()) { + return false; + } + + final int y = (int) event.getY(); + + if (mIsBeingDragged && y != mLastMotionY) { + final int yDx = y - mLastMotionY; + + /** + * Check to see if the user is scrolling the right direction + * (down). We allow a small scroll up which is the check against + * negative touch slop. + */ + if (yDx >= -mTouchSlop) { + onPull(view, y); + // Only record the y motion if the user has scrolled down. + if (yDx > 0) { + mLastMotionY = y; + } + } else { + onPullEnded(); + resetTouch(); + } + } + break; + } + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: { + checkScrollForRefresh(view); + if (mIsBeingDragged) { + onPullEnded(); + } + resetTouch(); + break; + } + } + + return true; + } + + void resetTouch() { + mIsBeingDragged = false; + mHandlingTouchEventFromDown = false; + mInitialMotionY = mLastMotionY = mPullBeginY = -1; + } + + void onPullStarted(int y) { + if (DEBUG) { + Log.d(LOG_TAG, "onPullStarted"); + } + showHeaderView(); + mPullBeginY = y; + } + + void onPull(View view, int y) { + if (DEBUG) { + Log.d(LOG_TAG, "onPull"); + } + + final float pxScrollForRefresh = getScrollNeededForRefresh(view); + final int scrollLength = y - mPullBeginY; + + if (scrollLength < pxScrollForRefresh) { + mHeaderTransformer.onPulled(scrollLength / pxScrollForRefresh); + } else { + if (mRefreshOnUp) { + mHeaderTransformer.onReleaseToRefresh(); + } else { + setRefreshingInt(view, true, true); + } + } + } + + void onPullEnded() { + if (DEBUG) { + Log.d(LOG_TAG, "onPullEnded"); + } + if (!mIsRefreshing) { + reset(true); + } + } + + void showHeaderView() { + if (mHeaderTransformer.showHeaderView()) { + if (mHeaderViewListener != null) { + mHeaderViewListener.onStateChanged(mHeaderView, + HeaderViewListener.STATE_VISIBLE); + } + } + } + + void hideHeaderView() { + if (mHeaderTransformer.hideHeaderView()) { + if (mHeaderViewListener != null) { + mHeaderViewListener.onStateChanged(mHeaderView, + HeaderViewListener.STATE_HIDDEN); + } + } + } + + protected EnvironmentDelegate createDefaultEnvironmentDelegate() { + return new EnvironmentDelegate(); + } + + protected HeaderTransformer createDefaultHeaderTransformer() { + return new DefaultHeaderTransformer(); + } + + private boolean checkScrollForRefresh(View view) { + if (mIsBeingDragged && mRefreshOnUp && view != null) { + if (mLastMotionY - mPullBeginY >= getScrollNeededForRefresh(view)) { + setRefreshingInt(view, true, true); + return true; + } + } + return false; + } + + private void setRefreshingInt(View view, boolean refreshing, boolean fromTouch) { + if (DEBUG) { + Log.d(LOG_TAG, "setRefreshingInt: " + refreshing); + } + // Check to see if we need to do anything + if (mIsRefreshing == refreshing) { + return; + } + + resetTouch(); + + if (refreshing && canRefresh(fromTouch, getRefreshListenerForView(view))) { + startRefresh(view, fromTouch); + } else { + reset(fromTouch); + } + } + + private OnRefreshListener getRefreshListenerForView(View view) { + if (view != null) { + ViewParams params = mRefreshableViews.get(view); + if (params != null) { + return params.onRefreshListener; + } + } + return null; + } + + /** + * @param fromTouch + * - Whether this is being invoked from a touch event + * @return true if we're currently in a state where a refresh can be + * started. + */ + private boolean canRefresh(boolean fromTouch, OnRefreshListener listener) { + return !mIsRefreshing && (!fromTouch || listener != null); + } + + private float getScrollNeededForRefresh(View view) { + return view.getHeight() * mRefreshScrollDistance; + } + + private void reset(boolean fromTouch) { + // Update isRefreshing state + mIsRefreshing = false; + + // Remove any minimize callbacks + if (mRefreshMinimize) { + mHandler.removeCallbacks(mRefreshMinimizeRunnable); + } + + // Hide Header View + hideHeaderView(); + } + + private void startRefresh(View view, boolean fromTouch) { + // Update isRefreshing state + mIsRefreshing = true; + + // Call OnRefreshListener if this call has originated from a touch event + if (fromTouch) { + OnRefreshListener listener = getRefreshListenerForView(view); + if (listener != null) { + listener.onRefreshStarted(view); + } + } + + // Call Transformer + mHeaderTransformer.onRefreshStarted(); + + // Show Header View + showHeaderView(); + + // Post a runnable to minimize the refresh header + if (mRefreshMinimize) { + if (mRefreshMinimizeDelay > 0) { + mHandler.postDelayed(mRefreshMinimizeRunnable, mRefreshMinimizeDelay); + } else { + mHandler.post(mRefreshMinimizeRunnable); + } + } + } + + /** + * Simple Listener to listen for any callbacks to Refresh. + */ + public interface OnRefreshListener { + /** + * Called when the user has initiated a refresh by pulling. + * + * @param view + * - View which the user has started the refresh from. + */ + public void onRefreshStarted(View view); + } + + public interface HeaderViewListener { + /** + * The state when the header view is completely visible. + */ + public static int STATE_VISIBLE = 0; + + /** + * The state when the header view is minimized. By default this means + * that the progress bar is still visible, but the rest of the view is + * hidden, showing the Action Bar behind. + *

+ * This will not be called in header minimization is disabled. + */ + public static int STATE_MINIMIZED = 1; + + /** + * The state when the header view is completely hidden. + */ + public static int STATE_HIDDEN = 2; + + /** + * Called when the visibility state of the Header View has changed. + * + * @param headerView + * HeaderView who's state has changed. + * @param state + * The new state. One of {@link #STATE_VISIBLE}, + * {@link #STATE_MINIMIZED} and {@link #STATE_HIDDEN} + */ + public void onStateChanged(View headerView, int state); + } + + /** + * HeaderTransformers are what controls and update the Header View to reflect the current state + * of the pull-to-refresh interaction. They are responsible for showing and hiding the header + * view, as well as update the state. + */ + public static abstract class HeaderTransformer { + + /** + * Called whether the header view has been inflated from the resources + * defined in {@link Options#headerLayout}. + * + * @param activity The {@link Activity} that the header view is attached to. + * @param headerView The inflated header view. + */ + public void onViewCreated(Activity activity, View headerView) {} + + /** + * @deprecated This will be removed before v1.0. Override + * {@link #onViewCreated(android.app.Activity, android.view.View)} instead. + */ + public void onViewCreated(View headerView) {} + + /** + * Called when the header should be reset. You should update any child + * views to reflect this. + *

+ * You should not change the visibility of the header + * view. + */ + public void onReset() {} + + /** + * Called the user has pulled on the scrollable view. + * + * @param percentagePulled value between 0.0f and 1.0f depending on how far the + * user has pulled. + */ + public void onPulled(float percentagePulled) {} + + /** + * Called when a refresh has begun. Theoretically this call is similar + * to that provided from {@link OnRefreshListener} but is more suitable + * for header view updates. + */ + public void onRefreshStarted() {} + + /** + * Called when a refresh can be initiated when the user ends the touch + * event. This is only called when {@link Options#refreshOnUp} is set to + * true. + */ + public void onReleaseToRefresh() {} + + /** + * Called when the current refresh has taken longer than the time + * specified in {@link Options#refreshMinimizeDelay}. + */ + public void onRefreshMinimized() {} + + /** + * Called when the Header View should be made visible, usually with an animation. + * + * @return true if the visibility has changed. + */ + public abstract boolean showHeaderView(); + + /** + * Called when the Header View should be made invisible, usually with an animation. + * + * @return true if the visibility has changed. + */ + public abstract boolean hideHeaderView(); + + /** + * Called when the Activity's configuration has changed. + * + * @param activity The {@link Activity} that the header view is attached to. + * @param newConfig New configuration. + * + * @see android.app.Activity#onConfigurationChanged(android.content.res.Configuration) + */ + public void onConfigurationChanged(Activity activity, Configuration newConfig) {} + } + + /** + * ViewDelegates are what are used to de-couple the Attacher from the different types of + * scrollable views. + */ + public static abstract class ViewDelegate { + + /** + * Allows you to provide support for View which do not have built-in + * support. In this method you should cast view to it's + * native class, and check if it is scrolled to the top. + * + * @param view + * The view which has should be checked against. + * @param x The X co-ordinate of the touch event + * @param y The Y co-ordinate of the touch event + * @return true if view is scrolled to the top. + */ + public abstract boolean isReadyForPull(View view, float x, float y); + } + + /** + * This is used to provide platform and environment specific functionality for the Attacher. + */ + public static class EnvironmentDelegate { + + /** + * @return Context which should be used for inflating the header layout + */ + public Context getContextForInflater(Activity activity) { + if (Build.VERSION.SDK_INT >= 14) { + return activity.getActionBar().getThemedContext(); + } else { + return activity; + } + } + } + + /** + * Allows you to specify a number of configuration options when instantiating a + * {@link PullToRefreshAttacher}. Used with {@link #get(Activity, Options) get()}. + */ + public static class Options { + + /** + * EnvironmentDelegate instance which will be used. If null, we will + * create an instance of the default class. + */ + public EnvironmentDelegate environmentDelegate = null; + + /** + * The layout resource ID which should be inflated to be displayed above + * the Action Bar + */ + public int headerLayout = DEFAULT_HEADER_LAYOUT; + + /** + * The header transformer to be used to transfer the header view. If + * null, an instance of {@link DefaultHeaderTransformer} will be used. + */ + public HeaderTransformer headerTransformer = null; + + /** + * The percentage of the refreshable view that needs to be scrolled + * before a refresh is initiated. + */ + public float refreshScrollDistance = DEFAULT_REFRESH_SCROLL_DISTANCE; + + /** + * Whether a refresh should only be initiated when the user has finished + * the touch event. + */ + public boolean refreshOnUp = DEFAULT_REFRESH_ON_UP; + + /** + * The delay after a refresh is started in which the header should be + * 'minimized'. By default, most of the header is faded out, leaving + * only the progress bar signifying that a refresh is taking place. + */ + public int refreshMinimizeDelay = DEFAULT_REFRESH_MINIMIZED_DELAY; + + /** + * Enable or disable the header 'minimization', which by default means that the majority of + * the header is hidden, leaving only the progress bar still showing. + *

+ * If set to true, the header will be minimized after the delay set in + * {@link #refreshMinimizeDelay}. If set to false then the whole header will be displayed + * until the refresh is finished. + */ + public boolean refreshMinimize = DEFAULT_REFRESH_MINIMIZE; + } + + /** + * This class allows us to insert a layer in between the system decor view + * and the actual decor. (e.g. Action Bar views). This is needed so we can + * receive a call to fitSystemWindows(Rect) so we can adjust the header view + * to fit the system windows too. + */ + final static class DecorChildLayout extends FrameLayout { + private final ViewGroup mHeaderViewWrapper; + + DecorChildLayout(Context context, ViewGroup systemDecorView, + View headerView) { + super(context); + + // Move all children from decor view to here + for (int i = 0, z = systemDecorView.getChildCount(); i < z; i++) { + View child = systemDecorView.getChildAt(i); + systemDecorView.removeView(child); + addView(child); + } + + /** + * Wrap the Header View in a FrameLayout and add it to this view. It + * is wrapped so any inset changes do not affect the actual header + * view. + */ + mHeaderViewWrapper = new FrameLayout(context); + mHeaderViewWrapper.addView(headerView); + addView(mHeaderViewWrapper, ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + } + + @Override + protected boolean fitSystemWindows(Rect insets) { + if (DEBUG) { + Log.d(LOG_TAG, "fitSystemWindows: " + insets.toString()); + } + + // Adjust the Header View's padding to take the insets into account + mHeaderViewWrapper.setPadding(insets.left, insets.top, + insets.right, insets.bottom); + + // Call return super so that the rest of the + return super.fitSystemWindows(insets); + } + } + + private static final class ViewParams { + final OnRefreshListener onRefreshListener; + final ViewDelegate viewDelegate; + + ViewParams(ViewDelegate _viewDelegate, + OnRefreshListener _onRefreshListener) { + onRefreshListener = _onRefreshListener; + viewDelegate = _viewDelegate; + } + } + + private final Runnable mRefreshMinimizeRunnable = new Runnable() { + @Override + public void run() { + mHeaderTransformer.onRefreshMinimized(); + + if (mHeaderViewListener != null) { + mHeaderViewListener.onStateChanged(mHeaderView, + HeaderViewListener.STATE_MINIMIZED); + } + } + }; + +} diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshLayout.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshLayout.java new file mode 100644 index 00000000..296a44f0 --- /dev/null +++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshLayout.java @@ -0,0 +1,133 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.senab.actionbarpulltorefresh.library; + +import android.content.Context; +import android.content.res.Configuration; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; + +/** + * FIXME + */ +public class PullToRefreshLayout extends FrameLayout { + + private static final boolean DEBUG = false; + private static final String LOG_TAG = "PullToRefreshLayout"; + + private PullToRefreshAttacher mPullToRefreshAttacher; + private View mCurrentTouchTarget; + + public PullToRefreshLayout(Context context) { + this(context, null); + } + + public PullToRefreshLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * Set the {@link PullToRefreshAttacher} to be used with this layout. The view which is added + * to this layout will automatically be added as a refreshable-view in the attacher. + */ + public void setPullToRefreshAttacher(PullToRefreshAttacher attacher, + PullToRefreshAttacher.OnRefreshListener refreshListener) { + View view; + for (int i = 0, z = getChildCount(); i < z; i++) { + view = getChildAt(i); + + if (mPullToRefreshAttacher != null) { + mPullToRefreshAttacher.removeRefreshableView(view); + } + + if (attacher != null) { + if (DEBUG) Log.d(LOG_TAG, "Adding View to Attacher: " + view); + attacher.addRefreshableView(view, null, refreshListener, false); + } + } + + mPullToRefreshAttacher = attacher; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + if (DEBUG) Log.d(LOG_TAG, "onInterceptTouchEvent. " + event.toString()); + + if (mPullToRefreshAttacher != null && getChildCount() > 0) { + View target = getChildForTouchEvent(event); + if (target != null && mPullToRefreshAttacher.onInterceptTouchEvent(target, event)) { + mCurrentTouchTarget = target; + return true; + } + } + // Reset Current Touch Target + mCurrentTouchTarget = null; + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (DEBUG) Log.d(LOG_TAG, "onTouchEvent. " + event.toString()); + + if (mPullToRefreshAttacher != null) { + // This is an edge-case. If the ViewGroup does not contain a valid touch target then + // Android calls onTouchEvent after onInterceptTouchEvent with ACTION_DOWN event. + // If that happens then we need to find the visible view and pass it to the attacher as + // usual. + if (mCurrentTouchTarget == null && event.getAction() == MotionEvent.ACTION_DOWN) { + mCurrentTouchTarget = getChildForTouchEvent(event); + } + + if (mCurrentTouchTarget != null) { + return mPullToRefreshAttacher.onTouchEvent(mCurrentTouchTarget, event); + } + } + // Reset Current Touch Target + mCurrentTouchTarget = null; + return super.onTouchEvent(event); + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + if (mPullToRefreshAttacher != null) { + mPullToRefreshAttacher.onConfigurationChanged(newConfig); + } + } + + private View getChildForTouchEvent(MotionEvent event) { + final float x = event.getX(), y = event.getY(); + View child; + for (int z = getChildCount() - 1; z >= 0 ; z--) { + child = getChildAt(z); + if (child.isShown() && x >= child.getLeft() && x <= child.getRight() + && y >= child.getTop() && y <= child.getBottom()) { + if (DEBUG) Log.d(LOG_TAG, "Got Child for Touch Event: " + child); + return child; + } + } + return null; + } +} diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/platform/SDK11.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/platform/SDK11.java new file mode 100644 index 00000000..da55ebb6 --- /dev/null +++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/platform/SDK11.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.senab.actionbarpulltorefresh.library.platform; + +import android.view.View; + +public class SDK11 { + + public static void setAlpha(View view, float alpha) { + view.setAlpha(alpha); + } + +} diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/AbsListViewDelegate.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/AbsListViewDelegate.java new file mode 100644 index 00000000..8276e146 --- /dev/null +++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/AbsListViewDelegate.java @@ -0,0 +1,93 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.senab.actionbarpulltorefresh.library.viewdelegates; + +import android.annotation.TargetApi; +import android.os.Build; +import android.view.View; +import android.widget.AbsListView; + +import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher; + +/** + * FIXME + */ +public class AbsListViewDelegate + extends PullToRefreshAttacher.ViewDelegate { + + public static final Class SUPPORTED_VIEW_CLASS = AbsListView.class; + + @Override + public boolean isReadyForPull(View view, final float x, final float y) { + boolean ready = false; + + // First we check whether we're scrolled to the top + AbsListView absListView = (AbsListView) view; + if (absListView.getCount() == 0) { + ready = true; + } else if (absListView.getFirstVisiblePosition() == 0) { + final View firstVisibleChild = absListView.getChildAt(0); + ready = firstVisibleChild != null && firstVisibleChild.getTop() >= 0; + } + + // Then we have to check whether the fas scroller is enabled, and check we're not starting + // the gesture from the scroller + if (ready && absListView.isFastScrollEnabled() && isFastScrollAlwaysVisible(absListView)) { + switch (getVerticalScrollbarPosition(absListView)) { + case View.SCROLLBAR_POSITION_RIGHT: + ready = x < absListView.getRight() - absListView.getVerticalScrollbarWidth(); + break; + case View.SCROLLBAR_POSITION_LEFT: + ready = x > absListView.getVerticalScrollbarWidth(); + break; + } + } + + return ready; + } + + int getVerticalScrollbarPosition(AbsListView absListView) { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? + CompatV11.getVerticalScrollbarPosition(absListView) : + Compat.getVerticalScrollbarPosition(absListView); + } + + boolean isFastScrollAlwaysVisible(AbsListView absListView) { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? + CompatV11.isFastScrollAlwaysVisible(absListView) : + Compat.isFastScrollAlwaysVisible(absListView); + } + + static class Compat { + static int getVerticalScrollbarPosition(AbsListView absListView) { + return View.SCROLLBAR_POSITION_RIGHT; + } + static boolean isFastScrollAlwaysVisible(AbsListView absListView) { + return false; + } + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + static class CompatV11 { + static int getVerticalScrollbarPosition(AbsListView absListView) { + return absListView.getVerticalScrollbarPosition(); + } + static boolean isFastScrollAlwaysVisible(AbsListView absListView) { + return absListView.isFastScrollAlwaysVisible(); + } + } +} diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/ScrollYDelegate.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/ScrollYDelegate.java new file mode 100644 index 00000000..a38885d0 --- /dev/null +++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/ScrollYDelegate.java @@ -0,0 +1,32 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.senab.actionbarpulltorefresh.library.viewdelegates; + +import android.view.View; + +import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher; + +/** + * FIXME + */ +public class ScrollYDelegate extends PullToRefreshAttacher.ViewDelegate { + + @Override + public boolean isReadyForPull(View view, float x, float y) { + return view.getScrollY() <= 0; + } +} diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/WebViewDelegate.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/WebViewDelegate.java new file mode 100644 index 00000000..80c6a83d --- /dev/null +++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/WebViewDelegate.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013 Chris Banes + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.co.senab.actionbarpulltorefresh.library.viewdelegates; + +import android.view.View; +import android.webkit.WebView; + +import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher; + +/** + * FIXME + */ +public class WebViewDelegate extends PullToRefreshAttacher.ViewDelegate { + + public static final Class SUPPORTED_VIEW_CLASS = WebView.class; + + @Override + public boolean isReadyForPull(View view, float x, float y) { + return view.getScrollY() <= 0; + } +} diff --git a/external/ColorPickerPreference/build.xml b/external/ColorPickerPreference/build.xml index c575c550..1b4d11f9 100644 --- a/external/ColorPickerPreference/build.xml +++ b/external/ColorPickerPreference/build.xml @@ -1,5 +1,5 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + +