This commit is contained in:
seven332 committed 2015-02-22 23:49:20 +08:00
1 parent 40cfddb348
commit 7375b1ca24
10 files changed
+420 -37

No files matched your search

@@ -16,13 +16,20 @@
package com.hippo.ehviewer.client;
import android.os.AsyncTask;
import android.os.Process;
import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.network.EhHttpHelper;
import com.hippo.network.ResponseCodeException;
import com.hippo.util.Utils;
import com.hippo.util.PriorityThreadFactory;
public class EhClient {
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public final class EhClient {
@SuppressWarnings("unused")
private static final String TAG = EhClient.class.getSimpleName();
@@ -46,33 +53,52 @@ public class EhClient {
public static final String API_EHVIEWER = "http://www.ehviewer.com/API";
private Object[] doGetGalleryList(int source, String url) throws Exception {
EhHttpHelper ehh = new EhHttpHelper();
String body = ehh.get(url);
final int responseCode = ehh.getResponseCode();
if (responseCode >= 400) {
throw new ResponseCodeException(responseCode);
}
private final ThreadPoolExecutor mRequestThreadPool;
ListParser parser = new ListParser();
parser.parse(body, source);
return new Object[]{parser.giArray, parser.pageNum};
private static final EhClient sInstance;
static {
sInstance = new EhClient();
}
public static EhClient getInstance() {
return sInstance;
}
private EhClient() {
int poolSize = 3;
BlockingQueue<Runnable> requestWorkQueue = new LinkedBlockingQueue<>();
ThreadFactory threadFactory = new PriorityThreadFactory(TAG,
Process.THREAD_PRIORITY_BACKGROUND);
mRequestThreadPool = new ThreadPoolExecutor(poolSize, poolSize,
1, TimeUnit.SECONDS, requestWorkQueue, threadFactory);
}
public static String getUrlHeader(int mode) {
switch (mode) {
default:
case SOURCE_G:
return HEADER_G;
case SOURCE_EX:
return HEADER_EX;
case SOURCE_LOFI:
return HEADER_LOFI;
}
}
public static interface EhClientListener {
public void onFailure(Exception e);
}
public abstract static class OnGetGalleryListListener implements EhClientListener {
public abstract void onSuccess(GalleryInfo[] glArray, int pageNum);
}
private void doBgJob(BgJobHelper bjh) {
Utils.execute(false, new AsyncTask<Object, Void, BgJobHelper>() {
new AsyncTask<BgJobHelper, Void, BgJobHelper>() {
@Override
protected BgJobHelper doInBackground(Object... params) {
BgJobHelper bjh = (BgJobHelper) params[0];
protected BgJobHelper doInBackground(BgJobHelper... params) {
BgJobHelper bjh = params[0];
bjh.doInBackground();
return bjh;
}
@@ -81,7 +107,7 @@ public class EhClient {
protected void onPostExecute(BgJobHelper bjh) {
bjh.onPostExecute();
}
}, bjh);
}.executeOnExecutor(mRequestThreadPool, bjh);
}
private interface BgJobHelper {
@@ -89,12 +115,12 @@ public class EhClient {
public void onPostExecute();
}
private abstract class SimpleBgJobHelper implements BgJobHelper {
private EhClientListener mListener;
private Exception mException;
public SimpleBgJobHelper(EhClientListener listener) {
mListener = listener;
}
@@ -124,7 +150,25 @@ public class EhClient {
public abstract void doSuccessCallback();
}
private void checkRequest(EhHttpHelper ehh) throws ResponseCodeException {
final int responseCode = ehh.getResponseCode();
if (responseCode >= 400) {
throw new ResponseCodeException(responseCode);
}
}
private Object[] doGetGalleryList(int source, String url) throws Exception {
EhHttpHelper ehh = new EhHttpHelper();
String body = ehh.get(url);
checkRequest(ehh);
ListParser parser = new ListParser();
parser.parse(body, source);
return new Object[]{parser.giArray, parser.pageNum};
}
private final class GetGalleryListHelper extends SimpleBgJobHelper {
private int mSource;
@@ -133,7 +177,7 @@ public class EhClient {
private GalleryInfo[] mGlArray;
private int mPageNum;
public GetGalleryListHelper(int source, String url, OnGetGalleryListListener listener) {
super(listener);
mSource = source;
@@ -156,7 +200,7 @@ public class EhClient {
/**
* Get gallery list
*
*
* @param source the source, one of {@link #SOURCE_G}, {@link #SOURCE_EX} and
* {@link #SOURCE_LOFI}
* @param url the url to get gallery list
@@ -0,0 +1,196 @@
/*
* Copyright (C) 2014-2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.data;
import com.hippo.ehviewer.client.EhClient;
import com.hippo.ehviewer.util.EhUtils;
import com.hippo.ehviewer.widget.AdvanceSearchTable;
import com.hippo.network.UrlBuilder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class ListUrlBuilder {
// Mode
public static final int MODE_NORMAL = 0x0;
public static final int MODE_UPLOADER = 0x1;
public static final int MODE_TAG = 0x2;
public static final int MODE_POPULAR = 0x3;
public static final int MODE_IMAGE_SEARCH = 0x4;
public static final int ALL_CATEGORT = EhUtils.UNKNOWN - 1;
//DOUJINSHI|MANGA|ARTIST_CG|GAME_CG|WESTERN|NON_H|IMAGE_SET|COSPLAY|ASIAN_PORN|MISC;
public static final int DEFAULT_ADVANCE = AdvanceSearchTable.SNAME | AdvanceSearchTable.STAGS;
public static final int DEFAULT_MIN_RATING = 2;
private int mMode = MODE_NORMAL;
private int mPageIndex = 0;
private int mCategory = EhUtils.NONE;
private String mSearchKey = null;
private int mAdvanceSearch = -1;
private int mMinRating = -1;
private String mSearchTag = null;
public int getMode() {
return mMode;
}
public void setMode(int mode) {
mMode = mode;
}
public int getPageIndex() {
return mPageIndex;
}
public void setPageIndex(int pageIndex) {
mPageIndex = pageIndex;
}
public int getCategory() {
return mCategory;
}
public void setCategory(int category) {
mCategory = category;
}
public String getSearchKey() {
return mSearchKey;
}
public void setSearchKey(String searchKey) {
mSearchKey = searchKey;
}
public int getAdvanceSearch() {
return mAdvanceSearch;
}
public void setAdvanceSearch(int advanceSearch) {
mAdvanceSearch = advanceSearch;
}
public int getMinRating() {
return mMinRating;
}
public void setMinRating(int minRating) {
mMinRating = minRating;
}
public String getSearchTag() {
return mSearchTag;
}
public void setSearchTag(String searchTag) {
mSearchTag = searchTag;
}
/**
* Make them the same
* @param glub The template
*/
public void set(ListUrlBuilder glub) {
mMode = glub.mMode;
mPageIndex = glub.mPageIndex;
mCategory = glub.mCategory;
mSearchKey = glub.mSearchKey;
mAdvanceSearch = glub.mAdvanceSearch;
mMinRating = glub.mMinRating;
mSearchTag = glub.mSearchTag;
}
public String build(int source) throws UnsupportedSearch {
switch (mMode) {
default:
case MODE_NORMAL:
case MODE_UPLOADER: {
boolean filter = false;
UrlBuilder ub = new UrlBuilder(EhClient.getUrlHeader(source));
if (mCategory != EhUtils.NONE) {
ub.addQuery("f_doujinshi", ((mCategory & EhUtils.DOUJINSHI) == 0) ? "0" : "1");
ub.addQuery("f_manga", ((mCategory & EhUtils.MANGA) == 0) ? "0" : "1");
ub.addQuery("f_artistcg", ((mCategory & EhUtils.ARTIST_CG) == 0) ? "0" : "1");
ub.addQuery("f_gamecg", ((mCategory & EhUtils.GAME_CG) == 0) ? "0" : "1");
ub.addQuery("f_western", ((mCategory & EhUtils.WESTERN) == 0) ? "0" : "1");
ub.addQuery("f_non-h", ((mCategory & EhUtils.NON_H) == 0) ? "0" : "1");
ub.addQuery("f_imageset", ((mCategory & EhUtils.IMAGE_SET) == 0) ? "0" : "1");
ub.addQuery("f_cosplay", ((mCategory & EhUtils.COSPLAY) == 0) ? "0" : "1");
ub.addQuery("f_asianporn", ((mCategory & EhUtils.ASIAN_PORN) == 0) ? "0" : "1");
ub.addQuery("f_misc", ((mCategory & EhUtils.MISC) == 0) ? "0" : "1");
filter = true;
}
// Search key
if (mSearchKey != null) {
try {
ub.addQuery("f_search", URLEncoder.encode(mSearchKey, "UTF-8"));
filter = true;
} catch (UnsupportedEncodingException e) {
// Empty
}
}
// Page index
if (mPageIndex != 0) {
ub.addQuery("page", mPageIndex);
}
// Advance search
if (mAdvanceSearch != -1) {
ub.addQuery("advsearch", "1");
if((mAdvanceSearch & AdvanceSearchTable.SNAME) != 0) ub.addQuery("f_sname", "on");
if((mAdvanceSearch & AdvanceSearchTable.STAGS) != 0) ub.addQuery("f_stags", "on");
if((mAdvanceSearch & AdvanceSearchTable.SDESC) != 0) ub.addQuery("f_sdesc", "on");
if((mAdvanceSearch & AdvanceSearchTable.STORR) != 0) ub.addQuery("f_storr", "on");
if((mAdvanceSearch & AdvanceSearchTable.STO) != 0) ub.addQuery("f_sto", "on");
if((mAdvanceSearch & AdvanceSearchTable.SDT1) != 0) ub.addQuery("f_sdt1", "on");
if((mAdvanceSearch & AdvanceSearchTable.SDT2) != 0) ub.addQuery("f_sdt2", "on");
if((mAdvanceSearch & AdvanceSearchTable.SH) != 0) ub.addQuery("f_sh", "on");
// Set min star
if (mMinRating != -1) {
ub.addQuery("f_sr", "on");
ub.addQuery("f_srdd", mMinRating);
}
filter = true;
}
// Add filter foot
if (filter) {
ub.addQuery("f_apply", "Apply+Filter");
}
return ub.build();
}
case MODE_TAG: {
if (source == EhClient.SOURCE_LOFI) {
throw new UnsupportedSearch("Lofi do not support tag search");
}
StringBuilder sb = new StringBuilder(EhClient.getUrlHeader(source));
sb.append("tag/");
try {
sb.append(URLEncoder.encode(mSearchTag, "UTF-8"));
} catch (UnsupportedEncodingException e) {
// Empty
}
return sb.toString();
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2015 Hippo Seven
* Copyright (C) 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +15,9 @@
package com.hippo.ehviewer.data;
public class GalleryListUrlBuilder {
/**
* Make them the same
* @param glub The template
*/
public void set(GalleryListUrlBuilder glub) {
public class UnsupportedSearch extends Exception {
public UnsupportedSearch(String detailMessage) {
super(detailMessage);
}
}
@@ -29,7 +29,7 @@ import android.view.View;
import android.view.ViewGroup;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.GalleryListUrlBuilder;
import com.hippo.ehviewer.data.ListUrlBuilder;
import com.hippo.ehviewer.widget.SearchLayout;
import com.hippo.scene.Scene;
@@ -51,6 +51,10 @@ public class SearchFragment extends Fragment implements SearchLayout.SearhLayout
sScene = scene;
}
public static void setOnSearchListener(OnSearchListener listener) {
sOnSearchListener = listener;
}
@Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
@@ -88,6 +92,13 @@ public class SearchFragment extends Fragment implements SearchLayout.SearhLayout
sScene.startActivityForResult(intent, this);
}
@Override
public void onRequestSearch(ListUrlBuilder lub) {
if (sOnSearchListener != null) {
sOnSearchListener.onRequestSearch(lub);
}
}
@Override
public void onGetResult(int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK && data != null) {
@@ -108,6 +119,6 @@ public class SearchFragment extends Fragment implements SearchLayout.SearhLayout
}
public interface OnSearchListener {
public void onSearch(GalleryListUrlBuilder glub);
public void onRequestSearch(ListUrlBuilder lub);
}
}
@@ -23,7 +23,7 @@ import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.GalleryListUrlBuilder;
import com.hippo.ehviewer.data.ListUrlBuilder;
import com.hippo.ehviewer.ui.fragment.GalleryListFragment;
import com.hippo.ehviewer.ui.fragment.SearchFragment;
import com.hippo.scene.Scene;
@@ -53,6 +53,7 @@ public class GalleryListScene extends Scene implements SearchFragment.OnSearchLi
mAppbar.setTitle(mResources.getString(R.string.app_name));
SearchFragment.setScene(this);
SearchFragment.setOnSearchListener(this);
}
@Override
@@ -70,10 +71,11 @@ public class GalleryListScene extends Scene implements SearchFragment.OnSearchLi
dispatchRemove();
SearchFragment.setScene(null);
SearchFragment.setOnSearchListener(null);
}
@Override
public void onSearch(GalleryListUrlBuilder glub) {
public void onRequestSearch(ListUrlBuilder lub) {
}
@@ -26,6 +26,15 @@ import com.hippo.ehviewer.R;
public class AdvanceSearchTable extends TableLayout {
public static final int SNAME = 0x1;
public static final int STAGS = 0x2;
public static final int SDESC = 0x4;
public static final int STORR = 0x8;
public static final int STO = 0x10;
public static final int SDT1 = 0x20;
public static final int SDT2 = 0x40;
public static final int SH = 0x80;
private CheckBox mSname;
private CheckBox mStags;
private CheckBox mSdesc;
@@ -63,4 +72,25 @@ public class AdvanceSearchTable extends TableLayout {
mMinRating = (Spinner) findViewById(R.id.search_min_rating);
}
public int getAdvanceSearch() {
int advanceSearch = 0;
if (mSname.isChecked()) advanceSearch |= SNAME;
if (mStags.isChecked()) advanceSearch |= STAGS;
if (mSdesc.isChecked()) advanceSearch |= SDESC;
if (mStorr.isChecked()) advanceSearch |= STORR;
if (mSto.isChecked()) advanceSearch |= STO;
if (mSdt1.isChecked()) advanceSearch |= SDT1;
if (mSdt2.isChecked()) advanceSearch |= SDT2;
if (mSh.isChecked()) advanceSearch |= SH;
return advanceSearch;
}
public int getMinRating() {
if (mSr.isChecked()) {
return mMinRating.getSelectedItemPosition() + 2;
} else {
return -1;
}
}
}
@@ -23,6 +23,7 @@ import android.os.Parcelable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SwitchCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.LayoutInflater;
@@ -35,6 +36,7 @@ import android.widget.TextView;
import com.hippo.effect.ripple.RippleSalon;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.ListUrlBuilder;
import com.hippo.util.ViewUtils;
import com.hippo.widget.FloatLabelEditText;
import com.hippo.widget.FloatingActionButton;
@@ -42,6 +44,7 @@ import com.hippo.widget.PrefixEditText;
import com.hippo.widget.recyclerview.EasyRecyclerView;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class SearchLayout extends FrameLayout implements CompoundButton.OnCheckedChangeListener,
View.OnClickListener, SelectSearchImageLayout.SelectSearchImageLayoutHelper {
@@ -104,6 +107,8 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke
private SearhLayoutHelper mHelper;
private ListUrlBuilder mTempListUrlBuilder = new ListUrlBuilder();
private Bitmap mSearchImage;
public SearchLayout(Context context) {
@@ -137,6 +142,8 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke
mSearchContainer.setAdapter(mAdapter);
mSearchContainer.setHasFixedSize(true);
mSearchContainer.setItemAnimator(mAnimator);
mFab.setOnClickListener(this);
}
public void setHelper(SearhLayoutHelper helper) {
@@ -213,6 +220,10 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke
// TODO add quick search
} else if (v == mAction2) {
taggleSearchMode();
} else if (v == mFab) {
if (mHelper != null) {
mHelper.onRequestSearch(getListUrlBuilder(null));
}
}
}
@@ -227,6 +238,45 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke
}
}
public ListUrlBuilder getListUrlBuilder(@Nullable ListUrlBuilder lub) {
if (lub == null) {
lub = mTempListUrlBuilder;
}
switch (mSearchMode) {
default:
case SEARCH_MODE_NORMAL:
lub.setMode(ListUrlBuilder.MODE_NORMAL);
if (mTableCategory != null) {
lub.setCategory(mTableCategory.getCategory());
}
if (mTextSearch != null) {
String searchKey = mTextSearch.getText().toString();
lub.setSearchKey(TextUtils.isEmpty(searchKey) ? null : searchKey);
}
if (mSwitchEnableAdvance.isChecked() && mTableAdvanceSearch != null) {
lub.setAdvanceSearch(mTableAdvanceSearch.getAdvanceSearch());
lub.setMinRating(mTableAdvanceSearch.getMinRating());
} else {
lub.setAdvanceSearch(-1);
lub.setMinRating(-1);
}
break;
case SEARCH_MODE_TAG:
lub.setMode(ListUrlBuilder.MODE_TAG);
if (mEditTextTag != null) {
lub.setSearchTag(mEditTextTag.getText().toString());
}
break;
case SEARCH_MODE_IMAGE:
lub.setMode(ListUrlBuilder.MODE_IMAGE_SEARCH);
// TODO
break;
}
return lub;
}
private class SearchHolder extends RecyclerView.ViewHolder {
public TextView title;
@@ -418,5 +468,7 @@ public class SearchLayout extends FrameLayout implements CompoundButton.OnChecke
public interface SearhLayoutHelper {
public void onRequestSelectImage();
public void onRequestSearch(ListUrlBuilder lub);
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.util;
import android.os.Process;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A thread factory that creates threads with a given thread priority.
*/
public class PriorityThreadFactory implements ThreadFactory {
private final int mPriority;
private final AtomicInteger mNumber = new AtomicInteger();
private final String mName;
public PriorityThreadFactory(String name, int priority) {
mName = name;
mPriority = priority;
}
@Override
public Thread newThread(Runnable r) {
return new Thread(r, mName + '-' + mNumber.getAndIncrement()) {
@Override
public void run() {
Process.setThreadPriority(mPriority);
super.run();
}
};
}
}
@@ -170,6 +170,10 @@ public class FloatLabelEditText extends FrameLayout {
}
}
public Editable getText() {
return mEditText.getText();
}
private TextWatcher mTextWatcher = new TextWatcher() {
@Override