package net.i2p.android.router.addressbook;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.Toast;
import com.eowise.recyclerview.stickyheaders.StickyHeadersBuilder;
import com.eowise.recyclerview.stickyheaders.StickyHeadersItemDecoration;
import com.pnikosis.materialishprogress.ProgressWheel;
import net.i2p.addressbook.Daemon;
import net.i2p.android.router.R;
import net.i2p.android.router.service.RouterService;
import net.i2p.android.router.service.State;
import net.i2p.android.router.util.Util;
import net.i2p.android.util.AlphanumericHeaderAdapter;
import net.i2p.android.util.FragmentUtils;
import net.i2p.android.widget.DividerItemDecoration;
import net.i2p.android.widget.LoadingRecyclerView;
import net.i2p.router.RouterContext;
import java.util.ArrayList;
import java.util.List;
public class AddressbookFragment extends Fragment implements
LoaderManager.LoaderCallbacks<List<AddressEntry>> {
public static final String BOOK_NAME = "book_name";
public static final String ROUTER_BOOK = "hosts.txt";
public static final String PRIVATE_BOOK = "privatehosts.txt";
private static final int ROUTER_LOADER_ID = 1;
private static final int PRIVATE_LOADER_ID = 2;
private OnAddressSelectedListener mCallback;
private LoadingRecyclerView mRecyclerView;
private AddressEntryAdapter mAdapter;
private String mBook;
private String mCurFilter;
private ImageButton mAddToAddressbook;
// Container Activity must implement this interface
public interface OnAddressSelectedListener {
void onAddressSelected(CharSequence host);
}
public static AddressbookFragment newInstance(String book) {
AddressbookFragment f = new AddressbookFragment();
Bundle args = new Bundle();
args.putString(AddressbookFragment.BOOK_NAME, book);
f.setArguments(args);
return f;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
mCallback = FragmentUtils.getParent(this, OnAddressSelectedListener.class);
if (mCallback == null)
throw new ClassCastException("Parent must implement OnAddressSelectedListener");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_list_with_add, container, false);
mRecyclerView = (LoadingRecyclerView) v.findViewById(R.id.list);
View empty = v.findViewById(R.id.empty);
ProgressWheel loading = (ProgressWheel) v.findViewById(R.id.loading);
mRecyclerView.setLoadingView(empty, loading);
mAddToAddressbook = (ImageButton) v.findViewById(R.id.promoted_action);
mAddToAddressbook.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent wi = new Intent(getActivity(), AddressbookAddWizardActivity.class);
getParentFragment().startActivityForResult(wi, AddressbookContainer.ADD_WIZARD_REQUEST);
}
});
return v;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mBook = getArguments().getString(BOOK_NAME);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
// use a linear layout manager
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
// Set the adapter for the list view
mAdapter = new AddressEntryAdapter(getActivity(), mCallback);
mRecyclerView.setAdapter(mAdapter);
// Build item decoration and add it to the RecyclerView
StickyHeadersItemDecoration decoration = new StickyHeadersBuilder()
.setAdapter(mAdapter)
.setRecyclerView(mRecyclerView)
.setStickyHeadersAdapter(new AlphanumericHeaderAdapter(mAdapter))
.build();
mRecyclerView.addItemDecoration(decoration);
// Initialize the adapter in case the RouterService has not been created
if (Util.getRouterContext() == null)
mAdapter.setAddresses(null);
}
@Override
public void onStart() {
super.onStart();
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getActivity());
IntentFilter filter = new IntentFilter();
filter.addAction(RouterService.LOCAL_BROADCAST_STATE_NOTIFICATION);
filter.addAction(RouterService.LOCAL_BROADCAST_STATE_CHANGED);
lbm.registerReceiver(onStateChange, filter);
}
private State lastRouterState = null;
private BroadcastReceiver onStateChange = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
State state = intent.getParcelableExtra(RouterService.LOCAL_BROADCAST_EXTRA_STATE);
if (lastRouterState == null || lastRouterState != state) {
updateState(state);
lastRouterState = state;
}
}
};
public void updateState(State state) {
int loaderId = PRIVATE_BOOK.equals(mBook) ?
PRIVATE_LOADER_ID : ROUTER_LOADER_ID;
if (state == State.STOPPING || state == State.STOPPED ||
state == State.MANUAL_STOPPING ||
state == State.MANUAL_STOPPED ||
state == State.MANUAL_QUITTING ||
state == State.MANUAL_QUITTED)
getLoaderManager().destroyLoader(loaderId);
else {
mRecyclerView.setLoading(true);
getLoaderManager().initLoader(loaderId, null, this);
}
}
@Override
public void onResume() {
super.onResume();
// Triggers loader init via updateState() if the router is running
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(new Intent(RouterService.LOCAL_BROADCAST_REQUEST_STATE));
}
@Override
public void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onStateChange);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_addressbook_actions, menu);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
RouterContext rCtx = Util.getRouterContext();
if (mAddToAddressbook != null)
mAddToAddressbook.setVisibility(rCtx == null ? View.GONE : View.VISIBLE);
// Only show "Reload subscriptions" for router addressbook
menu.findItem(R.id.action_reload_subscriptions).setVisible(
rCtx != null && !PRIVATE_BOOK.equals(mBook));
// Only allow adding to private book
if (!PRIVATE_BOOK.equals(mBook) && mAddToAddressbook != null) {
mAddToAddressbook.setVisibility(View.GONE);
mAddToAddressbook = null;
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_reload_subscriptions:
Daemon.wakeup();
Toast.makeText(getActivity(), "Reloading subscriptions...",
Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void filterAddresses(String query) {
mCurFilter = !TextUtils.isEmpty(query) ? query : null;
if (Util.getRouterContext() != null && mAdapter != null) {
mRecyclerView.setLoading(true);
getLoaderManager().restartLoader(PRIVATE_BOOK.equals(mBook) ?
PRIVATE_LOADER_ID : ROUTER_LOADER_ID, null, this);
}
}
// LoaderManager.LoaderCallbacks<List<AddressEntry>>
public Loader<List<AddressEntry>> onCreateLoader(int id, Bundle args) {
return new AddressEntryLoader(getActivity(), mBook, mCurFilter);
}
public void onLoadFinished(Loader<List<AddressEntry>> loader,
List<AddressEntry> data) {
if (loader.getId() == (PRIVATE_BOOK.equals(mBook) ?
PRIVATE_LOADER_ID : ROUTER_LOADER_ID)) {
mAdapter.setAddresses(data);
}
}
public void onLoaderReset(Loader<List<AddressEntry>> loader) {
if (loader.getId() == (PRIVATE_BOOK.equals(mBook) ?
PRIVATE_LOADER_ID : ROUTER_LOADER_ID)) {
if (Util.getRouterContext() == null)
mAdapter.setAddresses(null);
else
mAdapter.setAddresses(new ArrayList<AddressEntry>());
}
}
}