/*
* Copyright (c) 2015 Jarrad Hope
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package io.syng.activity;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;
import io.syng.R;
import io.syng.adapter.DAppDrawerAdapter;
import io.syng.adapter.DAppDrawerAdapter.OnDAppClickListener;
import io.syng.adapter.ProfileDrawerAdapter;
import io.syng.adapter.ProfileDrawerAdapter.OnProfileClickListener;
import io.syng.adapter.helper.SimpleItemTouchHelperCallback;
import io.syng.entity.Dapp;
import io.syng.entity.Profile;
import io.syng.fragment.profile.ProfileDialogFragment;
import io.syng.util.GeneralUtil;
import io.syng.util.ProfileManager;
import io.syng.util.ProfileManager.ProfilesChangeListener;
import static android.view.View.VISIBLE;
public abstract class BaseActivity extends AppCompatActivity implements
OnClickListener, OnDAppClickListener, OnProfileClickListener, OnLongClickListener, ProfilesChangeListener {
private static final int DRAWER_CLOSE_DELAY_SHORT = 200;
private static final int DRAWER_CLOSE_DELAY_LONG = 400;
private static final String CONTRIBUTE_LINK = "https://github.com/syng-io";
private static final String CONTINUE_SEARCH_LINK = "dapp://syng.io/store?q=search%20query";
private ActionBarDrawerToggle mDrawerToggle;
private EditText mSearchTextView;
private DrawerLayout mDrawerLayout;
Toolbar topToolbar;
boolean isTopToolbarShown = true;
Runnable mShowToolbarRunnable = new Runnable() {
@Override
public void run() {
topToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator()).start();
isTopToolbarShown = true;
}
};
Runnable mHideToolbarRunnable = new Runnable() {
@Override
public void run() {
topToolbar.animate().translationY(-topToolbar.getBottom()).setInterpolator(new AccelerateInterpolator()).start();
isTopToolbarShown = false;
}
};
Handler mTopToolbarHandler = new Handler();
private View mFrontView;
private View mBackView;
private Handler mHandler = new Handler();
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
mDrawerLayout.closeDrawer(GravityCompat.START);
}
};
private ImageView mHeaderImageView;
private DAppDrawerAdapter mDAppsDrawerAdapter;
private ProfileDrawerAdapter mProfileDrawerAdapter;
private ItemTouchHelper mDAppsTouchHelper;
private ItemTouchHelper mProfilesTouchHelper;
protected abstract void onDAppClick(Dapp dapp);
@SuppressLint("InflateParams")
@Override
public void setContentView(final int layoutResID) {
LayoutInflater inflater = getLayoutInflater();
mDrawerLayout = (DrawerLayout) inflater.inflate(R.layout.drawer, null, false);
super.setContentView(mDrawerLayout);
FrameLayout content = (FrameLayout) findViewById(R.id.content);
ViewGroup inflated = (ViewGroup) inflater.inflate(layoutResID, content, true);
topToolbar = (Toolbar) inflated.findViewById(R.id.app_toolbar);
if (topToolbar != null) {
setSupportActionBar(topToolbar);
mDrawerLayout.setStatusBarBackgroundColor(ContextCompat.getColor(this, android.R.color.black));
}
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, topToolbar,
R.string.drawer_open, R.string.drawer_close) {
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
GeneralUtil.hideKeyBoard(mSearchTextView, BaseActivity.this);
mDAppsDrawerAdapter.setEditModeEnabled(false);
mProfileDrawerAdapter.setEditModeEnabled(false);
if (!isDrawerFrontViewActive()) {
flipDrawer();
}
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mSearchTextView = (EditText) findViewById(R.id.search);
initSearch();
findViewById(R.id.ll_settings).setOnClickListener(this);
findViewById(R.id.ll_contribute).setOnClickListener(this);
findViewById(R.id.drawer_header_item).setOnClickListener(this);
findViewById(R.id.drawer_header_item).setOnLongClickListener(this);
mFrontView = findViewById(R.id.ll_front_view);
mBackView = findViewById(R.id.ll_back_view);
RecyclerView profilesRecyclerView = (RecyclerView) findViewById(R.id.profile_drawer_recycler_view);
RecyclerView.LayoutManager layoutManager2 = new LinearLayoutManager(this);
profilesRecyclerView.setLayoutManager(layoutManager2);
mProfileDrawerAdapter = new ProfileDrawerAdapter(this, this, new ProfileDrawerAdapter.OnStartDragListener() {
@Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
mProfilesTouchHelper.startDrag(viewHolder);
}
});
profilesRecyclerView.setAdapter(mProfileDrawerAdapter);
ItemTouchHelper.Callback profilesCallback = new SimpleItemTouchHelperCallback(mProfileDrawerAdapter);
mProfilesTouchHelper = new ItemTouchHelper(profilesCallback);
mProfilesTouchHelper.attachToRecyclerView(profilesRecyclerView);
updateCurrentProfileName();
populateProfiles();
RecyclerView dAppsRecyclerView = (RecyclerView) findViewById(R.id.dapp_drawer_recycler_view);
dAppsRecyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager1 = new LinearLayoutManager(this);
dAppsRecyclerView.setLayoutManager(layoutManager1);
mDAppsDrawerAdapter = new DAppDrawerAdapter(this, this, new DAppDrawerAdapter.OnStartDragListener() {
@Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
mDAppsTouchHelper.startDrag(viewHolder);
}
});
dAppsRecyclerView.setAdapter(mDAppsDrawerAdapter);
ItemTouchHelper.Callback dAppsCallback = new SimpleItemTouchHelperCallback(mDAppsDrawerAdapter);
mDAppsTouchHelper = new ItemTouchHelper(dAppsCallback);
mDAppsTouchHelper.attachToRecyclerView(dAppsRecyclerView);
populateDApps();
mHeaderImageView = (ImageView) findViewById(R.id.iv_header);
Glide.with(this).load(ProfileManager.getCurrentProfileBackgroundResourceId()).into(mHeaderImageView);
GeneralUtil.showWarningDialogIfNeed(this);
ProfileManager.setProfilesChangeListener(this);
}
public void hideToolbar(int seconds) {
if (isTopToolbarShown) {
isTopToolbarShown = false;
mTopToolbarHandler.postDelayed(mHideToolbarRunnable, seconds * 1000);
}
}
public void showToolbar(int seconds) {
if (!isTopToolbarShown) {
isTopToolbarShown = true;
mTopToolbarHandler.postDelayed(mShowToolbarRunnable, seconds * 1000);
}
}
private void populateProfiles() {
mProfileDrawerAdapter.swapData(ProfileManager.getProfiles());
}
private void populateDApps() {
updateDAppList(mSearchTextView.getText().toString());
}
private void closeDrawer(int delayMills) {
mHandler.postDelayed(mRunnable, delayMills);
}
protected void closeDrawer() {
mHandler.postDelayed(mRunnable, DRAWER_CLOSE_DELAY_SHORT);
}
private void requestChangeProfile(final Profile profile) {
GeneralUtil.showProfilePasswordRequestDialog(BaseActivity.this, profile.getName(), new MaterialDialog.ButtonCallback() {
@SuppressWarnings("ConstantConditions")
@Override
public void onPositive(MaterialDialog dialog) {
View view = dialog.getCustomView();
EditText passwordText = (EditText) view.findViewById(R.id.et_pass);
String password = passwordText.getText().toString();
if (profile.checkPassword(password)) {
ProfileManager.setCurrentProfile(profile, password);
flipDrawer();
dialog.dismiss();
} else {
Toast.makeText(BaseActivity.this, "Password is not correct", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onNegative(MaterialDialog dialog) {
dialog.dismiss();
}
});
}
private void updateCurrentProfileName() {
TextView textView = (TextView) findViewById(R.id.tv_name);
textView.setText(ProfileManager.getCurrentProfile().getName());
}
private void initSearch() {
mSearchTextView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
String searchValue = editable.toString();
updateDAppList(searchValue);
}
});
mSearchTextView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN && keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
GeneralUtil.hideKeyBoard(mSearchTextView, BaseActivity.this);
return true;
}
return false;
}
});
}
private void updateDAppList(String filter) {
List<Dapp> mDApps = ProfileManager.getCurrentProfile().getDapps();
ArrayList<Dapp> dapps = new ArrayList<>(mDApps.size());
int length = mDApps.size();
for (int i = 0; i < length; i++) {
Dapp item = mDApps.get(i);
if (item.getName().toLowerCase().contains(filter.toLowerCase())) {
dapps.add(item);
}
}
mDAppsDrawerAdapter.setEditModeEnabled(false);
mDAppsDrawerAdapter.swapData(dapps);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
ProfileManager.removeProfilesChangeListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ll_contribute:
String url = CONTRIBUTE_LINK;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
closeDrawer(DRAWER_CLOSE_DELAY_LONG);
break;
case R.id.ll_settings:
startActivity(new Intent(BaseActivity.this, SettingsActivity.class));
closeDrawer(DRAWER_CLOSE_DELAY_LONG);
break;
case R.id.drawer_header_item:
if (isDrawerFrontViewActive()) {
mDAppsDrawerAdapter.setEditModeEnabled(false);
GeneralUtil.hideKeyBoard(mSearchTextView, BaseActivity.this);
}else{
mProfileDrawerAdapter.setEditModeEnabled(false);
}
flipDrawer();
break;
}
}
private void flipDrawer() {
ImageView imageView = (ImageView) findViewById(R.id.drawer_indicator);
if (isDrawerFrontViewActive()) {
mFrontView.setVisibility(View.GONE);
mBackView.setVisibility(VISIBLE);
imageView.setImageResource(R.drawable.ic_arrow_drop_up_black_24dp);
} else {
mBackView.setVisibility(View.GONE);
mFrontView.setVisibility(VISIBLE);
imageView.setImageResource(R.drawable.ic_arrow_drop_down_black_24dp);
}
}
private boolean isDrawerFrontViewActive() {
return mFrontView.getVisibility() == VISIBLE;
}
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
mDrawerLayout.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public void onDAppItemClick(Dapp dapp) {
onDAppClick(dapp);
closeDrawer();
}
@Override
public void onProfileClick(Profile profile) {
if (!ProfileManager.getCurrentProfile().getId().equals(profile.getId())) {
requestChangeProfile(profile);
}
}
@Override
public void onDAppEdit(final Dapp dapp) {
GeneralUtil.showDAppEditDialog(dapp, this);
}
@SuppressWarnings("ConstantConditions")
@Override
public void onProfileEdit(final Profile profile) {
if (ProfileManager.getCurrentProfile().getId().equals(profile.getId())) {
ProfileDialogFragment dialogFragment = ProfileDialogFragment.newInstance(profile);
dialogFragment.show(getSupportFragmentManager(), "profile_dialog");
} else {
GeneralUtil.showProfilePasswordRequestDialog(BaseActivity.this, profile.getName(), new MaterialDialog.ButtonCallback() {
@Override
public void onPositive(MaterialDialog dialog) {
View view = dialog.getCustomView();
EditText password = (EditText) view.findViewById(R.id.et_pass);
if (profile.checkPassword(password.getText().toString())) {
dialog.dismiss();
ProfileDialogFragment dialogFragment = ProfileDialogFragment.newInstance(profile);
dialogFragment.show(getSupportFragmentManager(), "profile_dialog");
} else {
Toast.makeText(BaseActivity.this, "Password is not correct", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onNegative(MaterialDialog dialog) {
dialog.dismiss();
}
});
}
}
@Override
public void onDAppAdd() {
GeneralUtil.showDAppCreateDialog(this);
}
@Override
public void onDAppContinueSearch() {
String url = CONTINUE_SEARCH_LINK;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
closeDrawer();
mSearchTextView.getText().clear();
}
}
@Override
public void onProfileAdd() {
GeneralUtil.showProfileCreateDialog(this, true, null);
}
@Override
public boolean onLongClick(View v) {
if (v.getId() == R.id.drawer_header_item) {
GeneralUtil.showHeaderBackgroundDialog(this);
}
return true;
}
@Override
public void onProfilesChange() {
updateCurrentProfileName();
populateDApps();
populateProfiles();
Glide.with(this).load(ProfileManager.getCurrentProfileBackgroundResourceId()).into(mHeaderImageView);
}
}