/** * Copyright (C) 2013 - 2015 the enviroCar community * * This file is part of the enviroCar app. * * The enviroCar app is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The enviroCar app is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with the enviroCar app. If not, see http://www.gnu.org/licenses/. */ package org.envirocar.app.view.logbook; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.AdapterView; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.afollestad.materialdialogs.MaterialDialog; import org.envirocar.app.R; import org.envirocar.app.handler.CarPreferenceHandler; import org.envirocar.app.view.utils.ECAnimationUtils; import org.envirocar.core.UserManager; import org.envirocar.core.entity.Fueling; import org.envirocar.core.exception.NotConnectedException; import org.envirocar.core.exception.UnauthorizedException; import org.envirocar.core.injection.BaseInjectorActivity; import org.envirocar.core.logging.Logger; import org.envirocar.remote.DAOProvider; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.inject.Inject; import butterknife.ButterKnife; import butterknife.InjectView; import butterknife.OnClick; import rx.Observer; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; import rx.subscriptions.CompositeSubscription; /** * TODO JavaDoc * * @author dewall */ public class LogbookActivity extends BaseInjectorActivity implements LogbookUiListener { private static final Logger LOG = Logger.getLogger(LogbookActivity.class); @Inject protected CarPreferenceHandler carHandler; @Inject protected DAOProvider daoProvider; @Inject protected UserManager userManager; @InjectView(R.id.activity_logbook_toolbar) protected Toolbar toolbar; @InjectView(R.id.activity_logbook_header) protected View headerView; @InjectView(R.id.activity_logbook_toolbar_new_fueling_fab) protected View newFuelingFab; @InjectView(R.id.activity_logbook_toolbar_fuelinglist) protected ListView fuelingList; @InjectView(R.id.layout_general_info_background) protected View infoBackground; @InjectView(R.id.layout_general_info_background_img) protected ImageView infoBackgroundImg; @InjectView(R.id.layout_general_info_background_firstline) protected TextView infoBackgroundFirst; @InjectView(R.id.layout_general_info_background_secondline) protected TextView infoBackgroundSecond; // @InjectView(R.id.activity_logbook_not_logged_in) // protected View notLoggedInView; // @InjectView(R.id.activity_logbook_no_fuelings_info_view) // protected View noFuelingsView; protected LogbookListAdapter fuelingListAdapter; protected final List<Fueling> fuelings = new ArrayList<Fueling>(); private LogbookAddFuelingFragment addFuelingFragment; private final CompositeSubscription subscription = new CompositeSubscription(); @Override protected void onCreate(Bundle savedInstanceState) { LOG.info("onCreate()"); super.onCreate(savedInstanceState); // First, set the content view. setContentView(R.layout.activity_logbook); // Inject the Views. ButterKnife.inject(this); // Initializes the Toolbar. setSupportActionBar(toolbar); getSupportActionBar().setTitle("Logbook"); getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true); fuelingListAdapter = new LogbookListAdapter(this, fuelings); fuelingList.setAdapter(fuelingListAdapter); fuelingList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { final Fueling fueling = fuelings.get(position); new MaterialDialog.Builder(LogbookActivity.this) .title(R.string.logbook_dialog_delete_fueling_header) .content(R.string.logbook_dialog_delete_fueling_content) .positiveText(R.string.menu_delete) .negativeText(R.string.cancel) .onPositive((materialDialog, dialogAction) -> deleteFueling(fueling)) .show(); return false; } }); // When the user is logged in, then download its fuelings. Otherwise, show a "not logged // in" notification. if (userManager.isLoggedIn()) { downloadFuelings(); } else { LOG.info("User is not logged in."); headerView.setVisibility(View.GONE); newFuelingFab.setVisibility(View.GONE); showNotLoggedInInfo(); } } @Override protected void onDestroy() { LOG.info("onDestroy()"); super.onDestroy(); if (!subscription.isUnsubscribed()) { subscription.unsubscribe(); subscription.clear(); } } @Override public void onBackPressed() { LOG.info("onBackPressed()"); if(addFuelingFragment != null && addFuelingFragment.isVisible()){ hideAddFuelingCard(); LOG.info("AddFuelingCard was visible. Closing this card..."); return; } super.onBackPressed(); } @OnClick(R.id.activity_logbook_toolbar_new_fueling_fab) protected void onClickNewFuelingFAB() { if(carHandler.hasCars()) { // Click on the fab should first hide the fab and then open the AddFuelingFragment showAddFuelingCard(); } else { showSnackbarInfo(R.string.logbook_background_no_cars_second); } } @Override public void onHideAddFuelingCard() { hideAddFuelingCard(); } @Override public void onFuelingUploaded(Fueling fueling) { LOG.info("onFuelingUploaded()"); if (!this.fuelings.contains(fueling)) { fuelings.add(fueling); Collections.sort(fuelings); fuelingListAdapter.notifyDataSetChanged(); // Hide the NoFuelingsView if it is visible. if (!fuelings.isEmpty() && infoBackground.getVisibility() == View.VISIBLE) { ECAnimationUtils.animateHideView(LogbookActivity.this, infoBackground, R.anim.fade_out); } } } /** * Downloads the fuelings */ private void downloadFuelings() { LOG.info("downloadFuelings()"); subscription.add(daoProvider.getFuelingDAO().getFuelingsObservable() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<List<Fueling>>() { @Override public void onCompleted() { LOG.info("Download of fuelings completed"); if (fuelings.isEmpty()) { showNoFuelingsInfo(); } else { infoBackground.setVisibility(View.GONE); } } @Override public void onError(Throwable e) { LOG.error(e.getMessage(), e); } @Override public void onNext(List<Fueling> result) { // Add all remote fuelings fuelings.addAll(result); // Sort the list of fuelings Collections.sort(fuelings); // Redraw everything fuelingListAdapter.notifyDataSetChanged(); } })); } /** * Deletes a given fueling locally as well as from the enviroCar server. * * @param fueling the fueling to delete. */ private void deleteFueling(final Fueling fueling) { subscription.add(daoProvider.getFuelingDAO() .deleteFuelingObservable(fueling) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<Void>() { @Override public void onCompleted() { LOG.info(String.format("Successfully deleted fueling -> [%s]", fueling.getRemoteID())); // Remove the fueling from the local list. fuelings.remove(fueling); if (fuelings.isEmpty()) { showNoFuelingsInfo(); } fuelingListAdapter.notifyDataSetChanged(); // Show a notification about the success. showSnackbarInfo(R.string.logbook_deletion_success_tmp); } @Override public void onError(Throwable e) { LOG.warn(e.getMessage(), e); if (e instanceof NotConnectedException) { showSnackbarInfo(R.string.logbook_error_communication); } else if (e instanceof UnauthorizedException) { showSnackbarInfo(R.string.logbook_error_unauthorized); } } @Override public void onNext(Void aVoid) { // Nothing to do } })); } private void showNoFuelingsInfo() { showInfoBackground(R.drawable.img_logbook, R.string.logbook_background_no_fuelings_first, R.string.logbook_background_no_fuelings_second); } private void showNoCarsInfo() { showInfoBackground(R.drawable.img_car, R.string.logbook_background_no_cars_first, R.string.logbook_background_no_cars_second); } private void showNotLoggedInInfo() { showInfoBackground(R.drawable.img_logged_out, R.string.logbook_background_not_logged_in_first, R.string.logbook_background_no_fuelings_second); } private void showInfoBackground(int imgResource, int firstLine, int secondLine) { LOG.info("showInfoBackground()"); infoBackgroundImg.setImageResource(imgResource); infoBackgroundFirst.setText(firstLine); infoBackgroundSecond.setText(secondLine); ECAnimationUtils.animateShowView(this, infoBackground, R.anim.fade_in); } /** * Shows the AddFuelingCard */ private void showAddFuelingCard() { LOG.info("showAddFuelingCard()"); ECAnimationUtils.animateHideView(this, newFuelingFab, R.anim.fade_out, () -> { addFuelingFragment = new LogbookAddFuelingFragment(); getSupportFragmentManager() .beginTransaction() .replace(R.id.activity_logbook_container, addFuelingFragment) .commit(); LOG.info("AddFuelingCard should now be visible"); }); } /** * Hides the AddFuelingCard */ private void hideAddFuelingCard() { LOG.info("hideAddFuelingCard()"); getSupportFragmentManager() .beginTransaction() .remove(addFuelingFragment) .commit(); addFuelingFragment = null; ECAnimationUtils.animateShowView(LogbookActivity.this, newFuelingFab, R.anim.fade_in); } private void showSnackbarInfo(int resourceID) { Snackbar.make(toolbar, resourceID, Snackbar.LENGTH_LONG).show(); } }