/*
* Copyright (C) 2015 Federico Iosue (federico.iosue@gmail.com)
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package it.feio.android.omninotes;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.DatePicker;
import android.widget.TimePicker;
import android.widget.Toast;
import butterknife.Bind;
import butterknife.ButterKnife;
import de.greenrobot.event.EventBus;
import de.keyboardsurfer.android.widget.crouton.Crouton;
import de.keyboardsurfer.android.widget.crouton.Style;
import edu.emory.mathcs.backport.java.util.Arrays;
import it.feio.android.omninotes.async.UpdaterTask;
import it.feio.android.omninotes.async.bus.PasswordRemovedEvent;
import it.feio.android.omninotes.async.bus.SwitchFragmentEvent;
import it.feio.android.omninotes.async.notes.NoteProcessorDelete;
import it.feio.android.omninotes.db.DbHelper;
import it.feio.android.omninotes.intro.IntroActivity;
import it.feio.android.omninotes.models.Attachment;
import it.feio.android.omninotes.models.Category;
import it.feio.android.omninotes.models.Note;
import it.feio.android.omninotes.utils.Constants;
import it.feio.android.omninotes.utils.MiscUtils;
import it.feio.android.omninotes.utils.PasswordHelper;
import java.util.ArrayList;
import java.util.HashMap;
public class MainActivity extends BaseActivity implements OnDateSetListener, OnTimeSetListener {
@Bind(R.id.crouton_handle) ViewGroup croutonViewContainer;
@Bind(R.id.toolbar) Toolbar toolbar;
@Bind(R.id.drawer_layout) DrawerLayout drawerLayout;
public final String FRAGMENT_DRAWER_TAG = "fragment_drawer";
public final String FRAGMENT_LIST_TAG = "fragment_list";
public final String FRAGMENT_DETAIL_TAG = "fragment_detail";
public final String FRAGMENT_SKETCH_TAG = "fragment_sketch";
private FragmentManager mFragmentManager;
public Uri sketchUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.OmniNotesTheme_ApiSpec);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
EventBus.getDefault().register(this);
// This method starts the bootstrap chain.
checkPassword();
initUI();
if (IntroActivity.mustRun()) {
startActivity(new Intent(this.getApplicationContext(), IntroActivity.class));
}
new UpdaterTask(this).execute();
}
@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
private void initUI() {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
private void checkPassword() {
if (prefs.getString(Constants.PREF_PASSWORD, null) != null
&& prefs.getBoolean("settings_password_access", false)) {
PasswordHelper.requestPassword(this, passwordConfirmed -> {
if (passwordConfirmed) {
init();
} else {
finish();
}
});
} else {
init();
}
}
public void onEvent(PasswordRemovedEvent passwordRemovedEvent) {
init();
}
private void init() {
mFragmentManager = getSupportFragmentManager();
NavigationDrawerFragment mNavigationDrawerFragment = (NavigationDrawerFragment) mFragmentManager
.findFragmentById(R.id.navigation_drawer);
if (mNavigationDrawerFragment == null) {
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.navigation_drawer, new NavigationDrawerFragment(),
FRAGMENT_DRAWER_TAG).commit();
}
if (mFragmentManager.findFragmentByTag(FRAGMENT_LIST_TAG) == null) {
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container, new ListFragment(), FRAGMENT_LIST_TAG).commit();
}
// Handling of Intent actions
handleIntents();
}
@Override
protected void onNewIntent(Intent intent) {
if (intent.getAction() == null) {
intent.setAction(Constants.ACTION_START_APP);
}
setIntent(intent);
handleIntents();
Log.d(Constants.TAG, "onNewIntent");
super.onNewIntent(intent);
}
public MenuItem getSearchMenuItem() {
Fragment f = checkFragmentInstance(R.id.fragment_container, ListFragment.class);
if (f != null) {
return ((ListFragment) f).getSearchMenuItem();
} else {
return null;
}
}
public void editTag(Category tag) {
Fragment f = checkFragmentInstance(R.id.fragment_container, ListFragment.class);
if (f != null) {
((ListFragment) f).editCategory(tag);
}
}
public void initNotesList(Intent intent) {
Fragment f = checkFragmentInstance(R.id.fragment_container, ListFragment.class);
if (f != null) {
((ListFragment) f).toggleSearchLabel(false);
((ListFragment) f).initNotesList(intent);
}
}
public void commitPending() {
Fragment f = checkFragmentInstance(R.id.fragment_container, ListFragment.class);
if (f != null) {
((ListFragment) f).commitPending();
}
}
/**
* Checks if allocated fragment is of the required type and then returns it or returns null
*/
private Fragment checkFragmentInstance(int id, Object instanceClass) {
Fragment result = null;
if (mFragmentManager != null) {
Fragment fragment = mFragmentManager.findFragmentById(id);
if (instanceClass.equals(fragment.getClass())) {
result = fragment;
}
}
return result;
}
/*
* (non-Javadoc)
* @see android.support.v7.app.ActionBarActivity#onBackPressed()
*
* Overrides the onBackPressed behavior for the attached fragments
*/
public void onBackPressed() {
Fragment f;
// SketchFragment
f = checkFragmentInstance(R.id.fragment_container, SketchFragment.class);
if (f != null) {
((SketchFragment) f).save();
// Removes forced portrait orientation for this fragment
setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
mFragmentManager.popBackStack();
return;
}
// DetailFragment
f = checkFragmentInstance(R.id.fragment_container, DetailFragment.class);
if (f != null) {
((DetailFragment) f).goBack = true;
((DetailFragment) f).saveAndExit((DetailFragment) f);
return;
}
// ListFragment
f = checkFragmentInstance(R.id.fragment_container, ListFragment.class);
if (f != null) {
// Before exiting from app the navigation drawer is opened
if (prefs.getBoolean("settings_navdrawer_on_exit", false) && getDrawerLayout() != null &&
!getDrawerLayout().isDrawerOpen(GravityCompat.START)) {
getDrawerLayout().openDrawer(GravityCompat.START);
} else if (!prefs.getBoolean("settings_navdrawer_on_exit", false) && getDrawerLayout() != null &&
getDrawerLayout().isDrawerOpen(GravityCompat.START)) {
getDrawerLayout().closeDrawer(GravityCompat.START);
} else {
if (!((ListFragment)f).closeFab()) {
super.onBackPressed();
}
}
return;
}
super.onBackPressed();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("navigationTmp", navigationTmp);
}
@Override
protected void onPause() {
super.onPause();
Crouton.cancelAllCroutons();
}
public DrawerLayout getDrawerLayout() {
return drawerLayout;
}
public ActionBarDrawerToggle getDrawerToggle() {
if (mFragmentManager != null && mFragmentManager.findFragmentById(R.id.navigation_drawer) != null) {
return ((NavigationDrawerFragment) mFragmentManager.findFragmentById(R.id.navigation_drawer)).mDrawerToggle;
} else {
return null;
}
}
/**
* Finishes multiselection mode started by ListFragment
*/
public void finishActionMode() {
ListFragment fragment = (ListFragment) mFragmentManager.findFragmentByTag(FRAGMENT_LIST_TAG);
if (fragment != null) {
fragment.finishActionMode();
}
}
Toolbar getToolbar() {
return this.toolbar;
}
private void handleIntents() {
Intent i = getIntent();
if (i.getAction() == null) return;
if (Constants.ACTION_RESTART_APP.equals(i.getAction())) {
MiscUtils.restartApp(getApplicationContext(), MainActivity.class);
}
if (receivedIntent(i)) {
Note note = i.getParcelableExtra(Constants.INTENT_NOTE);
if (note == null) {
note = DbHelper.getInstance().getNote(i.getIntExtra(Constants.INTENT_KEY, 0));
}
// Checks if the same note is already opened to avoid to open again
if (note != null && noteAlreadyOpened(note)) {
return;
}
// Empty note instantiation
if (note == null) {
note = new Note();
}
switchToDetail(note);
return;
}
if (Constants.ACTION_SEND_AND_EXIT.equals(i.getAction())) {
saveAndExit(i);
return;
}
// Tag search
if (Intent.ACTION_VIEW.equals(i.getAction())) {
switchToList();
return;
}
// Home launcher shortcut widget
if (Constants.ACTION_SHORTCUT_WIDGET.equals(i.getAction())) {
switchToDetail(new Note());
return;
}
}
/**
* Used to perform a quick text-only note saving (eg. Tasker+Pushbullet)
*/
private void saveAndExit(Intent i) {
Note note = new Note();
note.setTitle(i.getStringExtra(Intent.EXTRA_SUBJECT));
note.setContent(i.getStringExtra(Intent.EXTRA_TEXT));
DbHelper.getInstance().updateNote(note, true);
showToast(getString(R.string.note_updated), Toast.LENGTH_SHORT);
finish();
}
private boolean receivedIntent(Intent i) {
return Constants.ACTION_SHORTCUT.equals(i.getAction())
|| Constants.ACTION_NOTIFICATION_CLICK.equals(i.getAction())
|| Constants.ACTION_WIDGET.equals(i.getAction())
|| Constants.ACTION_TAKE_PHOTO.equals(i.getAction())
|| ((Intent.ACTION_SEND.equals(i.getAction())
|| Intent.ACTION_SEND_MULTIPLE.equals(i.getAction())
|| Constants.INTENT_GOOGLE_NOW.equals(i.getAction()))
&& i.getType() != null)
|| i.getAction().contains(Constants.ACTION_NOTIFICATION_CLICK);
}
private boolean noteAlreadyOpened(Note note) {
DetailFragment detailFragment = (DetailFragment) mFragmentManager.findFragmentByTag(FRAGMENT_DETAIL_TAG);
return detailFragment != null && detailFragment.getCurrentNote() != null && detailFragment.getCurrentNote()
.get_id().equals(note.get_id());
}
public void switchToList() {
FragmentTransaction transaction = mFragmentManager.beginTransaction();
animateTransition(transaction, TRANSITION_HORIZONTAL);
ListFragment mListFragment = new ListFragment();
transaction.replace(R.id.fragment_container, mListFragment, FRAGMENT_LIST_TAG).addToBackStack
(FRAGMENT_DETAIL_TAG).commitAllowingStateLoss();
if (getDrawerToggle() != null) {
getDrawerToggle().setDrawerIndicatorEnabled(false);
}
mFragmentManager.getFragments();
EventBus.getDefault().post(new SwitchFragmentEvent(SwitchFragmentEvent.Direction.PARENT));
}
public void switchToDetail(Note note) {
FragmentTransaction transaction = mFragmentManager.beginTransaction();
animateTransition(transaction, TRANSITION_HORIZONTAL);
DetailFragment mDetailFragment = new DetailFragment();
Bundle b = new Bundle();
b.putParcelable(Constants.INTENT_NOTE, note);
mDetailFragment.setArguments(b);
if (mFragmentManager.findFragmentByTag(FRAGMENT_DETAIL_TAG) == null) {
transaction.replace(R.id.fragment_container, mDetailFragment, FRAGMENT_DETAIL_TAG).addToBackStack
(FRAGMENT_LIST_TAG).commitAllowingStateLoss();
} else {
transaction.replace(R.id.fragment_container, mDetailFragment, FRAGMENT_DETAIL_TAG).addToBackStack
(FRAGMENT_DETAIL_TAG).commitAllowingStateLoss();
}
}
/**
* Notes sharing
*/
public void shareNote(Note note) {
String titleText = note.getTitle();
String contentText = titleText
+ System.getProperty("line.separator")
+ note.getContent();
Intent shareIntent = new Intent();
// Prepare sharing intent with only text
if (note.getAttachmentsList().size() == 0) {
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
// Intent with single image attachment
} else if (note.getAttachmentsList().size() == 1) {
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType(note.getAttachmentsList().get(0).getMime_type());
shareIntent.putExtra(Intent.EXTRA_STREAM, note.getAttachmentsList().get(0).getUri());
// Intent with multiple images
} else if (note.getAttachmentsList().size() > 1) {
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
ArrayList<Uri> uris = new ArrayList<>();
// A check to decide the mime type of attachments to share is done here
HashMap<String, Boolean> mimeTypes = new HashMap<>();
for (Attachment attachment : note.getAttachmentsList()) {
uris.add(attachment.getUri());
mimeTypes.put(attachment.getMime_type(), true);
}
// If many mime types are present a general type is assigned to intent
if (mimeTypes.size() > 1) {
shareIntent.setType("*/*");
} else {
shareIntent.setType((String) mimeTypes.keySet().toArray()[0]);
}
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
}
shareIntent.putExtra(Intent.EXTRA_SUBJECT, titleText);
shareIntent.putExtra(Intent.EXTRA_TEXT, contentText);
startActivity(Intent.createChooser(shareIntent, getResources().getString(R.string.share_message_chooser)));
}
/**
* Single note permanent deletion
*
* @param note Note to be deleted
*/
public void deleteNote(Note note) {
new NoteProcessorDelete(Arrays.asList(new Note[]{note})).process();
BaseActivity.notifyAppWidgets(this);
Log.d(Constants.TAG, "Deleted permanently note with id '" + note.get_id() + "'");
}
public void showMessage(int messageId, Style style) {
showMessage(getString(messageId), style);
}
public void showMessage(String message, Style style) {
// ViewGroup used to show Crouton keeping compatibility with the new Toolbar
runOnUiThread(() -> Crouton.makeText(this, message, style, croutonViewContainer).show());
}
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
DetailFragment f = (DetailFragment) mFragmentManager.findFragmentByTag(FRAGMENT_DETAIL_TAG);
if (f != null && f.isAdded()) {
f.onTimeSetListener.onTimeSet(view, hourOfDay, minute);
}
}
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear,
int dayOfMonth) {
DetailFragment f = (DetailFragment) mFragmentManager.findFragmentByTag(FRAGMENT_DETAIL_TAG);
if (f != null && f.isAdded() && f.onDateSetListener != null) {
f.onDateSetListener.onDateSet(view, year, monthOfYear, dayOfMonth);
}
}
}