mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
443 lines
15 KiB
Java
443 lines
15 KiB
Java
/**
|
|
* Copyright (c) 2012 Todoroo Inc
|
|
*
|
|
* See the file "LICENSE" for the full license governing this code.
|
|
*/
|
|
package com.todoroo.astrid.activity;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.os.Bundle;
|
|
import android.support.v4.graphics.drawable.DrawableCompat;
|
|
import android.support.v7.widget.Toolbar;
|
|
import android.text.format.DateUtils;
|
|
import android.view.LayoutInflater;
|
|
import android.view.Menu;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.ViewGroup.LayoutParams;
|
|
import android.widget.FrameLayout;
|
|
import android.widget.LinearLayout;
|
|
|
|
import com.todoroo.andlib.utility.AndroidUtilities;
|
|
import com.todoroo.andlib.utility.DateUtilities;
|
|
import com.todoroo.astrid.dao.MetadataDao;
|
|
import com.todoroo.astrid.dao.UserActivityDao;
|
|
import com.todoroo.astrid.data.Task;
|
|
import com.todoroo.astrid.data.TaskAttachment;
|
|
import com.todoroo.astrid.data.UserActivity;
|
|
import com.todoroo.astrid.files.AACRecordingActivity;
|
|
import com.todoroo.astrid.files.FilesControlSet;
|
|
import com.todoroo.astrid.notes.EditNoteActivity;
|
|
import com.todoroo.astrid.service.TaskDeleter;
|
|
import com.todoroo.astrid.service.TaskService;
|
|
import com.todoroo.astrid.timers.TimerPlugin;
|
|
import com.todoroo.astrid.ui.EditTitleControlSet;
|
|
import com.todoroo.astrid.utility.Flags;
|
|
|
|
import org.tasks.R;
|
|
import org.tasks.dialogs.DialogBuilder;
|
|
import org.tasks.fragments.TaskEditControlSetFragmentManager;
|
|
import org.tasks.injection.ForActivity;
|
|
import org.tasks.injection.InjectingFragment;
|
|
import org.tasks.notifications.NotificationManager;
|
|
import org.tasks.preferences.ActivityPreferences;
|
|
import org.tasks.ui.MenuColorizer;
|
|
import org.tasks.ui.TaskEditControlFragment;
|
|
|
|
import java.util.List;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
import butterknife.Bind;
|
|
import butterknife.ButterKnife;
|
|
|
|
import static android.app.Activity.RESULT_OK;
|
|
import static org.tasks.date.DateTimeUtils.newDateTime;
|
|
|
|
/**
|
|
* This activity is responsible for creating new tasks and editing existing
|
|
* ones. It saves a task when it is paused (screen rotated, back button pressed)
|
|
* as long as the task has a title.
|
|
*
|
|
* @author timsu
|
|
*
|
|
*/
|
|
public final class TaskEditFragment extends InjectingFragment implements Toolbar.OnMenuItemClickListener {
|
|
|
|
public interface TaskEditFragmentCallbackHandler {
|
|
void taskEditFinished();
|
|
}
|
|
|
|
public static TaskEditFragment newTaskEditFragment(boolean isNewTask, Task task) {
|
|
TaskEditFragment taskEditFragment = new TaskEditFragment();
|
|
taskEditFragment.isNewTask = isNewTask;
|
|
taskEditFragment.model = task;
|
|
return taskEditFragment;
|
|
}
|
|
|
|
public static final String TAG_TASKEDIT_FRAGMENT = "taskedit_fragment"; //$NON-NLS-1$
|
|
|
|
// --- bundle tokens
|
|
|
|
/**
|
|
* Content Values to set
|
|
*/
|
|
public static final String TOKEN_VALUES = "v"; //$NON-NLS-1$
|
|
|
|
/**
|
|
* Task in progress (during orientation change)
|
|
*/
|
|
private static final String EXTRA_TASK = "extra_task"; //$NON-NLS-1$
|
|
private static final String EXTRA_IS_NEW_TASK = "extra_is_new_task";
|
|
|
|
// --- request codes
|
|
|
|
public static final int REQUEST_CODE_RECORD = 30; // TODO: move this to file control set
|
|
|
|
@Inject TaskService taskService;
|
|
@Inject MetadataDao metadataDao;
|
|
@Inject UserActivityDao userActivityDao;
|
|
@Inject TaskDeleter taskDeleter;
|
|
@Inject NotificationManager notificationManager;
|
|
@Inject ActivityPreferences preferences;
|
|
@Inject DialogBuilder dialogBuilder;
|
|
@Inject @ForActivity Context context;
|
|
@Inject TaskEditControlSetFragmentManager taskEditControlSetFragmentManager;
|
|
|
|
// --- UI components
|
|
|
|
private EditNoteActivity editNotes;
|
|
|
|
@Bind(R.id.edit_body) LinearLayout body;
|
|
@Bind(R.id.toolbar) Toolbar toolbar;
|
|
|
|
// --- other instance variables
|
|
|
|
/** true if editing started with a new task */
|
|
private boolean isNewTask = false;
|
|
|
|
/** task model */
|
|
Task model = null;
|
|
|
|
private boolean showEditComments;
|
|
private TaskEditFragmentCallbackHandler callback;
|
|
|
|
/*
|
|
* ======================================================================
|
|
* ======================================================= initialization
|
|
* ======================================================================
|
|
*/
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
// if we were editing a task already, restore it
|
|
if (savedInstanceState != null) {
|
|
model = savedInstanceState.getParcelable(EXTRA_TASK);
|
|
isNewTask = savedInstanceState.getBoolean(EXTRA_IS_NEW_TASK);
|
|
}
|
|
|
|
showEditComments = preferences.getBoolean(R.string.p_show_task_edit_comments, true);
|
|
|
|
getActivity().setResult(RESULT_OK);
|
|
}
|
|
|
|
@Override
|
|
public void onAttach(Activity activity) {
|
|
super.onAttach(activity);
|
|
|
|
callback = (TaskEditFragmentCallbackHandler) activity;
|
|
}
|
|
|
|
/*
|
|
* ======================================================================
|
|
* ==================================================== UI initialization
|
|
* ======================================================================
|
|
*/
|
|
|
|
@Override
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
Bundle savedInstanceState) {
|
|
View view = inflater.inflate(R.layout.fragment_task_edit, container, false);
|
|
ButterKnife.bind(this, view);
|
|
|
|
Drawable drawable = DrawableCompat.wrap(getResources().getDrawable(R.drawable.ic_save_24dp));
|
|
DrawableCompat.setTint(drawable, getResources().getColor(android.R.color.white));
|
|
toolbar.setNavigationIcon(drawable);
|
|
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
save();
|
|
}
|
|
});
|
|
toolbar.inflateMenu(R.menu.task_edit_fragment);
|
|
Menu menu = toolbar.getMenu();
|
|
for (int i = 0 ; i < menu.size() ; i++) {
|
|
MenuColorizer.colorMenuItem(menu.getItem(i), getResources().getColor(android.R.color.white));
|
|
}
|
|
toolbar.setOnMenuItemClickListener(this);
|
|
|
|
notificationManager.cancel(model.getId());
|
|
|
|
if (!showEditComments) {
|
|
// TODO: hide comment bar
|
|
}
|
|
|
|
return view;
|
|
}
|
|
|
|
|
|
@Override
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
AndroidUtilities.hideKeyboard(getActivity());
|
|
|
|
switch (item.getItemId()) {
|
|
case R.id.menu_record_note:
|
|
startRecordingAudio();
|
|
return true;
|
|
case R.id.menu_delete:
|
|
deleteButtonClick();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void onActivityCreated(Bundle savedInstanceState) {
|
|
super.onActivityCreated(savedInstanceState);
|
|
|
|
// Load task data in background
|
|
new TaskEditBackgroundLoader().start();
|
|
}
|
|
|
|
private void instantiateEditNotes() {
|
|
if (showEditComments) {
|
|
editNotes = new EditNoteActivity(metadataDao, userActivityDao, taskService, this, model.getId());
|
|
editNotes.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
|
|
body.addView(editNotes);
|
|
}
|
|
}
|
|
|
|
private void loadMoreContainer() {
|
|
if (editNotes == null) {
|
|
instantiateEditNotes();
|
|
} else {
|
|
editNotes.loadViewForTaskID(model.getId());
|
|
}
|
|
}
|
|
|
|
public Task stopTimer() {
|
|
TimerPlugin.stopTimer(notificationManager, taskService, context, model);
|
|
String elapsedTime = DateUtils.formatElapsedTime(model.getElapsedSeconds());
|
|
addComment(String.format("%s %s\n%s %s", //$NON-NLS-1$
|
|
getString(R.string.TEA_timer_comment_stopped),
|
|
DateUtilities.getTimeString(getActivity(), newDateTime()),
|
|
getString(R.string.TEA_timer_comment_spent),
|
|
elapsedTime), UserActivity.ACTION_TASK_COMMENT,
|
|
null);
|
|
return model;
|
|
}
|
|
|
|
public Task startTimer() {
|
|
TimerPlugin.startTimer(notificationManager, taskService, context, model);
|
|
addComment(String.format("%s %s",
|
|
getString(R.string.TEA_timer_comment_started),
|
|
DateUtilities.getTimeString(getActivity(), newDateTime())),
|
|
UserActivity.ACTION_TASK_COMMENT,
|
|
null);
|
|
return model;
|
|
}
|
|
|
|
/**
|
|
* Initialize task edit page in the background
|
|
*
|
|
* @author Tim Su <tim@todoroo.com>
|
|
*
|
|
*/
|
|
private class TaskEditBackgroundLoader extends Thread {
|
|
|
|
@Override
|
|
public void run() {
|
|
AndroidUtilities.sleepDeep(500L);
|
|
|
|
Activity activity = getActivity();
|
|
if (activity == null) {
|
|
return;
|
|
}
|
|
|
|
activity.runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (getActivity() != null) {
|
|
// todo: is this necessary?
|
|
loadMoreContainer();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ======================================================================
|
|
* =============================================== model reading / saving
|
|
* ======================================================================
|
|
*/
|
|
|
|
|
|
/** Save task model from values in UI components */
|
|
public void save() {
|
|
List<TaskEditControlFragment> fragments = taskEditControlSetFragmentManager.getFragmentsInPersistOrder();
|
|
if (hasChanges(fragments)) {
|
|
for (TaskEditControlFragment fragment : fragments) {
|
|
fragment.apply(model);
|
|
}
|
|
taskService.save(model);
|
|
|
|
boolean tagsChanged = Flags.check(Flags.TAGS_CHANGED);
|
|
|
|
// Notify task list fragment in multi-column case
|
|
// since the activity isn't actually finishing
|
|
TaskListActivity tla = (TaskListActivity) getActivity();
|
|
|
|
if (tagsChanged) {
|
|
tla.tagsChanged();
|
|
}
|
|
if (isNewTask) {
|
|
tla.getTaskListFragment().onTaskCreated(model.getId(), model.getUuid());
|
|
}
|
|
callback.taskEditFinished();
|
|
} else {
|
|
discard();
|
|
}
|
|
}
|
|
|
|
private EditTitleControlSet getEditTitleControlSet() {
|
|
return getFragment(EditTitleControlSet.TAG);
|
|
}
|
|
|
|
private FilesControlSet getFilesControlSet() {
|
|
return getFragment(FilesControlSet.TAG);
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private <T extends TaskEditControlFragment> T getFragment(int tag) {
|
|
return (T) getFragmentManager().findFragmentByTag(getString(tag));
|
|
}
|
|
|
|
/*
|
|
* ======================================================================
|
|
* ======================================================= event handlers
|
|
* ======================================================================
|
|
*/
|
|
|
|
private boolean hasChanges(List<TaskEditControlFragment> fragments) {
|
|
for (TaskEditControlFragment fragment : fragments) {
|
|
if (fragment.hasChanges(model)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void discardButtonClick() {
|
|
if (hasChanges(taskEditControlSetFragmentManager.getFragmentsInPersistOrder())) {
|
|
dialogBuilder.newMessageDialog(R.string.discard_confirmation)
|
|
.setPositiveButton(R.string.keep_editing, null)
|
|
.setNegativeButton(R.string.discard, new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
discard();
|
|
}
|
|
})
|
|
.show();
|
|
} else {
|
|
discard();
|
|
}
|
|
}
|
|
|
|
public void discard() {
|
|
if (isNewTask) {
|
|
TimerPlugin.stopTimer(notificationManager, taskService, getActivity(), model);
|
|
taskDeleter.delete(model);
|
|
}
|
|
|
|
callback.taskEditFinished();
|
|
}
|
|
|
|
protected void deleteButtonClick() {
|
|
dialogBuilder.newMessageDialog(R.string.DLG_delete_this_task_question)
|
|
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
TimerPlugin.stopTimer(notificationManager, taskService, getActivity(), model);
|
|
taskDeleter.delete(model);
|
|
callback.taskEditFinished();
|
|
}
|
|
})
|
|
.setNegativeButton(android.R.string.cancel, null)
|
|
.show();
|
|
}
|
|
|
|
private void startRecordingAudio() {
|
|
Intent recordAudio = new Intent(getActivity(), AACRecordingActivity.class);
|
|
startActivityForResult(recordAudio, REQUEST_CODE_RECORD);
|
|
}
|
|
|
|
@Override
|
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
if (editNotes == null) {
|
|
instantiateEditNotes();
|
|
}
|
|
|
|
if (requestCode == REQUEST_CODE_RECORD && resultCode == RESULT_OK) {
|
|
String recordedAudioPath = data.getStringExtra(AACRecordingActivity.RESULT_OUTFILE);
|
|
String recordedAudioName = data.getStringExtra(AACRecordingActivity.RESULT_FILENAME);
|
|
getFilesControlSet().createNewFileAttachment(recordedAudioPath, recordedAudioName, TaskAttachment.FILE_TYPE_AUDIO + "m4a"); //$NON-NLS-1$
|
|
} else {
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onSaveInstanceState(Bundle outState) {
|
|
super.onSaveInstanceState(outState);
|
|
|
|
outState.putParcelable(EXTRA_TASK, model);
|
|
outState.putBoolean(EXTRA_IS_NEW_TASK, isNewTask);
|
|
}
|
|
|
|
/*
|
|
* ======================================================================
|
|
* ========================================== UI component helper classes
|
|
* ======================================================================
|
|
*/
|
|
|
|
public void onPriorityChange(int priority) {
|
|
getEditTitleControlSet().setPriority(priority);
|
|
}
|
|
|
|
public void onRepeatChanged(boolean repeat) {
|
|
getEditTitleControlSet().repeatChanged(repeat);
|
|
}
|
|
|
|
public void addComment(String message, String actionCode, String picture) {
|
|
UserActivity userActivity = new UserActivity();
|
|
userActivity.setMessage(message);
|
|
userActivity.setAction(actionCode);
|
|
userActivity.setTargetId(model.getUuid());
|
|
userActivity.setCreatedAt(DateUtilities.now());
|
|
if (picture != null) {
|
|
userActivity.setPicture(picture);
|
|
}
|
|
userActivityDao.createNew(userActivity);
|
|
editNotes.reloadView();
|
|
}
|
|
}
|