Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
4fa8e62fbc
11 changed files with 399 additions and 79 deletions
|
@ -21,10 +21,23 @@ body {
|
||||||
|
|
||||||
.title-image {
|
.title-image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 20%;
|
height: 30%;
|
||||||
background: center;
|
background: center;
|
||||||
background-size: 100%;
|
background-size: 100%;
|
||||||
|
background-size:cover;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3em;
|
||||||
|
color: #212121;
|
||||||
|
font-family: serif;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
word-wrap: break-word;
|
||||||
|
padding-top: 5%;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
|
@ -33,7 +46,8 @@ h2 {
|
||||||
font-family: serif;
|
font-family: serif;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
padding-top: 5%;
|
margin-top: 3%;
|
||||||
|
margin-bottom: 3%;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
|
@ -41,21 +55,23 @@ h3 {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
padding-top: 5%;
|
margin-top: 3%;
|
||||||
|
margin-bottom: 3%;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
line-height: 1.6em;
|
line-height: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
/* font-size: 1.1em; */
|
/* font-size: 1.1em; */
|
||||||
line-height: 1.6em;
|
|
||||||
padding-top: 3%;
|
|
||||||
padding-bottom: 3%;
|
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
|
line-height: 1.6em;
|
||||||
|
margin-left: 5%;
|
||||||
|
padding: 0%;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
@ -64,6 +80,17 @@ li {
|
||||||
padding-bottom: 1%;
|
padding-bottom: 1%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.toc {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mw-headline {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 1.1em;
|
||||||
|
line-height: 1.6em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="oval">
|
||||||
|
<solid android:color="@color/color_transparent"/>
|
||||||
|
<size
|
||||||
|
android:width="28dp"
|
||||||
|
android:height="28dp"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item
|
||||||
|
android:id="@+id/placeholder_icon"
|
||||||
|
android:bottom="2dp"
|
||||||
|
android:left="2dp"
|
||||||
|
android:right="2dp"
|
||||||
|
android:top="2dp">
|
||||||
|
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@drawable/ic_action_history"
|
||||||
|
android:tint="@color/icon_color"/>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
>
|
|
||||||
<item>
|
<item>
|
||||||
<shape android:shape="oval">
|
<shape android:shape="oval">
|
||||||
<solid android:color="@color/color_transparent"/>
|
<solid android:color="@color/color_transparent"/>
|
||||||
|
|
|
@ -22,6 +22,7 @@ import net.osmand.AndroidUtils;
|
||||||
import net.osmand.IndexConstants;
|
import net.osmand.IndexConstants;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.wikivoyage.data.WikivoyageArticle;
|
import net.osmand.plus.wikivoyage.data.WikivoyageArticle;
|
||||||
|
import net.osmand.plus.wikivoyage.data.WikivoyageLocalDataHelper;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -40,7 +41,7 @@ public class WikivoyageArticleDialogFragment extends WikivoyageBaseDialogFragmen
|
||||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n" +
|
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n" +
|
||||||
"<meta http-equiv=\"cleartype\" content=\"on\" />\n" +
|
"<meta http-equiv=\"cleartype\" content=\"on\" />\n" +
|
||||||
"<link href=\"article_style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n" +
|
"<link href=\"article_style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n" +
|
||||||
"</head><body>";
|
"</head><body>\n";
|
||||||
private static final String FOOTER_INNER = "</div></body></html>";
|
private static final String FOOTER_INNER = "</div></body></html>";
|
||||||
|
|
||||||
private long cityId = NO_VALUE;
|
private long cityId = NO_VALUE;
|
||||||
|
@ -146,6 +147,8 @@ public class WikivoyageArticleDialogFragment extends WikivoyageBaseDialogFragmen
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WikivoyageLocalDataHelper.getInstance(getMyApplication()).addToHistory(article);
|
||||||
|
|
||||||
contentWebView.loadDataWithBaseURL(getBaseUrl(), createHtmlContent(article), "text/html", "UTF-8", null);
|
contentWebView.loadDataWithBaseURL(getBaseUrl(), createHtmlContent(article), "text/html", "UTF-8", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +158,8 @@ public class WikivoyageArticleDialogFragment extends WikivoyageBaseDialogFragmen
|
||||||
|
|
||||||
String articleTitle = article.getImageTitle();
|
String articleTitle = article.getImageTitle();
|
||||||
if (!TextUtils.isEmpty(articleTitle)) {
|
if (!TextUtils.isEmpty(articleTitle)) {
|
||||||
String url = WikivoyageArticle.getImageUrl(articleTitle);
|
String url = WikivoyageArticle.getImageUrl(articleTitle, false);
|
||||||
sb.append("<img class=\"title-image\" src=\"").append(url).append("\"/>");
|
sb.append("<div class=\"title-image\" style=\"background-image: url(").append(url).append(")\"></div>");
|
||||||
}
|
}
|
||||||
sb.append("<div class=\"main\">\n");
|
sb.append("<div class=\"main\">\n");
|
||||||
sb.append("<h1>").append(article.getTitle()).append("</h1>");
|
sb.append("<h1>").append(article.getTitle()).append("</h1>");
|
||||||
|
|
|
@ -12,6 +12,7 @@ public class WikivoyageArticle {
|
||||||
|
|
||||||
private static final String IMAGE_ROOT_URL = "https://upload.wikimedia.org/wikipedia/commons/";
|
private static final String IMAGE_ROOT_URL = "https://upload.wikimedia.org/wikipedia/commons/";
|
||||||
private static final String THUMB_PREFIX = "320px-";
|
private static final String THUMB_PREFIX = "320px-";
|
||||||
|
private static final String REGULAR_PREFIX = "800px-";
|
||||||
|
|
||||||
String id;
|
String id;
|
||||||
String title;
|
String title;
|
||||||
|
@ -75,15 +76,10 @@ public class WikivoyageArticle {
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static String getThumbImageUrl(@NonNull String imageTitle) {
|
public static String getImageUrl(@NonNull String imageTitle, boolean thumbnail) {
|
||||||
String[] hash = getHash(imageTitle);
|
String[] hash = getHash(imageTitle);
|
||||||
return IMAGE_ROOT_URL + "thumb/" + hash[0] + "/" + hash[1] + "/" + imageTitle + "/" + THUMB_PREFIX + imageTitle;
|
String prefix = thumbnail ? THUMB_PREFIX : REGULAR_PREFIX;
|
||||||
}
|
return IMAGE_ROOT_URL + "thumb/" + hash[0] + "/" + hash[1] + "/" + imageTitle + "/" + prefix + imageTitle;
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static String getImageUrl(@NonNull String imageTitle) {
|
|
||||||
String[] hash = getHash(imageTitle);
|
|
||||||
return IMAGE_ROOT_URL + hash[0] + "/" + hash[1] + "/" + imageTitle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Size(2)
|
@Size(2)
|
||||||
|
|
|
@ -62,22 +62,6 @@ public class WikivoyageDbHelper {
|
||||||
private static final String SEARCH_COL_ARTICLE_TITLE = "article_title";
|
private static final String SEARCH_COL_ARTICLE_TITLE = "article_title";
|
||||||
private static final String SEARCH_COL_LANG = "lang";
|
private static final String SEARCH_COL_LANG = "lang";
|
||||||
|
|
||||||
private static final String SEARCH_QUERY = "SELECT " +
|
|
||||||
SEARCH_COL_SEARCH_TERM + ", " +
|
|
||||||
SEARCH_TABLE_NAME + "." + SEARCH_COL_CITY_ID + ", " +
|
|
||||||
SEARCH_COL_ARTICLE_TITLE + ", " +
|
|
||||||
SEARCH_TABLE_NAME + "." + SEARCH_COL_LANG + ", " +
|
|
||||||
ARTICLES_COL_IS_PART_OF + ", " +
|
|
||||||
ARTICLES_COL_IMAGE_TITLE +
|
|
||||||
" FROM " + SEARCH_TABLE_NAME +
|
|
||||||
" JOIN " + ARTICLES_TABLE_NAME +
|
|
||||||
" ON " + SEARCH_TABLE_NAME + "." + SEARCH_COL_ARTICLE_TITLE + " = " + ARTICLES_TABLE_NAME + "." + ARTICLES_COL_TITLE +
|
|
||||||
" AND " + SEARCH_TABLE_NAME + "." + SEARCH_COL_LANG + " = " + ARTICLES_TABLE_NAME + "." + ARTICLES_COL_LANG +
|
|
||||||
" WHERE " + SEARCH_TABLE_NAME + "." + SEARCH_COL_CITY_ID +
|
|
||||||
" IN (SELECT " + SEARCH_TABLE_NAME + "." + SEARCH_COL_CITY_ID +
|
|
||||||
" FROM " + SEARCH_TABLE_NAME +
|
|
||||||
" WHERE " + SEARCH_COL_SEARCH_TERM + " LIKE ?)";
|
|
||||||
|
|
||||||
private final OsmandApplication application;
|
private final OsmandApplication application;
|
||||||
|
|
||||||
private Collator collator;
|
private Collator collator;
|
||||||
|
@ -91,20 +75,54 @@ public class WikivoyageDbHelper {
|
||||||
public List<WikivoyageSearchResult> search(final String searchQuery) {
|
public List<WikivoyageSearchResult> search(final String searchQuery) {
|
||||||
List<WikivoyageSearchResult> res = new ArrayList<>();
|
List<WikivoyageSearchResult> res = new ArrayList<>();
|
||||||
SQLiteConnection conn = openConnection();
|
SQLiteConnection conn = openConnection();
|
||||||
|
String[] queries = searchQuery.replace('_', ' ').replace('/', ' ').split(" ");
|
||||||
if (conn != null) {
|
if (conn != null) {
|
||||||
try {
|
try {
|
||||||
SQLiteCursor cursor = conn.rawQuery(SEARCH_QUERY, new String[]{searchQuery + "%"});
|
List<String> params = new ArrayList<>();
|
||||||
|
String query = "SELECT distinct wa.city_id, wa.title, wa.lang, wa.is_part_of, wa.image_title " +
|
||||||
|
"FROM wikivoyage_articles wa WHERE wa.city_id in " +
|
||||||
|
" (SELECT city_id FROM wikivoyage_search WHERE search_term LIKE";
|
||||||
|
for (String q : queries) {
|
||||||
|
if (q.trim().length() > 0) {
|
||||||
|
if (params.size() > 5) {
|
||||||
|
// don't explode the query search much
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (params.size() > 0) {
|
||||||
|
query += " AND city_id IN (SELECT city_id FROM wikivoyage_search WHERE search_term LIKE ?) ";
|
||||||
|
} else {
|
||||||
|
query += "?";
|
||||||
|
}
|
||||||
|
params.add(q.trim() + "%");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
query += ") ";
|
||||||
|
if (params.size() > 0) {
|
||||||
|
SQLiteCursor cursor = conn.rawQuery(query, params.toArray(new String[params.size()]));
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
res.add(readSearchResult(cursor));
|
WikivoyageSearchResult rs = new WikivoyageSearchResult();
|
||||||
|
rs.cityId = cursor.getLong(0);
|
||||||
|
rs.articleTitles.add(cursor.getString(1));
|
||||||
|
rs.langs.add(cursor.getString(2));
|
||||||
|
rs.isPartOf = cursor.getString(3);
|
||||||
|
rs.imageTitle = cursor.getString(4);
|
||||||
|
res.add(rs);
|
||||||
} while (cursor.moveToNext());
|
} while (cursor.moveToNext());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
conn.close();
|
conn.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<WikivoyageSearchResult> list = new ArrayList<>(groupSearchResultsByCityId(res));
|
List<WikivoyageSearchResult> list = new ArrayList<>(groupSearchResultsByCityId(res));
|
||||||
|
sortSearchResults(searchQuery, list);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sortSearchResults(final String searchQuery, List<WikivoyageSearchResult> list) {
|
||||||
Collections.sort(list, new Comparator<WikivoyageSearchResult>() {
|
Collections.sort(list, new Comparator<WikivoyageSearchResult>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(WikivoyageSearchResult o1, WikivoyageSearchResult o2) {
|
public int compare(WikivoyageSearchResult o1, WikivoyageSearchResult o2) {
|
||||||
|
@ -122,8 +140,6 @@ public class WikivoyageDbHelper {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<WikivoyageSearchResult> groupSearchResultsByCityId(List<WikivoyageSearchResult> res) {
|
private Collection<WikivoyageSearchResult> groupSearchResultsByCityId(List<WikivoyageSearchResult> res) {
|
||||||
|
@ -144,7 +160,6 @@ public class WikivoyageDbHelper {
|
||||||
}
|
}
|
||||||
prev.articleTitles.add(insInd, rs.articleTitles.get(0));
|
prev.articleTitles.add(insInd, rs.articleTitles.get(0));
|
||||||
prev.langs.add(insInd, rs.langs.get(0));
|
prev.langs.add(insInd, rs.langs.get(0));
|
||||||
prev.searchTerms.add(insInd, rs.searchTerms.get(0));
|
|
||||||
} else {
|
} else {
|
||||||
wikivoyage.put(rs.cityId, rs);
|
wikivoyage.put(rs.cityId, rs);
|
||||||
}
|
}
|
||||||
|
@ -179,20 +194,6 @@ public class WikivoyageDbHelper {
|
||||||
return application.getSQLiteAPI().openByAbsolutePath(path, true);
|
return application.getSQLiteAPI().openByAbsolutePath(path, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private WikivoyageSearchResult readSearchResult(SQLiteCursor cursor) {
|
|
||||||
WikivoyageSearchResult res = new WikivoyageSearchResult();
|
|
||||||
|
|
||||||
res.searchTerms.add(cursor.getString(0));
|
|
||||||
res.cityId = cursor.getLong(1);
|
|
||||||
res.articleTitles.add(cursor.getString(2));
|
|
||||||
res.langs.add(cursor.getString(3));
|
|
||||||
res.isPartOf = cursor.getString(4);
|
|
||||||
res.imageTitle = cursor.getString(5);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private WikivoyageArticle readArticle(SQLiteCursor cursor) {
|
private WikivoyageArticle readArticle(SQLiteCursor cursor) {
|
||||||
WikivoyageArticle res = new WikivoyageArticle();
|
WikivoyageArticle res = new WikivoyageArticle();
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
package net.osmand.plus.wikivoyage.data;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.api.SQLiteAPI.SQLiteConnection;
|
||||||
|
import net.osmand.plus.api.SQLiteAPI.SQLiteCursor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import gnu.trove.map.hash.TLongObjectHashMap;
|
||||||
|
|
||||||
|
public class WikivoyageLocalDataHelper {
|
||||||
|
|
||||||
|
private static WikivoyageLocalDataHelper instance;
|
||||||
|
|
||||||
|
private WikivoyageLocalDataDbHelper dbHelper;
|
||||||
|
|
||||||
|
private TLongObjectHashMap<WikivoyageSearchHistoryItem> historyMap;
|
||||||
|
|
||||||
|
private WikivoyageLocalDataHelper(OsmandApplication app) {
|
||||||
|
dbHelper = new WikivoyageLocalDataDbHelper(app);
|
||||||
|
historyMap = dbHelper.getAllHistoryMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WikivoyageLocalDataHelper getInstance(OsmandApplication app) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new WikivoyageLocalDataHelper(app);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<WikivoyageSearchHistoryItem> getAllHistory() {
|
||||||
|
List<WikivoyageSearchHistoryItem> res = new ArrayList<>(historyMap.valueCollection());
|
||||||
|
Collections.sort(res, new Comparator<WikivoyageSearchHistoryItem>() {
|
||||||
|
@Override
|
||||||
|
public int compare(WikivoyageSearchHistoryItem item1, WikivoyageSearchHistoryItem item2) {
|
||||||
|
if (item1.lastAccessed > item2.lastAccessed) {
|
||||||
|
return -1;
|
||||||
|
} else if (item1.lastAccessed == item2.lastAccessed) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addToHistory(WikivoyageArticle article) {
|
||||||
|
addToHistory(article.getCityId(), article.getTitle(), article.getLang(), article.getIsPartOf());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addToHistory(long cityId, String title, String lang, String isPartOf) {
|
||||||
|
WikivoyageSearchHistoryItem item = historyMap.get(cityId);
|
||||||
|
boolean newItem = item == null;
|
||||||
|
if (newItem) {
|
||||||
|
item = new WikivoyageSearchHistoryItem();
|
||||||
|
item.cityId = cityId;
|
||||||
|
}
|
||||||
|
item.articleTitle = title;
|
||||||
|
item.lang = lang;
|
||||||
|
item.isPartOf = isPartOf;
|
||||||
|
item.lastAccessed = System.currentTimeMillis();
|
||||||
|
if (newItem) {
|
||||||
|
dbHelper.addHistoryItem(item);
|
||||||
|
historyMap.put(item.cityId, item);
|
||||||
|
} else {
|
||||||
|
dbHelper.updateHistoryItem(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class WikivoyageLocalDataDbHelper {
|
||||||
|
|
||||||
|
private static final int DB_VERSION = 1;
|
||||||
|
private static final String DB_NAME = "wikivoyage_local_data";
|
||||||
|
|
||||||
|
private static final String HISTORY_TABLE_NAME = "wikivoyage_search_history";
|
||||||
|
private static final String HISTORY_COL_CITY_ID = "city_id";
|
||||||
|
private static final String HISTORY_COL_ARTICLE_TITLE = "article_title";
|
||||||
|
private static final String HISTORY_COL_LANG = "lang";
|
||||||
|
private static final String HISTORY_COL_IS_PART_OF = "is_part_of";
|
||||||
|
private static final String HISTORY_COL_LAST_ACCESSED = "last_accessed";
|
||||||
|
|
||||||
|
private static final String HISTORY_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS " +
|
||||||
|
HISTORY_TABLE_NAME + " (" +
|
||||||
|
HISTORY_COL_CITY_ID + " long, " +
|
||||||
|
HISTORY_COL_ARTICLE_TITLE + " TEXT, " +
|
||||||
|
HISTORY_COL_LANG + " TEXT, " +
|
||||||
|
HISTORY_COL_IS_PART_OF + " TEXT, " +
|
||||||
|
HISTORY_COL_LAST_ACCESSED + " long);";
|
||||||
|
|
||||||
|
private static final String HISTORY_TABLE_SELECT = "SELECT " +
|
||||||
|
HISTORY_COL_CITY_ID + ", " +
|
||||||
|
HISTORY_COL_ARTICLE_TITLE + ", " +
|
||||||
|
HISTORY_COL_LANG + ", " +
|
||||||
|
HISTORY_COL_IS_PART_OF + ", " +
|
||||||
|
HISTORY_COL_LAST_ACCESSED +
|
||||||
|
" FROM " + HISTORY_TABLE_NAME;
|
||||||
|
|
||||||
|
private final OsmandApplication context;
|
||||||
|
|
||||||
|
private WikivoyageLocalDataDbHelper(OsmandApplication context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SQLiteConnection openConnection(boolean readonly) {
|
||||||
|
SQLiteConnection conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, readonly);
|
||||||
|
int version = conn.getVersion();
|
||||||
|
if (version == 0 || DB_VERSION != version) {
|
||||||
|
if (readonly) {
|
||||||
|
conn.close();
|
||||||
|
conn = context.getSQLiteAPI().getOrCreateDatabase(DB_NAME, false);
|
||||||
|
}
|
||||||
|
version = conn.getVersion();
|
||||||
|
conn.setVersion(DB_VERSION);
|
||||||
|
if (version == 0) {
|
||||||
|
onCreate(conn);
|
||||||
|
} else {
|
||||||
|
onUpgrade(conn, version, DB_VERSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onCreate(SQLiteConnection conn) {
|
||||||
|
conn.execSQL(HISTORY_TABLE_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private void onUpgrade(SQLiteConnection conn, int oldVersion, int newVersion) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
TLongObjectHashMap<WikivoyageSearchHistoryItem> getAllHistoryMap() {
|
||||||
|
TLongObjectHashMap<WikivoyageSearchHistoryItem> res = new TLongObjectHashMap<>();
|
||||||
|
SQLiteConnection conn = openConnection(true);
|
||||||
|
if (conn != null) {
|
||||||
|
try {
|
||||||
|
SQLiteCursor cursor = conn.rawQuery(HISTORY_TABLE_SELECT, null);
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
|
do {
|
||||||
|
WikivoyageSearchHistoryItem item = readHistoryItem(cursor);
|
||||||
|
res.put(item.cityId, item);
|
||||||
|
} while (cursor.moveToNext());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addHistoryItem(WikivoyageSearchHistoryItem item) {
|
||||||
|
SQLiteConnection conn = openConnection(false);
|
||||||
|
if (conn != null) {
|
||||||
|
try {
|
||||||
|
conn.execSQL("INSERT INTO " + HISTORY_TABLE_NAME + " VALUES (?, ?, ?, ?, ?)",
|
||||||
|
new Object[]{item.cityId, item.articleTitle, item.lang, item.isPartOf, item.lastAccessed});
|
||||||
|
} finally {
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateHistoryItem(WikivoyageSearchHistoryItem item) {
|
||||||
|
SQLiteConnection conn = openConnection(false);
|
||||||
|
if (conn != null) {
|
||||||
|
try {
|
||||||
|
conn.execSQL("UPDATE " + HISTORY_TABLE_NAME + " SET " +
|
||||||
|
HISTORY_COL_ARTICLE_TITLE + " = ?, " +
|
||||||
|
HISTORY_COL_LANG + " = ?, " +
|
||||||
|
HISTORY_COL_IS_PART_OF + " = ?, " +
|
||||||
|
HISTORY_COL_LAST_ACCESSED + " = ? " +
|
||||||
|
"WHERE " + HISTORY_COL_CITY_ID + " = ?",
|
||||||
|
new Object[]{item.articleTitle, item.lang, item.isPartOf, item.lastAccessed, item.cityId});
|
||||||
|
} finally {
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private WikivoyageSearchHistoryItem readHistoryItem(SQLiteCursor cursor) {
|
||||||
|
WikivoyageSearchHistoryItem res = new WikivoyageSearchHistoryItem();
|
||||||
|
|
||||||
|
res.cityId = cursor.getLong(0);
|
||||||
|
res.articleTitle = cursor.getString(1);
|
||||||
|
res.lang = cursor.getString(2);
|
||||||
|
res.isPartOf = cursor.getString(3);
|
||||||
|
res.lastAccessed = cursor.getLong(4);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package net.osmand.plus.wikivoyage.data;
|
||||||
|
|
||||||
|
public class WikivoyageSearchHistoryItem {
|
||||||
|
|
||||||
|
long cityId;
|
||||||
|
String articleTitle;
|
||||||
|
String lang;
|
||||||
|
String isPartOf;
|
||||||
|
long lastAccessed;
|
||||||
|
|
||||||
|
public long getCityId() {
|
||||||
|
return cityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getArticleTitle() {
|
||||||
|
return articleTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLang() {
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsPartOf() {
|
||||||
|
return isPartOf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastAccessed() {
|
||||||
|
return lastAccessed;
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,17 +9,12 @@ public class WikivoyageSearchResult {
|
||||||
|
|
||||||
private static final int SHOW_LANGS = 3;
|
private static final int SHOW_LANGS = 3;
|
||||||
|
|
||||||
List<String> searchTerms = new ArrayList<>();
|
|
||||||
long cityId;
|
long cityId;
|
||||||
List<String> articleTitles = new ArrayList<>();
|
List<String> articleTitles = new ArrayList<>();
|
||||||
List<String> langs = new ArrayList<>();
|
List<String> langs = new ArrayList<>();
|
||||||
String isPartOf;
|
String isPartOf;
|
||||||
String imageTitle;
|
String imageTitle;
|
||||||
|
|
||||||
public List<String> getSearchTerms() {
|
|
||||||
return searchTerms;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCityId() {
|
public long getCityId() {
|
||||||
return cityId;
|
return cityId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,9 @@ import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.widgets.tools.CropCircleTransformation;
|
import net.osmand.plus.widgets.tools.CropCircleTransformation;
|
||||||
import net.osmand.plus.wikivoyage.data.WikivoyageArticle;
|
import net.osmand.plus.wikivoyage.data.WikivoyageArticle;
|
||||||
|
import net.osmand.plus.wikivoyage.data.WikivoyageSearchHistoryItem;
|
||||||
import net.osmand.plus.wikivoyage.data.WikivoyageSearchResult;
|
import net.osmand.plus.wikivoyage.data.WikivoyageSearchResult;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -29,7 +31,9 @@ public class SearchRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView
|
||||||
private static final int ITEM_TYPE = 1;
|
private static final int ITEM_TYPE = 1;
|
||||||
|
|
||||||
private OsmandApplication app;
|
private OsmandApplication app;
|
||||||
|
|
||||||
private LayerDrawable placeholder;
|
private LayerDrawable placeholder;
|
||||||
|
private LayerDrawable historyPlaceholder;
|
||||||
|
|
||||||
private List<Object> items = new ArrayList<>();
|
private List<Object> items = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -41,11 +45,8 @@ public class SearchRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView
|
||||||
|
|
||||||
SearchRecyclerViewAdapter(OsmandApplication app) {
|
SearchRecyclerViewAdapter(OsmandApplication app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
placeholder = (LayerDrawable) ContextCompat.getDrawable(app, R.drawable.wikivoyage_search_placeholder);
|
placeholder = getPlaceholder(false);
|
||||||
if (Build.VERSION.SDK_INT < 21 && placeholder != null) {
|
historyPlaceholder = getPlaceholder(true);
|
||||||
placeholder.setDrawableByLayerId(R.id.placeholder_icon,
|
|
||||||
app.getIconsCache().getIcon(R.drawable.ic_action_placeholder_city, R.color.icon_color));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -69,15 +70,24 @@ public class SearchRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView
|
||||||
ItemVH holder = (ItemVH) viewHolder;
|
ItemVH holder = (ItemVH) viewHolder;
|
||||||
boolean lastItem = pos == getItemCount() - 1;
|
boolean lastItem = pos == getItemCount() - 1;
|
||||||
|
|
||||||
WikivoyageSearchResult item = (WikivoyageSearchResult) getItem(pos);
|
Object item = getItem(pos);
|
||||||
|
if (item instanceof WikivoyageSearchResult) {
|
||||||
|
WikivoyageSearchResult searchRes = (WikivoyageSearchResult) item;
|
||||||
Picasso.get()
|
Picasso.get()
|
||||||
.load(WikivoyageArticle.getThumbImageUrl(item.getImageTitle()))
|
.load(WikivoyageArticle.getImageUrl(searchRes.getImageTitle(), true))
|
||||||
.transform(new CropCircleTransformation())
|
.transform(new CropCircleTransformation())
|
||||||
.placeholder(placeholder)
|
.placeholder(placeholder)
|
||||||
.into(holder.icon);
|
.into(holder.icon);
|
||||||
holder.title.setText(item.getArticleTitles().get(0));
|
holder.title.setText(searchRes.getArticleTitles().get(0));
|
||||||
holder.leftDescr.setText(item.getIsPartOf());
|
holder.leftDescr.setText(searchRes.getIsPartOf());
|
||||||
holder.rightDescr.setText(item.getFirstLangsString());
|
holder.rightDescr.setText(searchRes.getFirstLangsString());
|
||||||
|
} else {
|
||||||
|
WikivoyageSearchHistoryItem historyItem = (WikivoyageSearchHistoryItem) item;
|
||||||
|
holder.icon.setImageDrawable(historyPlaceholder);
|
||||||
|
holder.title.setText(historyItem.getArticleTitle());
|
||||||
|
holder.leftDescr.setText(historyItem.getIsPartOf());
|
||||||
|
holder.rightDescr.setText(Algorithms.capitalizeFirstLetter(historyItem.getLang()));
|
||||||
|
}
|
||||||
holder.divider.setVisibility(lastItem ? View.GONE : View.VISIBLE);
|
holder.divider.setVisibility(lastItem ? View.GONE : View.VISIBLE);
|
||||||
holder.shadow.setVisibility(lastItem ? View.VISIBLE : View.GONE);
|
holder.shadow.setVisibility(lastItem ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
|
@ -101,6 +111,15 @@ public class SearchRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView
|
||||||
return items.get(pos);
|
return items.get(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHistoryItems(@Nullable List<WikivoyageSearchHistoryItem> historyItems) {
|
||||||
|
this.items.clear();
|
||||||
|
if (historyItems != null && !historyItems.isEmpty()) {
|
||||||
|
this.items.add(app.getString(R.string.shared_string_history));
|
||||||
|
this.items.addAll(historyItems);
|
||||||
|
}
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
public void setItems(@Nullable List<WikivoyageSearchResult> items) {
|
public void setItems(@Nullable List<WikivoyageSearchResult> items) {
|
||||||
this.items.clear();
|
this.items.clear();
|
||||||
if (items != null && !items.isEmpty()) {
|
if (items != null && !items.isEmpty()) {
|
||||||
|
@ -110,6 +129,21 @@ public class SearchRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LayerDrawable getPlaceholder(boolean history) {
|
||||||
|
LayerDrawable res = (LayerDrawable) ContextCompat.getDrawable(
|
||||||
|
app, history
|
||||||
|
? R.drawable.wikivoyage_search_history_placeholder
|
||||||
|
: R.drawable.wikivoyage_search_placeholder
|
||||||
|
);
|
||||||
|
if (Build.VERSION.SDK_INT < 21 && res != null) {
|
||||||
|
res.setDrawableByLayerId(R.id.placeholder_icon, app.getIconsCache().getIcon(
|
||||||
|
history ? R.drawable.ic_action_history : R.drawable.ic_action_placeholder_city,
|
||||||
|
R.color.icon_color
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static class HeaderVH extends RecyclerView.ViewHolder {
|
static class HeaderVH extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
final TextView title;
|
final TextView title;
|
||||||
|
|
|
@ -8,6 +8,7 @@ import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -20,6 +21,7 @@ import net.osmand.ResultMatcher;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.wikivoyage.WikivoyageArticleDialogFragment;
|
import net.osmand.plus.wikivoyage.WikivoyageArticleDialogFragment;
|
||||||
import net.osmand.plus.wikivoyage.WikivoyageBaseDialogFragment;
|
import net.osmand.plus.wikivoyage.WikivoyageBaseDialogFragment;
|
||||||
|
import net.osmand.plus.wikivoyage.data.WikivoyageLocalDataHelper;
|
||||||
import net.osmand.plus.wikivoyage.data.WikivoyageSearchResult;
|
import net.osmand.plus.wikivoyage.data.WikivoyageSearchResult;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -71,7 +73,7 @@ public class WikivoyageSearchDialogFragment extends WikivoyageBaseDialogFragment
|
||||||
searchQuery = newQuery;
|
searchQuery = newQuery;
|
||||||
if (searchQuery.isEmpty()) {
|
if (searchQuery.isEmpty()) {
|
||||||
cancelSearch();
|
cancelSearch();
|
||||||
adapter.setItems(null);
|
setAdapterItems(null);
|
||||||
} else {
|
} else {
|
||||||
runSearch();
|
runSearch();
|
||||||
}
|
}
|
||||||
|
@ -117,6 +119,9 @@ public class WikivoyageSearchDialogFragment extends WikivoyageBaseDialogFragment
|
||||||
super.onResume();
|
super.onResume();
|
||||||
paused = false;
|
paused = false;
|
||||||
searchEt.requestFocus();
|
searchEt.requestFocus();
|
||||||
|
if (TextUtils.isEmpty(searchQuery)) {
|
||||||
|
setAdapterItems(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -132,6 +137,15 @@ public class WikivoyageSearchDialogFragment extends WikivoyageBaseDialogFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setAdapterItems(@Nullable List<WikivoyageSearchResult> items) {
|
||||||
|
if (items == null || items.isEmpty()) {
|
||||||
|
adapter.setHistoryItems(WikivoyageLocalDataHelper
|
||||||
|
.getInstance(getMyApplication()).getAllHistory());
|
||||||
|
} else {
|
||||||
|
adapter.setItems(items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void runSearch() {
|
private void runSearch() {
|
||||||
switchProgressBarVisibility(true);
|
switchProgressBarVisibility(true);
|
||||||
cancelled = false;
|
cancelled = false;
|
||||||
|
@ -141,7 +155,7 @@ public class WikivoyageSearchDialogFragment extends WikivoyageBaseDialogFragment
|
||||||
getMyApplication().runInUIThread(new Runnable() {
|
getMyApplication().runInUIThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!isCancelled()) {
|
if (!isCancelled()) {
|
||||||
adapter.setItems(results);
|
setAdapterItems(results);
|
||||||
switchProgressBarVisibility(false);
|
switchProgressBarVisibility(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue