package cgeo.geocaching; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.apps.navi.NavigationAppFactory; import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.list.StoredList; import cgeo.geocaching.models.Geocache; import cgeo.geocaching.network.Network; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.storage.DataStore; import cgeo.geocaching.ui.CacheDetailsCreator; import cgeo.geocaching.ui.WeakReferenceHandler; import cgeo.geocaching.utils.AndroidRxUtils; import cgeo.geocaching.utils.DisposableHandler; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.TextUtils; import cgeo.geocaching.utils.functions.Action1; import android.content.res.Configuration; import android.os.Bundle; import android.os.Message; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Set; import butterknife.ButterKnife; import io.reactivex.schedulers.Schedulers; import org.apache.commons.lang3.StringUtils; public class CachePopupFragment extends AbstractDialogFragment { private final Progress progress = new Progress(); public static DialogFragment newInstance(final String geocode) { final Bundle args = new Bundle(); args.putString(GEOCODE_ARG, geocode); final DialogFragment f = new CachePopupFragment(); f.setStyle(DialogFragment.STYLE_NO_TITLE, 0); f.setArguments(args); return f; } private static class StoreCacheHandler extends DisposableHandler { private final int progressMessage; private final WeakReference<CachePopupFragment> popupRef; StoreCacheHandler(final CachePopupFragment popup, final int progressMessage) { this.progressMessage = progressMessage; popupRef = new WeakReference<>(popup); } @Override public void handleRegularMessage(final Message msg) { if (msg.what == UPDATE_LOAD_PROGRESS_DETAIL && msg.obj instanceof String) { updateStatusMsg((String) msg.obj); } else { final CachePopupFragment popup = popupRef.get(); if (popup != null) { popup.init(); } } } private void updateStatusMsg(final String msg) { final CachePopupFragment popup = popupRef.get(); if (popup == null || !popup.isAdded()) { return; } popup.progress.setMessage(popup.getString(progressMessage) + "\n\n" + msg); } } private static class DropCacheHandler extends WeakReferenceHandler<CachePopupFragment> { DropCacheHandler(final CachePopupFragment popup) { super(popup); } @Override public void handleMessage(final Message msg) { final CachePopupFragment popup = getReference(); if (popup == null) { return; } popup.getActivity().finish(); } } @Override public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { final View v = inflater.inflate(R.layout.popup, container, false); initCustomActionBar(v); return v; } @Override protected void init() { super.init(); try { if (StringUtils.isNotBlank(cache.getName())) { setTitle(TextUtils.coloredCacheText(cache, cache.getName())); } else { setTitle(geocode); } final View view = getView(); assert view != null; final TextView titleView = ButterKnife.findById(view, R.id.actionbar_title); titleView.setCompoundDrawablesWithIntrinsicBounds(Compatibility.getDrawable(getResources(), cache.getType().markerId), null, null, null); final LinearLayout layout = ButterKnife.findById(view, R.id.details_list); details = new CacheDetailsCreator(getActivity(), layout); addCacheDetails(); // offline use CacheDetailActivity.updateOfflineBox(view, cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener(), null, new StoreCacheClickListener()); CacheDetailActivity.updateCacheLists(view, cache, res); } catch (final Exception e) { Log.e("CachePopupFragment.init", e); } // cache is loaded. remove progress-popup if any there progress.dismiss(); } @Override public boolean onOptionsItemSelected(final MenuItem item) { if (super.onOptionsItemSelected(item)) { return true; } final int menuItem = item.getItemId(); switch (menuItem) { case R.id.menu_delete: new DropCacheClickListener().onClick(getView()); return true; } return false; } @Override public void onConfigurationChanged(final Configuration newConfig) { super.onConfigurationChanged(newConfig); init(); } private class StoreCacheClickListener implements View.OnClickListener, View.OnLongClickListener { @Override public void onClick(final View arg0) { selectListsAndStore(false); } @Override public boolean onLongClick(final View v) { selectListsAndStore(true); return true; } private void selectListsAndStore(final boolean fastStoreOnLastSelection) { if (progress.isShowing()) { showToast(res.getString(R.string.err_detail_still_working)); return; } if (Settings.getChooseList() || cache.isOffline()) { // let user select list to store cache in new StoredList.UserInterface(getActivity()).promptForMultiListSelection(R.string.lists_title, new Action1<Set<Integer>>() { @Override public void call(final Set<Integer> selectedListIds) { storeCacheOnLists(selectedListIds); } }, true, cache.getLists(), fastStoreOnLastSelection); } else { storeCacheOnLists(Collections.singleton(StoredList.STANDARD_LIST_ID)); } } private void storeCacheOnLists(final Set<Integer> listIds) { if (cache.isOffline()) { // cache already offline, just add to another list DataStore.saveLists(Collections.singletonList(cache), listIds); CacheDetailActivity.updateOfflineBox(getView(), cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener(), null, new StoreCacheClickListener()); CacheDetailActivity.updateCacheLists(getView(), cache, res); } else { final StoreCacheHandler storeCacheHandler = new StoreCacheHandler(CachePopupFragment.this, R.string.cache_dialog_offline_save_message); final FragmentActivity activity = getActivity(); progress.show(activity, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.disposeMessage()); AndroidRxUtils.andThenOnUi(Schedulers.io(), new Runnable() { @Override public void run() { cache.store(listIds, storeCacheHandler); } }, new Runnable() { @Override public void run() { activity.supportInvalidateOptionsMenu(); final View view = getView(); if (view != null) { CacheDetailActivity.updateOfflineBox(view, cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener(), null, new StoreCacheClickListener()); CacheDetailActivity.updateCacheLists(view, cache, res); } } }); } } } private class RefreshCacheClickListener implements View.OnClickListener { @Override public void onClick(final View arg0) { if (progress.isShowing()) { showToast(res.getString(R.string.err_detail_still_working)); return; } if (!Network.isConnected()) { showToast(getString(R.string.err_server)); return; } final StoreCacheHandler refreshCacheHandler = new StoreCacheHandler(CachePopupFragment.this, R.string.cache_dialog_offline_save_message); progress.show(getActivity(), res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.disposeMessage()); cache.refresh(refreshCacheHandler, AndroidRxUtils.networkScheduler); } } private class DropCacheClickListener implements View.OnClickListener { @Override public void onClick(final View arg0) { if (progress.isShowing()) { showToast(res.getString(R.string.err_detail_still_working)); return; } final DropCacheHandler dropCacheHandler = new DropCacheHandler(CachePopupFragment.this); progress.show(getActivity(), res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true, null); cache.drop(dropCacheHandler); } } @Override public void navigateTo() { NavigationAppFactory.startDefaultNavigationApplication(1, getActivity(), cache); } @Override public void showNavigationMenu() { NavigationAppFactory.showNavigationMenu(getActivity(), cache, null, null, true, true); } /** * Tries to navigate to the {@link Geocache} of this activity. */ @Override protected void startDefaultNavigation2() { if (cache == null || cache.getCoords() == null) { showToast(res.getString(R.string.cache_coordinates_no)); return; } NavigationAppFactory.startDefaultNavigationApplication(2, getActivity(), cache); getActivity().finish(); } @Override protected TargetInfo getTargetInfo() { if (cache == null) { return null; } return new TargetInfo(cache.getCoords(), cache.getGeocode()); } }