diff --git a/app/build.gradle b/app/build.gradle index 798ffdf29..627133efb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,8 +39,8 @@ android { } dependencies { - compile 'com.android.support:support-v4:22.2.0' - compile 'com.android.support:appcompat-v7:22.2.0' + compile 'com.android.support:support-v4:22.2.1' + compile 'com.android.support:appcompat-v7:22.2.1' compile 'de.greenrobot:greendao:1.3.7' debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' diff --git a/app/src/main/assets/fonts/number.ttf b/app/src/main/assets/fonts/number.ttf index c6bb4c206..540100d68 100644 Binary files a/app/src/main/assets/fonts/number.ttf and b/app/src/main/assets/fonts/number.ttf differ diff --git a/app/src/main/java/com/hippo/ehviewer/client/GalleryDetailUrlParser.java b/app/src/main/java/com/hippo/ehviewer/client/GalleryDetailUrlParser.java new file mode 100644 index 000000000..dc8bc999e --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/client/GalleryDetailUrlParser.java @@ -0,0 +1,45 @@ +/* + * Copyright 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 + * 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.ehviewer.client; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class GalleryDetailUrlParser { + + public static Result parser(String url) { + if (url == null) { + return null; + } + + Pattern p = Pattern.compile("/(\\d+)/(\\w+)"); + Matcher m = p.matcher(url); + if (m.find()) { + Result result = new Result(); + result.gid = Integer.parseInt(m.group(1)); + result.token = m.group(2); + return result; + } else { + return null; + } + } + + public static class Result { + public int gid; + public String token; + } +} diff --git a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java index fff53637e..74b4926ed 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java @@ -232,7 +232,7 @@ public final class ContentActivity extends StageActivity @Override public void onClickSignIn() { mDrawerLayout.closeDrawers(); - startScene(SignInScene.class); + startScene(SignInScene.class, null, new OffsetCurtain(OffsetCurtain.DIRECTION_BOTTOM)); } @Override diff --git a/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java index 26042ede2..634e61e8c 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/GalleryActivity.java @@ -172,6 +172,7 @@ public class GalleryActivity extends StatsActivity implements TiledTexture.OnFre if (!mDieYoung) { GalleryPageView.setTextTexture(null); + mUploader.clear(); mTextTexture.recycle(); GifTexture.uninitialize(); TiledTexture.setOnFreeBitmapListener(null); diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java index c0bf40489..9ed7858fa 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2015 Hippo Seven + * Copyright 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 + * 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, @@ -21,30 +21,27 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.drawable.Drawable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.text.Html; -import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.FrameLayout; import android.widget.LinearLayout; -import android.widget.TextSwitcher; import android.widget.TextView; -import android.widget.ViewSwitcher; -import com.hippo.conaco.Conaco; import com.hippo.effect.ViewTransition; import com.hippo.ehviewer.EhApplication; import com.hippo.ehviewer.EhCacheKeyFactory; import com.hippo.ehviewer.R; import com.hippo.ehviewer.client.EhClient; -import com.hippo.ehviewer.client.EhException; +import com.hippo.ehviewer.client.EhConfig; import com.hippo.ehviewer.client.EhRequest; import com.hippo.ehviewer.client.EhUrl; -import com.hippo.ehviewer.client.OffensiveException; +import com.hippo.ehviewer.client.GalleryDetailUrlParser; import com.hippo.ehviewer.client.data.Comment; +import com.hippo.ehviewer.client.data.GalleryBase; import com.hippo.ehviewer.client.data.GalleryDetail; -import com.hippo.ehviewer.client.data.GalleryInfo; import com.hippo.ehviewer.client.data.PreviewSet; import com.hippo.ehviewer.client.data.TagGroup; import com.hippo.ehviewer.ui.GalleryActivity; @@ -61,20 +58,20 @@ import com.hippo.scene.RippleCurtain; import com.hippo.scene.Scene; import com.hippo.scene.SimpleDialog; import com.hippo.scene.UnionCurtain; +import com.hippo.util.ExceptionUtils; import com.hippo.util.URLImageGetter; import com.hippo.widget.AccurateClick; import com.hippo.widget.AutoWrapLayout; +import com.hippo.widget.NoopLayout; +import com.hippo.widget.recyclerview.LinearDividerItemDecoration; import com.hippo.yorozuya.LayoutUtils; import com.hippo.yorozuya.Say; import com.hippo.yorozuya.ViewUtils; import java.util.List; -import static com.hippo.ehviewer.R.id.no_tags; - -// TODO Use RecyclerView instead of ScrollView. It will improve swipe horizontally and animation public class GalleryDetailScene extends Scene implements View.OnClickListener, - AccurateClick.OnAccurateClickListener { + AccurateClick.OnAccurateClickListener, LinearDividerItemDecoration.ShowDividerHelper { private static final String TAG = GalleryDetailScene.class.getSimpleName(); @@ -87,55 +84,88 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener, public static final String KEY_TOKEN = "key_token"; public static final String KEY_URL = "key_url"; - private FrameLayout mDetailFrameLayout; + public static final int STATE_TOTALLY_LOADING = 0; + public static final int STATE_LOADING = 1; + public static final int STATE_LOADED = 2; + public static final int STATE_FAILED = 3; - private ViewGroup mHeader; + public static final int COUNT_LOADING = 3; + public static final int COUNT_LOADED = 7; + + public static final int TYPE_HEADER = 0; + public static final int TYPE_BUTTON = 1; + public static final int TYPE_INFO = 2; + public static final int TYPE_ACTION = 3; + public static final int TYPE_TAG = 4; + public static final int TYPE_COMMENT = 5; + public static final int TYPE_PREVIEW = 6; + public static final int TYPE_PROGRESS = 7; + + private EhConfig mEhConfig; + private int mSource; + + private String mActionStr; + private GalleryBase mGalleryBase; + private int mGid; + private String mToken; + private GalleryDetail mGalleryDetail; + private String mErrorMessage; + + private RecyclerView mRecyclerView; + private View mMainProgressView; + private ViewGroup mFailedView; + private TextView mFailedText; + private ViewTransition mViewTransition; + + private View mHeader; LoadImageView mThumb; TextView mTitle; TextView mUploader; TextView mCategory; - private ViewGroup mActionCard; - private View mRead; + private View mButton; private View mDownload; + private View mRead; - private ViewGroup mContent; - private ViewGroup mInfo; + private View mInfo; private TextView mLanguage; private TextView mPages; private TextView mSize; private TextView mPosted; private TextView mResize; private TextView mFavoredTimes; - private TextSwitcher mRatingText; + + private View mAction; + private TextView mRatingText; private RatingView mRating; private TextView mFavorite; private TextView mTorrent; private TextView mShare; private TextView mRate; - private LinearLayout mTag; - private TextView mNoTags; - private LinearLayout mComment; - private TextView mCommentMore; - private PreviewLayout mPreviewLayout; + private ViewGroup mTag; + private TextView mNoTagText; + + private ViewGroup mComment; + private TextView mCommentText; + + private PreviewLayout mPreview; + + private View mProgress; private View mProgressView; - private ViewTransition mViewTransition; + private DetailAdapter mAdapter; - private GalleryDetail mGalleryDetail; + private int mState; - private void requestGalleryDetail(GalleryInfo gi) { - EhClient client = EhApplication.getEhClient(getStageActivity()); - int source = Settings.getEhSource(); - String url = EhUrl.getDetailUrl(source, gi.gid, gi.token, 0); + private EhRequest mEhRequest; - EhRequest request = new EhRequest(); - request.setMethod(EhClient.METHOD_GET_GALLERY_DETAIL); - request.setEhListener(new EhDetailListener()); - request.setArgs(url, source); - // TODO request.setEhConfig(); - client.execute(request); + @Override + protected void onInit() { + super.onInit(); + + mEhConfig = EhApplication.getEhHttpClient(getStageActivity()).getEhConfigClone(); + mSource = Settings.getEhSource(); } @Override @@ -143,191 +173,106 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener, super.onCreate(rebirth); setContentView(R.layout.scene_gallery_detail); - mDetailFrameLayout = (FrameLayout) findViewById(R.id.detail_frame_layout); + ViewGroup main = (ViewGroup) findViewById(R.id.main); + mRecyclerView = (RecyclerView) main.getChildAt(0); + mMainProgressView = main.getChildAt(1); + mFailedView = (ViewGroup) main.getChildAt(2); + mFailedText = (TextView) mFailedView.getChildAt(1); + mViewTransition = new ViewTransition(mRecyclerView, mMainProgressView, mFailedView); - mHeader = (ViewGroup) findViewById(R.id.header); + LayoutInflater inflater = getStageActivity().getLayoutInflater(); + NoopLayout noopLayout = new NoopLayout(getStageActivity()); + + mHeader = inflater.inflate(R.layout.gallery_detail_header, noopLayout, false); mThumb = (LoadImageView) mHeader.findViewById(R.id.thumb); mTitle = (TextView) mHeader.findViewById(R.id.title); mUploader = (TextView) mHeader.findViewById(R.id.uploader); mCategory = (TextView) mHeader.findViewById(R.id.category); - mActionCard = (ViewGroup) findViewById(R.id.action_card); - mRead = mActionCard.findViewById(R.id.read); - mDownload = mActionCard.findViewById(R.id.download); + mButton = inflater.inflate(R.layout.gallery_detail_button, noopLayout, false); + mDownload = mButton.findViewById(R.id.download); + mRead = mButton.findViewById(R.id.read); - mContent = (ViewGroup) findViewById(R.id.content); - mInfo = (ViewGroup) mContent.findViewById(R.id.info); + mInfo = inflater.inflate(R.layout.gallery_detail_info, noopLayout, false); mLanguage = (TextView) mInfo.findViewById(R.id.language); mPages = (TextView) mInfo.findViewById(R.id.pages); mSize = (TextView) mInfo.findViewById(R.id.size); mPosted = (TextView) mInfo.findViewById(R.id.posted); mResize = (TextView) mInfo.findViewById(R.id.resize); mFavoredTimes = (TextView) mInfo.findViewById(R.id.favoredTimes); - mRatingText = (TextSwitcher) mContent.findViewById(R.id.rating_text); - mRating = (RatingView) mContent.findViewById(R.id.rating); - mFavorite = (TextView) mContent.findViewById(R.id.favorite); - mTorrent = (TextView) mContent.findViewById(R.id.torrent); - mShare = (TextView) mContent.findViewById(R.id.share); - mRate = (TextView) mContent.findViewById(R.id.rate); - mTag = (LinearLayout) mContent.findViewById(R.id.tag); - mNoTags = (TextView) mTag.findViewById(no_tags); - mComment = (LinearLayout) mContent.findViewById(R.id.comment); - mCommentMore = (TextView) mContent.findViewById(R.id.comment_more); - mPreviewLayout = (PreviewLayout) mContent.findViewById(R.id.preview); - mProgressView = findViewById(R.id.progress_view); + mAction = inflater.inflate(R.layout.gallery_detail_action, noopLayout, false); + mRatingText = (TextView) mAction.findViewById(R.id.rating_text); + mRating = (RatingView) mAction.findViewById(R.id.rating); + mFavorite = (TextView) mAction.findViewById(R.id.favorite); + mTorrent = (TextView) mAction.findViewById(R.id.torrent); + mShare = (TextView) mAction.findViewById(R.id.share); + mRate = (TextView) mAction.findViewById(R.id.rate); - mViewTransition = new ViewTransition(mContent, mProgressView); + mTag = (ViewGroup) inflater.inflate(R.layout.gallery_detail_tag, noopLayout, false); + mNoTagText = (TextView) mTag.getChildAt(0); + + mComment = (ViewGroup) inflater.inflate(R.layout.gallery_detail_comment, noopLayout, false); + mCommentText = (TextView) mComment.getChildAt(0); + + mPreview = (PreviewLayout) inflater.inflate(R.layout.gallery_detail_preview, noopLayout, false); + + mProgress = inflater.inflate(R.layout.gallery_detail_progress, noopLayout, false); + mProgressView = mProgress.findViewById(R.id.progress_view); + + Resources resources = getStageActivity().getResources(); + + mAdapter = new DetailAdapter(); + mRecyclerView.setAdapter(mAdapter); + mRecyclerView.setLayoutManager(new LinearLayoutManager(getStageActivity())); + mRecyclerView.hasFixedSize(); + LinearDividerItemDecoration decoration = new LinearDividerItemDecoration( + LinearDividerItemDecoration.VERTICAL, resources.getColor(R.color.divider_light), + LayoutUtils.dp2pix(getStageActivity(), 1)); + decoration.setShowDividerHelper(this); + decoration.setPadding(resources.getDimensionPixelOffset(R.dimen.keyline_margin_horizontal)); + mRecyclerView.addItemDecoration(decoration); + + mDownload.setOnClickListener(this); + mRead.setOnClickListener(this); + mFavorite.setOnClickListener(this); + mTorrent.setOnClickListener(this); + mShare.setOnClickListener(this); + mRate.setOnClickListener(this); + mFailedView.setOnClickListener(this); + + AccurateClick.setOnAccurateClickListener(mInfo, this); + AccurateClick.setOnAccurateClickListener(mComment, this); + + RippleSalon.addRipple(mDownload, false); + RippleSalon.addRipple(mRead, false); + RippleSalon.addRipple(mFavorite, false); + RippleSalon.addRipple(mTorrent, false); + RippleSalon.addRipple(mShare, false); + RippleSalon.addRipple(mRate, false); + + mPreview.setPreviewHelper(new SimplePreviewHelper()); } - private void handleAnnouncer(Announcer announcer) { - if (announcer == null) { - Say.e(TAG, "No announcer in GalleryDetailScene, finish itself"); - finish(); - return; - } + private void requestGalleryDetail(int gid, String token) { + EhClient client = EhApplication.getEhClient(getStageActivity()); + int source = Settings.getEhSource(); + String url = EhUrl.getDetailUrl(source, gid, token, 0); - String action = announcer.getAction(); - if (ACTION_GALLERY_INFO.equals(action)) { - GalleryInfo gi = announcer.getExtra(KEY_GALLERY_INFO, GalleryInfo.class); - if (gi != null) { - - Conaco conaco = EhApplication.getConaco(getStageActivity()); - mThumb.load(conaco, EhCacheKeyFactory.getThumbKey(gi.gid), gi.thumb); - mTitle.setText(EhUtils.getSuitableTitle(gi)); - mUploader.setText(gi.uploader); - mCategory.setText(EhUtils.getCategory(gi.category)); - mCategory.setTextColor(EhUtils.getCategoryColor(gi.category)); - - requestGalleryDetail(gi); - - - Context context = getStageActivity(); - Resources resources = context.getResources(); - - mViewTransition.showView(1, false); - - mRatingText.setFactory(new RatingTextViewFactory()); - - Drawable favoriteDrawable = resources.getDrawable(R.drawable.ic_heart_theme_primary); - Drawable torrentDrawable = resources.getDrawable(R.drawable.ic_water_pump_theme_primary); - Drawable shareDrawable = resources.getDrawable(R.drawable.ic_share_theme_primary); - Drawable rateDrawable = resources.getDrawable(R.drawable.ic_thumbs_up_down_theme_primary); - - int drawableSize = resources.getDimensionPixelOffset(R.dimen.detail_action_size); - favoriteDrawable.setBounds(0, 0, drawableSize, drawableSize); - torrentDrawable.setBounds(0, 0, drawableSize, drawableSize); - shareDrawable.setBounds(0, 0, drawableSize, drawableSize); - rateDrawable.setBounds(0, 0, drawableSize, drawableSize); - - mFavorite.setCompoundDrawables(null, favoriteDrawable, null, null); - mTorrent.setCompoundDrawables(null, torrentDrawable, null, null); - mShare.setCompoundDrawables(null, shareDrawable, null, null); - mRate.setCompoundDrawables(null, rateDrawable, null, null); - - - mRead.setOnClickListener(this); - mDownload.setOnClickListener(this); - mFavorite.setOnClickListener(this); - mTorrent.setOnClickListener(this); - mShare.setOnClickListener(this); - mRate.setOnClickListener(this); - - AccurateClick.setOnAccurateClickListener(mInfo, this); - AccurateClick.setOnAccurateClickListener(mComment, this); - - RippleSalon.addRipple(mRead, false); - RippleSalon.addRipple(mDownload, false); - RippleSalon.addRipple(mFavorite, false); - RippleSalon.addRipple(mTorrent, false); - RippleSalon.addRipple(mShare, false); - RippleSalon.addRipple(mRate, false); - - mPreviewLayout.setPreviewHelper(new SimplePreviewHelper()); - - } else { - Say.e(TAG, "Can't get GalleryDetail"); - finish(); - } - - } else if (ACTION_GID_TOKEN.equals(action)) { - - } else if (ACTION_URL.equals(action)) { - - } else { - Say.e(TAG, "GalleryDetailScene: Unkonwn action " + action); - finish(); - } + mEhRequest = new EhRequest(); + mEhRequest.setMethod(EhClient.METHOD_GET_GALLERY_DETAIL); + mEhRequest.setEhListener(new EhDetailListener()); + mEhRequest.setArgs(url, mSource); + mEhRequest.setEhConfig(mEhConfig); + client.execute(mEhRequest); } - @Override - protected void onBind() { - super.onBind(); - - handleAnnouncer(getAnnouncer()); - } - - @Override - protected void onRestore() { - super.onRestore(); - } - - @Override - protected void onGetFitPaddingBottom(int b) { - mDetailFrameLayout.setPadding(0, 0, 0, b); - } - - @Override - public void onClick(View v) { - GalleryDetail gd = mGalleryDetail; - if (gd == null) { - return; - } - - if (v == mRead) { - Intent intent = new Intent(getStageActivity(), GalleryActivity.class); - intent.setAction(GalleryActivity.ACTION_GALLERY_FROM_GALLERY_BASE); - intent.putExtra(GalleryActivity.KEY_GALLERY_BASE, mGalleryDetail); - //intent.setAction(GalleryActivity.ACTION_GALLERY_FROM_ARCHIVE); - //intent.putExtra(GalleryActivity.KEY_ARCHIVE_URI, - // Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "a.zip"))); - getStageActivity().startActivity(intent); - } else if (v == mDownload) { - - } else if (v == mFavorite) { - - } else if (v == mTorrent) { - - } else if (v == mShare) { - StartActivityHelper.share(getStageActivity(), - EhUrl.getDetailUrl(Settings.getEhSource(), gd.gid, gd.token, 0)); - } - } - - @Override - public void onAccurateClick(View v, float x, float y) { - GalleryDetail gd = mGalleryDetail; - if (gd == null) { - return; - } - - if (v == mInfo) { - int[] position = new int[2]; - ViewUtils.getLocationInAncestor(mInfo, position, getSceneView()); - Announcer announcer = new Announcer(); - announcer.putExtra(InfoScene.KEY_INFO, mGalleryDetail); - startScene(InfoScene.class, announcer, - new UnionCurtain(new RippleCurtain((int) x + position[0], (int) y + position[1]), - new OffsetCurtain(OffsetCurtain.DIRECTION_BOTTOM))); - } else if (v == mComment) { - int[] position = new int[2]; - ViewUtils.getLocationInAncestor(mComment, position, getSceneView()); - Announcer announcer = new Announcer(); - announcer.putExtra(CommentScene.KEY_COMMENTS, mGalleryDetail.comments); - startScene(CommentScene.class, announcer, - new UnionCurtain(new RippleCurtain((int) x + position[0], (int) y + position[1]), - new OffsetCurtain(OffsetCurtain.DIRECTION_BOTTOM))); - } + private void bindFirst(GalleryBase gb) { + mThumb.load(EhApplication.getConaco(getStageActivity()), EhCacheKeyFactory.getThumbKey(gb.gid), gb.thumb); + mTitle.setText(EhUtils.getSuitableTitle(gb)); + mUploader.setText(gb.uploader); + mCategory.setText(EhUtils.getCategory(gb.category)); + mCategory.setTextColor(EhUtils.getCategoryColor(gb.category)); } private String getRatingText(float rating) { @@ -376,7 +321,7 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener, private void fillTags(List tags) { if (tags.size() != 0) { - mNoTags.setVisibility(View.GONE); + mNoTagText.setVisibility(View.GONE); Context context = getStageActivity(); LayoutInflater inflater = getStageActivity().getLayoutInflater(); @@ -426,13 +371,13 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener, mTag.addView(tagGroupLayout); } } else { - mNoTags.setVisibility(View.VISIBLE); + mNoTagText.setVisibility(View.VISIBLE); } } @SuppressLint("InflateParams") private View createCommentView(Comment comment) { - View view = LayoutInflater.from(getStageActivity()).inflate(R.layout.item_comment, null); + View view = LayoutInflater.from(getStageActivity()).inflate(R.layout.item_comment, null); ((TextView) view.findViewById(R.id.user)).setText(comment.user); ((TextView) view.findViewById(R.id.time)).setText(comment.time); TextView commentText = (TextView) view.findViewById(R.id.comment); @@ -444,81 +389,330 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener, return view; } - private class RatingTextViewFactory implements ViewSwitcher.ViewFactory { - @Override - public View makeView() { - TextView tv = new TextView(getStageActivity()); - tv.setGravity(Gravity.CENTER); - return tv; + private void fillComment(List comments) { + int commentNum = comments.size(); + if (commentNum == 0) { + mCommentText.setText(R.string.no_comments); + // Remove padding interval + mCommentText.setPadding(0, 0, 0, 0); + } else if (commentNum <= 2){ + mCommentText.setText(R.string.no_more_comments); + } else { + mCommentText.setText(R.string.more_comment); + } + int maxShown = Math.min(2, commentNum); + for (int i = 0; i < maxShown; i++) { + mComment.addView(createCommentView(comments.get(i)), i, + new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT)); + } + } + + private void bindSecond(GalleryDetail gd) { + Resources resources = getStageActivity().getResources(); + mLanguage.setText(gd.language); + mPages.setText(String.format(resources.getString(R.string.page_count), + gd.pageCount)); + mSize.setText(gd.size); + mPosted.setText(gd.posted); + mResize.setText(gd.resize); + mFavoredTimes.setText(String.format(resources.getString(R.string.favorited_times), + gd.favoredTimes)); + + Drawable favoriteDrawable; + if (gd.isFavored) { + favoriteDrawable = resources.getDrawable(R.drawable.ic_heart_theme_primary); + } else { + favoriteDrawable = resources.getDrawable(R.drawable.ic_heart_outline_theme_primary); + } + if (favoriteDrawable == null) { + throw new IllegalStateException("Can't get favorite drawable"); + } + favoriteDrawable.setBounds(0, 0, favoriteDrawable.getIntrinsicWidth(), favoriteDrawable.getIntrinsicHeight()); + mFavorite.setCompoundDrawables(null, favoriteDrawable, null, null); + + mTorrent.setText(resources.getString(R.string.torrent) + " " + gd.torrentCount); + mRating.setRating(gd.rating); + mRatingText.setText(getAllRatingText(gd.rating, gd.ratedTimes)); + + fillTags(gd.tags); + + fillComment(gd.comments); + + mPreview.setData(gd.previewSetArray, + gd.gid, + getStageActivity().getLayoutInflater(), + EhApplication.getConaco(getStageActivity())); + mPreview.selectPreviewAt(0); + } + + private void bindGalleryInfo(GalleryBase galleryBase) { + mViewTransition.showView(0); // Show recycler view + + bindFirst(galleryBase); + mState = STATE_LOADING; + mAdapter.notifyDataSetChanged(); + requestGalleryDetail(galleryBase.gid, galleryBase.token); + } + + private void bindGidToken(int gid, String token) { + mViewTransition.showView(1); // Show progress view + + mState = STATE_TOTALLY_LOADING; + mAdapter.notifyDataSetChanged(); + requestGalleryDetail(gid, token); + } + + @Override + protected void onBind() { + super.onBind(); + + Announcer announcer = getAnnouncer(); + if (announcer != null) { + String action = announcer.getAction(); + mActionStr = action; + if (ACTION_GALLERY_INFO.equals(action)) { + mGalleryBase = announcer.getExtra(KEY_GALLERY_INFO, GalleryBase.class); + if (mGalleryBase != null) { + bindGalleryInfo(mGalleryBase); + return; + } + } else if (ACTION_GID_TOKEN.equals(action)) { + mGid = announcer.getIntExtra(KEY_GID, 0); + mToken = announcer.getStringExtra(KEY_TOKEN, null); + if (mGid != 0 && mToken != null) { + bindGidToken(mGid, mToken); + return; + } + } else if (ACTION_URL.equals(action)) { + GalleryDetailUrlParser.Result result = GalleryDetailUrlParser.parser( + announcer.getStringExtra(KEY_URL, null)); + if (result != null) { + result.gid = mGid; + result.token = mToken; + bindGidToken(mGid, mToken); + return; + } + } + } + + finish(); + } + + @Override + protected void onRestore() { + super.onRestore(); + + switch (mState) { + case STATE_TOTALLY_LOADING: + mViewTransition.showView(1); // Show progress view + break; + case STATE_LOADING: + mViewTransition.showView(0); // Show recycler view + bindFirst(mGalleryBase); + break; + case STATE_LOADED: + mViewTransition.showView(0); // Show recycler view + bindFirst(mGalleryDetail); + bindSecond(mGalleryDetail); + break; + case STATE_FAILED: + mViewTransition.showView(2); // Show failed view + mFailedText.setText(mErrorMessage); + break; + default: + throw new IllegalStateException("Unknown state " + mState); + } + } + + @Override + protected void onDie() { + super.onDie(); + + if (mEhRequest != null) { + mEhRequest.cancel(); + } + } + + @Override + public void onClick(View v) { + if (mFailedView == v) { + mViewTransition.showView(1); // Show progress view + mState = STATE_TOTALLY_LOADING; + mAdapter.notifyDataSetChanged(); + if (ACTION_GALLERY_INFO.equals(mActionStr)) { + requestGalleryDetail(mGalleryBase.gid, mGalleryBase.token); + } else { + requestGalleryDetail(mGid, mToken); + } + } else if (mDownload == v) { + // TODO + } else if (mRead == v) { + Intent intent = new Intent(getStageActivity(), GalleryActivity.class); + intent.setAction(GalleryActivity.ACTION_GALLERY_FROM_GALLERY_BASE); + intent.putExtra(GalleryActivity.KEY_GALLERY_BASE, mGalleryDetail); + //intent.setAction(GalleryActivity.ACTION_GALLERY_FROM_ARCHIVE); + //intent.putExtra(GalleryActivity.KEY_ARCHIVE_URI, + // Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "a.zip"))); + getStageActivity().startActivity(intent); + } else if (mFavorite == v) { + // TODO + } else if (mTorrent == v) { + if (mGalleryDetail.torrentCount > 0) { + // TODO + } + } else if (mShare == v) { + StartActivityHelper.share(getStageActivity(), + EhUrl.getDetailUrl(Settings.getEhSource(), mGalleryDetail.gid, mGalleryDetail.token, 0)); + } else if (mRate == v) { + // TODO + } + } + + @Override + public void onAccurateClick(View v, float x, float y) { + GalleryBase gb = mGalleryBase; + if (gb == null) { + gb = mGalleryDetail; + } + if (gb == null) { + return; + } + + if (v == mInfo) { + int[] position = new int[2]; + ViewUtils.getLocationInAncestor(mInfo, position, getSceneView()); + Announcer announcer = new Announcer(); + announcer.putExtra(InfoScene.KEY_INFO, mGalleryDetail); + startScene(InfoScene.class, announcer, + new UnionCurtain(new RippleCurtain((int) x + position[0], (int) y + position[1]), + new OffsetCurtain(OffsetCurtain.DIRECTION_BOTTOM))); + } else if (v == mComment) { + int[] position = new int[2]; + ViewUtils.getLocationInAncestor(mComment, position, getSceneView()); + Announcer announcer = new Announcer(); + announcer.putExtra(CommentScene.KEY_COMMENTS, mGalleryDetail.comments); + startScene(CommentScene.class, announcer, + new UnionCurtain(new RippleCurtain((int) x + position[0], (int) y + position[1]), + new OffsetCurtain(OffsetCurtain.DIRECTION_BOTTOM))); + } + } + + @Override + public boolean showDivider(int index) { + if (mState == STATE_LOADED) { + return index >= 3 && index <= 6; + } else { + return false; } } private class EhDetailListener extends EhClient.EhListener { @Override - public void onSuccess(GalleryDetail galleryDetail) { - mGalleryDetail = galleryDetail; + public void onSuccess(GalleryDetail result) { + mEhRequest = null; - Resources resources = getStageActivity().getResources(); - mLanguage.setText(galleryDetail.language); - mPages.setText(String.format(resources.getString(R.string.page_count), - galleryDetail.pageCount)); - mSize.setText(galleryDetail.size); - mPosted.setText(galleryDetail.posted); - mResize.setText(galleryDetail.resize); - mFavoredTimes.setText(String.format(resources.getString(R.string.favorited_times), - galleryDetail.favoredTimes)); - mRating.setRating(galleryDetail.rating); - mRatingText.setText(getAllRatingText(galleryDetail.rating, galleryDetail.ratedTimes)); - fillTags(galleryDetail.tags); - - int commentNum = galleryDetail.comments.size(); - if (commentNum == 0) { - mCommentMore.setText(R.string.no_comments); - // Remove padding interval - mCommentMore.setPadding(0, 0, 0, 0); - } else if (commentNum <= 2){ - mCommentMore.setText(R.string.no_more_comments); - } else { - mCommentMore.setText(R.string.more_comment); - } - int maxShown = Math.min(2, commentNum); - for (int i = 0; i < maxShown; i++) { - mComment.addView(createCommentView(galleryDetail.comments.get(i)), i, - new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT)); + int oldState = mState; + mGalleryDetail = result; + if (oldState == STATE_TOTALLY_LOADING) { + bindFirst(result); } + bindSecond(result); - mPreviewLayout.setData(galleryDetail.previewSetArray, - galleryDetail.gid, - getStageActivity().getLayoutInflater(), - EhApplication.getConaco(getStageActivity())); - mPreviewLayout.selectPreviewAt(0); - - mViewTransition.showView(0); + mState = STATE_LOADED; + mAdapter.notifyDataSetChanged(); + mViewTransition.showView(0); // Show recycler view } @Override public void onFailure(Exception e) { - e.printStackTrace(); - if (e instanceof OffensiveException) { + mEhRequest = null; - } else if (e instanceof EhException) { - new SimpleDialog.Builder(getStageActivity()).setTitle("Error") - .setMessage(e.getMessage()) - .setNegativeButton(android.R.string.cancel) - .setOnCloseListener(new SimpleDialog.OnCloseListener() { - @Override - public void onClose(SimpleDialog dialog, boolean cancel) { - finish(); - } - }).show(GalleryDetailScene.this); + Say.d(TAG, "Get gallery detail failed " + e.getClass().getName() + " " + e.getMessage()); + String readableError = ExceptionUtils.getReadableString(getStageActivity(), e); + String reason = ExceptionUtils.getReasonString(getStageActivity(), e); + if (reason != null) { + readableError += '\n' + reason; } + mErrorMessage = readableError; + mFailedText.setText(readableError); + + mState = STATE_FAILED; + mAdapter.notifyDataSetChanged(); + mViewTransition.showView(2); // Show failed view } @Override public void onCanceled() { + mEhRequest = null; + } + } + private class DetailHolder extends RecyclerView.ViewHolder { + + public DetailHolder(View itemView) { + super(itemView); + } + } + + private class DetailAdapter extends RecyclerView.Adapter { + + @Override + public DetailHolder onCreateViewHolder(ViewGroup parent, int viewType) { + switch (viewType) { + case TYPE_HEADER: + return new DetailHolder(mHeader); + case TYPE_BUTTON: + return new DetailHolder(mButton); + case TYPE_INFO: + return new DetailHolder(mInfo); + case TYPE_ACTION: + return new DetailHolder(mAction); + case TYPE_TAG: + return new DetailHolder(mTag); + case TYPE_COMMENT: + return new DetailHolder(mComment); + case TYPE_PREVIEW: + return new DetailHolder(mPreview); + case TYPE_PROGRESS: + return new DetailHolder(mProgress); + default: + throw new IllegalStateException("Unknown type " + viewType); + } + } + + @Override + public void onBindViewHolder(DetailHolder holder, int position) { + // Empty + } + + @Override + public int getItemViewType(int position) { + if (mState == STATE_LOADING) { + if (position >= 2) { + return TYPE_PROGRESS; + } else { + return position; + } + } else if (mState == STATE_LOADED) { + return position; + } else { + return -1; + } + } + + @Override + public int getItemCount() { + if (mState == STATE_TOTALLY_LOADING || mState == STATE_FAILED) { + return 0; + } else if (mState == STATE_LOADING) { + return COUNT_LOADING; + } else if (mState == STATE_LOADED) { + return COUNT_LOADED; + } else { + throw new IllegalStateException("Unknown state " + mState); + } } } @@ -532,17 +726,18 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener, EhRequest request = new EhRequest(); request.setMethod(EhClient.METHOD_GET_PREVIEW_SET); - // TODO request.setEhConfig(); - request.setArgs(url, source); + request.setEhConfig(mEhConfig); + request.setArgs(url, mSource); request.setEhListener(new EhClient.EhListener() { @Override public void onSuccess(PreviewSet result) { - mPreviewLayout.onGetPreview(result, index); + mPreview.onGetPreview(result, index); } @Override public void onFailure(Exception e) { + // TODO e.printStackTrace(); } @@ -568,14 +763,14 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener, } int[] position = new int[2]; - ViewUtils.getLocationInAncestor(mPreviewLayout, position, getSceneView()); + ViewUtils.getLocationInAncestor(mPreview, position, getSceneView()); new SimpleDialog.Builder(getStageActivity()).setTitle("Select page") .setStartPoint((int) (x + position[0]), (int) (y + position[1])) .setItems(array, new SimpleDialog.OnClickListener() { @Override public boolean onClick(SimpleDialog dialog, int which) { - mPreviewLayout.selectPreviewAt(which); + mPreview.selectPreviewAt(which); return true; } }).show(GalleryDetailScene.this); 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 3577b7a0f..a8c5ea126 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 @@ -588,15 +588,25 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper, } } + + @Override public void onApplySearch(String query) { // TODO check is source and search vaild - if (TextUtils.isEmpty(query) && (mViewTransition.getShownViewIndex() == 0 - || mSearchLayout.isSpecifyTag())) { - // Invaild search + if (mViewTransition.getShownViewIndex() == 0 && TextUtils.isEmpty(query)) { return; } + if (mViewTransition.getShownViewIndex() == 1) { + int searchMode = mSearchLayout.getSearchMode(); + if (searchMode == SearchLayout.SEARCH_MODE_NORMAL && + mSearchLayout.isSpecifyTag() && TextUtils.isEmpty(query)) { + return; + } else if (searchMode == SearchLayout.SEARCH_MODE_SPECIFY) { + return; + } + } + mDrawerListActivatedPosition = ContentActivity.DRAWER_LIST_NONE; mActivity.setDrawerListActivatedPosition(ContentActivity.DRAWER_LIST_NONE); @@ -740,6 +750,15 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper, // TODO } + @Override + public void onSpecifyGallery(int gid, String token) { + Announcer announcer = new Announcer(); + announcer.setAction(GalleryDetailScene.ACTION_GID_TOKEN); + announcer.putExtra(GalleryDetailScene.KEY_GID, gid); + announcer.putExtra(GalleryDetailScene.KEY_TOKEN, token); + startScene(GalleryDetailScene.class, announcer); + } + @Override public Scene getScene() { return this; diff --git a/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java b/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java index 67d6f568a..bc920111c 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java @@ -47,27 +47,31 @@ import com.hippo.yorozuya.ViewUtils; // TODO requst returnSearchBarPosition when content of recycler changed public class SearchLayout extends MonoRecyclerView implements CompoundButton.OnCheckedChangeListener, - View.OnClickListener, SelectSearchImageLayout.SelectSearchImageLayoutHelper { + View.OnClickListener, SelectSearchImageLayout.SelectSearchImageLayoutHelper, + SpecifyGalleryLayout.SpecifyGalleryHelper { private static final String STATE_KEY_SUPER = "super"; private static final String STATE_KEY_SEARCH_MODE = "search_mode"; private static final String STATE_KEY_ENABLE_ADVANCE = "enable_advance"; - private static final int SEARCH_MODE_NORMAL = 0; - private static final int SEARCH_MODE_IMAGE = 1; + public static final int SEARCH_MODE_NORMAL = 0; + public static final int SEARCH_MODE_IMAGE = 1; + public static final int SEARCH_MODE_SPECIFY = 2; private static final int ITEM_TYPE_NORMAL = 0; private static final int ITEM_TYPE_NORMAL_ADVANCE = 1; private static final int ITEM_TYPE_IMAGE = 2; - private static final int ITEM_TYPE_ACTION = 3; + private static final int ITEM_TYPE_SPECIFY = 3; + private static final int ITEM_TYPE_ACTION = 4; private static final int[] SEARCH_ITEM_COUNT_ARRAY = { - 3, 2 + 3, 2, 2 }; private static final int[][] SEARCH_ITEM_TYPE = { - {ITEM_TYPE_NORMAL, ITEM_TYPE_NORMAL_ADVANCE, ITEM_TYPE_ACTION}, // SEARCH_TYPE_NORMAL - {ITEM_TYPE_IMAGE, ITEM_TYPE_ACTION} // SEARCH_TYPE_IMAGE + {ITEM_TYPE_NORMAL, ITEM_TYPE_NORMAL_ADVANCE, ITEM_TYPE_ACTION}, // SEARCH_MODE_NORMAL + {ITEM_TYPE_IMAGE, ITEM_TYPE_ACTION}, // SEARCH_MODE_IMAGE + {ITEM_TYPE_SPECIFY, ITEM_TYPE_ACTION} // SEARCH_MODE_SPECIFY }; private Context mContext; @@ -89,6 +93,8 @@ public class SearchLayout extends MonoRecyclerView implements CompoundButton.OnC private SelectSearchImageLayout mImageSearchView; + private SpecifyGalleryLayout mSpecifyLayout; + private View mActionView; private TextView mAction1; private TextView mAction2; @@ -156,6 +162,12 @@ public class SearchLayout extends MonoRecyclerView implements CompoundButton.OnC // Init image search view mImageSearchView.setHelper(SearchLayout.this); + // Create specify gallery + mSpecifyLayout = (SpecifyGalleryLayout) mInflater.inflate(R.layout.search_specify, null); + + // Init specify gallery + mSpecifyLayout.setSpecifyGalleryHelper(this); + // Create action view mActionView = mInflater.inflate(R.layout.search_action, null); mAction1 = (TextView) mActionView.findViewById(R.id.search_action_1); @@ -170,6 +182,10 @@ public class SearchLayout extends MonoRecyclerView implements CompoundButton.OnC mAction2.setOnClickListener(SearchLayout.this); } + public int getSearchMode() { + return mSearchMode; + } + public void setFitPaddingTop(int fitPaddingTop) { setPadding(getPaddingLeft(), mSearchPaddingTopOrigin + fitPaddingTop, getPaddingRight(), getPaddingBottom()); } @@ -275,7 +291,7 @@ public class SearchLayout extends MonoRecyclerView implements CompoundButton.OnC int oldItemCount = mAdapter.getItemCount(); mSearchMode++; - if (mSearchMode > SEARCH_MODE_IMAGE) { + if (mSearchMode > SEARCH_MODE_SPECIFY) { mSearchMode = SEARCH_MODE_NORMAL; } @@ -316,6 +332,13 @@ public class SearchLayout extends MonoRecyclerView implements CompoundButton.OnC } } + @Override + public void onSpecifyGallery(int gid, String token) { + if (mHelper != null) { + mHelper.onSpecifyGallery(gid, token); + } + } + private class SimpleHolder extends RecyclerView.ViewHolder { public SimpleHolder(View itemView) { super(itemView); @@ -372,6 +395,10 @@ public class SearchLayout extends MonoRecyclerView implements CompoundButton.OnC ViewUtils.removeFromParent(mImageSearchView); content.addView(mImageSearchView); break; + case ITEM_TYPE_SPECIFY: + title.setText(R.string.search_specify_gallery); + ViewUtils.removeFromParent(mSpecifyLayout); + content.addView(mSpecifyLayout); } } @@ -389,6 +416,8 @@ public class SearchLayout extends MonoRecyclerView implements CompoundButton.OnC void onRequestSelectImage(); + void onSpecifyGallery(int gid, String token); + Scene getScene(); } } diff --git a/app/src/main/java/com/hippo/ehviewer/widget/SpecifyGalleryLayout.java b/app/src/main/java/com/hippo/ehviewer/widget/SpecifyGalleryLayout.java new file mode 100644 index 000000000..ca86497db --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/widget/SpecifyGalleryLayout.java @@ -0,0 +1,114 @@ +/* + * Copyright 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 + * 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.ehviewer.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.hippo.ehviewer.R; +import com.hippo.rippleold.RippleSalon; +import com.hippo.yorozuya.NumberUtils; + +public class SpecifyGalleryLayout extends LinearLayout implements View.OnClickListener, + TextView.OnEditorActionListener { + + private EditText mGid; + private EditText mToken; + private TextView mApply; + + private SpecifyGalleryHelper mHelper; + + public SpecifyGalleryLayout(Context context) { + super(context); + init(context); + } + + public SpecifyGalleryLayout(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public SpecifyGalleryLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + LayoutInflater.from(context).inflate(R.layout.widget_specify_gallery_layout, this, true); + setOrientation(VERTICAL); + + mGid = (EditText) findViewById(R.id.gid); + mToken = (EditText) findViewById(R.id.token); + mApply = (TextView) findViewById(R.id.apply); + + mToken.setOnEditorActionListener(this); + mApply.setOnClickListener(this); + + RippleSalon.addRipple(mApply, false); + } + + public void setSpecifyGalleryHelper(SpecifyGalleryHelper helper) { + mHelper = helper; + } + + private boolean checkToken(String token) { + token = token.toLowerCase(); + for (int i = 0, n = token.length(); i < n; i++) { + char ch = token.charAt(i); + if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) { + return false; + } + } + return true; + } + + @Override + public void onClick(View v) { + if (v == mApply) { + int gid = NumberUtils.parseIntSafely(mGid.getText().toString(), 0); + String token = mToken.getText().toString(); + if (token.length() == 10 && gid != 0 && checkToken(token)) { + mHelper.onSpecifyGallery(gid, token); + } else { + Toast.makeText(getContext(), R.string.em_invalid_input, Toast.LENGTH_SHORT).show(); + } + } + } + + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (v == mToken) { + if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) { + onClick(mApply); + return true; + } + } + return false; + } + + public interface SpecifyGalleryHelper { + void onSpecifyGallery(int gid, String token); + } +} diff --git a/app/src/main/java/com/hippo/scene/ElementsSharedCurtain.java b/app/src/main/java/com/hippo/scene/ElementsSharedCurtain.java index eb3763e04..b10731d5b 100644 --- a/app/src/main/java/com/hippo/scene/ElementsSharedCurtain.java +++ b/app/src/main/java/com/hippo/scene/ElementsSharedCurtain.java @@ -35,6 +35,7 @@ import com.hippo.yorozuya.Say; import com.hippo.yorozuya.ViewUtils; import java.util.HashSet; +import java.util.Iterator; import java.util.Set; public class ElementsSharedCurtain extends Curtain { @@ -148,7 +149,9 @@ public class ElementsSharedCurtain extends Curtain { int[] startloaction = new int[2]; int[] endloaction = new int[2]; - for (TransitionItem item : mTransitionItems) { + Iterator iterator = mTransitionItems.iterator(); + while (iterator.hasNext()) { + TransitionItem item = iterator.next(); final View enterView = item.enterView; final View exitView = item.exitView; @@ -157,6 +160,11 @@ public class ElementsSharedCurtain extends Curtain { int startWidth = exitView.getWidth(); int startHeight = exitView.getHeight(); + if (startWidth <= 0 || startHeight <= 0) { + iterator.remove(); + continue; + } + // Create bitmap view Bitmap bmp = ViewUtils.getBitmapFromView(enterView); View bmpView = new View(enterView.getContext()); diff --git a/app/src/main/java/com/hippo/scene/Scene.java b/app/src/main/java/com/hippo/scene/Scene.java index 0889b71ea..4db51c534 100644 --- a/app/src/main/java/com/hippo/scene/Scene.java +++ b/app/src/main/java/com/hippo/scene/Scene.java @@ -215,6 +215,12 @@ public abstract class Scene { } else { mSceneView.setVisibility(View.VISIBLE); } + + if (!rebirth) { + // Make sure soft key broad is hidden + InputMethodManager imm = (InputMethodManager) getStageActivity().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(getSceneView().getWindowToken(), 0); + } } void bind() { diff --git a/app/src/main/java/com/hippo/widget/NoopLayout.java b/app/src/main/java/com/hippo/widget/NoopLayout.java new file mode 100644 index 000000000..d5ee26e04 --- /dev/null +++ b/app/src/main/java/com/hippo/widget/NoopLayout.java @@ -0,0 +1,43 @@ +/* + * Copyright 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 + * 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.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.ViewGroup; + +/** + * An empty {@link ViewGroup} + */ +public class NoopLayout extends ViewGroup { + + public NoopLayout(Context context) { + super(context); + } + + public NoopLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public NoopLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + } +} diff --git a/app/src/main/java/com/hippo/widget/recyclerview/LinearDividerItemDecoration.java b/app/src/main/java/com/hippo/widget/recyclerview/LinearDividerItemDecoration.java index adcbe3f05..5d538b6fa 100644 --- a/app/src/main/java/com/hippo/widget/recyclerview/LinearDividerItemDecoration.java +++ b/app/src/main/java/com/hippo/widget/recyclerview/LinearDividerItemDecoration.java @@ -44,6 +44,8 @@ public class LinearDividerItemDecoration extends RecyclerView.ItemDecoration { private int mPaddingStart = 0; private int mPaddingEnd = 0; + private ShowDividerHelper mShowDividerHelper; + public LinearDividerItemDecoration(int orientation, int color, int thickness) { mRect = new Rect(); mPaint = new Paint(); @@ -53,6 +55,10 @@ public class LinearDividerItemDecoration extends RecyclerView.ItemDecoration { setThickness(thickness); } + public void setShowDividerHelper(ShowDividerHelper showDividerHelper) { + mShowDividerHelper = showDividerHelper; + } + public void setOrientation(int orientation) { if (orientation != HORIZONTAL && orientation != VERTICAL) { throw new IllegalArgumentException("invalid orientation"); @@ -92,20 +98,43 @@ public class LinearDividerItemDecoration extends RecyclerView.ItemDecoration { @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { - final int position = parent.getChildPosition(view); + final int position = parent.getChildLayoutPosition(view); final int itemCount = parent.getAdapter().getItemCount(); - if (mOrientation == VERTICAL) { - if (position == 0 && mShowFirstDivider) - outRect.top = mThickness; - outRect.bottom = mThickness; - if (position == itemCount - 1 && !mShowLastDivider) - outRect.bottom = 0; + + if (mShowDividerHelper != null) { + if (mOrientation == VERTICAL) { + if (position == 0 && mShowDividerHelper.showDivider(0)) { + outRect.top = mThickness; + } + if (mShowDividerHelper.showDivider(position + 1)) { + outRect.bottom = mThickness; + } + } else { + if (position == 0 && mShowDividerHelper.showDivider(0)) { + outRect.left = mThickness; + } + if (mShowDividerHelper.showDivider(position + 1)) { + outRect.right = mThickness; + } + } } else { - if (position == 0 && mShowFirstDivider) - outRect.left = mThickness; - outRect.right = mThickness; - if (position == itemCount - 1 && !mShowLastDivider) - outRect.left = 0; + if (mOrientation == VERTICAL) { + if (position == 0 && mShowFirstDivider) { + outRect.top = mThickness; + } + outRect.bottom = mThickness; + if (position == itemCount - 1 && !mShowLastDivider) { + outRect.bottom = 0; + } + } else { + if (position == 0 && mShowFirstDivider) { + outRect.left = mThickness; + } + outRect.right = mThickness; + if (position == itemCount - 1 && !mShowLastDivider) { + outRect.right = 0; + } + } } } @@ -133,20 +162,33 @@ public class LinearDividerItemDecoration extends RecyclerView.ItemDecoration { for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams(); + final int position = parent.getChildLayoutPosition(child); - if (i != childCount - 1 || mShowLastDivider - || parent.getChildPosition(child) != itemCount - 1) { + boolean show; + if (mShowDividerHelper != null) { + show = mShowDividerHelper.showDivider(position + 1); + } else { + show = position != itemCount - 1 || mShowLastDivider; + } + if (show) { final int top = child.getBottom() + lp.bottomMargin; final int bottom = top + mThickness; mRect.set(left, top, right, bottom); c.drawRect(mRect, mPaint); } - if (i == 0 && mShowFirstDivider && parent.getChildPosition(child) == 0) { - final int bottom = child.getTop() + lp.topMargin; - final int top = bottom - mThickness; - mRect.set(left, top, right, bottom); - c.drawRect(mRect, mPaint); + if (position == 0) { + if (mShowDividerHelper != null) { + show = mShowDividerHelper.showDivider(0); + } else { + show = mShowFirstDivider; + } + if (show) { + final int bottom = child.getTop() + lp.topMargin; + final int top = bottom - mThickness; + mRect.set(left, top, right, bottom); + c.drawRect(mRect, mPaint); + } } } } else { @@ -157,23 +199,39 @@ public class LinearDividerItemDecoration extends RecyclerView.ItemDecoration { for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams(); + final int position = parent.getChildLayoutPosition(child); - if (i != childCount - 1 || mShowLastDivider - || parent.getChildPosition(child) != itemCount - 1) { + boolean show; + if (mShowDividerHelper != null) { + show = mShowDividerHelper.showDivider(position + 1); + } else { + show = position != itemCount - 1 || mShowLastDivider; + } + if (show) { final int left = child.getRight() + lp.rightMargin; final int right = left + mThickness; mRect.set(left, top, right, bottom); c.drawRect(mRect, mPaint); } - if (i == 0 && mShowFirstDivider && parent.getChildPosition(child) == 0) { - final int right = child.getLeft() + lp.leftMargin; - final int left = right - mThickness; - mRect.set(left, top, right, bottom); - c.drawRect(mRect, mPaint); + if (position == 0) { + if (mShowDividerHelper != null) { + show = mShowDividerHelper.showDivider(0); + } else { + show = mShowFirstDivider; + } + if (show) { + final int right = child.getLeft() + lp.leftMargin; + final int left = right - mThickness; + mRect.set(left, top, right, bottom); + c.drawRect(mRect, mPaint); + } } } } } + public interface ShowDividerHelper { + boolean showDivider(int index); + } } diff --git a/app/src/main/res/drawable-hdpi/overscroll_edge.png b/app/src/main/res/drawable-hdpi/overscroll_edge.png deleted file mode 100644 index 1952e0ed3..000000000 Binary files a/app/src/main/res/drawable-hdpi/overscroll_edge.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/overscroll_glow.png b/app/src/main/res/drawable-hdpi/overscroll_glow.png deleted file mode 100644 index 45c013532..000000000 Binary files a/app/src/main/res/drawable-hdpi/overscroll_glow.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/overscroll_edge.png b/app/src/main/res/drawable-xhdpi/overscroll_edge.png deleted file mode 100644 index b5e6e61cd..000000000 Binary files a/app/src/main/res/drawable-xhdpi/overscroll_edge.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/overscroll_glow.png b/app/src/main/res/drawable-xhdpi/overscroll_glow.png deleted file mode 100644 index 779c3a590..000000000 Binary files a/app/src/main/res/drawable-xhdpi/overscroll_glow.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/overscroll_edge.png b/app/src/main/res/drawable-xxhdpi/overscroll_edge.png deleted file mode 100644 index 734bfa762..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/overscroll_edge.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/overscroll_glow.png b/app/src/main/res/drawable-xxhdpi/overscroll_glow.png deleted file mode 100644 index dc1f2795f..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/overscroll_glow.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_heart_outline_theme_primary.xml b/app/src/main/res/drawable/ic_heart_outline_theme_primary.xml new file mode 100644 index 000000000..0f06a0f49 --- /dev/null +++ b/app/src/main/res/drawable/ic_heart_outline_theme_primary.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_heart_theme_primary.xml b/app/src/main/res/drawable/ic_heart_theme_primary.xml index 8c6b800a3..52e803b0b 100644 --- a/app/src/main/res/drawable/ic_heart_theme_primary.xml +++ b/app/src/main/res/drawable/ic_heart_theme_primary.xml @@ -19,13 +19,13 @@ xmlns:auto="http://schemas.android.com/apk/res-auto" tools:targetApi="21" - auto:width="24dp" - auto:height="24dp" + auto:width="48dp" + auto:height="48dp" auto:viewportWidth="24" auto:viewportHeight="24" - android:width="24dp" - android:height="24dp" + android:width="48dp" + android:height="48dp" android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/src/main/res/drawable/ic_share_theme_primary.xml b/app/src/main/res/drawable/ic_share_theme_primary.xml index 3f0084620..f3d8610ac 100644 --- a/app/src/main/res/drawable/ic_share_theme_primary.xml +++ b/app/src/main/res/drawable/ic_share_theme_primary.xml @@ -19,13 +19,13 @@ xmlns:auto="http://schemas.android.com/apk/res-auto" tools:targetApi="21" - auto:width="24dp" - auto:height="24dp" + auto:width="48dp" + auto:height="48dp" auto:viewportWidth="24" auto:viewportHeight="24" - android:width="24dp" - android:height="24dp" + android:width="48dp" + android:height="48dp" android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/src/main/res/drawable/ic_thumbs_up_down_theme_primary.xml b/app/src/main/res/drawable/ic_thumbs_up_down_theme_primary.xml index fda917a3d..9d9843616 100644 --- a/app/src/main/res/drawable/ic_thumbs_up_down_theme_primary.xml +++ b/app/src/main/res/drawable/ic_thumbs_up_down_theme_primary.xml @@ -19,13 +19,13 @@ xmlns:auto="http://schemas.android.com/apk/res-auto" tools:targetApi="21" - auto:width="24dp" - auto:height="24dp" + auto:width="48dp" + auto:height="48dp" auto:viewportWidth="24" auto:viewportHeight="24" - android:width="24dp" - android:height="24dp" + android:width="48dp" + android:height="48dp" android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/src/main/res/drawable/ic_water_pump_theme_primary.xml b/app/src/main/res/drawable/ic_water_pump_theme_primary.xml index fba2a1179..f7a22d7ca 100644 --- a/app/src/main/res/drawable/ic_water_pump_theme_primary.xml +++ b/app/src/main/res/drawable/ic_water_pump_theme_primary.xml @@ -19,13 +19,13 @@ xmlns:auto="http://schemas.android.com/apk/res-auto" tools:targetApi="21" - auto:width="24dp" - auto:height="24dp" + auto:width="48dp" + auto:height="48dp" auto:viewportWidth="24" auto:viewportHeight="24" - android:width="24dp" - android:height="24dp" + android:width="48dp" + android:height="48dp" android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/src/main/res/layout-v21/gallery_detail_button_background.xml b/app/src/main/res/layout-v21/gallery_detail_button_background.xml new file mode 100644 index 000000000..97d5270ac --- /dev/null +++ b/app/src/main/res/layout-v21/gallery_detail_button_background.xml @@ -0,0 +1,36 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/gallery_detail_action.xml b/app/src/main/res/layout/gallery_detail_action.xml index 18529bcc1..3e808fca2 100644 --- a/app/src/main/res/layout/gallery_detail_action.xml +++ b/app/src/main/res/layout/gallery_detail_action.xml @@ -22,15 +22,11 @@ android:paddingTop="16dp" android:paddingBottom="16dp"> - + android:layout_gravity="center_horizontal"/> + auto:max="5"/> + android:text="@string/favorite" + android:drawablePadding="8dp"/> + android:drawablePadding="8dp" + android:drawableTop="@drawable/ic_water_pump_theme_primary"/> + android:text="@string/share" + android:drawablePadding="8dp" + android:drawableTop="@drawable/ic_share_theme_primary"/> + android:text="@string/rate" + android:drawablePadding="8dp" + android:drawableTop="@drawable/ic_thumbs_up_down_theme_primary"/> diff --git a/app/src/main/res/layout/gallery_detail_button.xml b/app/src/main/res/layout/gallery_detail_button.xml new file mode 100644 index 000000000..d2633103a --- /dev/null +++ b/app/src/main/res/layout/gallery_detail_button.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/gallery_detail_button_background.xml b/app/src/main/res/layout/gallery_detail_button_background.xml new file mode 100644 index 000000000..68b480a4c --- /dev/null +++ b/app/src/main/res/layout/gallery_detail_button_background.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/gallery_detail_comment.xml b/app/src/main/res/layout/gallery_detail_comment.xml index ba729b847..227e34a51 100644 --- a/app/src/main/res/layout/gallery_detail_comment.xml +++ b/app/src/main/res/layout/gallery_detail_comment.xml @@ -26,7 +26,7 @@ android:paddingRight="@dimen/keyline_margin"> - + android:layout_height="@dimen/gallery_detail_header_height" + android:background="?attr/colorPrimary" + android:paddingLeft="@dimen/keyline_margin_horizontal" + android:paddingRight="@dimen/keyline_margin_horizontal" + android:paddingTop="@dimen/keyline_margin_vertical" + android:paddingBottom="@dimen/keyline_margin_vertical"> - + - + - + - + - - - - - - - + diff --git a/app/src/main/res/layout/gallery_detail_info.xml b/app/src/main/res/layout/gallery_detail_info.xml index e116fc979..8acebf5c0 100644 --- a/app/src/main/res/layout/gallery_detail_info.xml +++ b/app/src/main/res/layout/gallery_detail_info.xml @@ -20,14 +20,16 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:paddingTop="@dimen/gallery_detail_info_margin_top" - android:paddingBottom="16dp"> + android:paddingTop="@dimen/keyline_margin_vertical" + android:paddingBottom="@dimen/keyline_margin_vertical" + android:paddingLeft="@dimen/keyline_margin_horizontal" + android:paddingRight="@dimen/keyline_margin_horizontal"> + android:paddingLeft="@dimen/keyline_margin_horizontal" + android:paddingRight="@dimen/keyline_margin_horizontal"> diff --git a/app/src/main/res/layout/gallery_detail_progress.xml b/app/src/main/res/layout/gallery_detail_progress.xml new file mode 100644 index 000000000..c544e2163 --- /dev/null +++ b/app/src/main/res/layout/gallery_detail_progress.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/app/src/main/res/layout/scene_gallery_detail.xml b/app/src/main/res/layout/scene_gallery_detail.xml index 942a003f6..912a1cf2f 100644 --- a/app/src/main/res/layout/scene_gallery_detail.xml +++ b/app/src/main/res/layout/scene_gallery_detail.xml @@ -1,12 +1,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_height="match_parent"/> + + + + + + + + diff --git a/app/src/main/res/layout/search_specify.xml b/app/src/main/res/layout/search_specify.xml new file mode 100644 index 000000000..fe12b8f5c --- /dev/null +++ b/app/src/main/res/layout/search_specify.xml @@ -0,0 +1,20 @@ + + + diff --git a/app/src/main/res/layout/widget_specify_gallery_layout.xml b/app/src/main/res/layout/widget_specify_gallery_layout.xml new file mode 100644 index 000000000..1e6e8ca61 --- /dev/null +++ b/app/src/main/res/layout/widget_specify_gallery_layout.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 21ebd8f78..bb3600f60 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -17,6 +17,8 @@ 16dp + 16dp + 16dp 24sp @@ -141,8 +143,14 @@ 2dp + 224dp 128dp 192dp + + + + + 40dp 224dp 248dp diff --git a/app/src/main/res/values/pathdata.xml b/app/src/main/res/values/pathdata.xml index bebe0a722..f1d43c5f4 100644 --- a/app/src/main/res/values/pathdata.xml +++ b/app/src/main/res/values/pathdata.xml @@ -28,6 +28,7 @@ M11.71,19C9.93,19 8.5,17.59 8.5,15.86C8.5,14.24 9.53,13.1 11.3,12.74C13.07,12.38 14.9,11.53 15.92,10.16C16.31,11.45 16.5,12.81 16.5,14.2C16.5,16.84 14.36,19 11.71,19M13.5,0.67C13.5,0.67 14.24,3.32 14.24,5.47C14.24,7.53 12.89,9.2 10.83,9.2C8.76,9.2 7.2,7.53 7.2,5.47L7.23,5.1C5.21,7.5 4,10.61 4,14A8,8 0 0,0 12,22A8,8 0 0,0 20,14C20,8.6 17.41,3.8 13.5,0.67Z M11,7V12.11L15.71,14.9L16.5,13.62L12.5,11.25V7M12.5,2C8.97,2 5.91,3.92 4.27,6.77L2,4.5V11H8.5L5.75,8.25C6.96,5.73 9.5,4 12.5,4A7.5,7.5 0 0,1 20,11.5A7.5,7.5 0 0,1 12.5,19C9.23,19 6.47,16.91 5.44,14H3.34C4.44,18.03 8.11,21 12.5,21C17.74,21 22,16.75 22,11.5A9.5,9.5 0 0,0 12.5,2Z M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z + M12.1,18.55L12,18.65L11.89,18.55C7.14,14.24 4,11.39 4,8.5C4,6.5 5.5,5 7.5,5C9.04,5 10.54,6 11.07,7.36H12.93C13.46,6 14.96,5 16.5,5C18.5,5 20,6.5 20,8.5C20,11.39 16.86,14.24 12.1,18.55M16.5,3C14.76,3 13.09,3.81 12,5.08C10.91,3.81 9.24,3 7.5,3C4.42,3 2,5.41 2,8.5C2,12.27 5.4,15.36 10.55,20.03L12,21.35L13.45,20.03C18.6,15.36 22,12.27 22,8.5C22,5.41 19.58,3 16.5,3Z M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z M17.25,18H6.75V4H17.25M14,21H10V20H14M16,1H8A3,3 0 0,0 5,4V20A3,3 0 0,0 8,23H16A3,3 0 0,0 19,20V4A3,3 0 0,0 16,1Z diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4551728ab..b4955cef6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -40,6 +40,7 @@ Advance Options Tag Search Image Search + Specify gallery Specify uploader Specify tag No keyword is OK @@ -128,6 +129,7 @@ Too many redirections Network error Weird + Invalid input Network available ? Can\'t find target Activity @@ -203,6 +205,7 @@ Retry Go to Unknown + Apply Homepage What\'s hot @@ -220,6 +223,7 @@ Read Torrent Share + Rate Comments Info diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 4c06b1407..66b19a3b4 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -66,7 +66,7 @@ @style/TextAppearance.AppCompat.Button bold center - 40dp + 48dp 88dp @dimen/card_button_padding ?attr/colorPrimary @@ -164,7 +164,7 @@ @@ -177,4 +177,15 @@ sans-serif-medium + + diff --git a/beerbelly b/beerbelly index 2d6dcbcc8..b3370ac00 160000 --- a/beerbelly +++ b/beerbelly @@ -1 +1 @@ -Subproject commit 2d6dcbcc8aa91eeceae51366178842e58bfd7477 +Subproject commit b3370ac00710f77401f745c8610dfd03e6a9d633 diff --git a/cardsalon b/cardsalon index f77d54a8f..a0184dfbd 160000 --- a/cardsalon +++ b/cardsalon @@ -1 +1 @@ -Subproject commit f77d54a8f09bd6d5837e7e659badb10893ee8c15 +Subproject commit a0184dfbd182aeeb5dede0b888fa27a9dd5ad5cc diff --git a/conaco b/conaco index ef916a783..005035b94 160000 --- a/conaco +++ b/conaco @@ -1 +1 @@ -Subproject commit ef916a783822c7bb3902321dc2492915a859951f +Subproject commit 005035b946ce9ff4f0affb0d2bc17930b512cc06 diff --git a/httpclient b/httpclient index 244f6d280..a195fb763 160000 --- a/httpclient +++ b/httpclient @@ -1 +1 @@ -Subproject commit 244f6d280110cb8dec23e843e057a81fa864a50d +Subproject commit a195fb76378cfc2a1c1c4545ac661b6d65268f5f diff --git a/rippleold b/rippleold index 4a8e513a0..9e13a3a61 160000 --- a/rippleold +++ b/rippleold @@ -1 +1 @@ -Subproject commit 4a8e513a01651100b9abd82b4cfe470e2dc9668e +Subproject commit 9e13a3a615b0efd86c3005d73740de035cb0a71e diff --git a/unifile b/unifile index 797141f39..a4330e1cb 160000 --- a/unifile +++ b/unifile @@ -1 +1 @@ -Subproject commit 797141f39ff5cf95c86aede2779929bba63c4373 +Subproject commit a4330e1cb7530ac8bf068ca494bda2e2e4c1f4e1 diff --git a/vectorold b/vectorold index 392080ca4..63d37f5ad 160000 --- a/vectorold +++ b/vectorold @@ -1 +1 @@ -Subproject commit 392080ca4aee11d20f877332da59a78a45948f9d +Subproject commit 63d37f5ad6bc90cee7c4fc08fe6572289a6223e1 diff --git a/yorozuya b/yorozuya index 75f9410d6..1c50a47df 160000 --- a/yorozuya +++ b/yorozuya @@ -1 +1 @@ -Subproject commit 75f9410d66feba9f8f19313c31518258801bf973 +Subproject commit 1c50a47dfc8c89c6168114c1fc6b5f0672d18466