package com.github.miao1007.animewallpaper.ui.activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.MainThread;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import android.support.v4.view.ViewCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.github.miao1007.animewallpaper.R;
import com.github.miao1007.animewallpaper.support.GlobalContext;
import com.github.miao1007.animewallpaper.support.api.ImageVO;
import com.github.miao1007.animewallpaper.support.api.konachan.DanbooruAPI;
import com.github.miao1007.animewallpaper.support.api.konachan.ImageResult;
import com.github.miao1007.animewallpaper.ui.adapter.BaseAdapter;
import com.github.miao1007.animewallpaper.ui.adapter.CardAdapter;
import com.github.miao1007.animewallpaper.ui.widget.ActionSheet;
import com.github.miao1007.animewallpaper.ui.widget.ExitAlertDialog;
import com.github.miao1007.animewallpaper.ui.widget.HistoryActionSheet;
import com.github.miao1007.animewallpaper.ui.widget.NavigationBar;
import com.github.miao1007.animewallpaper.ui.widget.Position;
import com.github.miao1007.animewallpaper.ui.widget.blur.BlurDrawable;
import com.github.miao1007.animewallpaper.utils.FileUtils;
import com.github.miao1007.animewallpaper.utils.LogUtils;
import com.github.miao1007.animewallpaper.utils.SquareUtils;
import com.github.miao1007.animewallpaper.utils.StatusBarUtils;
import com.google.gson.stream.MalformedJsonException;
import com.squareup.picasso.Picasso;
import im.fir.sdk.FIR;
import java.io.File;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
public class MainActivity extends AppCompatActivity
implements CardAdapter.OnItemClickListener, BaseAdapter.OnLoadMoreListener {
private static final String TAG = LogUtils.makeLogTag(MainActivity.class);
private static final String EXTRA_MAP = "ext";
private final Map<String, Object> query = new HashMap<>(4);
@BindView(R.id.navigation_bar) NavigationBar mNavigationBar;
@BindView(R.id.rv_frag_card) RecyclerView mRvFragCard;
@BindView(R.id.card_holder) FrameLayout mCardHolder;
@BindView(R.id.card_error_page) RelativeLayout mCardErrorPage;
//void multiple dynamic proxy
private DanbooruAPI repo;
private boolean isLoadingMore;
private BlurDrawable drawable;
public static void startRefreshActivity(Context context, String query) {
Intent intent = new Intent(context, MainActivity.class);
//destroy caller activity and this activity and recreate a new activity
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(EXTRA_MAP, query);
context.startActivity(intent);
}
private static String parseIntent(Intent intent) {
return intent.getStringExtra(EXTRA_MAP);
}
@OnClick(R.id.iv_history) void settings(View v) {
final File file = new File(FileUtils.EXT_STORAGE);
final ActionSheet a =
new HistoryActionSheet(getWindow(), new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Intent shareIntent = new Intent(Intent.ACTION_VIEW);
shareIntent.setDataAndType(Uri.fromFile(file.listFiles()[position]), "image/*");
startActivity(Intent.createChooser(shareIntent, getString(R.string.view_image_by)));
}
}, file);
a.setDrawable(drawable);
a.show();
}
@OnClick(R.id.iv_search) void iv_search(View v) {
startActivity(new Intent(this, SearchActivity.class));
}
@OnClick(R.id.error_page_refresh) void error_page_refresh() {
mCardErrorPage.setVisibility(View.GONE);
mRvFragCard.setVisibility(View.VISIBLE);
onRefresh();
}
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
SquareUtils.getDispatcher().executorService().execute(new Runnable() {
@WorkerThread @Override public void run() {
//116ms
GlobalContext.startThirdFrameWork();
//120ms
repo = SquareUtils.getRetrofit(DanbooruAPI.KONACHAN).create(DanbooruAPI.class);
runOnUiThread(new Runnable() {
@Override public void run() {
//using repo to load pages
onRefresh();
}
});
}
});
super.onCreate(savedInstanceState);
//draw views using WMS
setContentView(R.layout.fragment_card);
ButterKnife.bind(this);
StatusBarUtils.from(this)
.setLightStatusBar(true)
.setTransparentStatusbar(true)
.setTransparentNavigationbar(true)
.setActionbarView(mNavigationBar)
.process();
setUpList();
}
private void setUpList() {
CardAdapter mAdapter = new CardAdapter();
mAdapter.setLoadMoreListener(this);
mAdapter.setItemClickListener(this);
final LinearLayoutManager mLayoutManager = new LinearLayoutManager(this);
mRvFragCard.setLayoutManager(mLayoutManager);
mRvFragCard.setAdapter(mAdapter);
mRvFragCard.post(new Runnable() {
@Override public void run() {
int padding = mNavigationBar.getHeight() + StatusBarUtils.getStatusBarOffsetPx(
getApplicationContext());
mRvFragCard.setPadding(0, padding, 0, 0);
}
});
mRvFragCard.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
Picasso.with(recyclerView.getContext()).resumeTag(TAG);
} else {
Picasso.with(recyclerView.getContext()).pauseTag(TAG);
}
}
@Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
ViewCompat.postInvalidateOnAnimation(mNavigationBar);
}
});
drawable = new BlurDrawable(mCardHolder);
mNavigationBar.setBackgroundDrawable(drawable);
String tag = parseIntent(getIntent());
if (tag != null) {
query.clear();
query.put(DanbooruAPI.TAGS, tag + DanbooruAPI.TAG_SAFE);
}
}
private void loadPage(Map<String, Object> query) {
if (isLoadingMore) {
return;
}
if (mNavigationBar != null) {
mNavigationBar.setProgressBar(true);
}
if (query == null) {
query = new HashMap<>();
}
if ((query.isEmpty()) || (!query.containsKey(DanbooruAPI.TAGS))) {
query.put(DanbooruAPI.TAGS, DanbooruAPI.TAG_SAFE);
query.put(DanbooruAPI.LIMIT, 10);
}
repo.getImageList(query)
.subscribeOn(SquareUtils.getRxWorkerScheduler())
.flatMap(new Func1<List<ImageResult>, Observable<ImageResult>>() {
@Override public Observable<ImageResult> call(List<ImageResult> imageResults) {
return Observable.from(imageResults);
}
})
.map(ImageVO.FROM_IMAGE_RESULT)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<ImageVO>() {
@Override public void onCompleted() {
if (mRvFragCard != null && mRvFragCard.getAdapter() != null) {
mRvFragCard.getAdapter().notifyDataSetChanged();
}
if (mNavigationBar != null) {
mNavigationBar.setProgressBar(false);
}
isLoadingMore = false;
mCardErrorPage.setVisibility(View.INVISIBLE);
}
@Override public void onError(Throwable e) {
e.printStackTrace();
if (mNavigationBar != null) {
mNavigationBar.setProgressBar(false);
}
isLoadingMore = false;
mRvFragCard.setVisibility(View.GONE);
mCardErrorPage.setVisibility(View.VISIBLE);
//fix bugs on chinaNet
if (e instanceof MalformedJsonException) {
Toast.makeText(MainActivity.this, R.string.server_err_response, Toast.LENGTH_SHORT)
.show();
return;
}
//fix bugs on gfw
//ConnectException << SocketException
if (e instanceof SocketException | e instanceof UnknownHostException) {
Toast.makeText(MainActivity.this, R.string.please_try_proxy, Toast.LENGTH_SHORT)
.show();
FIR.addCustomizeValue("SOCKET", "can't connect by xxx");
FIR.sendCrashManually(e);
}
}
@Override public void onNext(ImageVO imageVO) {
((CardAdapter) mRvFragCard.getAdapter()).getData().add(imageVO);
}
});
}
@Override public void onItemClick(View v, int position) {
List<ImageVO> imageResult = ((CardAdapter) mRvFragCard.getAdapter()).getData();
DetailedActivity.startActivity(v.getContext(), Position.from(v), imageResult.get(position));
}
//swipe layout refresh callback
@MainThread private void onRefresh() {
Log.d(TAG, "onRefresh:query = " + query);
((CardAdapter) mRvFragCard.getAdapter()).getData().clear();
mRvFragCard.getAdapter().notifyDataSetChanged();
loadMore(1);
}
@Override public void loadMore(int page) {
Log.d(TAG, "loadMore:" + query);
query.put(DanbooruAPI.PAGE, page);
loadPage(query);//这里多线程也要手动控制isLoadingMore
}
@Override protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
// FIXME: 5/12/16 Calling RS with no Context active.
//if (drawable != null) {
// drawable.onDestroy();
//}
}
/**
* reuse drawable
*/
@Override public void onBackPressed() {
mRvFragCard.stopScroll();
final ExitAlertDialog dialog = new ExitAlertDialog(this, new View.OnClickListener() {
@Override public void onClick(View v) {
finish();
}
});
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override public void onCancel(DialogInterface dialog) {
drawable.setCornerRadius(0);
drawable.setDrawOffset(0, 0);
//restore dialog height to origin
drawable.setBounds(0, 0, mNavigationBar.getWidth(), mNavigationBar.getHeight());
}
});
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override public void onShow(DialogInterface dialog) {
//void random bug on screen
//mRvFragCard.stopNestedScroll();
}
});
dialog.getWindow().getDecorView().post(new Runnable() {
@Override public void run() {
drawable.setCornerRadius(getResources().getDimension(R.dimen.internal_searchbar_radius));
drawable.setDrawOffset(
(getWindow().getDecorView().getWidth() - dialog.getWindow().getDecorView().getWidth())
/ 2,
(getWindow().getDecorView().getHeight() - dialog.getWindow().getDecorView().getHeight()
+ StatusBarUtils.getStatusBarOffsetPx(getApplicationContext())) / 2/*Gravity.Center contains statusbar*/);
//equals to dialog.getWindow().geDecoView.setBackgroundDrawable(drawable);
dialog.getWindow().setBackgroundDrawable(drawable);
}
});
dialog.show();
}
}