Convert comment bar to fragment

pull/384/head
Alex Baker 9 years ago
parent b2e5236e56
commit b8c1f6d621

@ -351,6 +351,18 @@ public class AndroidUtilities {
return string.substring(0, 1).toUpperCase() + string.substring(1);
}
public static void hideKeyboard(Activity activity) {
try {
View currentFocus = activity.getCurrentFocus();
if (currentFocus != null) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(currentFocus.getWindowToken(), 0);
}
} catch (Exception e) {
Timber.e(e, e.getMessage());
}
}
/**
* Dismiss the keyboard if it is displayed by any of the listed views
* @param views - a list of views that might potentially be displaying the keyboard

@ -1,87 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.actfm;
import android.app.Fragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.widget.ArrayAdapter;
import com.todoroo.astrid.activity.TaskEditFragment;
import org.tasks.R;
import org.tasks.activities.CameraActivity;
import org.tasks.dialogs.DialogBuilder;
import org.tasks.preferences.Device;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
public class ActFmCameraModule {
private final Fragment fragment;
private Device device;
private DialogBuilder dialogBuilder;
public interface ClearImageCallback {
void clearImage();
}
@Inject
public ActFmCameraModule(Fragment fragment, Device device, DialogBuilder dialogBuilder) {
this.fragment = fragment;
this.device = device;
this.dialogBuilder = dialogBuilder;
}
public void showPictureLauncher(final ClearImageCallback clearImageOption) {
final List<Runnable> runnables = new ArrayList<>();
List<String> options = new ArrayList<>();
final boolean cameraAvailable = device.hasCamera();
if (cameraAvailable) {
runnables.add(new Runnable() {
@Override
public void run() {
fragment.startActivityForResult(new Intent(fragment.getActivity(), CameraActivity.class), TaskEditFragment.REQUEST_CODE_CAMERA);
}
});
options.add(fragment.getString(R.string.take_a_picture));
}
if (clearImageOption != null) {
runnables.add(new Runnable() {
@Override
public void run() {
clearImageOption.clearImage();
}
});
options.add(fragment.getString(R.string.actfm_picture_clear));
}
if (runnables.size() == 1) {
runnables.get(0).run();
} else {
ArrayAdapter<String> adapter = new ArrayAdapter<>(fragment.getActivity(),
android.R.layout.simple_spinner_dropdown_item, options.toArray(new String[options.size()]));
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface d, int which) {
runnables.get(which).run();
d.dismiss();
}
};
// show a menu of available options
dialogBuilder.newDialog()
.setAdapter(adapter, listener)
.show().setOwnerActivity(fragment.getActivity());
}
}
}

@ -10,38 +10,36 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
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.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.actfm.ActFmCameraModule;
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.TimerControlSet;
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.activities.CameraActivity;
import org.tasks.dialogs.DialogBuilder;
import org.tasks.fragments.TaskEditControlSetFragmentManager;
import org.tasks.injection.ForActivity;
@ -59,6 +57,7 @@ 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
@ -96,15 +95,9 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
private static final String EXTRA_TASK = "extra_task"; //$NON-NLS-1$
private static final String EXTRA_IS_NEW_TASK = "extra_is_new_task";
/**
* Token for saving a bitmap in the intent before it has been added with a comment
*/
public static final String TOKEN_PICTURE_IN_PROGRESS = "picture_in_progress"; //$NON-NLS-1$
// --- request codes
public static final int REQUEST_CODE_RECORD = 30; // TODO: move this to file control set
public static final int REQUEST_CODE_CAMERA = 60;
@Inject TaskService taskService;
@Inject MetadataDao metadataDao;
@ -112,7 +105,6 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
@Inject TaskDeleter taskDeleter;
@Inject NotificationManager notificationManager;
@Inject ActivityPreferences preferences;
@Inject ActFmCameraModule actFmCameraModule;
@Inject DialogBuilder dialogBuilder;
@Inject @ForActivity Context context;
@Inject TaskEditControlSetFragmentManager taskEditControlSetFragmentManager;
@ -121,9 +113,7 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
private EditNoteActivity editNotes;
@Bind(R.id.updatesFooter) View commentsBar;
@Bind(R.id.edit_body) LinearLayout body;
@Bind(R.id.commentField) EditText commentField;
@Bind(R.id.toolbar) Toolbar toolbar;
// --- other instance variables
@ -196,7 +186,7 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
notificationManager.cancel(model.getId());
if (!showEditComments) {
commentsBar.setVisibility(View.GONE);
// TODO: hide comment bar
}
return view;
@ -205,7 +195,7 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
@Override
public boolean onMenuItemClick(MenuItem item) {
hideKeyboard();
AndroidUtilities.hideKeyboard(getActivity());
switch (item.getItemId()) {
case R.id.menu_record_note:
@ -229,10 +219,8 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
private void instantiateEditNotes() {
if (showEditComments) {
editNotes = new EditNoteActivity(actFmCameraModule, metadataDao, userActivityDao,
taskService, this, getView(), model.getId());
editNotes.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
editNotes = new EditNoteActivity(metadataDao, userActivityDao, taskService, this, model.getId());
editNotes.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
body.addView(editNotes);
}
}
@ -243,22 +231,27 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
} else {
editNotes.loadViewForTaskID(model.getId());
}
if (editNotes != null) {
TimerControlSet timerControl = getTimerControl();
if (timerControl != null) {
timerControl.setEditNotes(editNotes);
}
}
}
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;
}
@ -319,7 +312,6 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
if (isNewTask) {
tla.getTaskListFragment().onTaskCreated(model.getId(), model.getUuid());
}
removeExtrasFromIntent(getActivity().getIntent());
callback.taskEditFinished();
} else {
discard();
@ -334,24 +326,11 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
return getFragment(FilesControlSet.TAG);
}
private TimerControlSet getTimerControl() {
return getFragment(TimerControlSet.TAG );
}
@SuppressWarnings("unchecked")
private <T extends TaskEditControlFragment> T getFragment(int tag) {
return (T) getFragmentManager().findFragmentByTag(getString(tag));
}
/**
* Helper to remove task edit specific info from activity intent
*/
public static void removeExtrasFromIntent(Intent intent) {
if (intent != null) {
intent.removeExtra(TOKEN_PICTURE_IN_PROGRESS);
}
}
/*
* ======================================================================
* ======================================================= event handlers
@ -389,7 +368,6 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
taskDeleter.delete(model);
}
removeExtrasFromIntent(getActivity().getIntent());
callback.taskEditFinished();
}
@ -422,11 +400,6 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
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 if (requestCode == REQUEST_CODE_CAMERA) {
if (editNotes != null && resultCode == RESULT_OK) {
Uri uri = data.getParcelableExtra(CameraActivity.EXTRA_URI);
editNotes.setPictureUri(uri);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
@ -446,12 +419,6 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
* ======================================================================
*/
private void hideKeyboard() {
getEditTitleControlSet().hideKeyboard();
AndroidUtilities.hideSoftInputForViews(getActivity(), commentField);
commentField.setCursorVisible(false);
}
public void onPriorityChange(int priority) {
getEditTitleControlSet().setPriority(priority);
}
@ -459,4 +426,17 @@ public final class TaskEditFragment extends InjectingFragment implements Toolbar
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();
}
}

@ -33,6 +33,7 @@ import com.todoroo.astrid.subtasks.SubtasksHelper;
import com.todoroo.astrid.timers.TimerControlSet;
import org.tasks.R;
import org.tasks.fragments.CommentBarFragment;
import org.tasks.fragments.TaskEditControlSetFragmentManager;
import org.tasks.injection.InjectingAppCompatActivity;
import org.tasks.intents.TaskIntents;
@ -58,7 +59,8 @@ public class TaskListActivity extends InjectingAppCompatActivity implements
PriorityControlSet.OnPriorityChanged,
TimerControlSet.TimerControlSetCallback,
RepeatControlSet.RepeatChangedListener,
TaskEditFragment.TaskEditFragmentCallbackHandler {
TaskEditFragment.TaskEditFragmentCallbackHandler,
CommentBarFragment.CommentBarFragmentCallback {
@Inject ActivityPreferences preferences;
@Inject StartupService startupService;
@ -200,7 +202,6 @@ public class TaskListActivity extends InjectingAppCompatActivity implements
@Override
public void onFilterItemClicked(FilterListItem item) {
TaskEditFragment.removeExtrasFromIntent(getIntent());
TaskEditFragment tef = getTaskEditFragment();
if (tef != null) {
getTaskEditFragment().save();
@ -441,4 +442,12 @@ public class TaskListActivity extends InjectingAppCompatActivity implements
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
@Override
public void addComment(String message, String actionCode, String picture) {
TaskEditFragment taskEditFragment = getTaskEditFragment();
if (taskEditFragment != null) {
taskEditFragment.addComment(message, actionCode, picture);
}
}
}

@ -10,42 +10,28 @@ import android.content.Intent;
import android.database.sqlite.SQLiteException;
import android.graphics.Color;
import android.net.Uri;
import android.text.Editable;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.format.DateUtils;
import android.text.util.Linkify;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import com.todoroo.andlib.data.Callback;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.actfm.ActFmCameraModule;
import com.todoroo.astrid.actfm.ActFmCameraModule.ClearImageCallback;
import com.todoroo.astrid.activity.TaskEditFragment;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.UserActivityDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.RemoteModel;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.UserActivity;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.timers.TimerActionListener;
import org.json.JSONObject;
import org.tasks.R;
import java.util.ArrayList;
@ -54,41 +40,29 @@ import java.util.Comparator;
import timber.log.Timber;
import static org.tasks.date.DateTimeUtils.newDateTime;
import static org.tasks.files.FileHelper.getPathFromUri;
import static org.tasks.files.ImageHelper.sampleBitmap;
public class EditNoteActivity extends LinearLayout implements TimerActionListener {
public class EditNoteActivity extends LinearLayout {
private Task task;
private ActFmCameraModule actFmCameraModule;
private final MetadataDao metadataDao;
private final UserActivityDao userActivityDao;
private final TaskService taskService;
private final ArrayList<NoteOrUpdate> items = new ArrayList<>();
private EditText commentField;
private final View commentsBar;
private View commentButton;
private int commentItems = 10;
private ImageButton pictureButton;
private Uri pendingCommentPicture = null;
private final Fragment fragment;
private final TaskListActivity activity;
private final int cameraButton;
public EditNoteActivity(
ActFmCameraModule actFmCameraModule,
MetadataDao metadataDao,
UserActivityDao userActivityDao,
TaskService taskService,
Fragment fragment,
View parent,
long t) {
super(fragment.getActivity());
this.actFmCameraModule = actFmCameraModule;
this.metadataDao = metadataDao;
this.userActivityDao = userActivityDao;
this.taskService = taskService;
@ -97,12 +71,8 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene
this.activity = (TaskListActivity) fragment.getActivity();
cameraButton = R.drawable.ic_camera_alt_white_24dp;
setOrientation(VERTICAL);
commentsBar = parent.findViewById(R.id.updatesFooter);
loadViewForTaskID(t);
}
@ -120,90 +90,12 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene
return;
}
setUpInterface();
setUpListAdapter();
reloadView();
}
// --- UI preparation
private void setUpInterface() {
commentButton = commentsBar.findViewById(R.id.commentButton);
commentField = (EditText) commentsBar.findViewById(R.id.commentField);
commentField.setHorizontallyScrolling(false);
commentField.setMaxLines(Integer.MAX_VALUE);
commentField.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
AndroidUtilities.hideSoftInputForViews(activity, commentField);
return true;
}
return false;
}
});
commentField.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
commentField.setCursorVisible(true);
}
});
commentField.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
commentButton.setVisibility((s.length() > 0 || pendingCommentPicture != null) ? View.VISIBLE
: View.GONE);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//
}
});
commentField.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
if (commentField.getText().length() > 0) {
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
// commentField.setCursorVisible(false);
addComment();
}
}
return false;
}
});
commentButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
addComment();
}
});
final ClearImageCallback clearImage = new ClearImageCallback() {
@Override
public void clearImage() {
pendingCommentPicture = null;
pictureButton.setImageResource(cameraButton);
}
};
pictureButton = (ImageButton) commentsBar.findViewById(R.id.picture);
pictureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (pendingCommentPicture != null) {
actFmCameraModule.showPictureLauncher(clearImage);
} else {
actFmCameraModule.showPictureLauncher(null);
}
}
});
if(!TextUtils.isEmpty(task.getNotes())) {
TextView notes = new TextView(activity);
notes.setLinkTextColor(Color.rgb(100, 160, 255));
@ -212,17 +104,9 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene
notes.setPadding(5, 10, 5, 10);
Linkify.addLinks(notes, Linkify.ALL);
}
if (activity != null) {
String uri = activity.getIntent().getStringExtra(TaskEditFragment.TOKEN_PICTURE_IN_PROGRESS);
if (uri != null) {
pendingCommentPicture = Uri.parse(uri);
setPictureButtonToPendingPicture();
}
}
}
private void setUpListAdapter() {
public void reloadView() {
items.clear();
this.removeAllViews();
metadataDao.byTaskAndKey(task.getId(), NoteMetadata.METADATA_KEY, new Callback<Metadata>() {
@ -267,7 +151,7 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene
public void onClick(View v) {
// Perform action on click
commentItems += 10;
setUpListAdapter();
reloadView();
}
});
this.addView(loadMore);
@ -322,47 +206,6 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene
}
}
private void addComment() {
addComment(commentField.getText().toString(), UserActivity.ACTION_TASK_COMMENT, task.getUuid(), true);
AndroidUtilities.hideSoftInputForViews(activity, commentField);
commentField.setCursorVisible(false);
}
private void addComment(String message, String actionCode, String uuid, boolean usePicture) {
// Allow for users to just add picture
if (TextUtils.isEmpty(message) && usePicture) {
message = " ";
}
UserActivity userActivity = new UserActivity();
userActivity.setMessage(message);
userActivity.setAction(actionCode);
userActivity.setTargetId(uuid);
userActivity.setCreatedAt(DateUtilities.now());
if (usePicture && pendingCommentPicture != null) {
JSONObject pictureJson = RemoteModel.PictureHelper.savePictureJson(pendingCommentPicture);
if (pictureJson != null) {
userActivity.setPicture(pictureJson.toString());
}
}
userActivityDao.createNew(userActivity);
if (commentField != null) {
commentField.setText(""); //$NON-NLS-1$
}
pendingCommentPicture = usePicture ? null : pendingCommentPicture;
if (usePicture) {
if (activity != null) {
activity.getIntent().removeExtra(TaskEditFragment.TOKEN_PICTURE_IN_PROGRESS);
}
}
if (pictureButton != null) {
pictureButton.setImageResource(cameraButton);
}
setUpListAdapter();
}
private static class NoteOrUpdate {
private final Spanned title;
private final Uri commentBitmap;
@ -408,40 +251,4 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene
return Html.fromHtml(message);
}
}
@Override
public void timerStarted(Task t) {
addComment(String.format("%s %s", //$NON-NLS-1$
activity.getString(R.string.TEA_timer_comment_started),
DateUtilities.getTimeString(activity, newDateTime())),
UserActivity.ACTION_TASK_COMMENT,
t.getUuid(),
false);
}
@Override
public void timerStopped(Task t) {
String elapsedTime = DateUtils.formatElapsedTime(t.getElapsedSeconds());
addComment(String.format("%s %s\n%s %s", //$NON-NLS-1$
activity.getString(R.string.TEA_timer_comment_stopped),
DateUtilities.getTimeString(activity, newDateTime()),
activity.getString(R.string.TEA_timer_comment_spent),
elapsedTime), UserActivity.ACTION_TASK_COMMENT,
t.getUuid(),
false);
}
public void setPictureUri(Uri uri) {
if (activity != null) {
activity.getIntent().putExtra(TaskEditFragment.TOKEN_PICTURE_IN_PROGRESS, uri.toString());
}
pendingCommentPicture = uri;
setPictureButtonToPendingPicture();
commentField.requestFocus();
}
private void setPictureButtonToPendingPicture() {
String path = getPathFromUri(activity, pendingCommentPicture);
pictureButton.setImageBitmap(sampleBitmap(path, pictureButton.getWidth(), pictureButton.getHeight()));
}
}

@ -25,7 +25,6 @@ import android.widget.TextView;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.notes.EditNoteActivity;
import com.todoroo.astrid.ui.TimeDurationControlSet;
import org.tasks.R;
@ -34,9 +33,6 @@ import org.tasks.injection.ForActivity;
import org.tasks.preferences.ActivityPreferences;
import org.tasks.ui.TaskEditControlFragment;
import java.util.LinkedList;
import java.util.List;
import javax.inject.Inject;
import butterknife.Bind;
@ -72,7 +68,6 @@ public class TimerControlSet extends TaskEditControlFragment {
private TimeDurationControlSet estimated;
private TimeDurationControlSet elapsed;
private long timerStarted;
private final List<TimerActionListener> listeners = new LinkedList<>();
protected AlertDialog dialog;
private View dialogView;
private int elapsedSeconds;
@ -147,18 +142,12 @@ public class TimerControlSet extends TaskEditControlFragment {
Task task = callback.stopTimer();
elapsed.setTimeDuration(task.getElapsedSeconds());
timerStarted = 0;
for (TimerActionListener listener : listeners) {
listener.timerStopped(task);
}
chronometer.stop();
refreshDisplayView();
} else {
Task task = callback.startTimer();
timerStarted = task.getTimerStart();
chronometer.start();
for (TimerActionListener listener : listeners) {
listener.timerStarted(task);
}
}
updateChronometer();
}
@ -197,11 +186,6 @@ public class TimerControlSet extends TaskEditControlFragment {
task.setEstimatedSeconds(estimated.getTimeDurationInSeconds());
}
public void setEditNotes(EditNoteActivity editNotes) {
removeListener(editNotes);
addListener(editNotes);
}
private void refresh() {
refreshDisplayView();
updateChronometer();
@ -267,16 +251,6 @@ public class TimerControlSet extends TaskEditControlFragment {
}
}
public void addListener(TimerActionListener listener) {
this.listeners.add(listener);
}
public void removeListener(TimerActionListener listener) {
if (listeners.contains(listener)) {
listeners.remove(listener);
}
}
private boolean timerActive() {
return timerStarted > 0;
}

@ -0,0 +1,238 @@
package org.tasks.fragments;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import com.google.common.base.Strings;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.data.RemoteModel;
import com.todoroo.astrid.data.UserActivity;
import org.json.JSONObject;
import org.tasks.R;
import org.tasks.activities.CameraActivity;
import org.tasks.dialogs.DialogBuilder;
import org.tasks.injection.InjectingFragment;
import org.tasks.preferences.Device;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnEditorAction;
import butterknife.OnTextChanged;
import static org.tasks.files.FileHelper.getPathFromUri;
import static org.tasks.files.ImageHelper.sampleBitmap;
public class CommentBarFragment extends InjectingFragment {
public interface CommentBarFragmentCallback {
void addComment(String message, String actionCode, String picture);
}
public interface ClearImageCallback {
void clearImage();
}
private static final int REQUEST_CODE_CAMERA = 60;
private static final String TOKEN_PICTURE_IN_PROGRESS = "picture_in_progress"; //$NON-NLS-1$
private final int cameraButton = R.drawable.ic_camera_alt_white_24dp;
@Inject Activity activity;
@Inject DialogBuilder dialogBuilder;
@Inject Device device;
@Bind(R.id.commentButton) View commentButton;
@Bind(R.id.commentField) EditText commentField;
@Bind(R.id.picture) ImageView pictureButton;
private CommentBarFragmentCallback callback;
private Uri pendingCommentPicture = null;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callback = (CommentBarFragmentCallback) activity;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_comment_bar, container, false);
ButterKnife.bind(this, view);
if (savedInstanceState != null) {
String uri = savedInstanceState.getString(TOKEN_PICTURE_IN_PROGRESS);
if (uri != null) {
pendingCommentPicture = Uri.parse(uri);
setPictureButtonToPendingPicture();
}
}
commentField.setHorizontallyScrolling(false);
commentField.setMaxLines(Integer.MAX_VALUE);
return view;
}
@OnTextChanged(R.id.commentField)
void onTextChanged(CharSequence s) {
commentButton.setVisibility(pendingCommentPicture == null && Strings.isNullOrEmpty(s.toString())
? View.GONE
: View.VISIBLE);
}
@OnEditorAction(R.id.commentField)
boolean onEditorAction(KeyEvent key) {
int actionId = key.getAction();
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
if (commentField.getText().length() > 0 || pendingCommentPicture != null) {
addComment();
return true;
}
}
return false;
}
@OnClick(R.id.commentButton)
void addClicked() {
addComment();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (pendingCommentPicture != null) {
outState.putString(TOKEN_PICTURE_IN_PROGRESS, pendingCommentPicture.toString());
}
}
@OnClick(R.id.picture)
void onClickPicture() {
if (pendingCommentPicture == null) {
showPictureLauncher(null);
} else {
showPictureLauncher(new ClearImageCallback() {
@Override
public void clearImage() {
pendingCommentPicture = null;
pictureButton.setImageResource(cameraButton);
}
});
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
pendingCommentPicture = data.getParcelableExtra(CameraActivity.EXTRA_URI);
setPictureButtonToPendingPicture();
commentField.requestFocus();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void addComment() {
addComment(commentField.getText().toString(), UserActivity.ACTION_TASK_COMMENT);
AndroidUtilities.hideSoftInputForViews(activity, commentField);
}
private void setPictureButtonToPendingPicture() {
String path = getPathFromUri(activity, pendingCommentPicture);
Bitmap bitmap = sampleBitmap(path, pictureButton.getLayoutParams().width, pictureButton.getLayoutParams().height);
pictureButton.setImageBitmap(bitmap);
commentButton.setVisibility(View.VISIBLE);
}
private void addComment(String message, String actionCode) {
// Allow for users to just add picture
if (TextUtils.isEmpty(message)) {
message = " ";
}
String picture = null;
if (pendingCommentPicture != null) {
JSONObject pictureJson = RemoteModel.PictureHelper.savePictureJson(pendingCommentPicture);
if (pictureJson != null) {
picture = pictureJson.toString();
}
}
if (commentField != null) {
commentField.setText(""); //$NON-NLS-1$
}
pendingCommentPicture = null;
pictureButton.setImageResource(cameraButton);
callback.addComment(message, actionCode, picture);
}
private void showPictureLauncher(final ClearImageCallback clearImageOption) {
final List<Runnable> runnables = new ArrayList<>();
List<String> options = new ArrayList<>();
final boolean cameraAvailable = device.hasCamera();
if (cameraAvailable) {
runnables.add(new Runnable() {
@Override
public void run() {
startActivityForResult(new Intent(activity, CameraActivity.class), REQUEST_CODE_CAMERA);
}
});
options.add(getString(R.string.take_a_picture));
}
if (clearImageOption != null) {
runnables.add(new Runnable() {
@Override
public void run() {
clearImageOption.clearImage();
}
});
options.add(getString(R.string.actfm_picture_clear));
}
if (runnables.size() == 1) {
runnables.get(0).run();
} else {
ArrayAdapter<String> adapter = new ArrayAdapter<>(activity,
android.R.layout.simple_spinner_dropdown_item, options.toArray(new String[options.size()]));
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface d, int which) {
runnables.get(which).run();
d.dismiss();
}
};
// show a menu of available options
dialogBuilder.newDialog()
.setAdapter(adapter, listener)
.show().setOwnerActivity(activity);
}
}
}

@ -18,6 +18,7 @@ import com.todoroo.astrid.ui.EditTitleControlSet;
import com.todoroo.astrid.ui.HideUntilControlSet;
import com.todoroo.astrid.ui.ReminderControlSet;
import org.tasks.fragments.CommentBarFragment;
import org.tasks.ui.CalendarControlSet;
import org.tasks.ui.DeadlineControlSet;
import org.tasks.ui.DescriptionControlSet;
@ -48,7 +49,8 @@ import dagger.Provides;
EditTitleControlSet.class,
TimerControlSet.class,
TagsControlSet.class,
RepeatControlSet.class
RepeatControlSet.class,
CommentBarFragment.class
})
public class FragmentModule {

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/updatesFooter"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="?attr/asAbBackgroundColor"
android:gravity="center_vertical"
android:minHeight="50dp"
android:orientation="horizontal"
android:paddingLeft="@dimen/keyline_first"
android:paddingStart="@dimen/keyline_first"
android:paddingRight="@dimen/keyline_first"
android:paddingEnd="@dimen/keyline_first">
<ImageView
android:id="@+id/picture"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:src="@drawable/ic_camera_alt_white_24dp"
tools:ignore="ContentDescription" />
<EditText
android:id="@+id/commentField"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="100"
android:background="?attr/asEditTextBackground"
android:freezesText="true"
android:hint="@string/TVA_add_comment"
android:imeOptions="flagNoExtractUi|actionDone"
android:inputType="textCapSentences"
android:paddingLeft="@dimen/keyline_second"
android:paddingStart="@dimen/keyline_second"
android:textColor="@color/white_text"
android:textColorHint="@color/white_text_hint"
android:textCursorDrawable="@null"
android:textSize="16sp" />
<ImageView
android:id="@+id/commentButton"
android:layout_width="39dip"
android:layout_height="39dip"
android:layout_marginLeft="3dip"
android:layout_weight="1"
android:scaleType="center"
android:src="@drawable/ic_add_24dp"
android:tint="@android:color/white"
android:visibility="gone" />
</LinearLayout>

@ -90,65 +90,10 @@
android:layout_height="1px"
android:background="?attr/asToolbarSeparator" />
<LinearLayout
android:id="@+id/updatesFooter"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="?attr/asAbBackgroundColor"
android:gravity="center_vertical"
android:minHeight="50dp"
android:orientation="horizontal"
android:padding="3dip"
android:paddingBottom="0dip">
<!-- Voice Add Button -->
<ImageButton
android:id="@+id/picture"
android:layout_width="39dip"
android:layout_height="39dip"
android:layout_marginRight="3dip"
android:layout_weight="1"
android:background="@android:color/transparent"
android:paddingBottom="2dip"
android:scaleType="centerInside"
android:src="@drawable/ic_camera_alt_white_24dp" />
<!-- Quick Add Task -->
<EditText
android:id="@+id/commentField"
android:layout_width="wrap_content"
android:layout_height="39dip"
android:layout_marginBottom="2dip"
android:layout_marginLeft="1dip"
android:layout_marginRight="1dip"
android:layout_marginTop="2dip"
android:layout_weight="100"
android:autoText="true"
android:background="?attr/asEditTextBackground"
android:capitalize="sentences"
android:hint="@string/TVA_add_comment"
android:imeOptions="flagNoExtractUi|actionDone"
android:inputType="textCapSentences"
android:paddingLeft="10dip"
android:textColor="@color/white_text"
android:textColorHint="@color/white_text_hint"
android:textSize="16sp" />
<!-- Extended Add Button -->
<ImageButton
android:id="@+id/commentButton"
android:layout_width="39dip"
android:layout_height="39dip"
android:layout_marginLeft="3dip"
android:layout_weight="1"
android:background="@android:color/transparent"
android:scaleType="center"
android:src="@drawable/ic_add_24dp"
android:tint="@android:color/white"
android:visibility="gone" />
</LinearLayout>
<fragment
android:name="org.tasks.fragments.CommentBarFragment"
android:id="@+id/comment_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

Loading…
Cancel
Save