Merge pull request #3830 from ByteHamster/search-podcasts
Improved search function
This commit is contained in:
commit
634c98317f
|
@ -9,15 +9,12 @@ import android.view.ViewGroup;
|
|||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedComponent;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.SearchResult;
|
||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||
|
||||
/**
|
||||
|
@ -40,7 +37,7 @@ public class SearchlistAdapter extends BaseAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SearchResult getItem(int position) {
|
||||
public FeedComponent getItem(int position) {
|
||||
return itemAccess.getItem(position);
|
||||
}
|
||||
|
||||
|
@ -52,8 +49,7 @@ public class SearchlistAdapter extends BaseAdapter {
|
|||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
final Holder holder;
|
||||
SearchResult result = getItem(position);
|
||||
FeedComponent component = result.getComponent();
|
||||
FeedComponent component = getItem(position);
|
||||
|
||||
// Inflate Layout
|
||||
if (convertView == null) {
|
||||
|
@ -93,7 +89,7 @@ public class SearchlistAdapter extends BaseAdapter {
|
|||
} else if (component.getClass() == FeedItem.class) {
|
||||
final FeedItem item = (FeedItem) component;
|
||||
holder.title.setText(item.getTitle());
|
||||
holder.subtitle.setText(result.getLocation().getDescription());
|
||||
holder.subtitle.setVisibility(View.VISIBLE);
|
||||
|
||||
convertView.setAlpha(item.isPlayed() ? 0.5f : 1.0f);
|
||||
|
||||
|
@ -121,7 +117,7 @@ public class SearchlistAdapter extends BaseAdapter {
|
|||
public interface ItemAccess {
|
||||
int getCount();
|
||||
|
||||
SearchResult getItem(int position);
|
||||
FeedComponent getItem(int position);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ public abstract class EpisodesListFragment extends Fragment {
|
|||
|
||||
MenuItem searchItem = menu.findItem(R.id.action_search);
|
||||
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
|
||||
sv.setQueryHint(getString(R.string.search_hint));
|
||||
sv.setQueryHint(getString(R.string.search_label));
|
||||
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String s) {
|
||||
|
|
|
@ -186,7 +186,7 @@ public class FeedItemlistFragment extends ListFragment {
|
|||
|
||||
MenuItem searchItem = menu.findItem(R.id.action_search);
|
||||
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
|
||||
sv.setQueryHint(getString(R.string.search_hint));
|
||||
sv.setQueryHint(getString(R.string.search_label));
|
||||
searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
|
||||
@Override
|
||||
public boolean onMenuItemActionExpand(MenuItem item) {
|
||||
|
|
|
@ -289,7 +289,7 @@ public class QueueFragment extends Fragment {
|
|||
|
||||
MenuItem searchItem = menu.findItem(R.id.action_search);
|
||||
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
|
||||
sv.setQueryHint(getString(R.string.search_hint));
|
||||
sv.setQueryHint(getString(R.string.search_label));
|
||||
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String s) {
|
||||
|
|
|
@ -25,7 +25,6 @@ import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
|||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedComponent;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.SearchResult;
|
||||
import de.danoeh.antennapod.core.storage.FeedSearcher;
|
||||
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||
import io.reactivex.Observable;
|
||||
|
@ -47,9 +46,8 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
|
|||
private static final String ARG_FEED = "feed";
|
||||
|
||||
private SearchlistAdapter searchAdapter;
|
||||
private List<SearchResult> searchResults = new ArrayList<>();
|
||||
private List<FeedComponent> searchResults = new ArrayList<>();
|
||||
private Disposable disposable;
|
||||
private ListView listView;
|
||||
private ProgressBar progressBar;
|
||||
private EmptyViewHandler emptyViewHandler;
|
||||
|
||||
|
@ -57,7 +55,9 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
|
|||
* Create a new SearchFragment that searches all feeds.
|
||||
*/
|
||||
public static SearchFragment newInstance(String query) {
|
||||
if (query == null) query = "";
|
||||
if (query == null) {
|
||||
query = "";
|
||||
}
|
||||
SearchFragment fragment = new SearchFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_QUERY, query);
|
||||
|
@ -103,7 +103,7 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
|
|||
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(R.string.search_label);
|
||||
|
||||
View layout = inflater.inflate(R.layout.search_fragment, container, false);
|
||||
listView = layout.findViewById(R.id.listview);
|
||||
ListView listView = layout.findViewById(R.id.listview);
|
||||
progressBar = layout.findViewById(R.id.progressBar);
|
||||
searchAdapter = new SearchlistAdapter(getActivity(), itemAccess);
|
||||
listView.setAdapter(searchAdapter);
|
||||
|
@ -125,15 +125,12 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
|
|||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
SearchResult result = (SearchResult) listView.getAdapter().getItem(position);
|
||||
FeedComponent comp = result.getComponent();
|
||||
FeedComponent comp = searchAdapter.getItem(position);
|
||||
if (comp.getClass() == Feed.class) {
|
||||
((MainActivity) getActivity()).loadFeedFragmentById(comp.getId(), null);
|
||||
} else {
|
||||
if (comp.getClass() == FeedItem.class) {
|
||||
FeedItem item = (FeedItem) comp;
|
||||
((MainActivity) getActivity()).loadChildFragment(ItemPagerFragment.newInstance(item.getId()));
|
||||
}
|
||||
} else if (comp.getClass() == FeedItem.class) {
|
||||
FeedItem item = (FeedItem) comp;
|
||||
((MainActivity) getActivity()).loadChildFragment(ItemPagerFragment.newInstance(item.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,7 +140,7 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
|
|||
MenuItem item = menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label);
|
||||
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
|
||||
final SearchView sv = new SearchView(getActivity());
|
||||
sv.setQueryHint(getString(R.string.search_hint));
|
||||
sv.setQueryHint(getString(R.string.search_label));
|
||||
sv.setQuery(getArguments().getString(ARG_QUERY), false);
|
||||
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
|
@ -167,7 +164,7 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
|
|||
search();
|
||||
}
|
||||
|
||||
private void onSearchResults(List<SearchResult> results) {
|
||||
private void onSearchResults(List<FeedComponent> results) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
searchResults = results;
|
||||
searchAdapter.notifyDataSetChanged();
|
||||
|
@ -182,7 +179,7 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
|
|||
}
|
||||
|
||||
@Override
|
||||
public SearchResult getItem(int position) {
|
||||
public FeedComponent getItem(int position) {
|
||||
if (0 <= position && position < searchResults.size()) {
|
||||
return searchResults.get(position);
|
||||
} else {
|
||||
|
@ -204,7 +201,7 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
|
|||
}
|
||||
|
||||
@NonNull
|
||||
private List<SearchResult> performSearch() {
|
||||
private List<FeedComponent> performSearch() {
|
||||
Bundle args = getArguments();
|
||||
String query = args.getString(ARG_QUERY);
|
||||
long feed = args.getLong(ARG_FEED);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:hint="@string/search_hint"
|
||||
android:hint="@string/search_label"
|
||||
android:label="@string/app_name"/>
|
|
@ -1,22 +0,0 @@
|
|||
package de.danoeh.antennapod.core.feed;
|
||||
|
||||
import de.danoeh.antennapod.core.storage.SearchLocation;
|
||||
|
||||
public class SearchResult {
|
||||
private final FeedComponent component;
|
||||
private SearchLocation location;
|
||||
|
||||
public SearchResult(FeedComponent component, SearchLocation location) {
|
||||
super();
|
||||
this.component = component;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public FeedComponent getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
public SearchLocation getLocation() {
|
||||
return location;
|
||||
}
|
||||
}
|
|
@ -54,10 +54,10 @@ import de.danoeh.antennapod.core.event.settings.SpeedPresetChangedEvent;
|
|||
import de.danoeh.antennapod.core.event.settings.VolumeAdaptionChangedEvent;
|
||||
import de.danoeh.antennapod.core.feed.Chapter;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedComponent;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.feed.MediaType;
|
||||
import de.danoeh.antennapod.core.feed.SearchResult;
|
||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
|
||||
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
|
||||
|
@ -1634,16 +1634,17 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
|||
public void onPlayFromSearch(String query, Bundle extras) {
|
||||
Log.d(TAG, "onPlayFromSearch query=" + query + " extras=" + extras.toString());
|
||||
|
||||
List<SearchResult> results = FeedSearcher.performSearch(getBaseContext(), query, 0);
|
||||
for (SearchResult result : results) {
|
||||
try {
|
||||
FeedMedia p = ((FeedItem) (result.getComponent())).getMedia();
|
||||
mediaPlayer.playMediaObject(p, !p.localFileAvailable(), true, true);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, e.getMessage());
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
List<FeedComponent> results = FeedSearcher.performSearch(getBaseContext(), query, 0);
|
||||
for (FeedComponent result : results) {
|
||||
if (result instanceof FeedItem) {
|
||||
try {
|
||||
FeedMedia media = ((FeedItem) result).getMedia();
|
||||
mediaPlayer.playMediaObject(media, !media.localFileAvailable(), true, true);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
onPlay();
|
||||
|
|
|
@ -553,6 +553,23 @@ public final class DBTasks {
|
|||
});
|
||||
}
|
||||
|
||||
public static FutureTask<List<Feed>> searchFeeds(final Context context, final String query) {
|
||||
return new FutureTask<>(new QueryTask<List<Feed>>(context) {
|
||||
@Override
|
||||
public void execute(PodDBAdapter adapter) {
|
||||
Cursor cursor = adapter.searchFeeds(query);
|
||||
List<Feed> items = new ArrayList<>();
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
items.add(Feed.fromCursor(cursor));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
setResult(items);
|
||||
cursor.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A runnable which should be used for database queries. The onCompletion
|
||||
* method is executed on the database executor to handle Cursors correctly.
|
||||
|
|
|
@ -2,21 +2,15 @@ package de.danoeh.antennapod.core.storage;
|
|||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedComponent;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Chapter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
import de.danoeh.antennapod.core.R;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.SearchResult;
|
||||
import de.danoeh.antennapod.core.util.comparator.InReverseChronologicalOrder;
|
||||
|
||||
/**
|
||||
* Performs search on Feeds and FeedItems.
|
||||
*/
|
||||
|
@ -37,48 +31,19 @@ public class FeedSearcher {
|
|||
* @return list of episodes containing the query
|
||||
*/
|
||||
@NonNull
|
||||
public static List<SearchResult> performSearch(final Context context, final String query, final long selectedFeed) {
|
||||
final List<SearchResult> result = new ArrayList<>();
|
||||
public static List<FeedComponent> performSearch(final Context context, final String query, final long selectedFeed) {
|
||||
final List<FeedComponent> result = new ArrayList<>();
|
||||
try {
|
||||
FutureTask<List<FeedItem>> searchTask = DBTasks.searchFeedItems(context, selectedFeed, query);
|
||||
searchTask.run();
|
||||
final List<FeedItem> items = searchTask.get();
|
||||
for (FeedItem item : items) {
|
||||
SearchLocation location;
|
||||
if (safeContains(item.getTitle(), query)) {
|
||||
location = SearchLocation.TITLE;
|
||||
} else if (safeContains(item.getContentEncoded(), query)) {
|
||||
location = SearchLocation.SHOWNOTES;
|
||||
} else if (safeContains(item.getDescription(), query)) {
|
||||
location = SearchLocation.SHOWNOTES;
|
||||
} else if (safeContains(item.getChapters(), query)) {
|
||||
location = SearchLocation.CHAPTERS;
|
||||
} else if (safeContains(item.getFeed().getAuthor(), query)) {
|
||||
location = SearchLocation.AUTHORS;
|
||||
} else {
|
||||
location = SearchLocation.FEED;
|
||||
}
|
||||
result.add(new SearchResult(item, location));
|
||||
}
|
||||
FutureTask<List<FeedItem>> itemSearchTask = DBTasks.searchFeedItems(context, selectedFeed, query);
|
||||
FutureTask<List<Feed>> feedSearchTask = DBTasks.searchFeeds(context, query);
|
||||
itemSearchTask.run();
|
||||
feedSearchTask.run();
|
||||
|
||||
result.addAll(feedSearchTask.get());
|
||||
result.addAll(itemSearchTask.get());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean safeContains(String haystack, String needle) {
|
||||
return haystack != null && haystack.contains(needle);
|
||||
}
|
||||
|
||||
private static boolean safeContains(List<Chapter> haystack, String needle) {
|
||||
if (haystack == null) {
|
||||
return false;
|
||||
}
|
||||
for (Chapter chapter : haystack) {
|
||||
if (safeContains(chapter.getTitle(), needle)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -285,10 +285,13 @@ public class PodDBAdapter {
|
|||
* Contains FEEDITEM_SEL_FI_SMALL as comma-separated list. Useful for raw queries.
|
||||
*/
|
||||
private static final String SEL_FI_SMALL_STR;
|
||||
private static final String FEED_SEL_STD_STR;
|
||||
|
||||
static {
|
||||
String selFiSmall = Arrays.toString(FEEDITEM_SEL_FI_SMALL);
|
||||
SEL_FI_SMALL_STR = selFiSmall.substring(1, selFiSmall.length() - 1);
|
||||
String selFeedSmall = Arrays.toString(FEED_SEL_STD);
|
||||
FEED_SEL_STD_STR = selFeedSmall.substring(1, selFeedSmall.length() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1275,21 +1278,29 @@ public class PodDBAdapter {
|
|||
}
|
||||
|
||||
String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS
|
||||
+ " LEFT JOIN " + TABLE_NAME_SIMPLECHAPTERS
|
||||
+ " ON " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_FEEDITEM
|
||||
+ "=" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID
|
||||
+ " LEFT JOIN " + TABLE_NAME_FEEDS
|
||||
+ " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED
|
||||
+ "=" + TABLE_NAME_FEEDS + "." + KEY_ID
|
||||
+ " WHERE " + queryFeedId + " AND ("
|
||||
+ TABLE_NAME_FEED_ITEMS + "." + KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' OR "
|
||||
+ TABLE_NAME_FEED_ITEMS + "." + KEY_CONTENT_ENCODED + " LIKE '%" + preparedQuery + "%' OR "
|
||||
+ TABLE_NAME_FEED_ITEMS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR "
|
||||
+ TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR "
|
||||
+ TABLE_NAME_FEEDS + "." + KEY_AUTHOR + " LIKE '%" + preparedQuery + "%' OR "
|
||||
+ TABLE_NAME_FEEDS + "." + KEY_FEED_IDENTIFIER + " LIKE '%" + preparedQuery + "%'"
|
||||
+ KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' OR "
|
||||
+ KEY_CONTENT_ENCODED + " LIKE '%" + preparedQuery + "%' OR "
|
||||
+ KEY_TITLE + " LIKE '%" + preparedQuery + "%'"
|
||||
+ ") ORDER BY " + KEY_PUBDATE + " DESC "
|
||||
+ "LIMIT 500";
|
||||
+ "LIMIT 300";
|
||||
return db.rawQuery(query, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for the given query in various values of all feeds.
|
||||
*
|
||||
* @return A cursor with all search results in SEL_FI_EXTRA selection.
|
||||
*/
|
||||
public Cursor searchFeeds(String searchQuery) {
|
||||
String preparedQuery = prepareSearchQuery(searchQuery);
|
||||
String query = "SELECT " + FEED_SEL_STD_STR + " FROM " + TABLE_NAME_FEEDS + " WHERE "
|
||||
+ KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR "
|
||||
+ KEY_CUSTOM_TITLE + " LIKE '%" + preparedQuery + "%' OR "
|
||||
+ KEY_AUTHOR + " LIKE '%" + preparedQuery + "%' OR "
|
||||
+ KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' "
|
||||
+ "ORDER BY " + KEY_TITLE + " ASC "
|
||||
+ "LIMIT 300";
|
||||
return db.rawQuery(query, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import de.danoeh.antennapod.core.R;
|
||||
|
||||
public enum SearchLocation {
|
||||
TITLE(R.string.found_in_title_label),
|
||||
CHAPTERS(R.string.found_in_chapters_label),
|
||||
SHOWNOTES(R.string.found_in_shownotes_label),
|
||||
AUTHORS(R.string.found_in_authors_label),
|
||||
FEED(R.string.found_in_feeds_label);
|
||||
|
||||
private int description;
|
||||
SearchLocation(@StringRes int description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public @StringRes int getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package de.danoeh.antennapod.core.util.comparator;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.SearchResult;
|
||||
|
||||
public class InReverseChronologicalOrder implements Comparator<SearchResult> {
|
||||
/**
|
||||
* Compare items and sort it on chronological order.
|
||||
*/
|
||||
@Override
|
||||
public int compare(SearchResult o1, SearchResult o2) {
|
||||
if ((o1.getComponent() instanceof FeedItem) && (o2.getComponent() instanceof FeedItem)) {
|
||||
FeedItem item1 = (FeedItem) o1.getComponent();
|
||||
FeedItem item2 = (FeedItem) o2.getComponent();
|
||||
return item2.getPubDate().compareTo(item1.getPubDate());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -536,14 +536,8 @@
|
|||
<string name="licenses_summary">AntennaPod uses other great software</string>
|
||||
|
||||
<!-- Search -->
|
||||
<string name="search_hint">Search for episodes</string>
|
||||
<string name="found_in_shownotes_label">Found in show notes</string>
|
||||
<string name="found_in_chapters_label">Found in chapters</string>
|
||||
<string name="found_in_authors_label">Found in author(s)</string>
|
||||
<string name="found_in_feeds_label">Found in podcast</string>
|
||||
<string name="search_status_no_results">No results were found</string>
|
||||
<string name="search_label">Search</string>
|
||||
<string name="found_in_title_label">Found in title</string>
|
||||
<string name="no_results_for_query">No results were found for \"%1$s\"</string>
|
||||
|
||||
<!-- import and export -->
|
||||
|
|
Loading…
Reference in New Issue