diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhClient.java b/app/src/main/java/com/hippo/ehviewer/client/EhClient.java index 327ca93c3..2e628359e 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhClient.java +++ b/app/src/main/java/com/hippo/ehviewer/client/EhClient.java @@ -51,6 +51,8 @@ public class EhClient { public static final int METHOD_IMAGE_SEARCH = 16; public static final int METHOD_ARCHIVE_LIST = 17; public static final int METHOD_DOWNLOAD_ARCHIVE = 18; + public static final int METHOD_GET_SUGGESTION = 19; + public static final int METHOD_GET_SUGGESTION_DETAIL = 20; private final ThreadPoolExecutor mRequestThreadPool; private final OkHttpClient mOkHttpClient; @@ -171,6 +173,10 @@ protected Object doInBackground(Object... params) { return EhEngine.getArchiveList(this, mOkHttpClient, (String) params[0], (Long) params[1], (String) params[2]); case METHOD_DOWNLOAD_ARCHIVE: return EhEngine.downloadArchive(this, mOkHttpClient, (Long) params[0], (String) params[1], (String) params[2], (String) params[3]); + case METHOD_GET_SUGGESTION: + return EhEngine.getSuggestion(this,mOkHttpClient,(String)params[0]); + case METHOD_GET_SUGGESTION_DETAIL: + return EhEngine.getSuggestionDetail(this,mOkHttpClient,(String)params[0]); default: return new IllegalStateException("Can't detect method " + mMethod); } diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhEngine.java b/app/src/main/java/com/hippo/ehviewer/client/EhEngine.java index 8e9728ce9..381c1b0d2 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhEngine.java +++ b/app/src/main/java/com/hippo/ehviewer/client/EhEngine.java @@ -44,6 +44,7 @@ import com.hippo.ehviewer.client.parser.ProfileParser; import com.hippo.ehviewer.client.parser.RateGalleryParser; import com.hippo.ehviewer.client.parser.SignInParser; +import com.hippo.ehviewer.client.parser.SuggestionParser; import com.hippo.ehviewer.client.parser.TorrentParser; import com.hippo.ehviewer.client.parser.VoteCommentParser; import com.hippo.network.StatusCodeException; @@ -986,4 +987,36 @@ public static GalleryPageApiParser.Result getGalleryPageApi(@Nullable EhClient.T throw e; } } + + public static SuggestionParser.Result[] getSuggestion(@Nullable EhClient.Task task, + OkHttpClient okHttpClient, String keyword) throws Throwable { + String url = "https://zh.moegirl.org/api.php?action=opensearch&search=" + keyword; + String referer = "https://zh.moegirl.org/"; + Request request = new EhRequestBuilder(url, referer) + .build(); + Call call = okHttpClient.newCall(request); + + try { + Response response = call.execute(); + return SuggestionParser.parse(response.body().string()); + } catch (Throwable e) { + Log.e(TAG, "error to get suggestion",e); + return new SuggestionParser.Result[]{}; + } + } + + public static String[] getSuggestionDetail(@Nullable EhClient.Task task, + OkHttpClient okHttpClient, String url) throws Throwable { + String referer = "https://zh.moegirl.org/"; + Request request = new EhRequestBuilder(url, referer) + .build(); + Call call = okHttpClient.newCall(request); + try { + Response response = call.execute(); + return SuggestionParser.parseDetail(response.body().string()); + } catch (Throwable e) { + Log.e(TAG, "error to get suggestion",e); + return new String[]{}; + } + } } diff --git a/app/src/main/java/com/hippo/ehviewer/client/parser/SuggestionParser.java b/app/src/main/java/com/hippo/ehviewer/client/parser/SuggestionParser.java new file mode 100644 index 000000000..36fe6ea13 --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/client/parser/SuggestionParser.java @@ -0,0 +1,54 @@ +package com.hippo.ehviewer.client.parser; + +import org.json.JSONArray; +import org.json.JSONException; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + +import java.util.ArrayList; +import java.util.List; + +public class SuggestionParser { + + public static class Result { + public String keyword; + public String url; + + Result(String keyword, String url) { + this.keyword = keyword; + this.url = url; + } + } + + public static Result[] parse(String body) throws JSONException { + + List result = new ArrayList<>(); + + JSONArray jo = new JSONArray(body); + JSONArray words = jo.getJSONArray(1); + JSONArray links = jo.getJSONArray(3); + + for (int i = 0; i < words.length(); i++) { + String keyword = words.getString(i); + String link = links.getString(i); + result.add(new Result(keyword, link)); + } + + return result.toArray(new Result[0]); + } + + public static String[] parseDetail(String body) { + Document doc = Jsoup.parse(body); + Element e = doc.selectFirst("tr:contains(姓名)"); + // e.select("span[lang=ja]"); + // e.select("span[lang=ja]"); + Element nameObject = e.select("span[itemprop=name]").first(); + nameObject.select("ruby").remove(); + String name = nameObject.text(); + String nameEn = name.replaceAll("[()()]", "").replace((char) 12288, ' ').trim(); + + return new String[]{nameEn}; + } + +} diff --git a/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java b/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java index 4331734bb..9be3b927d 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java @@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; +import android.os.Handler; import android.os.Parcelable; import android.text.Editable; import android.text.TextUtils; @@ -42,7 +43,15 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.cardview.widget.CardView; + +import com.hippo.ehviewer.EhApplication; import com.hippo.ehviewer.R; +import com.hippo.ehviewer.client.EhClient; +import com.hippo.ehviewer.client.EhRequest; +import com.hippo.ehviewer.client.parser.SuggestionParser; +import com.hippo.ehviewer.ui.scene.EhCallback; +import com.hippo.ehviewer.ui.scene.GalleryListScene; +import com.hippo.scene.SceneFragment; import com.hippo.view.ViewTransition; import com.hippo.yorozuya.AnimationUtils; import com.hippo.yorozuya.MathUtils; @@ -93,6 +102,8 @@ public class SearchBar extends CardView implements View.OnClickListener, private boolean mAllowEmptySearch = true; private boolean mInAnimation; + private Handler mLoadSuggestionHandler; + private LoadSuggestionTask mLoadSuggestionTask; public SearchBar(Context context) { super(context); @@ -151,6 +162,8 @@ public boolean onItemLongClick(AdapterView parent, View view, int position, l return true; } }); + + mLoadSuggestionHandler = new Handler(); } private void addListHeader() { @@ -192,6 +205,13 @@ private void updateSuggestions(boolean scrollToTop) { if (scrollToTop) { mListView.setSelection(0); } + + + if(mLoadSuggestionTask != null) { + mLoadSuggestionHandler.removeCallbacks(mLoadSuggestionTask); + } + mLoadSuggestionTask = new LoadSuggestionTask(text); + mLoadSuggestionHandler.postDelayed(mLoadSuggestionTask,500); } public void setAllowEmptySearch(boolean allowEmptySearch) { @@ -563,11 +583,17 @@ public abstract static class Suggestion { public class KeywordSuggestion extends Suggestion { private String mKeyword; + private String mUrl; private KeywordSuggestion(String keyword) { mKeyword = keyword; } + public KeywordSuggestion(String keyword,String url) { + mKeyword = keyword; + mUrl = url; + } + @Override public CharSequence getText(float textSize) { return mKeyword; @@ -577,6 +603,10 @@ public CharSequence getText(float textSize) { public void onClick() { mEditText.setText(mKeyword); mEditText.setSelection(mEditText.getText().length()); + + if(mUrl != null) { + loadSuggestionsFromNetwork(mKeyword,mUrl); + } } @Override @@ -585,4 +615,97 @@ public void onLongClick() { updateSuggestions(false); } } + + public void loadSuggestionsFromNetwork(String keyword) { + if (TextUtils.isEmpty(keyword)) { + return; + } + + EhRequest request = new EhRequest(); + request.setMethod(EhClient.METHOD_GET_SUGGESTION); + request.setCallback(new EhCallback( + getContext(), + getState(), (String) getTag() + ) { + + @Override + public void onSuccess(SuggestionParser.Result[] result) { + if (mSuggestionList != null) { + for (SuggestionParser.Result item : result) + mSuggestionList.add(0, new KeywordSuggestion(item.keyword, item.url)); + } + mSuggestionAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(Exception e) { + + } + + @Override + public void onCancel() { + + } + + @Override + public boolean isInstance(SceneFragment scene) { + return scene instanceof GalleryListScene; + } + }); + request.setArgs(keyword); + EhApplication.getEhClient(getContext()).execute(request); + } + + public void loadSuggestionsFromNetwork(String keyword, String url) { + if (TextUtils.isEmpty(keyword) || TextUtils.isEmpty(url)) { + return; + } + + EhRequest request = new EhRequest(); + request.setMethod(EhClient.METHOD_GET_SUGGESTION_DETAIL); + request.setCallback(new EhCallback( + getContext(), + getState(), (String) getTag() + ) { + + @Override + public void onSuccess(String[] result) { + if (mSuggestionList != null) { + for (String keyword : result) + mSuggestionList.add(0, new KeywordSuggestion(keyword)); + } + mSuggestionAdapter.notifyDataSetChanged(); + } + + @Override + public void onFailure(Exception e) { + + } + + @Override + public void onCancel() { + + } + + @Override + public boolean isInstance(SceneFragment scene) { + return scene instanceof GalleryListScene; + } + }); + request.setArgs(url); + EhApplication.getEhClient(getContext()).execute(request); + } + + public class LoadSuggestionTask implements Runnable { + private String keyword; + + public LoadSuggestionTask(String keyword) { + this.keyword = keyword; + } + + @Override + public void run() { + loadSuggestionsFromNetwork(keyword); + } + } }