/* * 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.nimingban.ui; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.text.TextUtils; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.hippo.easyrecyclerview.EasyRecyclerView; import com.hippo.easyrecyclerview.MarginItemDecoration; import com.hippo.easyrecyclerview.RawMarginItemDecoration; import com.hippo.nimingban.Constants; import com.hippo.nimingban.NMBApplication; import com.hippo.nimingban.R; import com.hippo.nimingban.client.NMBClient; import com.hippo.nimingban.client.NMBRequest; import com.hippo.nimingban.client.ac.data.ACSearchItem; import com.hippo.nimingban.client.data.ACSite; import com.hippo.nimingban.util.ReadableTime; import com.hippo.nimingban.util.Settings; import com.hippo.nimingban.widget.ContentLayout; import com.hippo.nimingban.widget.FontTextView; import com.hippo.nimingban.widget.LoadImageView; import com.hippo.ripple.Ripple; import com.hippo.util.DrawableManager; import com.hippo.yorozuya.LayoutUtils; import com.hippo.yorozuya.Messenger; import com.hippo.yorozuya.ResourcesUtils; import java.lang.ref.WeakReference; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import jp.wasabeef.recyclerview.animators.SlideInUpAnimator; public class SearchActivity extends TranslucentActivity implements EasyRecyclerView.OnItemClickListener { public static final String ACTION_SEARCH = "com.hippo.nimingban.ui.SearchActivity.action.SEARCH"; public static final String KEY_KEYWORD = "keyword"; private NMBClient mNMBClient; private ContentLayout mContentLayout; private EasyRecyclerView mRecyclerView; private SearchAdapter mSearchAdapter; private SearchHelper mSearchHelper; private RecyclerView.OnScrollListener mOnScrollListener; private NMBRequest mNMBRequest; private String mKeyword; private List<WeakReference<SearchHolder>> mHolderList = new LinkedList<>(); @Override protected int getLightThemeResId() { return Settings.getColorStatusBar() ? R.style.NormalActivity : R.style.NormalActivity_NoStatus; } @Override protected int getDarkThemeResId() { return Settings.getColorStatusBar() ? R.style.NormalActivity_Dark : R.style.NormalActivity_Dark_NoStatus; } // false for error private boolean handlerIntent(Intent intent) { if (intent == null) { return false; } String action = intent.getAction(); if (ACTION_SEARCH.equals(action)) { String keyword = intent.getStringExtra(KEY_KEYWORD); if (keyword != null) { mKeyword = keyword; setTitle(getString(R.string.search_title, keyword)); return true; } } return false; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (!handlerIntent(getIntent())) { finish(); return; } mNMBClient = NMBApplication.getNMBClient(this); setStatusBarColor(ResourcesUtils.getAttrColor(this, R.attr.colorPrimaryDark)); ToolbarActivityHelper.setContentView(this, R.layout.activity_search); setActionBarUpIndicator(DrawableManager.getDrawable(this, R.drawable.v_arrow_left_dark_x24)); mContentLayout = (ContentLayout) findViewById(R.id.content_layout); EasyRecyclerView recyclerView = mContentLayout.getRecyclerView(); mRecyclerView = recyclerView; mSearchHelper = new SearchHelper(); mSearchHelper.setEmptyString(getString(R.string.not_found)); mContentLayout.setHelper(mSearchHelper); if (Settings.getFastScroller()) { mContentLayout.showFastScroll(); } else { mContentLayout.hideFastScroll(); } mSearchAdapter = new SearchAdapter(); recyclerView.setAdapter(mSearchAdapter); recyclerView.setSelector(Ripple.generateRippleDrawable(this, ResourcesUtils.getAttrBoolean(this, R.attr.dark))); recyclerView.setDrawSelectorOnTop(true); recyclerView.setOnItemClickListener(this); recyclerView.hasFixedSize(); recyclerView.setClipToPadding(false); mOnScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (RecyclerView.SCROLL_STATE_DRAGGING == newState) { pauseHolders(); } else if (RecyclerView.SCROLL_STATE_IDLE == newState) { resumeHolders(); } } }; recyclerView.addOnScrollListener(mOnScrollListener); int interval = getResources().getDimensionPixelOffset(R.dimen.card_interval); if (getResources().getBoolean(R.bool.two_way)) { mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)); MarginItemDecoration decoration = new MarginItemDecoration(interval, interval, interval, interval, interval); mRecyclerView.addItemDecoration(decoration); decoration.applyPaddings(mRecyclerView); mRecyclerView.setItemAnimator(new SlideInUpAnimator()); } else { int halfInterval = interval / 2; mRecyclerView.addItemDecoration(new RawMarginItemDecoration(0, halfInterval, 0, halfInterval)); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerView.setPadding(0, halfInterval, 0, halfInterval); } mSearchHelper.firstRefresh(); Messenger.getInstance().register(Constants.MESSENGER_ID_FAST_SCROLLER, this); } @Override protected void onDestroy() { super.onDestroy(); Messenger.getInstance().unregister(Constants.MESSENGER_ID_FAST_SCROLLER, this); if (mNMBRequest != null) { mNMBRequest.cancel(); mNMBRequest = null; } mRecyclerView.removeOnScrollListener(mOnScrollListener); for (WeakReference<SearchHolder> ref : mHolderList) { SearchHolder holder = ref.get(); if (holder != null) { holder.thumb.unload(); } } mHolderList.clear(); } private void resumeHolders() { Iterator<WeakReference<SearchHolder>> iterator = mHolderList.iterator(); while (iterator.hasNext()) { SearchHolder holder = iterator.next().get(); if (holder != null) { // Only resume attached view holder if (holder.itemView.getParent() != null) { holder.thumb.start(); } } else { iterator.remove(); } } } @Override public void onResume() { super.onResume(); resumeHolders(); } private void pauseHolders() { Iterator<WeakReference<SearchHolder>> iterator = mHolderList.iterator(); while (iterator.hasNext()) { SearchHolder holder = iterator.next().get(); if (holder != null) { holder.thumb.stop(); } else { iterator.remove(); } } } @Override public void onPause() { super.onPause(); pauseHolders(); } @Override public void onReceive(int id, Object obj) { if (Constants.MESSENGER_ID_FAST_SCROLLER == id) { if (obj instanceof Boolean) { if ((Boolean) obj) { mContentLayout.showFastScroll(); } else { mContentLayout.hideFastScroll(); } } } else { super.onReceive(id, obj); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); return true; default: return super.onOptionsItemSelected(item); } } @Override public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) { Intent intent = new Intent(this, PostActivity.class); intent.setAction(PostActivity.ACTION_SITE_ID); intent.putExtra(PostActivity.KEY_SITE, ACSite.getInstance().getId()); intent.putExtra(PostActivity.KEY_ID, mSearchHelper.getDataAt(position).getNMBPostId()); startActivity(intent); return true; } private class SearchHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public TextView leftText; public TextView centerText; public TextView rightText; public FontTextView content; public LoadImageView thumb; public SearchHolder(View itemView) { super(itemView); leftText = (TextView) itemView.findViewById(R.id.left_text); centerText = (TextView) itemView.findViewById(R.id.center_text); rightText = (TextView) itemView.findViewById(R.id.right_text); content = (FontTextView) itemView.findViewById(R.id.content); thumb = (LoadImageView) itemView.findViewById(R.id.thumb); thumb.setOnClickListener(this); } @Override public void onClick(View v) { int position = getAdapterPosition(); if (position >= 0 && position < mSearchHelper.size()) { ACSearchItem item = mSearchHelper.getDataAt(position); String key = item.getNMBImageKey(); String image = item.getNMBImageUrl(); if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(image)) { Intent intent = new Intent(SearchActivity.this, GalleryActivity2.class); intent.setAction(GalleryActivity2.ACTION_SINGLE_IMAGE); intent.putExtra(GalleryActivity2.KEY_SITE, item.getNMBSite().getId()); intent.putExtra(GalleryActivity2.KEY_ID, item.getNMBId()); intent.putExtra(GalleryActivity2.KEY_KEY, key); intent.putExtra(GalleryActivity2.KEY_IMAGE, image); SearchActivity.this.startActivity(intent); } } } } private class SearchAdapter extends RecyclerView.Adapter<SearchHolder> { @Override public SearchHolder onCreateViewHolder(ViewGroup parent, int viewType) { SearchHolder holder = new SearchHolder(getLayoutInflater().inflate(R.layout.item_search, parent, false)); mHolderList.add(new WeakReference<>(holder)); return holder; } @Override public void onBindViewHolder(SearchHolder holder, int position) { ACSearchItem item = mSearchHelper.getDataAt(position); holder.leftText.setText(item.getNMBDisplayUsername()); holder.centerText.setText("No." + item.getNMBId()); holder.rightText.setText(ReadableTime.getDisplayTime(item.getNMBTime())); holder.content.setText(item.getNMBDisplayContent()); String thumbKey = item.getNMBThumbKey(); String thumbUrl = item.getNMBThumbUrl(); boolean showImage; boolean loadFromNetwork; int ils = Settings.getImageLoadingStrategy(); if (ils == Settings.IMAGE_LOADING_STRATEGY_ALL || (ils == Settings.IMAGE_LOADING_STRATEGY_WIFI && NMBApplication.isConnectedWifi(SearchActivity.this))) { showImage = true; loadFromNetwork = true; } else { showImage = Settings.getImageLoadingStrategy2(); loadFromNetwork = false; } if (!TextUtils.isEmpty(thumbKey) && !TextUtils.isEmpty(thumbUrl) && showImage) { holder.thumb.setVisibility(View.VISIBLE); holder.thumb.unload(); holder.thumb.load(thumbKey, thumbUrl, loadFromNetwork); } else { holder.thumb.setVisibility(View.GONE); holder.thumb.unload(); } holder.content.setTextSize(Settings.getFontSize()); holder.content.setLineSpacing(LayoutUtils.dp2pix(SearchActivity.this, Settings.getLineSpacing()), 1.0f); if (Settings.getFixEmojiDisplay()) { holder.content.useCustomTypeface(); } else { holder.content.useOriginalTypeface(); } } @Override public int getItemCount() { return mSearchHelper.size(); } @Override public void onViewAttachedToWindow(SearchHolder holder) { holder.thumb.start(); } @Override public void onViewDetachedFromWindow(SearchHolder holder) { holder.thumb.stop(); } } private class SearchHelper extends ContentLayout.ContentHelper<ACSearchItem> { @Override protected void getPageData(int taskId, int type, int page) { if (mNMBRequest != null) { mNMBRequest.cancel(); mNMBRequest = null; } NMBRequest request = new NMBRequest(); mNMBRequest = request; request.setSite(ACSite.getInstance()); request.setMethod(NMBClient.METHOD_SEARCH); request.setArgs(mKeyword, page); request.setCallback(new SearchListener(taskId, type, page)); mNMBClient.execute(request); } @Override protected Context getContext() { return SearchActivity.this; } @Override protected void notifyDataSetChanged() { mSearchAdapter.notifyDataSetChanged(); } @Override protected void notifyItemRangeRemoved(int positionStart, int itemCount) { mSearchAdapter.notifyItemRangeRemoved(positionStart, itemCount); } @Override protected void notifyItemRangeInserted(int positionStart, int itemCount) { mSearchAdapter.notifyItemRangeInserted(positionStart, itemCount); } } private class SearchListener implements NMBClient.Callback<List<ACSearchItem>> { private int mTaskId; private int mTaskType; private int mPage; public SearchListener(int taskId, int taskType, int page) { mTaskId = taskId; mTaskType = taskType; mPage = page; } @Override public void onSuccess(List<ACSearchItem> result) { // Clear mNMBRequest = null; if (result.isEmpty()) { mSearchHelper.onGetEmptyData(mTaskId); mSearchHelper.setPages(mPage); } else { mSearchHelper.onGetPageData(mTaskId, result); mSearchHelper.setPages(Integer.MAX_VALUE); } } @Override public void onFailure(Exception e) { // Clear mNMBRequest = null; mSearchHelper.onGetExpection(mTaskId, e); } @Override public void onCancel() { // Clear mNMBRequest = null; } } }