From df78b45f69252dc8dc6e841ff7b98e189514705b Mon Sep 17 00:00:00 2001 From: tarsin Date: Sun, 6 Nov 2022 14:58:05 +0800 Subject: [PATCH] Initial support for jump to certain date --- .../ehviewer/client/data/ListUrlBuilder.kt | 992 +++++++++--------- .../ehviewer/ui/scene/FavoritesScene.java | 1 + .../ehviewer/ui/scene/GalleryListScene.java | 3 + .../widget/GalleryInfoContentHelper.kt | 164 +-- .../java/com/hippo/widget/ContentLayout.java | 2 +- 5 files changed, 558 insertions(+), 604 deletions(-) diff --git a/app/src/main/java/com/hippo/ehviewer/client/data/ListUrlBuilder.kt b/app/src/main/java/com/hippo/ehviewer/client/data/ListUrlBuilder.kt index cde045f73..36897f53d 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/data/ListUrlBuilder.kt +++ b/app/src/main/java/com/hippo/ehviewer/client/data/ListUrlBuilder.kt @@ -13,631 +13,579 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.hippo.ehviewer.client.data -package com.hippo.ehviewer.client.data; +import android.os.Parcel +import android.os.Parcelable +import android.os.Parcelable.Creator +import android.text.TextUtils +import androidx.annotation.IntDef +import com.hippo.ehviewer.client.EhConfig +import com.hippo.ehviewer.client.EhUrl +import com.hippo.ehviewer.client.EhUtils +import com.hippo.ehviewer.dao.QuickSearch +import com.hippo.ehviewer.widget.AdvanceSearchTable +import com.hippo.network.UrlBuilder +import com.hippo.yorozuya.NumberUtils +import com.hippo.yorozuya.StringUtils +import java.io.UnsupportedEncodingException +import java.net.URLDecoder +import java.net.URLEncoder -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -import androidx.annotation.IntDef; -import androidx.annotation.Nullable; - -import com.hippo.ehviewer.client.EhConfig; -import com.hippo.ehviewer.client.EhUrl; -import com.hippo.ehviewer.client.EhUtils; -import com.hippo.ehviewer.dao.QuickSearch; -import com.hippo.ehviewer.widget.AdvanceSearchTable; -import com.hippo.network.UrlBuilder; -import com.hippo.yorozuya.NumberUtils; -import com.hippo.yorozuya.StringUtils; - -import java.io.UnsupportedEncodingException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.net.URLDecoder; -import java.net.URLEncoder; - -public class ListUrlBuilder implements Cloneable, Parcelable { - - // 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_WHATS_HOT = 0x3; - public static final int MODE_IMAGE_SEARCH = 0x4; - public static final int MODE_SUBSCRIPTION = 0x5; - public static final int MODE_TOPLIST = 0x6; - public static final int DEFAULT_ADVANCE = AdvanceSearchTable.SNAME | AdvanceSearchTable.STAGS; - public static final int DEFAULT_MIN_RATING = 2; - public static final Creator CREATOR = new Creator() { - @Override - public ListUrlBuilder createFromParcel(Parcel source) { - return new ListUrlBuilder(source); - } - - @Override - public ListUrlBuilder[] newArray(int size) { - return new ListUrlBuilder[size]; - } - }; +open class ListUrlBuilder : Cloneable, Parcelable { + @get:Mode @Mode - private int mMode = MODE_NORMAL; + var mode = MODE_NORMAL + private var mNextGid = 0 + private var mPrevGid = 0 + private var mJumpTo: String? = null + var category = EhUtils.NONE + private var mKeyword: String? = null + private var mSHash: String? = null + var advanceSearch = -1 + var minRating = -1 + var pageFrom = -1 + var pageTo = -1 + var imagePath: String? = null + var isUseSimilarityScan = false + var isOnlySearchCovers = false + var isShowExpunged = false - private int mNextGid = 0; - private int mPrevGid = 0; - - private int mCategory = EhUtils.NONE; - private String mKeyword = null; - private String mSHash = null; - - private int mAdvanceSearch = -1; - private int mMinRating = -1; - private int mPageFrom = -1; - private int mPageTo = -1; - - private String mImagePath; - private boolean mUseSimilarityScan; - private boolean mOnlySearchCovers; - private boolean mShowExpunged; - - public ListUrlBuilder() { + constructor() + protected constructor(parcel: Parcel) { + mode = parcel.readInt() + mNextGid = parcel.readInt() + mPrevGid = parcel.readInt() + mJumpTo = parcel.readString() + this.category = parcel.readInt() + mKeyword = parcel.readString() + advanceSearch = parcel.readInt() + minRating = parcel.readInt() + pageFrom = parcel.readInt() + pageTo = parcel.readInt() + imagePath = parcel.readString() + isUseSimilarityScan = parcel.readByte().toInt() != 0 + isOnlySearchCovers = parcel.readByte().toInt() != 0 + isShowExpunged = parcel.readByte().toInt() != 0 + mSHash = parcel.readString() } - @SuppressWarnings("WrongConstant") - protected ListUrlBuilder(Parcel in) { - this.mMode = in.readInt(); - this.mNextGid = in.readInt(); - this.mPrevGid = in.readInt(); - this.mCategory = in.readInt(); - this.mKeyword = in.readString(); - this.mAdvanceSearch = in.readInt(); - this.mMinRating = in.readInt(); - this.mPageFrom = in.readInt(); - this.mPageTo = in.readInt(); - this.mImagePath = in.readString(); - this.mUseSimilarityScan = in.readByte() != 0; - this.mOnlySearchCovers = in.readByte() != 0; - this.mShowExpunged = in.readByte() != 0; - this.mSHash = in.readString(); + fun reset() { + mode = MODE_NORMAL + mNextGid = 0 + mPrevGid = 0 + mJumpTo = null + this.category = EhUtils.NONE + mKeyword = null + advanceSearch = -1 + minRating = -1 + pageFrom = -1 + pageTo = -1 + imagePath = null + isUseSimilarityScan = false + isOnlySearchCovers = false + isShowExpunged = false + mSHash = null } - /** - * Make this ListUrlBuilder point to homepage - */ - public void reset() { - mMode = MODE_NORMAL; - mNextGid = 0; - mPrevGid = 0; - mCategory = EhUtils.NONE; - mKeyword = null; - mAdvanceSearch = -1; - mMinRating = -1; - mPageFrom = -1; - mPageTo = -1; - mImagePath = null; - mUseSimilarityScan = false; - mOnlySearchCovers = false; - mShowExpunged = false; - mSHash = null; - } - - @Override - public ListUrlBuilder clone() { - try { - return (ListUrlBuilder) super.clone(); - } catch (CloneNotSupportedException e) { - throw new IllegalStateException(e); + public override fun clone(): ListUrlBuilder { + return try { + super.clone() as ListUrlBuilder + } catch (e: CloneNotSupportedException) { + throw IllegalStateException(e) } } - @Mode - public int getMode() { - return mMode; + fun setNextGid(nextGid: Int) { + mNextGid = nextGid } - public void setMode(@Mode int mode) { - mMode = mode; + fun setJumpTo(jumpTo: String?) { + mJumpTo = jumpTo } - public void setNextGid(int nextGid) { - mNextGid = nextGid; - } - - public void setPrevGid(int prevGid) { - mPrevGid = prevGid; - } - - public int getCategory() { - return mCategory; - } - - public void setCategory(int category) { - mCategory = category; - } - - public String getKeyword() { - return MODE_UPLOADER == mMode ? "uploader:" + mKeyword : mKeyword; - } - - public void setKeyword(String keyword) { - mKeyword = keyword; - } - - 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 int getPageFrom() { - return mPageFrom; - } - - public void setPageFrom(int pageFrom) { - mPageFrom = pageFrom; - } - - public int getPageTo() { - return mPageTo; - } - - public void setPageTo(int pageTo) { - mPageTo = pageTo; - } - - @Nullable - public String getImagePath() { - return mImagePath; - } - - public void setImagePath(String imagePath) { - mImagePath = imagePath; - } - - public boolean isUseSimilarityScan() { - return mUseSimilarityScan; - } - - public void setUseSimilarityScan(boolean useSimilarityScan) { - mUseSimilarityScan = useSimilarityScan; - } - - public boolean isOnlySearchCovers() { - return mOnlySearchCovers; - } - - public void setOnlySearchCovers(boolean onlySearchCovers) { - mOnlySearchCovers = onlySearchCovers; - } - - public boolean isShowExpunged() { - return mShowExpunged; - } - - public void setShowExpunged(boolean showExpunged) { - mShowExpunged = showExpunged; - } + var keyword: String? + get() = if (MODE_UPLOADER == mode) "uploader:$mKeyword" else mKeyword + set(keyword) { + mKeyword = keyword + } /** * Make them the same * * @param lub The template */ - public void set(ListUrlBuilder lub) { - mMode = lub.mMode; - mNextGid = lub.mNextGid; - mPrevGid = lub.mPrevGid; - mCategory = lub.mCategory; - mKeyword = lub.mKeyword; - mAdvanceSearch = lub.mAdvanceSearch; - mMinRating = lub.mMinRating; - mPageFrom = lub.mPageFrom; - mPageTo = lub.mPageTo; - mImagePath = lub.mImagePath; - mUseSimilarityScan = lub.mUseSimilarityScan; - mOnlySearchCovers = lub.mOnlySearchCovers; - mShowExpunged = lub.mShowExpunged; - mSHash = lub.mSHash; + fun set(lub: ListUrlBuilder) { + mode = lub.mode + mNextGid = lub.mNextGid + mPrevGid = lub.mPrevGid + mJumpTo = lub.mJumpTo + this.category = lub.category + mKeyword = lub.mKeyword + advanceSearch = lub.advanceSearch + minRating = lub.minRating + pageFrom = lub.pageFrom + pageTo = lub.pageTo + imagePath = lub.imagePath + isUseSimilarityScan = lub.isUseSimilarityScan + isOnlySearchCovers = lub.isOnlySearchCovers + isShowExpunged = lub.isShowExpunged + mSHash = lub.mSHash } - public void set(QuickSearch q) { - mMode = q.mode; - mCategory = q.category; - mKeyword = q.keyword; - mAdvanceSearch = q.advanceSearch; - mMinRating = q.minRating; - mPageFrom = q.pageFrom; - mPageTo = q.pageTo; - mImagePath = null; - mUseSimilarityScan = false; - mOnlySearchCovers = false; - mShowExpunged = false; + fun set(q: QuickSearch) { + mode = q.mode + this.category = q.category + mKeyword = q.keyword + advanceSearch = q.advanceSearch + minRating = q.minRating + pageFrom = q.pageFrom + pageTo = q.pageTo + imagePath = null + isUseSimilarityScan = false + isOnlySearchCovers = false + isShowExpunged = false } - public QuickSearch toQuickSearch() { - QuickSearch q = new QuickSearch(); - q.mode = mMode; - q.category = mCategory; - q.keyword = mKeyword; - q.advanceSearch = mAdvanceSearch; - q.minRating = mMinRating; - q.pageFrom = mPageFrom; - q.pageTo = mPageTo; - return q; + fun toQuickSearch(): QuickSearch { + val q = QuickSearch() + q.mode = mode + q.category = this.category + q.keyword = mKeyword + q.advanceSearch = advanceSearch + q.minRating = minRating + q.pageFrom = pageFrom + q.pageTo = pageTo + return q } - public boolean equalsQuickSearch(QuickSearch q) { + fun equalsQuickSearch(q: QuickSearch?): Boolean { if (null == q) { - return false; + return false } - - if (q.mode != mMode) { - return false; + if (q.mode != mode) { + return false } - if (q.category != mCategory) { - return false; + if (q.category != this.category) { + return false } if (!StringUtils.equals(q.keyword, mKeyword)) { - return false; + return false } - if (q.advanceSearch != mAdvanceSearch) { - return false; + if (q.advanceSearch != advanceSearch) { + return false } - if (q.minRating != mMinRating) { - return false; + if (q.minRating != minRating) { + return false } - if (q.pageFrom != mPageFrom) { - return false; - } - return q.pageTo == mPageTo; + return if (q.pageFrom != pageFrom) { + false + } else q.pageTo == pageTo } /** * @param query xxx=yyy&mmm=nnn */ // TODO page - public void setQuery(String query) { - reset(); - + fun setQuery(query: String?) { + reset() if (TextUtils.isEmpty(query)) { - return; + return } - String[] querys = StringUtils.split(query, '&'); - int category = 0; - String keyword = null; - boolean enableAdvanceSearch = false; - int advanceSearch = 0; - boolean enableMinRating = false; - int minRating = -1; - boolean enablePage = false; - int pageFrom = -1; - int pageTo = -1; - for (String str : querys) { - int index = str.indexOf('='); + val querys = StringUtils.split(query, '&') + var category = 0 + var keyword: String? = null + var enableAdvanceSearch = false + var advanceSearch = 0 + var enableMinRating = false + var minRating = -1 + var enablePage = false + var pageFrom = -1 + var pageTo = -1 + for (str in querys) { + val index = str.indexOf('=') if (index < 0) { - continue; + continue } - String key = str.substring(0, index); - String value = str.substring(index + 1); - switch (key) { - case "f_cats": - int cats = NumberUtils.parseIntSafely(value, EhConfig.ALL_CATEGORY); - category |= (~cats) & EhConfig.ALL_CATEGORY; - break; - case "f_doujinshi": - if ("1".equals(value)) { - category |= EhConfig.DOUJINSHI; - } - break; - case "f_manga": - if ("1".equals(value)) { - category |= EhConfig.MANGA; - } - break; - case "f_artistcg": - if ("1".equals(value)) { - category |= EhConfig.ARTIST_CG; - } - break; - case "f_gamecg": - if ("1".equals(value)) { - category |= EhConfig.GAME_CG; - } - break; - case "f_western": - if ("1".equals(value)) { - category |= EhConfig.WESTERN; - } - break; - case "f_non-h": - if ("1".equals(value)) { - category |= EhConfig.NON_H; - } - break; - case "f_imageset": - if ("1".equals(value)) { - category |= EhConfig.IMAGE_SET; - } - break; - case "f_cosplay": - if ("1".equals(value)) { - category |= EhConfig.COSPLAY; - } - break; - case "f_asianporn": - if ("1".equals(value)) { - category |= EhConfig.ASIAN_PORN; - } - break; - case "f_misc": - if ("1".equals(value)) { - category |= EhConfig.MISC; - } - break; - case "f_search": - try { - keyword = URLDecoder.decode(value, "utf-8"); - } catch (UnsupportedEncodingException | IllegalArgumentException e) { - // Ignore - } - break; - case "advsearch": - if ("1".equals(value)) { - enableAdvanceSearch = true; - } - break; - case "f_sname": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.SNAME; - } - break; - case "f_stags": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.STAGS; - } - break; - case "f_sdesc": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.SDESC; - } - break; - case "f_storr": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.STORR; - } - break; - case "f_sto": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.STO; - } - break; - case "f_sdt1": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.SDT1; - } - break; - case "f_sdt2": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.SDT2; - } - break; - case "f_sh": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.SH; - } - break; - case "f_sfl": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.SFL; - } - break; - case "f_sfu": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.SFU; - } - break; - case "f_sft": - if ("on".equals(value)) { - advanceSearch |= AdvanceSearchTable.SFT; - } - break; - case "f_sr": - if ("on".equals(value)) { - enableMinRating = true; - } - break; - case "f_srdd": - minRating = NumberUtils.parseIntSafely(value, -1); - break; - case "f_sp": - if ("on".equals(value)) { - enablePage = true; - } - break; - case "f_spf": - pageFrom = NumberUtils.parseIntSafely(value, -1); - break; - case "f_spt": - pageTo = NumberUtils.parseIntSafely(value, -1); - break; - case "f_shash": - mSHash = value; - break; + val key = str.substring(0, index) + val value = str.substring(index + 1) + when (key) { + "f_cats" -> { + val cats = NumberUtils.parseIntSafely(value, EhConfig.ALL_CATEGORY) + category = category or (cats.inv() and EhConfig.ALL_CATEGORY) + } + + "f_doujinshi" -> if ("1" == value) { + category = category or EhConfig.DOUJINSHI + } + + "f_manga" -> if ("1" == value) { + category = category or EhConfig.MANGA + } + + "f_artistcg" -> if ("1" == value) { + category = category or EhConfig.ARTIST_CG + } + + "f_gamecg" -> if ("1" == value) { + category = category or EhConfig.GAME_CG + } + + "f_western" -> if ("1" == value) { + category = category or EhConfig.WESTERN + } + + "f_non-h" -> if ("1" == value) { + category = category or EhConfig.NON_H + } + + "f_imageset" -> if ("1" == value) { + category = category or EhConfig.IMAGE_SET + } + + "f_cosplay" -> if ("1" == value) { + category = category or EhConfig.COSPLAY + } + + "f_asianporn" -> if ("1" == value) { + category = category or EhConfig.ASIAN_PORN + } + + "f_misc" -> if ("1" == value) { + category = category or EhConfig.MISC + } + + "f_search" -> try { + keyword = URLDecoder.decode(value, "utf-8") + } catch (e: UnsupportedEncodingException) { + // Ignore + } catch (_: IllegalArgumentException) { + } + + "advsearch" -> if ("1" == value) { + enableAdvanceSearch = true + } + + "f_sname" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.SNAME + } + + "f_stags" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.STAGS + } + + "f_sdesc" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.SDESC + } + + "f_storr" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.STORR + } + + "f_sto" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.STO + } + + "f_sdt1" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.SDT1 + } + + "f_sdt2" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.SDT2 + } + + "f_sh" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.SH + } + + "f_sfl" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.SFL + } + + "f_sfu" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.SFU + } + + "f_sft" -> if ("on" == value) { + advanceSearch = advanceSearch or AdvanceSearchTable.SFT + } + + "f_sr" -> if ("on" == value) { + enableMinRating = true + } + + "f_srdd" -> minRating = NumberUtils.parseIntSafely(value, -1) + "f_sp" -> if ("on" == value) { + enablePage = true + } + + "f_spf" -> pageFrom = NumberUtils.parseIntSafely(value, -1) + "f_spt" -> pageTo = NumberUtils.parseIntSafely(value, -1) + "f_shash" -> mSHash = value } } - - mCategory = category; - mKeyword = keyword; + this.category = category + mKeyword = keyword if (enableAdvanceSearch) { - mAdvanceSearch = advanceSearch; + this.advanceSearch = advanceSearch if (enableMinRating) { - mMinRating = minRating; + this.minRating = minRating } else { - mMinRating = -1; + this.minRating = -1 } if (enablePage) { - mPageFrom = pageFrom; - mPageTo = pageTo; + this.pageFrom = pageFrom + this.pageTo = pageTo } else { - mPageFrom = -1; - mPageTo = -1; + this.pageFrom = -1 + this.pageTo = -1 } } else { - mAdvanceSearch = -1; + this.advanceSearch = -1 } } - public String build() { - switch (mMode) { - default: - case MODE_NORMAL: - case MODE_SUBSCRIPTION: { - String url; - if (mMode == MODE_NORMAL) { - url = EhUrl.getHost(); + fun build(): String { + return when (mode) { + MODE_NORMAL, MODE_SUBSCRIPTION -> { + val url: String = if (mode == MODE_NORMAL) { + EhUrl.getHost() } else { - url = EhUrl.getWatchedUrl(); + EhUrl.getWatchedUrl() } - - UrlBuilder ub = new UrlBuilder(url); - if (mCategory != EhUtils.NONE) { - ub.addQuery("f_cats", (~mCategory) & EhConfig.ALL_CATEGORY); + val ub = UrlBuilder(url) + if (this.category != EhUtils.NONE) { + ub.addQuery("f_cats", category.inv() and EhConfig.ALL_CATEGORY) } // Search key if (mKeyword != null) { - String keyword = mKeyword.trim(); - if (!keyword.isEmpty()) { + val keyword = mKeyword!!.trim { it <= ' ' } + if (keyword.isNotEmpty()) { try { - ub.addQuery("f_search", URLEncoder.encode(mKeyword, "UTF-8")); - } catch (UnsupportedEncodingException e) { + ub.addQuery("f_search", URLEncoder.encode(mKeyword, "UTF-8")) + } catch (e: UnsupportedEncodingException) { // Empty } } } if (mSHash != null) { - ub.addQuery("f_shash", mSHash); + ub.addQuery("f_shash", mSHash!!) + } + mJumpTo?.let { + ub.addQuery("seek", mJumpTo!!) + mNextGid = 0 + mPrevGid = 0 } if (mNextGid != 0) { - ub.addQuery("next", mNextGid); + ub.addQuery("next", mNextGid) } if (mPrevGid != 0) { - ub.addQuery("prev", mPrevGid); + ub.addQuery("prev", mPrevGid) } // 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"); - if ((mAdvanceSearch & AdvanceSearchTable.SFL) != 0) ub.addQuery("f_sfl", "on"); - if ((mAdvanceSearch & AdvanceSearchTable.SFU) != 0) ub.addQuery("f_sfu", "on"); - if ((mAdvanceSearch & AdvanceSearchTable.SFT) != 0) ub.addQuery("f_sft", "on"); + if (advanceSearch != -1) { + ub.addQuery("advsearch", "1") + if (advanceSearch and AdvanceSearchTable.SNAME != 0) ub.addQuery( + "f_sname", + "on" + ) + if (advanceSearch and AdvanceSearchTable.STAGS != 0) ub.addQuery( + "f_stags", + "on" + ) + if (advanceSearch and AdvanceSearchTable.SDESC != 0) ub.addQuery( + "f_sdesc", + "on" + ) + if (advanceSearch and AdvanceSearchTable.STORR != 0) ub.addQuery( + "f_storr", + "on" + ) + if (advanceSearch and AdvanceSearchTable.STO != 0) ub.addQuery("f_sto", "on") + if (advanceSearch and AdvanceSearchTable.SDT1 != 0) ub.addQuery("f_sdt1", "on") + if (advanceSearch and AdvanceSearchTable.SDT2 != 0) ub.addQuery("f_sdt2", "on") + if (advanceSearch and AdvanceSearchTable.SH != 0) ub.addQuery("f_sh", "on") + if (advanceSearch and AdvanceSearchTable.SFL != 0) ub.addQuery("f_sfl", "on") + if (advanceSearch and AdvanceSearchTable.SFU != 0) ub.addQuery("f_sfu", "on") + if (advanceSearch and AdvanceSearchTable.SFT != 0) ub.addQuery("f_sft", "on") // Set min star - if (mMinRating != -1) { - ub.addQuery("f_sr", "on"); - ub.addQuery("f_srdd", mMinRating); + if (minRating != -1) { + ub.addQuery("f_sr", "on") + ub.addQuery("f_srdd", minRating) } // Pages - if (mPageFrom != -1 || mPageTo != -1) { - ub.addQuery("f_sp", "on"); - ub.addQuery("f_spf", mPageFrom != -1 ? Integer.toString(mPageFrom) : ""); - ub.addQuery("f_spt", mPageTo != -1 ? Integer.toString(mPageTo) : ""); + if (pageFrom != -1 || pageTo != -1) { + ub.addQuery("f_sp", "on") + ub.addQuery("f_spf", if (pageFrom != -1) pageFrom.toString() else "") + ub.addQuery("f_spt", if (pageTo != -1) pageTo.toString() else "") } } - return ub.build(); + ub.build() } - case MODE_UPLOADER: { - StringBuilder sb = new StringBuilder(EhUrl.getHost()); - sb.append("uploader/"); + + MODE_UPLOADER -> { + val sb = StringBuilder(EhUrl.getHost()) + sb.append("uploader/") try { - sb.append(URLEncoder.encode(mKeyword, "UTF-8")); - } catch (UnsupportedEncodingException e) { + sb.append(URLEncoder.encode(mKeyword, "UTF-8")) + } catch (e: UnsupportedEncodingException) { // Empty } if (mNextGid != 0) { - sb.append("?next=").append(mNextGid); + sb.append("?next=").append(mNextGid) } - return sb.toString(); + sb.toString() } - case MODE_TAG: { - StringBuilder sb = new StringBuilder(EhUrl.getHost()); - sb.append("tag/"); + + MODE_TAG -> { + val sb = StringBuilder(EhUrl.getHost()) + sb.append("tag/") try { - sb.append(URLEncoder.encode(mKeyword, "UTF-8")); - } catch (UnsupportedEncodingException e) { + sb.append(URLEncoder.encode(mKeyword, "UTF-8")) + } catch (e: UnsupportedEncodingException) { // Empty } if (mNextGid != 0) { - sb.append("?next=").append(mNextGid); + sb.append("?next=").append(mNextGid) } - return sb.toString(); + sb.toString() } - case MODE_WHATS_HOT: - return EhUrl.getPopularUrl(); - case MODE_IMAGE_SEARCH: - return EhUrl.getImageSearchUrl(); - case MODE_TOPLIST: - StringBuilder sb = new StringBuilder(EhUrl.HOST_E); - sb.append("toplist.php?tl="); + + MODE_WHATS_HOT -> EhUrl.getPopularUrl() + MODE_IMAGE_SEARCH -> EhUrl.getImageSearchUrl() + MODE_TOPLIST -> { + val sb = StringBuilder(EhUrl.HOST_E) + sb.append("toplist.php?tl=") try { - sb.append(URLEncoder.encode(mKeyword, "UTF-8")); - } catch (UnsupportedEncodingException e) { + sb.append(URLEncoder.encode(mKeyword, "UTF-8")) + } catch (e: UnsupportedEncodingException) { // Empty } if (mNextGid != 0) { - sb.append("&p=").append(mNextGid); + sb.append("&p=").append(mNextGid) } - return sb.toString(); + sb.toString() + } + + else -> { + val url: String = if (mode == MODE_NORMAL) { + EhUrl.getHost() + } else { + EhUrl.getWatchedUrl() + } + val ub = UrlBuilder(url) + if (this.category != EhUtils.NONE) { + ub.addQuery("f_cats", category.inv() and EhConfig.ALL_CATEGORY) + } + if (mKeyword != null) { + val keyword = mKeyword!!.trim { it <= ' ' } + if (keyword.isNotEmpty()) { + try { + ub.addQuery("f_search", URLEncoder.encode(mKeyword, "UTF-8")) + } catch (_: UnsupportedEncodingException) { + } + } + } + if (mSHash != null) { + ub.addQuery("f_shash", mSHash!!) + } + if (mNextGid != 0) { + ub.addQuery("next", mNextGid) + } + if (mPrevGid != 0) { + ub.addQuery("prev", mPrevGid) + } + if (advanceSearch != -1) { + ub.addQuery("advsearch", "1") + if (advanceSearch and AdvanceSearchTable.SNAME != 0) ub.addQuery( + "f_sname", + "on" + ) + if (advanceSearch and AdvanceSearchTable.STAGS != 0) ub.addQuery( + "f_stags", + "on" + ) + if (advanceSearch and AdvanceSearchTable.SDESC != 0) ub.addQuery( + "f_sdesc", + "on" + ) + if (advanceSearch and AdvanceSearchTable.STORR != 0) ub.addQuery( + "f_storr", + "on" + ) + if (advanceSearch and AdvanceSearchTable.STO != 0) ub.addQuery("f_sto", "on") + if (advanceSearch and AdvanceSearchTable.SDT1 != 0) ub.addQuery("f_sdt1", "on") + if (advanceSearch and AdvanceSearchTable.SDT2 != 0) ub.addQuery("f_sdt2", "on") + if (advanceSearch and AdvanceSearchTable.SH != 0) ub.addQuery("f_sh", "on") + if (advanceSearch and AdvanceSearchTable.SFL != 0) ub.addQuery("f_sfl", "on") + if (advanceSearch and AdvanceSearchTable.SFU != 0) ub.addQuery("f_sfu", "on") + if (advanceSearch and AdvanceSearchTable.SFT != 0) ub.addQuery("f_sft", "on") + if (minRating != -1) { + ub.addQuery("f_sr", "on") + ub.addQuery("f_srdd", minRating) + } + if (pageFrom != -1 || pageTo != -1) { + ub.addQuery("f_sp", "on") + ub.addQuery("f_spf", if (pageFrom != -1) pageFrom.toString() else "") + ub.addQuery("f_spt", if (pageTo != -1) pageTo.toString() else "") + } + } + ub.build() + } } } - @Override - public int describeContents() { - return 0; + override fun describeContents(): Int { + return 0 } - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.mMode); - dest.writeInt(this.mNextGid); - dest.writeInt(this.mPrevGid); - dest.writeInt(this.mCategory); - dest.writeString(this.mKeyword); - dest.writeInt(this.mAdvanceSearch); - dest.writeInt(this.mMinRating); - dest.writeInt(this.mPageFrom); - dest.writeInt(this.mPageTo); - dest.writeString(this.mImagePath); - dest.writeByte(mUseSimilarityScan ? (byte) 1 : (byte) 0); - dest.writeByte(mOnlySearchCovers ? (byte) 1 : (byte) 0); - dest.writeByte(mShowExpunged ? (byte) 1 : (byte) 0); - dest.writeString(this.mSHash); + override fun writeToParcel(dest: Parcel, flags: Int) { + dest.writeInt(mode) + dest.writeInt(mNextGid) + dest.writeInt(mPrevGid) + dest.writeString(mJumpTo) + dest.writeInt(this.category) + dest.writeString(mKeyword) + dest.writeInt(advanceSearch) + dest.writeInt(minRating) + dest.writeInt(pageFrom) + dest.writeInt(pageTo) + dest.writeString(imagePath) + dest.writeByte(if (isUseSimilarityScan) 1.toByte() else 0.toByte()) + dest.writeByte(if (isOnlySearchCovers) 1.toByte() else 0.toByte()) + dest.writeByte(if (isShowExpunged) 1.toByte() else 0.toByte()) + dest.writeString(mSHash) } - @IntDef({MODE_NORMAL, MODE_UPLOADER, MODE_TAG, MODE_WHATS_HOT, MODE_IMAGE_SEARCH, MODE_SUBSCRIPTION, MODE_TOPLIST}) - @Retention(RetentionPolicy.SOURCE) - private @interface Mode { + @IntDef( + MODE_NORMAL, + MODE_UPLOADER, + MODE_TAG, + MODE_WHATS_HOT, + MODE_IMAGE_SEARCH, + MODE_SUBSCRIPTION, + MODE_TOPLIST + ) + @Retention(AnnotationRetention.SOURCE) + private annotation class Mode + companion object { + const val MODE_NORMAL = 0x0 + const val MODE_UPLOADER = 0x1 + const val MODE_TAG = 0x2 + const val MODE_WHATS_HOT = 0x3 + const val MODE_IMAGE_SEARCH = 0x4 + const val MODE_SUBSCRIPTION = 0x5 + const val MODE_TOPLIST = 0x6 + + @JvmField + val CREATOR: Creator = object : Creator { + override fun createFromParcel(source: Parcel): ListUrlBuilder { + return ListUrlBuilder(source) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/FavoritesScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/FavoritesScene.java index 065c39fd2..0ec608c57 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/FavoritesScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/FavoritesScene.java @@ -649,6 +649,7 @@ public class FavoritesScene extends BaseScene implements .build(); datePicker.show(requireActivity().getSupportFragmentManager(), "date-picker"); datePicker.addOnPositiveButtonClickListener(v -> { + mHelper.goTo(v); }); } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java index 30c9adc16..bfb97d3af 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java @@ -863,6 +863,7 @@ public final class GalleryListScene extends BaseScene .build(); datePicker.show(requireActivity().getSupportFragmentManager(), "date-picker"); datePicker.addOnPositiveButtonClickListener(v -> { + mHelper.goTo(v); }); } @@ -1702,6 +1703,8 @@ public final class GalleryListScene extends BaseScene mUrlBuilder.setNextGid(minGid); else mUrlBuilder.setNextGid(0); + mUrlBuilder.setJumpTo(jumpTo); + jumpTo = null; if (ListUrlBuilder.MODE_IMAGE_SEARCH == mUrlBuilder.getMode()) { EhRequest request = new EhRequest(); request.setMethod(EhClient.METHOD_IMAGE_SEARCH); diff --git a/app/src/main/java/com/hippo/ehviewer/widget/GalleryInfoContentHelper.kt b/app/src/main/java/com/hippo/ehviewer/widget/GalleryInfoContentHelper.kt index 828d338be..c019ac33c 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/GalleryInfoContentHelper.kt +++ b/app/src/main/java/com/hippo/ehviewer/widget/GalleryInfoContentHelper.kt @@ -13,116 +13,118 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.hippo.ehviewer.widget -package com.hippo.ehviewer.widget; +import android.annotation.SuppressLint +import android.icu.text.SimpleDateFormat +import android.icu.util.Calendar +import android.os.Bundle +import android.os.Parcelable +import com.hippo.ehviewer.EhApplication +import com.hippo.ehviewer.FavouriteStatusRouter +import com.hippo.ehviewer.client.data.GalleryInfo +import com.hippo.widget.ContentLayout.ContentHelper +import com.hippo.yorozuya.IntIdGenerator +import java.util.Locale -import android.annotation.SuppressLint; -import android.os.Bundle; -import android.os.Parcelable; +abstract class GalleryInfoContentHelper : ContentHelper() { + @JvmField + var maxGid = -1 + @JvmField + var minGid = -1 + @JvmField + var jumpTo : String? = null + private val listener: FavouriteStatusRouter.Listener -import com.hippo.ehviewer.EhApplication; -import com.hippo.ehviewer.FavouriteStatusRouter; -import com.hippo.ehviewer.client.data.GalleryInfo; -import com.hippo.widget.ContentLayout; -import com.hippo.yorozuya.IntIdGenerator; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public abstract class GalleryInfoContentHelper extends ContentLayout.ContentHelper { - public int maxGid = -1; - public int minGid = -1; - - private static final String KEY_DATA_MAP = "data_map"; - private static final String KEY_MAX_GID = "max_gid"; - private static final String KEY_MIN_GID = "min_gid"; - - public static final String KEY_NEXT_PAGE = "next_page"; - private final FavouriteStatusRouter.Listener listener; @SuppressLint("UseSparseArrays") - private Map map = new HashMap<>(); + private var map: MutableMap = HashMap() - public GalleryInfoContentHelper() { - listener = (gid, slot) -> { - GalleryInfo info = map.get(gid); + init { + listener = FavouriteStatusRouter.Listener { gid: Long, slot: Int -> + val info = map[gid] if (info != null) { - info.favoriteSlot = slot; + info.favoriteSlot = slot } - }; - EhApplication.getFavouriteStatusRouter().addListener(listener); + } + EhApplication.getFavouriteStatusRouter().addListener(listener) } - public void destroy() { - EhApplication.getFavouriteStatusRouter().removeListener(listener); + fun destroy() { + EhApplication.getFavouriteStatusRouter().removeListener(listener) } - @Override - protected void onAddData(GalleryInfo data) { - map.put(data.gid, data); + override fun onAddData(data: GalleryInfo?) { + data?.let { map[data.gid] = data } } - @Override - protected void onAddData(List data) { - for (GalleryInfo info : data) { - if (maxGid == -1) - maxGid = (int) info.gid; - if (minGid == -1) - minGid = (int) info.gid; - maxGid = (int) Math.max(maxGid, info.gid); - minGid = (int) Math.min(minGid, info.gid); - map.put(info.gid, info); + override fun onAddData(data: List) { + for (info in data) { + info?.let { + if (maxGid == -1) maxGid = info.gid.toInt() + if (minGid == -1) minGid = info.gid.toInt() + maxGid = Math.max(maxGid.toLong(), info.gid).toInt() + minGid = Math.min(minGid.toLong(), info.gid).toInt() + map[info.gid] = info + } } } - @Override - protected void onRemoveData(GalleryInfo data) { - map.remove(data.gid); + override fun onRemoveData(data: GalleryInfo?) { + data?.let { map.remove(data.gid) } } - @Override - protected void onRemoveData(List data) { - for (GalleryInfo info : data) { - map.remove(info.gid); + override fun onRemoveData(data: List) { + for (info in data) { + info?.let { map.remove(info.gid) } } } - @Override - protected void onClearData() { - map.clear(); - maxGid = -1; - minGid = -1; + override fun onClearData() { + map.clear() + maxGid = -1 + minGid = -1 } - @Override - protected Parcelable saveInstanceState(Parcelable superState) { - Bundle bundle = (Bundle) super.saveInstanceState(superState); + override fun saveInstanceState(superState: Parcelable): Parcelable { + val bundle = super.saveInstanceState(superState) as Bundle // TODO It's a bad design - FavouriteStatusRouter router = EhApplication.getFavouriteStatusRouter(); - int id = router.saveDataMap(map); - bundle.putInt(KEY_DATA_MAP, id); - bundle.putInt(KEY_MIN_GID, minGid); - bundle.putInt(KEY_MAX_GID, maxGid); - - return bundle; + val router = EhApplication.getFavouriteStatusRouter() + val id = router.saveDataMap(map) + bundle.putInt(KEY_DATA_MAP, id) + bundle.putInt(KEY_MIN_GID, minGid) + bundle.putInt(KEY_MAX_GID, maxGid) + return bundle } - @Override - protected Parcelable restoreInstanceState(Parcelable state) { - Bundle bundle = (Bundle) state; - - int id = bundle.getInt(KEY_DATA_MAP, IntIdGenerator.INVALID_ID); + override fun restoreInstanceState(state: Parcelable): Parcelable { + val bundle = state as Bundle + val id = bundle.getInt(KEY_DATA_MAP, IntIdGenerator.INVALID_ID) if (id != IntIdGenerator.INVALID_ID) { - FavouriteStatusRouter router = EhApplication.getFavouriteStatusRouter(); - Map map = router.restoreDataMap(id); + val router = EhApplication.getFavouriteStatusRouter() + val map = router.restoreDataMap(id) if (map != null) { - this.map = map; + this.map = map } } - minGid = bundle.getInt(KEY_MIN_GID); - maxGid = bundle.getInt(KEY_MAX_GID); - - return super.restoreInstanceState(state); + minGid = bundle.getInt(KEY_MIN_GID) + maxGid = bundle.getInt(KEY_MAX_GID) + return super.restoreInstanceState(state) } -} + + fun goTo(time: Long) { + val calendar = Calendar.getInstance() + calendar.timeInMillis = time + val date = calendar.time + val format = SimpleDateFormat("yyyy-MM-dd", Locale.US) + jumpTo = format.format(date) + doRefresh() + } + + companion object { + private const val KEY_DATA_MAP = "data_map" + private const val KEY_MAX_GID = "max_gid" + private const val KEY_MIN_GID = "min_gid" + const val KEY_NEXT_PAGE = "next_page" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/hippo/widget/ContentLayout.java b/app/src/main/java/com/hippo/widget/ContentLayout.java index 53fb432c6..50aa6d630 100644 --- a/app/src/main/java/com/hippo/widget/ContentLayout.java +++ b/app/src/main/java/com/hippo/widget/ContentLayout.java @@ -747,7 +747,7 @@ public class ContentLayout extends FrameLayout { getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage); } - private void doRefresh() { + protected void doRefresh() { mStartPage = 0; mEndPage = 1; mPages = 0;