diff options
22 files changed, 971 insertions, 362 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 0d041079c..36ff8eef7 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,345 +1,387 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="de.danoeh.antennapod" - android:versionCode="31" - android:versionName="0.9.7.4" > + package="de.danoeh.antennapod" + android:versionCode="31" + android:versionName="0.9.7.4"> - <uses-permission android:name="android.permission.INTERNET" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-sdk android:minSdkVersion="10" - android:targetSdkVersion="18" /> + android:targetSdkVersion="18"/> - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true" - android:xlargeScreens="true" /> + android:xlargeScreens="true"/> <uses-feature android:name="android.hardware.screen.portrait" - android:required="false" /> + android:required="false"/> <uses-feature android:name="android.hardware.touchscreen" - android:required="false" /> + android:required="false"/> - <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> - <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> + <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <application android:name="de.danoeh.antennapod.PodcastApp" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:logo="@drawable/ic_launcher" - android:theme="@style/Theme.AntennaPod.Light" > + android:theme="@style/Theme.AntennaPod.Light"> <activity android:name=".activity.MainActivity" android:configChanges="keyboardHidden|orientation" - android:label="@string/app_name" > + android:label="@string/app_name"> <meta-data android:name="android.app.default_searchable" - android:value="de.danoeh.antennapod.activity.SearchActivity" /> + android:value="de.danoeh.antennapod.activity.SearchActivity"/> <meta-data android:name="android.app.searchable" - android:resource="@xml/searchable" /> + android:resource="@xml/searchable"/> + <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name="de.danoeh.antennapod.activity.AddFeedActivity" android:configChanges="keyboardHidden|orientation" android:label="@string/add_new_feed_label" - android:windowSoftInputMode="adjustResize" > + android:windowSoftInputMode="adjustResize"> + <intent-filter> + <action android:name="android.intent.action.VIEW"/> + + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.BROWSABLE"/> + + <data android:scheme="http"/> + <data android:scheme="https"/> + <data android:host="*"/> + <data android:pathPattern=".*\\.xml"/> + <data android:pathPattern=".*\\.rss"/> + </intent-filter> + + <intent-filter> + <action android:name="android.intent.action.VIEW"/> + + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.BROWSABLE"/> + + <data android:scheme="http"/> + <data android:scheme="https"/> + <data android:host="feeds.feedburner.com"/> + <data android:host="feedproxy.google.com"/> + <data android:host="feeds2.feedburner.com"/> + <data android:host="feedsproxy.google.com"/> + </intent-filter> + <intent-filter> - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.BROWSABLE"/> - <data android:scheme="http"/> - <data android:scheme="https"/> - <data android:host="*"/> - <data android:pathPattern=".*\\.xml"/> - <data android:pathPattern=".*\\.rss"/> - </intent-filter> - - <intent-filter> - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.BROWSABLE"/> - <data android:scheme="http"/> - <data android:scheme="https"/> - <data android:host="feeds.feedburner.com"/> - <data android:host="feedproxy.google.com"/> - <data android:host="feeds2.feedburner.com"/> - <data android:host="feedsproxy.google.com"/> - </intent-filter> - - <intent-filter> - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.BROWSABLE"/> - <data android:scheme="http"/> - <data android:scheme="https"/> - <data android:mimeType="text/xml"/> - <data android:mimeType="application/rss+xml"/> - <data android:mimeType="application/atom+xml"/> - <data android:mimeType="application/xml"/> - </intent-filter> + <action android:name="android.intent.action.VIEW"/> + + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.BROWSABLE"/> + + <data android:scheme="http"/> + <data android:scheme="https"/> + <data android:mimeType="text/xml"/> + <data android:mimeType="application/rss+xml"/> + <data android:mimeType="application/atom+xml"/> + <data android:mimeType="application/xml"/> + </intent-filter> <intent-filter> - <action android:name="android.intent.action.SEND" /> + <action android:name="android.intent.action.SEND"/> - <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.DEFAULT"/> - <data android:mimeType="text/plain" /> + <data android:mimeType="text/plain"/> </intent-filter> </activity> <activity android:name="de.danoeh.antennapod.activity.FeedItemlistActivity" - android:configChanges="orientation|screenSize" > + android:configChanges="orientation|screenSize"> <meta-data android:name="android.app.default_searchable" - android:value="de.danoeh.antennapod.activity.SearchActivity" /> + android:value="de.danoeh.antennapod.activity.SearchActivity"/> <meta-data android:name="android.app.searchable" - android:resource="@xml/searchable" /> + android:resource="@xml/searchable"/> </activity> <activity android:name="de.danoeh.antennapod.activity.ItemviewActivity" - android:configChanges="keyboard|orientation" /> + android:configChanges="keyboard|orientation"/> <activity android:name="de.danoeh.antennapod.activity.DownloadActivity" - android:label="@string/downloads_label" /> + android:label="@string/downloads_label"/> <activity android:name=".activity.AudioplayerActivity" - android:launchMode="singleTop" > + android:launchMode="singleTop"> <intent-filter> - <action android:name="android.intent.action.VIEW" /> + <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.BROWSABLE"/> - <data android:scheme="file" /> - <data android:mimeType="audio/*" /> + <data android:scheme="file"/> + <data android:mimeType="audio/*"/> </intent-filter> </activity> <service android:name=".service.download.DownloadService" - android:enabled="true" /> + android:enabled="true"/> <service android:name="de.danoeh.antennapod.service.PlaybackService" - android:enabled="true" > + android:enabled="true"> </service> <activity android:name=".activity.PreferenceActivity" android:configChanges="keyboardHidden|orientation" - android:label="@string/settings_label" > + android:label="@string/settings_label"> </activity> <activity android:name=".activity.DownloadLogActivity" - android:label="@string/download_log_label" > + android:label="@string/download_log_label"> </activity> <receiver android:name=".receiver.MediaButtonReceiver" - android:exported="true" > + android:exported="true"> <intent-filter> - <action android:name="android.intent.action.MEDIA_BUTTON" /> + <action android:name="android.intent.action.MEDIA_BUTTON"/> </intent-filter> <intent-filter> - <action android:name="de.danoeh.antennapod.NOTIFY_BUTTON_RECEIVER" /> + <action android:name="de.danoeh.antennapod.NOTIFY_BUTTON_RECEIVER"/> </intent-filter> </receiver> - <activity android:name=".activity.FeedInfoActivity" > + <activity android:name=".activity.FeedInfoActivity"> </activity> <service android:name=".service.PlayerWidgetService" android:enabled="true" - android:exported="false" > + android:exported="false"> </service> - <receiver android:name=".receiver.PlayerWidget" > + <receiver android:name=".receiver.PlayerWidget"> <intent-filter> - <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> + <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/> </intent-filter> <intent-filter> - <action android:name="de.danoeh.antennapod.FORCE_WIDGET_UPDATE" /> + <action android:name="de.danoeh.antennapod.FORCE_WIDGET_UPDATE"/> </intent-filter> <meta-data android:name="android.appwidget.provider" - android:resource="@xml/player_widget_info" /> + android:resource="@xml/player_widget_info"/> <intent-filter> - <action android:name="de.danoeh.antennapod.STOP_WIDGET_UPDATE" /> + <action android:name="de.danoeh.antennapod.STOP_WIDGET_UPDATE"/> </intent-filter> </receiver> - <receiver android:name=".receiver.FeedUpdateReceiver" > + <receiver android:name=".receiver.FeedUpdateReceiver"> <intent-filter> - <action android:name="de.danoeh.antennapod.feedupdatereceiver.refreshFeeds" /> + <action android:name="de.danoeh.antennapod.feedupdatereceiver.refreshFeeds"/> </intent-filter> </receiver> - <activity android:name=".activity.StorageErrorActivity" > + <activity android:name=".activity.StorageErrorActivity"> </activity> <activity android:name=".activity.FlattrAuthActivity" - android:label="@string/flattr_auth_label" > + android:label="@string/flattr_auth_label"> <intent-filter> - <action android:name=".activities.FlattrAuthActivity" /> + <action android:name=".activities.FlattrAuthActivity"/> - <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <intent-filter> - <action android:name="android.intent.action.VIEW" /> + <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.BROWSABLE"/> <data android:host="de.danoeh.antennapod" - android:scheme="flattr4j" /> + android:scheme="flattr4j"/> </intent-filter> </activity> <activity android:name=".activity.AboutActivity" - android:label="@string/about_pref" > + android:label="@string/about_pref"> </activity> <activity android:name=".activity.OpmlImportFromPathActivity" android:configChanges="keyboardHidden|orientation" - android:label="@string/opml_import_label" > + android:label="@string/opml_import_label"> </activity> <activity android:name=".activity.OpmlImportFromIntentActivity" android:configChanges="keyboardHidden|orientation" - android:label="@string/opml_import_label" > + android:label="@string/opml_import_label"> <intent-filter> - <action android:name="android.intent.action.VIEW" /> + <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.BROWSABLE"/> <data android:host="*" android:mimeType="*/*" android:pathPattern=".*\\.opml" - android:scheme="file" /> + android:scheme="file"/> </intent-filter> <intent-filter> - <action android:name="android.intent.action.VIEW" /> + <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.BROWSABLE"/> <data android:host="*" android:pathPattern=".*\\.opml" android:scheme="file" - android:mimeType="text/x-opml" /> + android:mimeType="text/x-opml"/> </intent-filter> </activity> <activity android:name=".activity.OpmlFeedChooserActivity" - android:label="@string/opml_import_label" > + android:label="@string/opml_import_label"> </activity> <activity android:name=".activity.SearchActivity" android:configChanges="keyboardHidden|orientation" android:label="@string/search_results_label" - android:launchMode="singleTop" > + android:launchMode="singleTop"> <intent-filter> - <action android:name="android.intent.action.SEARCH" /> + <action android:name="android.intent.action.SEARCH"/> </intent-filter> <meta-data android:name="android.app.searchable" - android:resource="@xml/searchable" /> + android:resource="@xml/searchable"/> </activity> <activity android:name=".activity.MiroGuideMainActivity" - android:label="@string/miro_guide_label" > + android:label="@string/miro_guide_label"> <meta-data android:name="android.app.default_searchable" - android:value="de.danoeh.antennapod.activity.MiroGuideSearchActivity" /> + android:value="de.danoeh.antennapod.activity.MiroGuideSearchActivity"/> <meta-data android:name="android.app.searchable" - android:resource="@xml/miroguide_searchable" /> + android:resource="@xml/miroguide_searchable"/> </activity> <activity android:name=".activity.MiroGuideSearchActivity" android:configChanges="keyboardHidden|orientation" - android:launchMode="singleTop" > + android:launchMode="singleTop"> <intent-filter> - <action android:name="android.intent.action.SEARCH" /> + <action android:name="android.intent.action.SEARCH"/> </intent-filter> <meta-data android:name="android.app.searchable" - android:resource="@xml/miroguide_searchable" /> + android:resource="@xml/miroguide_searchable"/> </activity> <activity android:name=".activity.MiroGuideCategoryActivity" - android:configChanges="keyboardHidden|orientation" > + android:configChanges="keyboardHidden|orientation"> </activity> <activity android:name=".activity.MiroGuideChannelViewActivity" android:configChanges="keyboard|orientation" - android:label="@string/miro_guide_label" > + android:label="@string/miro_guide_label"> </activity> <activity android:name=".activity.VideoplayerActivity" android:configChanges="keyboardHidden|orientation" - android:screenOrientation="landscape" > + android:screenOrientation="landscape"> <intent-filter> - <action android:name="android.intent.action.VIEW" /> + <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.BROWSABLE"/> - <data android:scheme="file" /> - <data android:mimeType="video/*" /> + <data android:scheme="file"/> + <data android:mimeType="video/*"/> </intent-filter> </activity> <activity android:name=".activity.PlaybackHistoryActivity" - android:label="@string/playback_history_label" /> + android:label="@string/playback_history_label"/> <activity android:name=".activity.DirectoryChooserActivity" - android:label="@string/choose_data_directory" /> + android:label="@string/choose_data_directory"/> <activity android:name=".activity.OrganizeQueueActivity" android:configChanges="orientation" - android:label="@string/organize_queue_label" > + android:label="@string/organize_queue_label"> </activity> <activity android:name=".activity.gpoddernet.GpodnetMainActivity" android:configChanges="orientation" - android:label="@string/gpodnet_main_label"/> + android:label="@string/gpodnet_main_label"> + + <meta-data + android:name="android.app.default_searchable" + android:value="de.danoeh.antennapod.activity.gpoddernet.GpodnetSearchActivity"/> + <meta-data + android:name="android.app.searchable" + android:resource="@xml/gpodnet_searchable"/> + </activity> + <activity + android:name=".activity.gpoddernet.GpodnetTagActivity" + android:configChanges="orientation"> + <meta-data + android:name="android.app.default_searchable" + android:value="de.danoeh.antennapod.activity.gpoddernet.GpodnetSearchActivity"/> + <meta-data + android:name="android.app.searchable" + android:resource="@xml/gpodnet_searchable"/> + </activity> + + <activity + android:name=".activity.gpoddernet.GpodnetSearchActivity" + android:configChanges="orientation" + android:label="@string/search_label" + android:launchMode="singleTop"> + <intent-filter> + <action android:name="android.intent.action.SEARCH"/> + </intent-filter> + <meta-data + android:name="android.app.searchable" + android:resource="@xml/gpodnet_searchable"/> + </activity> + + <activity + android:name=".activity.DefaultOnlineFeedViewActivity" + android:configChanges="orientation"/> - <receiver android:name=".receiver.ConnectivityActionReceiver" > + <receiver android:name=".receiver.ConnectivityActionReceiver"> <intent-filter> - <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> + <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> </intent-filter> </receiver> - <receiver android:name=".receiver.AlarmUpdateReceiver" > + <receiver android:name=".receiver.AlarmUpdateReceiver"> <intent-filter> - <action android:name="android.intent.action.BOOT_COMPLETED" /> + <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> <intent-filter> - <action android:name="android.intent.action.PACKAGE_REPLACED" /> + <action android:name="android.intent.action.PACKAGE_REPLACED"/> <data android:path="de.danoeh.antennapod" - android:scheme="package" /> + android:scheme="package"/> </intent-filter> </receiver> </application> diff --git a/res/layout/gpodnet_main.xml b/res/layout/gpodnet_main.xml index 7e382a641..1017a6a65 100644 --- a/res/layout/gpodnet_main.xml +++ b/res/layout/gpodnet_main.xml @@ -1,12 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> - <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" + android:id="@+id/main_view" android:layout_width="match_parent" - android:layout_height="match_parent"> - <FrameLayout + android:layout_height="match_parent" + android:orientation="vertical" > + + <android.support.v4.view.ViewPager + android:id="@+id/viewpager" android:layout_width="match_parent" - android:layout_height="match_parent" - android:id="@+id/toplist_fragment"/> + android:layout_height="0px" + android:layout_weight="1"> + <android.support.v4.view.PagerTabStrip + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="top" /> + </android.support.v4.view.ViewPager> -</LinearLayout>
\ No newline at end of file +</LinearLayout> diff --git a/res/layout/gpodnet_podcast_listitem.xml b/res/layout/gpodnet_podcast_listitem.xml index 596eee136..f6ddb3bd8 100644 --- a/res/layout/gpodnet_podcast_listitem.xml +++ b/res/layout/gpodnet_podcast_listitem.xml @@ -5,8 +5,8 @@ android:layout_height="match_parent"> <ImageView android:id="@+id/imgvCover" - android:layout_width="@dimen/thumbnail_length" - android:layout_height="@dimen/thumbnail_length" + android:layout_width="@dimen/thumbnail_length_itemlist" + android:layout_height="@dimen/thumbnail_length_itemlist" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_marginRight="4dip" @@ -16,7 +16,7 @@ <LinearLayout android:layout_width="match_parent" - android:layout_height="@dimen/thumbnail_length" + android:layout_height="@dimen/thumbnail_length_itemlist" android:layout_centerVertical="true" android:layout_toRightOf="@id/imgvCover" android:layout_marginRight="8dp" diff --git a/res/layout/gpodnet_search.xml b/res/layout/gpodnet_search.xml new file mode 100644 index 000000000..deb9cffd6 --- /dev/null +++ b/res/layout/gpodnet_search.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <FrameLayout + android:id="@+id/searchListFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + +</LinearLayout>
\ No newline at end of file diff --git a/res/layout/gpodnet_tag_activity.xml b/res/layout/gpodnet_tag_activity.xml new file mode 100644 index 000000000..01feb216f --- /dev/null +++ b/res/layout/gpodnet_tag_activity.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <FrameLayout + android:id="@+id/taglistFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + +</LinearLayout>
\ No newline at end of file diff --git a/res/layout/itemdescription_listitem.xml b/res/layout/itemdescription_listitem.xml new file mode 100644 index 000000000..d6a3f6a16 --- /dev/null +++ b/res/layout/itemdescription_listitem.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <TextView + android:id="@+id/txtvTitle" + android:layout_margin="8dp" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:lines="1" + android:ellipsize="end" + android:textColor="?android:attr/textColorPrimary" + android:textSize="@dimen/text_size_small"/> + + <TextView + android:id="@+id/txtvDescription" + android:layout_margin="8dp" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:lines="3" + android:ellipsize="end" + android:textColor="?android:attr/textColorTertiary" + android:textSize="@dimen/text_size_micro"/> +</LinearLayout>
\ No newline at end of file diff --git a/res/layout/onlinefeedview_header.xml b/res/layout/onlinefeedview_header.xml new file mode 100644 index 000000000..59b7a9b24 --- /dev/null +++ b/res/layout/onlinefeedview_header.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ImageView + android:id="@+id/imgvCover" + android:layout_width="@dimen/thumbnail_length_itemlist" + android:layout_height="@dimen/thumbnail_length_itemlist" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:layout_margin="4dp"/> + + <TextView + android:id="@+id/txtvTitle" + android:layout_width="0dp" + android:layout_height="0dp" + android:ellipsize="end" + android:gravity="center_vertical" + android:layout_alignTop="@id/imgvCover" + android:layout_alignBottom="@id/imgvCover" + android:layout_toRightOf="@id/imgvCover" + android:layout_alignParentRight="true" + android:textColor="?android:attr/textColorPrimary" + android:textSize="@dimen/text_size_large" + android:layout_margin="4dp"/> + + <TextView + android:id="@+id/txtvDescription" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/imgvCover" + android:maxLines="3" + android:ellipsize="end" + android:textColor="?android:attr/textColorTertiary" + android:textSize="@dimen/text_size_micro" + android:layout_margin="4dp"/> +</RelativeLayout>
\ No newline at end of file diff --git a/res/values/colors.xml b/res/values/colors.xml index 5cf84ec4a..a666f8967 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -28,6 +28,7 @@ <color name="status_playing">#E0EE5F52</color> <color name="overlay_dark">#262C31</color> <color name="overlay_light">#DDDDDD</color> + <color name="default_image_color">#858585</color> <!-- Use Gingerbread-orange --> <color name="selection_background_color_dark">#FEBB20</color> diff --git a/res/values/strings.xml b/res/values/strings.xml index 78a92e249..2709f6c4c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -238,6 +238,11 @@ <string name="add_feed_label">Add feed</string> <string name="miro_feed_added">Feed is being added</string> + <!-- gpodder.net --> + <string name="gpodnet_taglist_header">CATEGORIES</string> + <string name="gpodnet_toplist_header">TOP PODCASTS</string> + <string name="gpodnet_search_hint">Search gpodder.net</string> + <!-- Directory chooser --> <string name="selected_folder_label">Selected folder:</string> <string name="create_folder_label">Create folder</string> diff --git a/res/xml/gpodnet_searchable.xml b/res/xml/gpodnet_searchable.xml new file mode 100644 index 000000000..d2c14d7f7 --- /dev/null +++ b/res/xml/gpodnet_searchable.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<searchable xmlns:android="http://schemas.android.com/apk/res/android" android:hint="@string/gpodnet_search_hint" android:label="@string/app_name" android:icon="@drawable/ic_launcher"> + + +</searchable>
\ No newline at end of file diff --git a/src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java b/src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java new file mode 100644 index 000000000..c72c777c1 --- /dev/null +++ b/src/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java @@ -0,0 +1,46 @@ +package de.danoeh.antennapod.activity; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.adapter.FeedItemlistDescriptionAdapter; +import de.danoeh.antennapod.asynctask.ImageDiskCache; +import de.danoeh.antennapod.feed.Feed; + +/** + * Created by daniel on 24.08.13. + */ +public class DefaultOnlineFeedViewActivity extends OnlineFeedViewActivity { + + @Override + protected void showFeedInformation(Feed feed) { + super.showFeedInformation(feed); + setContentView(R.layout.listview_activity); + + ListView listView = (ListView) findViewById(R.id.listview); + LayoutInflater inflater = (LayoutInflater) + getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View header = inflater.inflate(R.layout.onlinefeedview_header, null); + listView.addHeaderView(header); + + listView.setAdapter(new FeedItemlistDescriptionAdapter(this, 0, feed.getItems())); + + ImageView cover = (ImageView) header.findViewById(R.id.imgvCover); + TextView title = (TextView) header.findViewById(R.id.txtvTitle); + TextView description = (TextView) header.findViewById(R.id.txtvDescription); + + if (feed.getImage() != null) { + ImageDiskCache.getDefaultInstance().loadThumbnailBitmap(feed.getImage().getDownload_url(), cover, (int) getResources().getDimension( + R.dimen.thumbnail_length)); + } + title.setText(feed.getTitle()); + description.setText(feed.getDescription()); + + + } +} + diff --git a/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java index fbac7057d..ff2e4987e 100644 --- a/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -1,23 +1,15 @@ package de.danoeh.antennapod.activity; -import java.io.File; -import java.io.IOException; -import java.util.Date; - -import javax.xml.parsers.ParserConfigurationException; - -import android.support.v7.app.ActionBarActivity; -import org.xml.sax.SAXException; - import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.os.Bundle; +import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.Gravity; import android.widget.LinearLayout; import android.widget.ProgressBar; - +import android.widget.RelativeLayout; import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.feed.Feed; @@ -25,7 +17,6 @@ import de.danoeh.antennapod.preferences.UserPreferences; import de.danoeh.antennapod.service.download.DownloadRequest; import de.danoeh.antennapod.service.download.DownloadStatus; import de.danoeh.antennapod.service.download.Downloader; -import de.danoeh.antennapod.service.download.DownloaderCallback; import de.danoeh.antennapod.service.download.HttpDownloader; import de.danoeh.antennapod.syndication.handler.FeedHandler; import de.danoeh.antennapod.syndication.handler.UnsupportedFeedtypeException; @@ -33,207 +24,230 @@ import de.danoeh.antennapod.util.DownloadError; import de.danoeh.antennapod.util.FileNameGenerator; import de.danoeh.antennapod.util.StorageUtils; import de.danoeh.antennapod.util.URLChecker; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.IOException; +import java.util.Date; /** * Downloads a feed from a feed URL and parses it. Subclasses can display the * feed object that was parsed. This activity MUST be started with a given URL * or an Exception will be thrown. - * + * <p/> * If the feed cannot be downloaded or parsed, an error dialog will be displayed * and the activity will finish as soon as the error dialog is closed. */ public abstract class OnlineFeedViewActivity extends ActionBarActivity { - private static final String TAG = "OnlineFeedViewActivity"; - private static final String ARG_FEEDURL = "arg.feedurl"; - - public static final int RESULT_ERROR = 2; - - private Feed feed; - private Downloader downloader; - - @Override - protected void onCreate(Bundle arg0) { - setTheme(UserPreferences.getTheme()); - super.onCreate(arg0); - StorageUtils.checkStorageAvailability(this); - final String feedUrl = getIntent().getStringExtra(ARG_FEEDURL); - if (feedUrl == null) { - throw new IllegalArgumentException( - "Activity must be started with feedurl argument!"); - } - if (AppConfig.DEBUG) - Log.d(TAG, "Activity was started with url " + feedUrl); - setLoadingLayout(); - startFeedDownload(feedUrl); - } - - @Override - protected void onStop() { - super.onStop(); - if (downloader != null && !downloader.isFinished()) { - downloader.cancel(); - } - } - - private DownloaderCallback downloaderCallback = new DownloaderCallback() { - @Override - public void onDownloadCompleted(final Downloader downloader) { - runOnUiThread(new Runnable() { - - @Override - public void run() { - DownloadStatus status = downloader.getResult(); - if (status != null) { - if (!status.isCancelled()) { - if (status.isSuccessful()) { - parseFeed(); - } else { - String errorMsg = status.getReason().getErrorString( - OnlineFeedViewActivity.this); - if (errorMsg != null - && status.getReasonDetailed() != null) { - errorMsg += " (" - + status.getReasonDetailed() + ")"; - } - showErrorDialog(errorMsg); - } - } - } else { - Log.wtf(TAG, - "DownloadStatus returned by Downloader was null"); - finish(); - } - } - }); - - } - }; - - private void startFeedDownload(String url) { - if (AppConfig.DEBUG) - Log.d(TAG, "Starting feed download"); - url = URLChecker.prepareURL(url); - feed = new Feed(url, new Date()); - String fileUrl = new File(getExternalCacheDir(), - FileNameGenerator.generateFileName(feed.getDownload_url())) - .toString(); - feed.setFile_url(fileUrl); - DownloadRequest request = new DownloadRequest(feed.getFile_url(), - feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED); - /* TODO update - HttpDownloader httpDownloader = new HttpDownloader(downloaderCallback, - request); - httpDownloader.start(); - */ - } - - /** Displays a progress indicator. */ - private void setLoadingLayout() { - LinearLayout ll = new LinearLayout(this); - LinearLayout.LayoutParams llLayoutParams = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT); - - ProgressBar pb = new ProgressBar(this); - pb.setIndeterminate(true); - LinearLayout.LayoutParams pbLayoutParams = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT); - pbLayoutParams.gravity = Gravity.CENTER; - ll.addView(pb, pbLayoutParams); - addContentView(ll, llLayoutParams); - } - - private void parseFeed() { - if (feed == null || feed.getFile_url() == null) { - throw new IllegalStateException( - "feed must be non-null and downloaded when parseFeed is called"); - } - - if (AppConfig.DEBUG) - Log.d(TAG, "Parsing feed"); - - Thread thread = new Thread() { - - @Override - public void run() { - String reasonDetailed = ""; - boolean successful = false; - FeedHandler handler = new FeedHandler(); - try { - handler.parseFeed(feed); - successful = true; - } catch (SAXException e) { - e.printStackTrace(); - reasonDetailed = e.getMessage(); - } catch (IOException e) { - e.printStackTrace(); - reasonDetailed = e.getMessage(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - reasonDetailed = e.getMessage(); - } catch (UnsupportedFeedtypeException e) { - e.printStackTrace(); - reasonDetailed = e.getMessage(); - } finally { - boolean rc = new File(feed.getFile_url()).delete(); - if (AppConfig.DEBUG) - Log.d(TAG, "Deleted feed source file. Result: " + rc); - } - - if (successful) { - runOnUiThread(new Runnable() { - @Override - public void run() { - showFeedInformation(); - } - }); - } else { - final String errorMsg = - DownloadError.ERROR_PARSER_EXCEPTION.getErrorString( - OnlineFeedViewActivity.this) - + " (" + reasonDetailed + ")"; - runOnUiThread(new Runnable() { - - @Override - public void run() { - showErrorDialog(errorMsg); - } - }); - } - } - }; - thread.start(); - } - - /** Called when feed parsed successfully */ - protected void showFeedInformation() { - - } - - private void showErrorDialog(String errorMsg) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.error_label); - if (errorMsg != null) { - builder.setMessage(getString(R.string.error_msg_prefix) + errorMsg); - } else { - builder.setMessage(R.string.error_msg_prefix); - } - builder.setNeutralButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - } - }); - builder.setOnCancelListener(new OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - setResult(RESULT_ERROR); - finish(); - } - }); - } + private static final String TAG = "OnlineFeedViewActivity"; + public static final String ARG_FEEDURL = "arg.feedurl"; + + /** Optional argument: specify a title for the actionbar. */ + public static final String ARG_TITLE = "title"; + + public static final int RESULT_ERROR = 2; + + private Feed feed; + private Downloader downloader; + + @Override + protected void onCreate(Bundle arg0) { + setTheme(UserPreferences.getTheme()); + super.onCreate(arg0); + + if (getIntent() != null && getIntent().hasExtra(ARG_TITLE)) { + getSupportActionBar().setTitle(getIntent().getStringExtra(ARG_TITLE)); + } + + StorageUtils.checkStorageAvailability(this); + final String feedUrl = getIntent().getStringExtra(ARG_FEEDURL); + if (feedUrl == null) { + throw new IllegalArgumentException( + "Activity must be started with feedurl argument!"); + } + if (AppConfig.DEBUG) + Log.d(TAG, "Activity was started with url " + feedUrl); + setLoadingLayout(); + startFeedDownload(feedUrl); + } + + @Override + protected void onStop() { + super.onStop(); + if (downloader != null && !downloader.isFinished()) { + downloader.cancel(); + } + } + + + private void onDownloadCompleted(final Downloader downloader) { + runOnUiThread(new Runnable() { + + @Override + public void run() { + if (AppConfig.DEBUG) Log.d(TAG, "Download was completed"); + DownloadStatus status = downloader.getResult(); + if (status != null) { + if (!status.isCancelled()) { + if (status.isSuccessful()) { + parseFeed(); + } else { + String errorMsg = status.getReason().getErrorString( + OnlineFeedViewActivity.this); + if (errorMsg != null + && status.getReasonDetailed() != null) { + errorMsg += " (" + + status.getReasonDetailed() + ")"; + } + showErrorDialog(errorMsg); + } + } + } else { + Log.wtf(TAG, + "DownloadStatus returned by Downloader was null"); + finish(); + } + } + }); + + } + + private void startFeedDownload(String url) { + if (AppConfig.DEBUG) + Log.d(TAG, "Starting feed download"); + url = URLChecker.prepareURL(url); + feed = new Feed(url, new Date()); + String fileUrl = new File(getExternalCacheDir(), + FileNameGenerator.generateFileName(feed.getDownload_url())) + .toString(); + feed.setFile_url(fileUrl); + final DownloadRequest request = new DownloadRequest(feed.getFile_url(), + feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED); + downloader = new HttpDownloader( + request); + new Thread() { + @Override + public void run() { + downloader.call(); + onDownloadCompleted(downloader); + } + }.start(); + + + } + + /** + * Displays a progress indicator. + */ + private void setLoadingLayout() { + RelativeLayout rl = new RelativeLayout(this); + RelativeLayout.LayoutParams rlLayoutParams = new RelativeLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT); + + ProgressBar pb = new ProgressBar(this); + pb.setIndeterminate(true); + RelativeLayout.LayoutParams pbLayoutParams = new RelativeLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + pbLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT); + rl.addView(pb, pbLayoutParams); + addContentView(rl, rlLayoutParams); + } + + private void parseFeed() { + if (feed == null || feed.getFile_url() == null) { + throw new IllegalStateException( + "feed must be non-null and downloaded when parseFeed is called"); + } + + if (AppConfig.DEBUG) + Log.d(TAG, "Parsing feed"); + + Thread thread = new Thread() { + + @Override + public void run() { + String reasonDetailed = ""; + boolean successful = false; + FeedHandler handler = new FeedHandler(); + try { + handler.parseFeed(feed); + successful = true; + } catch (SAXException e) { + e.printStackTrace(); + reasonDetailed = e.getMessage(); + } catch (IOException e) { + e.printStackTrace(); + reasonDetailed = e.getMessage(); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + reasonDetailed = e.getMessage(); + } catch (UnsupportedFeedtypeException e) { + e.printStackTrace(); + reasonDetailed = e.getMessage(); + } finally { + boolean rc = new File(feed.getFile_url()).delete(); + if (AppConfig.DEBUG) + Log.d(TAG, "Deleted feed source file. Result: " + rc); + } + + if (successful) { + runOnUiThread(new Runnable() { + @Override + public void run() { + showFeedInformation(feed); + } + }); + } else { + final String errorMsg = + DownloadError.ERROR_PARSER_EXCEPTION.getErrorString( + OnlineFeedViewActivity.this) + + " (" + reasonDetailed + ")"; + runOnUiThread(new Runnable() { + + @Override + public void run() { + showErrorDialog(errorMsg); + } + }); + } + } + }; + thread.start(); + } + + /** + * Called when feed parsed successfully + */ + protected void showFeedInformation(Feed feed) { + + } + + private void showErrorDialog(String errorMsg) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.error_label); + if (errorMsg != null) { + builder.setMessage(getString(R.string.error_msg_prefix) + errorMsg); + } else { + builder.setMessage(R.string.error_msg_prefix); + } + builder.setNeutralButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.cancel(); + } + }); + builder.setOnCancelListener(new OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + setResult(RESULT_ERROR); + finish(); + } + }); + } } diff --git a/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetActivity.java b/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetActivity.java new file mode 100644 index 000000000..08b37ae60 --- /dev/null +++ b/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetActivity.java @@ -0,0 +1,44 @@ +package de.danoeh.antennapod.activity.gpoddernet; + +import android.app.SearchManager; +import android.content.Context; +import android.os.Bundle; +import android.support.v4.view.MenuItemCompat; +import android.support.v7.app.ActionBarActivity; +import android.support.v7.widget.SearchView; +import android.view.Menu; +import android.view.MenuItem; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.preferences.UserPreferences; + +/** + * Created by daniel on 23.08.13. + */ +public class GpodnetActivity extends ActionBarActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(UserPreferences.getTheme()); + super.onCreate(savedInstanceState); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuItemCompat.setShowAsAction(menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label) + .setIcon( + obtainStyledAttributes( + new int[]{R.attr.action_search}) + .getDrawable(0)), + MenuItem.SHOW_AS_ACTION_IF_ROOM); + MenuItemCompat.setActionView(menu.findItem(R.id.search_item), new SearchView(this)); + + SearchManager searchManager = + (SearchManager) getSystemService(Context.SEARCH_SERVICE); + SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.search_item)); + searchView.setIconifiedByDefault(true); + searchView.setSearchableInfo( + searchManager.getSearchableInfo(getComponentName())); + + return true; + } +} diff --git a/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetMainActivity.java b/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetMainActivity.java index 316ea2e88..d85ae4202 100644 --- a/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetMainActivity.java +++ b/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetMainActivity.java @@ -1,25 +1,67 @@ package de.danoeh.antennapod.activity.gpoddernet; import android.os.Bundle; -import android.support.v4.app.FragmentTransaction; -import android.support.v7.app.ActionBarActivity; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; +import android.support.v4.view.ViewPager; import de.danoeh.antennapod.R; import de.danoeh.antennapod.fragment.gpodnet.PodcastTopListFragment; +import de.danoeh.antennapod.fragment.gpodnet.TagListFragment; /** * Created by daniel on 22.08.13. */ -public class GpodnetMainActivity extends ActionBarActivity { +public class GpodnetMainActivity extends GpodnetActivity { + private static final String TAG = "GPodnetMainActivity"; + + private static final int POS_TAGS = 0; + private static final int POS_TOPLIST = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gpodnet_main); - FragmentTransaction transaction = getSupportFragmentManager() - .beginTransaction(); - PodcastTopListFragment topListFragment = new PodcastTopListFragment(); - transaction.replace(R.id.toplist_fragment, topListFragment); - transaction.commit(); + ViewPager viewpager = (ViewPager) findViewById(R.id.viewpager); + viewpager.setAdapter(new PagerAdapter(getSupportFragmentManager())); + } + + private class PagerAdapter extends FragmentStatePagerAdapter { + + private static final int NUM_PAGES = 2; + + public PagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int i) { + switch (i) { + case POS_TAGS: + return new TagListFragment(); + case POS_TOPLIST: + return new PodcastTopListFragment(); + default: + return null; + } + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case POS_TAGS: + return getString(R.string.gpodnet_taglist_header); + case POS_TOPLIST: + return getString(R.string.gpodnet_toplist_header); + default: + return super.getPageTitle(position); + } + } + + @Override + public int getCount() { + return NUM_PAGES; + } } } diff --git a/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetSearchActivity.java b/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetSearchActivity.java new file mode 100644 index 000000000..e0e3f822a --- /dev/null +++ b/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetSearchActivity.java @@ -0,0 +1,50 @@ +package de.danoeh.antennapod.activity.gpoddernet; + +import android.app.SearchManager; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentTransaction; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.fragment.gpodnet.SearchListFragment; +import org.apache.commons.lang3.StringUtils; + +/** + * Created by daniel on 23.08.13. + */ +public class GpodnetSearchActivity extends GpodnetActivity { + + private SearchListFragment searchFragment; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.gpodnet_search); + } + + @Override + protected void onResume() { + super.onResume(); + Intent intent = getIntent(); + if (StringUtils.equals(intent.getAction(), Intent.ACTION_SEARCH)) { + handleSearchRequest(intent.getStringExtra(SearchManager.QUERY)); + } + } + + @Override + protected void onNewIntent(Intent intent) { + setIntent(intent); + } + + private void handleSearchRequest(String query) { + getSupportActionBar().setSubtitle(getString(R.string.search_term_label) + query); + if (searchFragment == null) { + FragmentTransaction transaction = getSupportFragmentManager() + .beginTransaction(); + searchFragment = SearchListFragment.newInstance(query); + transaction.replace(R.id.searchListFragment, searchFragment); + transaction.commit(); + } else { + searchFragment.changeQuery(query); + } + } +} diff --git a/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetTagActivity.java b/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetTagActivity.java new file mode 100644 index 000000000..aabd03685 --- /dev/null +++ b/src/de/danoeh/antennapod/activity/gpoddernet/GpodnetTagActivity.java @@ -0,0 +1,51 @@ +package de.danoeh.antennapod.activity.gpoddernet; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.fragment.gpodnet.PodcastListFragment; +import de.danoeh.antennapod.fragment.gpodnet.SearchListFragment; +import de.danoeh.antennapod.gpoddernet.GpodnetService; +import de.danoeh.antennapod.gpoddernet.GpodnetServiceException; +import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.gpoddernet.model.GpodnetTag; + +import java.util.List; + +/** + * Created by daniel on 23.08.13. + */ +public class GpodnetTagActivity extends GpodnetActivity{ + + private static final int PODCAST_COUNT = 50; + public static final String ARG_TAGNAME = "tagname"; + + private GpodnetTag tag; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.gpodnet_tag_activity); + + if (!getIntent().hasExtra(ARG_TAGNAME)) { + throw new IllegalArgumentException("No tagname argument"); + } + tag = new GpodnetTag(getIntent().getStringExtra(ARG_TAGNAME)); + getSupportActionBar().setTitle(tag.getName()); + + FragmentTransaction transaction = getSupportFragmentManager() + .beginTransaction(); + Fragment taglistFragment = new TaglistFragment(); + transaction.replace(R.id.taglistFragment, taglistFragment); + transaction.commit(); + } + + private class TaglistFragment extends PodcastListFragment { + + @Override + protected List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException { + return service.getPodcastsForTag(tag, PODCAST_COUNT); + } + } +} diff --git a/src/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java b/src/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java new file mode 100644 index 000000000..5fb204b26 --- /dev/null +++ b/src/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java @@ -0,0 +1,55 @@ +package de.danoeh.antennapod.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.feed.FeedItem; + +import java.util.List; + +/** + * Created by daniel on 24.08.13. + */ +public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> { + + public FeedItemlistDescriptionAdapter(Context context, int resource, List<FeedItem> objects) { + super(context, resource, objects); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + Holder holder; + + FeedItem item = getItem(position); + + // Inflate layout + if (convertView == null) { + holder = new Holder(); + LayoutInflater inflater = (LayoutInflater) getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + convertView = inflater.inflate(R.layout.itemdescription_listitem, null); + holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); + holder.description = (TextView) convertView.findViewById(R.id.txtvDescription); + + convertView.setTag(holder); + } else { + holder = (Holder) convertView.getTag(); + } + + holder.title.setText(item.getTitle()); + if (item.getDescription() != null) { + holder.description.setText(item.getDescription()); + } + + return convertView; + } + + static class Holder { + TextView title; + TextView description; + } +} diff --git a/src/de/danoeh/antennapod/asynctask/ImageDiskCache.java b/src/de/danoeh/antennapod/asynctask/ImageDiskCache.java index e0675982f..0179260cc 100644 --- a/src/de/danoeh/antennapod/asynctask/ImageDiskCache.java +++ b/src/de/danoeh/antennapod/asynctask/ImageDiskCache.java @@ -49,11 +49,16 @@ public class ImageDiskCache { if (path == null) { throw new NullPointerException(); } + if (cacheSingletons.containsKey(path)) { + return cacheSingletons.get(path); + } + ImageDiskCache cache = cacheSingletons.get(path); if (cache == null) { cache = new ImageDiskCache(path, maxCacheSize); cacheSingletons.put(new File(path).getAbsolutePath(), cache); } + cacheSingletons.put(path, cache); return cache; } @@ -75,7 +80,7 @@ public class ImageDiskCache { } executor = Executors.newFixedThreadPool(Runtime.getRuntime() - .availableProcessors()); + .availableProcessors() * 2); } private synchronized void initCacheFolder() { @@ -189,10 +194,11 @@ public class ImageDiskCache { } } target.setTag(R.id.image_disk_cache_key, url); + target.setImageResource(R.color.default_image_color); executor.submit(new ImageDownloader(url) { @Override protected void onImageLoaded(DiskCacheObject diskCacheObject) { - if (target.getTag(R.id.image_disk_cache_key) == url) { + if (target.getTag(R.id.image_disk_cache_key).equals(url)) { il.loadThumbnailBitmap(diskCacheObject.loadImage(), target, length); } } @@ -215,10 +221,11 @@ public class ImageDiskCache { } } target.setTag(R.id.image_disk_cache_key, url); + target.setImageResource(R.color.default_image_color); executor.submit(new ImageDownloader(url) { @Override protected void onImageLoaded(DiskCacheObject diskCacheObject) { - if (target.getTag(R.id.image_disk_cache_key) == url) { + if (target.getTag(R.id.image_disk_cache_key).equals(url)) { il.loadCoverBitmap(diskCacheObject.loadImage(), target, length); } } diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java index ba74d9d03..32e11e0ce 100644 --- a/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java +++ b/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java @@ -1,9 +1,11 @@ package de.danoeh.antennapod.fragment.gpodnet; import android.content.Context; +import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -11,7 +13,10 @@ import android.widget.AdapterView; import android.widget.GridView; import android.widget.ProgressBar; import android.widget.TextView; +import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.DefaultOnlineFeedViewActivity; +import de.danoeh.antennapod.activity.OnlineFeedViewActivity; import de.danoeh.antennapod.adapter.gpodnet.PodcastListAdapter; import de.danoeh.antennapod.gpoddernet.GpodnetService; import de.danoeh.antennapod.gpoddernet.GpodnetServiceException; @@ -49,11 +54,17 @@ public abstract class PodcastListFragment extends Fragment { return root; } - protected abstract void onPodcastSelected(GpodnetPodcast selection); + protected void onPodcastSelected(GpodnetPodcast selection) { + if (AppConfig.DEBUG) Log.d(TAG, "Selected podcast: " + selection.toString()); + Intent intent = new Intent(getActivity(), DefaultOnlineFeedViewActivity.class); + intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, selection.getUrl()); + intent.putExtra(DefaultOnlineFeedViewActivity.ARG_TITLE, getString(R.string.gpodnet_main_label)); + startActivity(intent); + } protected abstract List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException; - private void loadData() { + protected final void loadData() { AsyncTask<Void, Void, List<GpodnetPodcast>> loaderTask = new AsyncTask<Void, Void, List<GpodnetPodcast>>() { volatile Exception exception = null; @@ -95,7 +106,7 @@ public abstract class PodcastListFragment extends Fragment { @Override protected void onPreExecute() { super.onPreExecute(); - // gridView.setVisibility(View.GONE); + gridView.setVisibility(View.GONE); progressBar.setVisibility(View.VISIBLE); } }; diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java index 4e7e42aa3..7007d0b9a 100644 --- a/src/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java +++ b/src/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java @@ -16,11 +16,6 @@ public class PodcastTopListFragment extends PodcastListFragment { private static final int PODCAST_COUNT = 50; @Override - protected void onPodcastSelected(GpodnetPodcast selection) { - if (AppConfig.DEBUG) Log.d(TAG, "Selected: " + selection.getTitle()); - } - - @Override protected List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException { return service.getPodcastToplist(PODCAST_COUNT); } diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java new file mode 100644 index 000000000..322d13097 --- /dev/null +++ b/src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java @@ -0,0 +1,48 @@ +package de.danoeh.antennapod.fragment.gpodnet; + +import android.os.Bundle; +import de.danoeh.antennapod.gpoddernet.GpodnetService; +import de.danoeh.antennapod.gpoddernet.GpodnetServiceException; +import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast; + +import java.util.List; + +/** + * Created by daniel on 23.08.13. + */ +public class SearchListFragment extends PodcastListFragment { + private static final String ARG_QUERY = "query"; + + private String query; + + public static SearchListFragment newInstance(String query) { + SearchListFragment fragment = new SearchListFragment(); + Bundle args = new Bundle(); + args.putString(ARG_QUERY, query); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null && getArguments().containsKey(ARG_QUERY)) { + this.query = getArguments().getString(ARG_QUERY); + } else { + this.query = ""; + } + } + + @Override + protected List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException { + return service.searchPodcasts(query, 0); + } + + public void changeQuery(String query) { + if (query == null) { + throw new NullPointerException(); + } + this.query = query; + loadData(); + } +} diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java new file mode 100644 index 000000000..3d63f2e58 --- /dev/null +++ b/src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java @@ -0,0 +1,96 @@ +package de.danoeh.antennapod.fragment.gpodnet; + +import android.R; +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.TextView; +import de.danoeh.antennapod.activity.gpoddernet.GpodnetTagActivity; +import de.danoeh.antennapod.gpoddernet.GpodnetService; +import de.danoeh.antennapod.gpoddernet.GpodnetServiceException; +import de.danoeh.antennapod.gpoddernet.model.GpodnetTag; + +import java.util.ArrayList; +import java.util.List; + +public class TagListFragment extends ListFragment { + private static final String TAG = "TagListFragment"; + private static final int COUNT = 50; + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + setRetainInstance(true); + + getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + String selectedTag = (String) getListAdapter().getItem(position); + Intent intent = new Intent(getActivity(), GpodnetTagActivity.class); + intent.putExtra(GpodnetTagActivity.ARG_TAGNAME, selectedTag); + startActivity(intent); + } + }); + + loadData(); + } + + private void loadData() { + AsyncTask<Void, Void, List<GpodnetTag>> task = new AsyncTask<Void, Void, List<GpodnetTag>>() { + private Exception exception; + + @Override + protected List<GpodnetTag> doInBackground(Void... params) { + GpodnetService service = new GpodnetService(); + try { + return service.getTopTags(COUNT); + } catch (GpodnetServiceException e) { + e.printStackTrace(); + exception = e; + return null; + } finally { + service.shutdown(); + } + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + setListShown(false); + } + + @Override + protected void onPostExecute(List<GpodnetTag> gpodnetTags) { + super.onPostExecute(gpodnetTags); + final Context context = getActivity(); + if (context != null) { + if (gpodnetTags != null) { + List<String> tagNames = new ArrayList<String>(); + for (GpodnetTag tag : gpodnetTags) { + tagNames.add(tag.getName()); + } + setListAdapter(new ArrayAdapter<String>(context, R.layout.simple_list_item_1, tagNames)); + setListShown(true); + } else if (exception != null) { + TextView txtvError = new TextView(getActivity()); + txtvError.setText(exception.getMessage()); + getListView().setEmptyView(txtvError); + } else { + setListShown(true); + } + } + } + }; + if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { + task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + task.execute(); + } + } +} + |