Eric Kok
11 years ago
32 changed files with 1251 additions and 36 deletions
@ -0,0 +1,40 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:baselineAligned="false" |
||||||
|
tools:context=".SearchActivity" > |
||||||
|
|
||||||
|
<com.actionbarsherlock.view.SherlockListView |
||||||
|
android:id="@+id/searchsites_list" |
||||||
|
android:layout_width="0dip" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:layout_weight="1" |
||||||
|
android:choiceMode="singleChoice" |
||||||
|
android:listSelector="?attr/selectable_background_transdroid" /> |
||||||
|
|
||||||
|
<fragment |
||||||
|
android:id="@+id/searchresults_list" |
||||||
|
android:layout_width="0dip" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:layout_weight="3" |
||||||
|
class="org.transdroid.core.gui.search.SearchResultsFragment_" |
||||||
|
tools:layout="@layout/fragment_searchresults" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/installmodule_text" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_gravity="center" |
||||||
|
android:drawablePadding="8dip" |
||||||
|
android:drawableTop="?attr/loading_progress" |
||||||
|
android:gravity="center" |
||||||
|
android:maxWidth="400dip" |
||||||
|
android:padding="@dimen/margin_default" |
||||||
|
android:text="@string/search_installsearch" |
||||||
|
android:textIsSelectable="false" |
||||||
|
android:visibility="gone" /> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,17 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:orientation="vertical" |
||||||
|
android:paddingRight="@dimen/margin_half" > |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/searchsite_text" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:textColor="?attr/text_actionbar" |
||||||
|
android:textIsSelectable="false" |
||||||
|
android:textSize="@dimen/abs__action_bar_title_text_size" |
||||||
|
android:fontFamily="sans-serif-condensed" /> |
||||||
|
|
||||||
|
</FrameLayout> |
@ -0,0 +1,29 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
tools:context=".SearchActivity" > |
||||||
|
|
||||||
|
<fragment |
||||||
|
android:id="@+id/searchresults_list" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
class="org.transdroid.core.gui.search.SearchResultsFragment_" |
||||||
|
tools:layout="@layout/fragment_searchresults" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/installmodule_text" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_gravity="center" |
||||||
|
android:drawablePadding="8dip" |
||||||
|
android:drawableTop="?attr/loading_progress" |
||||||
|
android:gravity="center" |
||||||
|
android:maxWidth="400dip" |
||||||
|
android:padding="@dimen/margin_default" |
||||||
|
android:text="@string/search_installsearch" |
||||||
|
android:textIsSelectable="false" |
||||||
|
android:visibility="gone" /> |
||||||
|
|
||||||
|
</FrameLayout> |
@ -0,0 +1,37 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" > |
||||||
|
|
||||||
|
<com.actionbarsherlock.view.SherlockListView |
||||||
|
android:id="@+id/searchresults_list" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:choiceMode="multipleChoiceModal" |
||||||
|
android:listSelector="?attr/selectable_background_transdroid" |
||||||
|
android:visibility="gone" /> |
||||||
|
|
||||||
|
<ProgressBar |
||||||
|
android:id="@+id/loading_progress" |
||||||
|
android:layout_width="128dp" |
||||||
|
android:layout_height="128dp" |
||||||
|
android:layout_gravity="center" |
||||||
|
android:indeterminate="true" |
||||||
|
android:indeterminateDrawable="?attr/loading_progress" |
||||||
|
android:indeterminateOnly="true" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/empty_text" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_gravity="center" |
||||||
|
android:drawablePadding="8dip" |
||||||
|
android:drawableTop="?attr/loading_progress" |
||||||
|
android:gravity="center" |
||||||
|
android:maxWidth="400dip" |
||||||
|
android:padding="@dimen/margin_default" |
||||||
|
android:text="@string/search_noresults" |
||||||
|
android:textIsSelectable="false" |
||||||
|
android:visibility="gone" /> |
||||||
|
|
||||||
|
</FrameLayout> |
@ -0,0 +1,58 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<org.transdroid.core.gui.rss.RssitemStatusLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:background="?attr/selectable_background_transdroid" |
||||||
|
android:paddingBottom="@dimen/margin_half" |
||||||
|
android:paddingLeft="@dimen/margin_default" |
||||||
|
android:paddingRight="@dimen/margin_default" |
||||||
|
android:paddingTop="@dimen/margin_half" > |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/name_text" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:fontFamily="sans-serif-condensed" |
||||||
|
android:textColor="?attr/text_bright" |
||||||
|
android:textIsSelectable="false" |
||||||
|
android:textSize="@dimen/text_enlarged" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/leechers_text" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_below="@id/name_text" |
||||||
|
android:layout_alignParentRight="true" |
||||||
|
android:layout_marginTop="4dip" |
||||||
|
android:textIsSelectable="false" |
||||||
|
android:textSize="@dimen/text_small" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/seeders_text" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_alignBaseline="@id/leechers_text" |
||||||
|
android:layout_toLeftOf="@id/leechers_text" |
||||||
|
android:layout_marginRight="@dimen/margin_default" |
||||||
|
android:textIsSelectable="false" |
||||||
|
android:textSize="@dimen/text_small" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/size_text" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_alignBaseline="@id/leechers_text" |
||||||
|
android:textIsSelectable="false" |
||||||
|
android:textSize="@dimen/text_small" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/date_text" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_alignBaseline="@id/leechers_text" |
||||||
|
android:layout_toRightOf="@id/size_text" |
||||||
|
android:layout_marginRight="@dimen/margin_default" |
||||||
|
android:textIsSelectable="false" |
||||||
|
android:textSize="@dimen/text_small" /> |
||||||
|
|
||||||
|
</org.transdroid.core.gui.rss.RssitemStatusLayout> |
@ -0,0 +1,28 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:paddingBottom="@dimen/margin_half" |
||||||
|
android:paddingLeft="@dimen/margin_default" |
||||||
|
android:paddingRight="@dimen/margin_default" |
||||||
|
android:paddingTop="@dimen/margin_half" > |
||||||
|
|
||||||
|
<ImageView |
||||||
|
android:id="@+id/favicon_image" |
||||||
|
android:layout_width="24dip" |
||||||
|
android:layout_height="24dip" |
||||||
|
android:layout_marginRight="@dimen/margin_half" |
||||||
|
android:scaleType="centerCrop" |
||||||
|
tools:ignore="contentDescription" /> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/name_text" |
||||||
|
android:layout_width="0dip" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_marginTop="1dip" |
||||||
|
android:textIsSelectable="false" /> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,18 @@ |
|||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" > |
||||||
|
|
||||||
|
<item |
||||||
|
android:id="@+id/action_refresh" |
||||||
|
android:icon="?attr/ic_action_refresh" |
||||||
|
android:showAsAction="always" |
||||||
|
android:title="@string/action_refresh"/> |
||||||
|
<item |
||||||
|
android:id="@+id/action_search" |
||||||
|
android:icon="?attr/ic_action_search" |
||||||
|
android:showAsAction="collapseActionView|ifRoom" |
||||||
|
android:title="@string/action_search"/> |
||||||
|
<item |
||||||
|
android:id="@+id/action_downloadsearch" |
||||||
|
android:showAsAction="always" |
||||||
|
android:title="@string/search_download"/> |
||||||
|
|
||||||
|
</menu> |
@ -1,9 +1,15 @@ |
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" > |
<menu xmlns:android="http://schemas.android.com/apk/res/android" > |
||||||
|
|
||||||
|
<item |
||||||
|
android:id="@+id/action_showdetails" |
||||||
|
android:icon="?attr/ic_action_new" |
||||||
|
android:showAsAction="always" |
||||||
|
android:title="@string/action_showdetails" /> |
||||||
|
|
||||||
<item |
<item |
||||||
android:id="@+id/action_addall" |
android:id="@+id/action_addall" |
||||||
android:icon="?attr/ic_action_new" |
android:icon="?attr/ic_action_new" |
||||||
android:showAsAction="always" |
android:showAsAction="always" |
||||||
android:title="@string/action_addall" /> |
android:title="@string/action_addall" /> |
||||||
|
|
||||||
</menu> |
</menu> |
@ -0,0 +1,9 @@ |
|||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" > |
||||||
|
|
||||||
|
<item |
||||||
|
android:id="@+id/action_addall" |
||||||
|
android:icon="?attr/ic_action_new" |
||||||
|
android:showAsAction="always" |
||||||
|
android:title="@string/action_addall" /> |
||||||
|
|
||||||
|
</menu> |
@ -0,0 +1,248 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.androidannotations.annotations.AfterViews; |
||||||
|
import org.androidannotations.annotations.Bean; |
||||||
|
import org.androidannotations.annotations.EActivity; |
||||||
|
import org.androidannotations.annotations.FragmentById; |
||||||
|
import org.androidannotations.annotations.OptionsItem; |
||||||
|
import org.androidannotations.annotations.OptionsMenu; |
||||||
|
import org.androidannotations.annotations.SystemService; |
||||||
|
import org.androidannotations.annotations.ViewById; |
||||||
|
import org.transdroid.core.R; |
||||||
|
import org.transdroid.core.app.search.SearchHelper; |
||||||
|
import org.transdroid.core.app.search.SearchSite; |
||||||
|
import org.transdroid.core.app.settings.ApplicationSettings; |
||||||
|
import org.transdroid.core.app.settings.SystemSettings_; |
||||||
|
import org.transdroid.core.app.settings.WebsearchSetting; |
||||||
|
import org.transdroid.core.gui.TorrentsActivity_; |
||||||
|
import org.transdroid.core.gui.navigation.NavigationHelper; |
||||||
|
|
||||||
|
import android.annotation.TargetApi; |
||||||
|
import android.app.SearchManager; |
||||||
|
import android.content.Intent; |
||||||
|
import android.net.Uri; |
||||||
|
import android.os.Build; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.provider.SearchRecentSuggestions; |
||||||
|
import android.view.View; |
||||||
|
import android.widget.AdapterView; |
||||||
|
import android.widget.AdapterView.OnItemClickListener; |
||||||
|
import android.widget.TextView; |
||||||
|
|
||||||
|
import com.actionbarsherlock.app.ActionBar; |
||||||
|
import com.actionbarsherlock.app.ActionBar.OnNavigationListener; |
||||||
|
import com.actionbarsherlock.app.SherlockFragmentActivity; |
||||||
|
import com.actionbarsherlock.view.Menu; |
||||||
|
import com.actionbarsherlock.view.MenuItem; |
||||||
|
import com.actionbarsherlock.view.SherlockListView; |
||||||
|
import com.actionbarsherlock.widget.SearchView; |
||||||
|
|
||||||
|
/** |
||||||
|
* An activity that shows search results to the user (after a query was supplied by the standard Android search manager) |
||||||
|
* and either shows the list of search sites on the left (e.g. on tablets) or allows switching between search sites via |
||||||
|
* the action bar spinner. |
||||||
|
* @author Eric Kok |
||||||
|
*/ |
||||||
|
@EActivity(resName = "activity_search") |
||||||
|
@OptionsMenu(resName = "activity_search") |
||||||
|
public class SearchActivity extends SherlockFragmentActivity implements OnNavigationListener { |
||||||
|
|
||||||
|
@FragmentById(resName = "searchresults_list") |
||||||
|
protected SearchResultsFragment fragmentResults; |
||||||
|
@ViewById |
||||||
|
protected SherlockListView searchsitesList; |
||||||
|
@ViewById |
||||||
|
protected TextView installmoduleText; |
||||||
|
@Bean |
||||||
|
protected ApplicationSettings applicationSettings; |
||||||
|
@Bean |
||||||
|
protected NavigationHelper navigationHelper; |
||||||
|
@Bean |
||||||
|
protected SearchHelper searchHelper; |
||||||
|
@SystemService |
||||||
|
protected SearchManager searchManager; |
||||||
|
private SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, |
||||||
|
TorrentSearchHistoryProvider.AUTHORITY, TorrentSearchHistoryProvider.MODE); |
||||||
|
|
||||||
|
private List<SearchSetting> searchSites; |
||||||
|
private SearchSetting lastUsedSite; |
||||||
|
private String lastUsedQuery; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCreate(Bundle savedInstanceState) { |
||||||
|
// Set the theme according to the user preference
|
||||||
|
if (SystemSettings_.getInstance_(this).useDarkTheme()) { |
||||||
|
setTheme(R.style.TransdroidTheme_Dark); |
||||||
|
getSupportActionBar().setIcon(R.drawable.ic_activity_torrents); |
||||||
|
} |
||||||
|
super.onCreate(savedInstanceState); |
||||||
|
} |
||||||
|
|
||||||
|
@AfterViews |
||||||
|
protected void init() { |
||||||
|
|
||||||
|
// Get the user query, as coming from the standard SearchManager
|
||||||
|
handleIntent(getIntent()); |
||||||
|
|
||||||
|
if (!searchHelper.isTorrentSearchInstalled()) { |
||||||
|
// The module install text will be shown instead (in onPrepareOptionsMenu)
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// Load sites and find the last used (or set as default) search site
|
||||||
|
searchSites = applicationSettings.getSearchSettings(); |
||||||
|
lastUsedSite = applicationSettings.getLastUsedSearchSite(); |
||||||
|
int lastUsedPosition = -1; |
||||||
|
if (lastUsedSite != null) { |
||||||
|
for (int i = 0; i < searchSites.size(); i++) { |
||||||
|
if (searchSites.get(i).getKey().equals(lastUsedSite.getKey())) |
||||||
|
lastUsedPosition = i; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Allow site selection via list (on large screens) or action bar spinner
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true); |
||||||
|
if (searchsitesList != null) { |
||||||
|
// The current layout has a dedicated list view to select the search site
|
||||||
|
SearchSitesAdapter searchSitesAdapter = SearchSitesAdapter_.getInstance_(this); |
||||||
|
searchSitesAdapter.update(searchSites); |
||||||
|
searchsitesList.setAdapter(searchSitesAdapter); |
||||||
|
searchsitesList.setOnItemClickListener(onSearchSiteClicked); |
||||||
|
// Select the last used site; this also starts the search!
|
||||||
|
if (lastUsedPosition >= 0) |
||||||
|
searchsitesList.setItemChecked(lastUsedPosition, true); |
||||||
|
} else { |
||||||
|
// Use the action bar spinner to select sites
|
||||||
|
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); |
||||||
|
getSupportActionBar().setDisplayShowTitleEnabled(false); |
||||||
|
getSupportActionBar().setListNavigationCallbacks(new SearchSettingsDropDownAdapter(this, searchSites), this); |
||||||
|
// Select the last used site; this also starts the search!
|
||||||
|
if (lastUsedPosition >= 0) |
||||||
|
getSupportActionBar().setSelectedNavigationItem(lastUsedPosition); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.FROYO) |
||||||
|
@Override |
||||||
|
public boolean onCreateOptionsMenu(Menu menu) { |
||||||
|
super.onCreateOptionsMenu(menu); |
||||||
|
if (navigationHelper.enableSearchUi()) { |
||||||
|
// For Android 2.1+, add an expandable SearchView to the action bar
|
||||||
|
MenuItem item = menu.findItem(R.id.action_search); |
||||||
|
if (android.os.Build.VERSION.SDK_INT >= 8) { |
||||||
|
final SearchView searchView = new SearchView(this); |
||||||
|
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); |
||||||
|
searchView.setQueryRefinementEnabled(true); |
||||||
|
item.setActionView(searchView); |
||||||
|
} |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onPrepareOptionsMenu(Menu menu) { |
||||||
|
super.onPrepareOptionsMenu(menu); |
||||||
|
|
||||||
|
boolean searchInstalled = searchHelper.isTorrentSearchInstalled(); |
||||||
|
menu.findItem(R.id.action_search).setVisible(searchInstalled); |
||||||
|
menu.findItem(R.id.action_refresh).setVisible(searchInstalled); |
||||||
|
menu.findItem(R.id.action_downloadsearch).setVisible(!searchInstalled); |
||||||
|
if (searchsitesList != null) |
||||||
|
searchsitesList.setVisibility(searchInstalled ? View.VISIBLE : View.GONE); |
||||||
|
if (searchInstalled) |
||||||
|
getSupportFragmentManager().beginTransaction().show(fragmentResults).commit(); |
||||||
|
else |
||||||
|
getSupportFragmentManager().beginTransaction().hide(fragmentResults).commit(); |
||||||
|
installmoduleText.setVisibility(searchInstalled ? View.GONE : View.VISIBLE); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onNewIntent(Intent intent) { |
||||||
|
handleIntent(intent); |
||||||
|
refreshSearch(); |
||||||
|
} |
||||||
|
|
||||||
|
private void handleIntent(Intent intent) { |
||||||
|
lastUsedQuery = getQuery(intent); |
||||||
|
getSupportActionBar().setTitle(NavigationHelper.buildCondensedFontString(lastUsedQuery)); |
||||||
|
|
||||||
|
// Is this actually a full HTTP URL? Then redirect this request to add the URL directly
|
||||||
|
if (lastUsedQuery != null |
||||||
|
&& (lastUsedQuery.startsWith("http") || lastUsedQuery.startsWith("https") |
||||||
|
|| lastUsedQuery.startsWith("magnet") || lastUsedQuery.startsWith("file"))) { |
||||||
|
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(lastUsedQuery))); |
||||||
|
finish(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.HONEYCOMB) |
||||||
|
@OptionsItem(android.R.id.home) |
||||||
|
protected void navigateUp() { |
||||||
|
TorrentsActivity_.intent(this).flags(Intent.FLAG_ACTIVITY_CLEAR_TOP).start(); |
||||||
|
} |
||||||
|
|
||||||
|
private OnItemClickListener onSearchSiteClicked = new OnItemClickListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { |
||||||
|
lastUsedSite = searchSites.get(position); |
||||||
|
refreshSearch(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onNavigationItemSelected(int itemPosition, long itemId) { |
||||||
|
lastUsedSite = searchSites.get(itemPosition); |
||||||
|
refreshSearch(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Extracts the query string from the search {@link Intent} |
||||||
|
* @return The query string that was entered by the user |
||||||
|
*/ |
||||||
|
private String getQuery(Intent intent) { |
||||||
|
|
||||||
|
String query = null; |
||||||
|
if (intent.getAction().equals(Intent.ACTION_SEARCH)) { |
||||||
|
query = intent.getStringExtra(SearchManager.QUERY); |
||||||
|
} else if (intent.getAction().equals(Intent.ACTION_SEND)) { |
||||||
|
query = SendIntentHelper.cleanUpText(intent); |
||||||
|
} |
||||||
|
if (query != null && query.length() > 0) { |
||||||
|
|
||||||
|
// Remember this search query to later show as a suggestion
|
||||||
|
suggestions.saveRecentQuery(query, null); |
||||||
|
return query; |
||||||
|
|
||||||
|
} |
||||||
|
return null; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@OptionsItem(resName = "action_refresh") |
||||||
|
protected void refreshSearch() { |
||||||
|
if (lastUsedSite instanceof WebsearchSetting) { |
||||||
|
// Start a browser page directly to the requested search results
|
||||||
|
WebsearchSetting websearch = (WebsearchSetting) lastUsedSite; |
||||||
|
startActivity(new Intent(Intent.ACTION_VIEW, |
||||||
|
Uri.parse(String.format(websearch.getBaseUrl(), lastUsedQuery)))); |
||||||
|
} else if (lastUsedSite instanceof SearchSite) { |
||||||
|
// Ask the resutls fragment to start a search for the specified query
|
||||||
|
fragmentResults.startSearch(lastUsedQuery, (SearchSite) lastUsedSite); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@OptionsItem(resName = "action_downloadsearch") |
||||||
|
protected void downloadSearchModule() { |
||||||
|
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.transdroid.org/latest-search"))); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import org.androidannotations.annotations.EViewGroup; |
||||||
|
import org.androidannotations.annotations.ViewById; |
||||||
|
import org.transdroid.core.R; |
||||||
|
import org.transdroid.core.app.search.SearchResult; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.text.format.DateUtils; |
||||||
|
import android.widget.TextView; |
||||||
|
import fr.marvinlabs.widget.CheckableRelativeLayout; |
||||||
|
|
||||||
|
/** |
||||||
|
* View that represents a {@link SearchResult} object from an in-app search |
||||||
|
* @author Eric Kok |
||||||
|
*/ |
||||||
|
@EViewGroup(resName = "list_item_searchresult") |
||||||
|
public class SearchResultView extends CheckableRelativeLayout { |
||||||
|
|
||||||
|
// Views
|
||||||
|
@ViewById |
||||||
|
protected TextView nameText, seedersText, leechersText, sizeText, dateText; |
||||||
|
|
||||||
|
public SearchResultView(Context context) { |
||||||
|
super(context); |
||||||
|
} |
||||||
|
|
||||||
|
public void bind(SearchResult result) { |
||||||
|
|
||||||
|
nameText.setText(result.getName()); |
||||||
|
sizeText.setText(result.getSize()); |
||||||
|
dateText.setText(result.getAddedOn() == null ? "" : DateUtils.getRelativeDateTimeString(getContext(), result |
||||||
|
.getAddedOn().getTime(), DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, |
||||||
|
DateUtils.FORMAT_ABBREV_MONTH)); |
||||||
|
seedersText.setText(getContext().getString(R.string.search_seeders, result.getSeeders())); |
||||||
|
leechersText.setText(getContext().getString(R.string.search_leechers, result.getLeechers())); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.androidannotations.annotations.EBean; |
||||||
|
import org.androidannotations.annotations.RootContext; |
||||||
|
import org.transdroid.core.app.search.SearchResult; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.view.View; |
||||||
|
import android.view.ViewGroup; |
||||||
|
import android.widget.BaseAdapter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Adapter that contains a list of {@link SearchResult}s. |
||||||
|
* @author Eric Kok |
||||||
|
*/ |
||||||
|
@EBean |
||||||
|
public class SearchResultsAdapter extends BaseAdapter { |
||||||
|
|
||||||
|
private List<SearchResult> results = null; |
||||||
|
|
||||||
|
@RootContext |
||||||
|
protected Context context; |
||||||
|
|
||||||
|
/** |
||||||
|
* Allows updating the search results, replacing the old data |
||||||
|
* @param newRssfeeds The new list of search results |
||||||
|
*/ |
||||||
|
public void update(List<SearchResult> results) { |
||||||
|
this.results = results; |
||||||
|
notifyDataSetChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean hasStableIds() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getCount() { |
||||||
|
if (results == null) |
||||||
|
return 0; |
||||||
|
return results.size(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public SearchResult getItem(int position) { |
||||||
|
if (results == null) |
||||||
|
return null; |
||||||
|
return results.get(position); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public long getItemId(int position) { |
||||||
|
return position; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public View getView(int position, View convertView, ViewGroup parent) { |
||||||
|
SearchResultView rssitemView; |
||||||
|
if (convertView == null) { |
||||||
|
rssitemView = SearchResultView_.build(context); |
||||||
|
} else { |
||||||
|
rssitemView = (SearchResultView) convertView; |
||||||
|
} |
||||||
|
rssitemView.bind(getItem(position)); |
||||||
|
return rssitemView; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,168 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.androidannotations.annotations.AfterViews; |
||||||
|
import org.androidannotations.annotations.Background; |
||||||
|
import org.androidannotations.annotations.Bean; |
||||||
|
import org.androidannotations.annotations.EFragment; |
||||||
|
import org.androidannotations.annotations.InstanceState; |
||||||
|
import org.androidannotations.annotations.ItemClick; |
||||||
|
import org.androidannotations.annotations.UiThread; |
||||||
|
import org.androidannotations.annotations.ViewById; |
||||||
|
import org.transdroid.core.R; |
||||||
|
import org.transdroid.core.app.search.SearchHelper; |
||||||
|
import org.transdroid.core.app.search.SearchHelper.SearchSortOrder; |
||||||
|
import org.transdroid.core.app.search.SearchResult; |
||||||
|
import org.transdroid.core.app.search.SearchSite; |
||||||
|
import org.transdroid.core.gui.navigation.SelectionManagerMode; |
||||||
|
|
||||||
|
import android.content.Intent; |
||||||
|
import android.net.Uri; |
||||||
|
import android.view.View; |
||||||
|
import android.widget.ProgressBar; |
||||||
|
import android.widget.TextView; |
||||||
|
import android.widget.Toast; |
||||||
|
|
||||||
|
import com.actionbarsherlock.app.SherlockFragment; |
||||||
|
import com.actionbarsherlock.view.ActionMode; |
||||||
|
import com.actionbarsherlock.view.Menu; |
||||||
|
import com.actionbarsherlock.view.MenuItem; |
||||||
|
import com.actionbarsherlock.view.SherlockListView; |
||||||
|
import com.actionbarsherlock.view.SherlockListView.MultiChoiceModeListenerCompat; |
||||||
|
|
||||||
|
/** |
||||||
|
* Fragment that lists the items in a specific RSS feed |
||||||
|
* @author Eric Kok |
||||||
|
*/ |
||||||
|
@EFragment(resName = "fragment_searchresults") |
||||||
|
public class SearchResultsFragment extends SherlockFragment { |
||||||
|
|
||||||
|
@InstanceState |
||||||
|
protected ArrayList<SearchResult> results = null; |
||||||
|
@Bean |
||||||
|
protected SearchHelper searchHelper; |
||||||
|
|
||||||
|
// Views
|
||||||
|
@ViewById(resName = "searchresults_list") |
||||||
|
protected SherlockListView resultsList; |
||||||
|
@Bean |
||||||
|
protected SearchResultsAdapter resultsAdapter; |
||||||
|
@ViewById |
||||||
|
protected TextView emptyText; |
||||||
|
@ViewById |
||||||
|
protected ProgressBar loadingProgress; |
||||||
|
|
||||||
|
@AfterViews |
||||||
|
protected void init() { |
||||||
|
|
||||||
|
// Set up the list adapter, which allows multi-select
|
||||||
|
resultsList.setAdapter(resultsAdapter); |
||||||
|
resultsList.setMultiChoiceModeListener(onItemsSelected); |
||||||
|
if (results != null) |
||||||
|
showResults(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void startSearch(String query, SearchSite site) { |
||||||
|
loadingProgress.setVisibility(View.VISIBLE); |
||||||
|
resultsList.setVisibility(View.GONE); |
||||||
|
emptyText.setVisibility(View.GONE); |
||||||
|
performSearch(query, site); |
||||||
|
} |
||||||
|
|
||||||
|
@Background |
||||||
|
protected void performSearch(String query, SearchSite site) { |
||||||
|
results = searchHelper.search(query, site, SearchSortOrder.BySeeders); |
||||||
|
showResults(); |
||||||
|
} |
||||||
|
|
||||||
|
@UiThread |
||||||
|
protected void showResults() { |
||||||
|
loadingProgress.setVisibility(View.GONE); |
||||||
|
if (results == null || results.size() == 0) { |
||||||
|
resultsList.setVisibility(View.GONE); |
||||||
|
emptyText.setVisibility(View.VISIBLE); |
||||||
|
return; |
||||||
|
} |
||||||
|
resultsAdapter.update(results); |
||||||
|
resultsList.setVisibility(View.VISIBLE); |
||||||
|
emptyText.setVisibility(View.GONE); |
||||||
|
} |
||||||
|
|
||||||
|
@ItemClick(resName = "searchresults_list") |
||||||
|
protected void onItemClicked(SearchResult item) { |
||||||
|
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(item.getTorrentUrl())); |
||||||
|
i.putExtra("TORRENT_TITLE", item.getName()); |
||||||
|
startActivity(i); |
||||||
|
} |
||||||
|
|
||||||
|
private MultiChoiceModeListenerCompat onItemsSelected = new MultiChoiceModeListenerCompat() { |
||||||
|
|
||||||
|
SelectionManagerMode selectionManagerMode; |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onCreateActionMode(ActionMode mode, Menu menu) { |
||||||
|
// Show contextual action bar to add items in batch mode
|
||||||
|
mode.getMenuInflater().inflate(R.menu.fragment_searchresults_cab, menu); |
||||||
|
selectionManagerMode = new SelectionManagerMode(resultsList, R.plurals.search_resutlsselected); |
||||||
|
selectionManagerMode.onCreateActionMode(mode, menu); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean onPrepareActionMode(ActionMode mode, Menu menu) { |
||||||
|
return selectionManagerMode.onPrepareActionMode(mode, menu); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean onActionItemClicked(ActionMode mode, MenuItem item) { |
||||||
|
|
||||||
|
// Get checked torrents
|
||||||
|
List<SearchResult> checked = new ArrayList<SearchResult>(); |
||||||
|
for (int i = 0; i < resultsList.getCheckedItemPositions().size(); i++) { |
||||||
|
if (resultsList.getCheckedItemPositions().valueAt(i)) |
||||||
|
checked.add(resultsAdapter.getItem(resultsList.getCheckedItemPositions().keyAt(i))); |
||||||
|
} |
||||||
|
|
||||||
|
int itemId = item.getItemId(); |
||||||
|
if (itemId == R.id.action_addall) { |
||||||
|
// Start an Intent that adds multiple items at once, by supplying the urls and titles as string array
|
||||||
|
// extras and setting the Intent action to ADD_MULTIPLE
|
||||||
|
Intent intent = new Intent("org.transdroid.ADD_MULTIPLE"); |
||||||
|
String[] urls = new String[checked.size()]; |
||||||
|
String[] titles = new String[checked.size()]; |
||||||
|
for (int i = 0; i < checked.size(); i++) { |
||||||
|
urls[i] = checked.get(i).getTorrentUrl(); |
||||||
|
titles[i] = checked.get(i).getName(); |
||||||
|
} |
||||||
|
intent.putExtra("TORRENT_URLS", urls); |
||||||
|
intent.putExtra("TORRENT_TITLES", titles); |
||||||
|
startActivity(intent); |
||||||
|
mode.finish(); |
||||||
|
return true; |
||||||
|
} else if (itemId == R.id.action_showdetails) { |
||||||
|
SearchResult first = checked.get(0); |
||||||
|
// Open the torrent's web page in the browser
|
||||||
|
Toast.makeText(getActivity(), getString(R.string.search_openingdetails, first), Toast.LENGTH_LONG) |
||||||
|
.show(); |
||||||
|
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(first.getDetailsUrl()))); |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { |
||||||
|
selectionManagerMode.onItemCheckedStateChanged(mode, position, id, checked); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onDestroyActionMode(ActionMode mode) { |
||||||
|
selectionManagerMode.onDestroyActionMode(mode); |
||||||
|
} |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import org.transdroid.core.gui.lists.SimpleListItem; |
||||||
|
|
||||||
|
public interface SearchSetting extends SimpleListItem { |
||||||
|
|
||||||
|
/** |
||||||
|
* Should return a unique key for this search setting, so that it can be compared (using equals()) to other settings. |
||||||
|
* @return A unique string identifying this search setting |
||||||
|
*/ |
||||||
|
public String getKey(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Should return an URL (which may still be abstract and not the actual search URL) specific to the search site |
||||||
|
* @return A clean URL directing to the search site, to, for example, get the favicon of the site |
||||||
|
*/ |
||||||
|
public String getBaseUrl(); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import org.androidannotations.annotations.EViewGroup; |
||||||
|
import org.androidannotations.annotations.ViewById; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.widget.FrameLayout; |
||||||
|
import android.widget.TextView; |
||||||
|
|
||||||
|
/** |
||||||
|
* View that shows, as part of the action bar spinner, which {@link SearchSetting} is currently chosen. |
||||||
|
* @author Eric Kok |
||||||
|
*/ |
||||||
|
@EViewGroup(resName = "actionbar_searchsite") |
||||||
|
public class SearchSettingSelectionView extends FrameLayout { |
||||||
|
|
||||||
|
@ViewById |
||||||
|
protected TextView searchsiteText; |
||||||
|
|
||||||
|
public SearchSettingSelectionView(Context context) { |
||||||
|
super(context); |
||||||
|
} |
||||||
|
|
||||||
|
public void bind(SearchSetting searchSettingItem) { |
||||||
|
searchsiteText.setText(searchSettingItem.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.transdroid.core.gui.lists.SimpleListItem; |
||||||
|
import org.transdroid.core.gui.navigation.FilterListItemAdapter; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.view.View; |
||||||
|
import android.view.ViewGroup; |
||||||
|
|
||||||
|
/** |
||||||
|
* List adapter that holds search settings, that is, web searches and in-app search sites, displayed as content to a |
||||||
|
* Spinner instead of a ListView. |
||||||
|
* @author Eric Kok |
||||||
|
*/ |
||||||
|
public class SearchSettingsDropDownAdapter extends FilterListItemAdapter { |
||||||
|
|
||||||
|
private final Context context; |
||||||
|
protected SearchSettingSelectionView searchSettingView = null; |
||||||
|
|
||||||
|
public SearchSettingsDropDownAdapter(Context context, List<? extends SimpleListItem> items) { |
||||||
|
super(context, items); |
||||||
|
this.context = context; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public View getView(int position, View convertView, ViewGroup parent) { |
||||||
|
// This returns the item to show in the action bar spinner
|
||||||
|
if (searchSettingView == null) { |
||||||
|
searchSettingView = SearchSettingSelectionView_.build(context); |
||||||
|
} |
||||||
|
searchSettingView.bind((SearchSetting) getItem(position)); |
||||||
|
return searchSettingView; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public View getDropDownView(int position, View convertView, ViewGroup parent) { |
||||||
|
// This returns the item to show in the drop down list
|
||||||
|
return super.getView(position, convertView, parent); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import org.androidannotations.annotations.Bean; |
||||||
|
import org.androidannotations.annotations.EViewGroup; |
||||||
|
import org.androidannotations.annotations.ViewById; |
||||||
|
import org.transdroid.core.app.settings.RssfeedSetting; |
||||||
|
import org.transdroid.core.gui.navigation.NavigationHelper; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.widget.ImageView; |
||||||
|
import android.widget.LinearLayout; |
||||||
|
import android.widget.TextView; |
||||||
|
|
||||||
|
/** |
||||||
|
* View that represents some {@link RssfeedSetting} object and displays name as well as loads a favicon for the feed's |
||||||
|
* site and can load how many new items are available. |
||||||
|
* @author Eric Kok |
||||||
|
*/ |
||||||
|
@EViewGroup(resName = "list_item_searchsite") |
||||||
|
public class SearchSiteView extends LinearLayout { |
||||||
|
|
||||||
|
private static final String GETFVO_URL = "http://g.etfv.co/%1$s"; |
||||||
|
|
||||||
|
@Bean |
||||||
|
protected NavigationHelper navigationHelper; |
||||||
|
|
||||||
|
// Views
|
||||||
|
@ViewById |
||||||
|
protected ImageView faviconImage; |
||||||
|
@ViewById |
||||||
|
protected TextView nameText; |
||||||
|
|
||||||
|
public SearchSiteView(Context context) { |
||||||
|
super(context); |
||||||
|
} |
||||||
|
|
||||||
|
public void bind(SearchSetting rssfeedLoader) { |
||||||
|
|
||||||
|
// Show the RSS feed name and either a loading indicator or the number of new items
|
||||||
|
nameText.setText(rssfeedLoader.getName()); |
||||||
|
// Clear and then asynchronously load the site's favicon
|
||||||
|
// Uses the g.etfv.co service to resolve the favicon of any URL
|
||||||
|
faviconImage.setImageDrawable(null); |
||||||
|
navigationHelper.getImageCache().displayImage(String.format(GETFVO_URL, rssfeedLoader.getBaseUrl()), |
||||||
|
faviconImage); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,72 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.androidannotations.annotations.EBean; |
||||||
|
import org.androidannotations.annotations.RootContext; |
||||||
|
import org.transdroid.core.app.search.SearchSite; |
||||||
|
import org.transdroid.core.app.settings.WebsearchSetting; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.view.View; |
||||||
|
import android.view.ViewGroup; |
||||||
|
import android.widget.BaseAdapter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Adapter that contains a list of {@link SearchSetting}s, either {@link SearchSite} or {@link WebsearchSetting}. |
||||||
|
* @author Eric Kok |
||||||
|
*/ |
||||||
|
@EBean |
||||||
|
public class SearchSitesAdapter extends BaseAdapter { |
||||||
|
|
||||||
|
private List<SearchSetting> sites = null; |
||||||
|
|
||||||
|
@RootContext |
||||||
|
protected Context context; |
||||||
|
|
||||||
|
/** |
||||||
|
* Allows updating the full internal list of sites at once, replacing the old list |
||||||
|
* @param sites The new list of search sites, either in-app or web search settings |
||||||
|
*/ |
||||||
|
public void update(List<SearchSetting> sites) { |
||||||
|
this.sites = sites; |
||||||
|
notifyDataSetChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean hasStableIds() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getCount() { |
||||||
|
if (sites == null) |
||||||
|
return 0; |
||||||
|
return sites.size(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public SearchSetting getItem(int position) { |
||||||
|
if (sites == null) |
||||||
|
return null; |
||||||
|
return sites.get(position); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public long getItemId(int position) { |
||||||
|
return position; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public View getView(int position, View convertView, ViewGroup parent) { |
||||||
|
SearchSiteView rssfeedView; |
||||||
|
if (convertView == null) { |
||||||
|
rssfeedView = SearchSiteView_.build(context); |
||||||
|
} else { |
||||||
|
rssfeedView = (SearchSiteView) convertView; |
||||||
|
} |
||||||
|
rssfeedView.bind(getItem(position)); |
||||||
|
return rssfeedView; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import android.content.Intent; |
||||||
|
|
||||||
|
/** |
||||||
|
* Used to clean up text as received from a generic ACTION_SEND intent. This class is highly custom-based for known |
||||||
|
* applications, i.e. the EXTRA_TEXT send by some known applications. |
||||||
|
* @author Eric Kok |
||||||
|
*/ |
||||||
|
public class SendIntentHelper { |
||||||
|
|
||||||
|
private static final String SOUNDHOUND1 = "Just used #SoundHound to find "; |
||||||
|
private static final String SOUNDHOUND1_END = " http://"; |
||||||
|
private static final String SHAZAM = "I just used Shazam to discover "; |
||||||
|
private static final String SHAZAM_END = ". http://"; |
||||||
|
private static final String YOUTUBE_ID = "Watch \""; |
||||||
|
private static final String YOUTUBE_START = "\""; |
||||||
|
private static final String YOUTUBE_END = "\""; |
||||||
|
|
||||||
|
/** |
||||||
|
* Cleans a SEND intent text string by removing irrelevant parts, so that the remaining text can be used as search |
||||||
|
* string. Typically deals with specific known applications such as Shazam and YouTube's SEND intents. |
||||||
|
* @param intent The original SEND intent that was received |
||||||
|
* @return A cleaned string to be used as search query |
||||||
|
*/ |
||||||
|
public static String cleanUpText(Intent intent) { |
||||||
|
|
||||||
|
if (intent == null || !intent.hasExtra(Intent.EXTRA_TEXT)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
String text = intent.getStringExtra(Intent.EXTRA_TEXT); |
||||||
|
try { |
||||||
|
|
||||||
|
// Soundhound song/artist share
|
||||||
|
if (text.startsWith(SOUNDHOUND1)) { |
||||||
|
return cutOut(text, SOUNDHOUND1, SOUNDHOUND1_END).replace(" by ", " "); |
||||||
|
} |
||||||
|
// Shazam song share
|
||||||
|
if (text.startsWith(SHAZAM)) { |
||||||
|
return cutOut(text, SHAZAM, SHAZAM_END).replace(" by ", " "); |
||||||
|
} |
||||||
|
// YouTube app share (stores title in EXTRA_SUBJECT)
|
||||||
|
if (intent.hasExtra(Intent.EXTRA_SUBJECT)) { |
||||||
|
String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT); |
||||||
|
if (subject.startsWith(YOUTUBE_ID)) { |
||||||
|
return cutOut(subject, YOUTUBE_START, YOUTUBE_END); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} catch (Exception e) { |
||||||
|
// Ignore any errors in parsing; just return the raw text
|
||||||
|
} |
||||||
|
return text; |
||||||
|
} |
||||||
|
|
||||||
|
private static String cutOut(String text, String start, String end) { |
||||||
|
int startAt = text.indexOf(start) + start.length(); |
||||||
|
return text.substring(startAt, text.indexOf(end, startAt)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package org.transdroid.core.gui.search; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.content.SearchRecentSuggestionsProvider; |
||||||
|
import android.provider.SearchRecentSuggestions; |
||||||
|
|
||||||
|
/** |
||||||
|
* Provides a wrapper for the {@link SearchRecentSuggestionsProvider} to show the last torrent searches to the user. |
||||||
|
* @author Eric Kok |
||||||
|
*/ |
||||||
|
public class TorrentSearchHistoryProvider extends SearchRecentSuggestionsProvider { |
||||||
|
|
||||||
|
public static final String AUTHORITY = "org.transdroid.core.gui.search.TorrentSearchHistoryProvider"; |
||||||
|
public static final int MODE = DATABASE_MODE_QUERIES; |
||||||
|
|
||||||
|
public TorrentSearchHistoryProvider() { |
||||||
|
super(); |
||||||
|
setupSuggestions(AUTHORITY, MODE); |
||||||
|
} |
||||||
|
|
||||||
|
public static void clearHistory(Context context) { |
||||||
|
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(context, |
||||||
|
TorrentSearchHistoryProvider.AUTHORITY, TorrentSearchHistoryProvider.MODE); |
||||||
|
suggestions.clearHistory(); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue