4343import com .boruminc .borumjot .android .server .requests .DeleteJottingRequest ;
4444import com .boruminc .borumjot .android .server .requests .PinJottingRequest ;
4545import com .boruminc .borumjot .android .server .requests .UpdateTaskRequest ;
46+ import com .boruminc .borumjot .android .subtasks .SubtaskActivity ;
4647import com .google .android .material .appbar .MaterialToolbar ;
4748
4849import org .json .JSONException ;
5354import java .time .LocalDate ;
5455import java .time .ZoneId ;
5556import java .util .ArrayList ;
56- import java .util .Comparator ;
5757import java .util .Locale ;
5858import java .util .stream .Collectors ;
5959import java .util .stream .Stream ;
@@ -256,7 +256,7 @@ public void onBackPressed() {
256256
257257 /* Helper Methods */
258258
259- private void setSubtask (EditText view , boolean isCompleted ) {
259+ private void setSubtask (TextView view , boolean isCompleted ) {
260260 if (isCompleted )
261261 // Add a strikethrough to the already existing paint flags using "|" bitwise operator
262262 view .setPaintFlags (view .getPaintFlags () | Paint .STRIKE_THRU_TEXT_FLAG );
@@ -441,7 +441,7 @@ private void scheduleTaskDueDateNotification(long delay) {
441441 * @param name The new name of the jotting
442442 */
443443 protected void setJottingName (String name ) {
444- taskTitle .setText (name );
444+ taskTitle .setText (SlashNormalizer . unescapeUserSlashes ( name ) );
445445 }
446446
447447 /**
@@ -497,6 +497,7 @@ private void setSubtasksTableContent(ArrayList<Task> subtasks) {
497497 }
498498
499499 TableRow addSubtaskLayout = new TableRow (this );
500+
500501 addSubtaskLayout .setLayoutParams (new TableRow .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .WRAP_CONTENT ));
501502 addSubtaskLayout .setGravity (Gravity .START );
502503 ImageButton addSubtaskBtn = generateCherryRasboraPlusButton ();
@@ -542,6 +543,13 @@ private LinearLayout addSubtaskToTable(Task subtask) {
542543
543544 /* Event Handlers */
544545
546+ public void onEnterSubtaskClick (View v ) {
547+ Intent subtask = new Intent (getApplicationContext (), SubtaskActivity .class );
548+
549+ subtask .putExtra ("id" , (int ) ((ViewGroup ) v .getParent ()).getTag ());
550+ startActivity (subtask );
551+ }
552+
545553 public void onDeleteClick () {
546554 android .app .AlertDialog .Builder deleteDialog = new android .app .AlertDialog .Builder (this );
547555 deleteDialog
@@ -640,44 +648,8 @@ public void onComplete(JSONObject result) {
640648 Task subtask = new Task (newSubtaskField .getText ().toString ());
641649 subtask .setId (result .getJSONObject ("data" ).getInt ("id" ));
642650
643- /*
644- * Add right after last incomplete task using binary search for the last incomplete subtask
645- * The algorithm is as follows:
646- * 1. Start at first element and check if complete
647- * 2. If complete, then
648- * 3. If the first element OR the previous element is incomplete, then
649- * ADD SUBTASK; END
650- * 4. Else, (previous element is complete), then
651- * (the last incomplete subtask is BEFORE i) divide i by 2 and REPEAT
652- * 7. Else, (current element is incomplete), then
653- * (the last incomplete subtask is AFTER i) set i to be between its current value
654- * and the index of the last element
655- */
656- ArrayList <Task > currSubtasks = getTaskData ().getSubtasks ();
657- int i = getTaskData ().getSubtasks ().size () / 2 ;
658-
659- while (i < getTaskData ().getSubtasks ().size ()) {
660-
661- if (currSubtasks .get (i ).isCompleted ()) {
662- if (i == 0 || !currSubtasks .get (i - 1 ).isCompleted ()) {
663- getTaskData ().addSubtask (i , subtask );
664- subtaskList .addView (addSubtaskToTable (subtask ), i );
665-
666- break ;
667- } else {
668- i /= 2 ;
669- }
670- } else {
671- if (i != currSubtasks .size () - 1 && currSubtasks .get (i + 1 ).isCompleted ()) {
672- getTaskData ().addSubtask (i , subtask );
673- subtaskList .addView (addSubtaskToTable (subtask ), i + 1 );
674-
675- break ;
676- } else {
677- i = (currSubtasks .size () + i ) / 2 ;
678- }
679- }
680- }
651+ int indexAfterLastIncompleteTask = searchForLastIncompleteTask (subtask );
652+ subtaskList .addView (addSubtaskToTable (subtask ), indexAfterLastIncompleteTask );
681653
682654 ((EditText ) subtaskList .findViewById (R .id .newSubtaskFieldId )).setText ("" );
683655 }
@@ -689,20 +661,48 @@ public void onComplete(JSONObject result) {
689661 );
690662 }
691663
692- public void onDeleteSubtaskClick (View view ) {
693- TableRow subtaskRow = (TableRow ) view .getParent ();
694-
695- new TaskRunner ().executeAsync (
696- new DeleteJottingRequest ((Integer ) subtaskRow .getTag (), getUserApiKey (), "task" ), data -> {
697- if (data != null ) {
698- if (data .optInt ("statusCode" ) == 200 ) {
699- TableLayout subtaskTable = (TableLayout ) subtaskRow .getParent ();
700- getTaskData ().getSubtasks ().remove (subtaskTable .indexOfChild (subtaskRow ));
701- subtaskTable .removeView (subtaskRow );
702- }
703- }
664+ /**
665+ * Add right after last incomplete task using binary search for the last incomplete subtask
666+ * @implNote The algorithm is as follows:
667+ * <ol>
668+ * <li>Start at first element and check if complete</li>
669+ * <li>If complete, then</li>
670+ * <li>If the first element OR the previous element is incomplete, then</li>
671+ * ADD SUBTASK; END
672+ * <li>Else, (previous element is complete), then
673+ * (the last incomplete subtask is BEFORE i) divide i by 2 and REPEAT
674+ * <li>Else, (current element is incomplete), then</li>
675+ * (the last incomplete subtask is AFTER i) set i to be between its current value
676+ * and the index of the last element</li>
677+ * </ol>
678+ * @return one index after the last incomplete subtask, or 0 if there were no subtasks
679+ */
680+ private int searchForLastIncompleteTask (Task subtask ) {
681+ ArrayList <Task > currSubtasks = getTaskData ().getSubtasks ();
682+ int subtaskSize = currSubtasks .size ();
683+ int i = subtaskSize / 2 ;
684+
685+ while (i < subtaskSize ) {
686+ if (currSubtasks .get (i ).isCompleted ()) {
687+ if (i == 0 || !currSubtasks .get (i - 1 ).isCompleted ()) {
688+ getTaskData ().addSubtask (i , subtask );
689+
690+ return i ;
691+ } else {
692+ i /= 2 ;
704693 }
705- );
694+ } else {
695+ if (i != currSubtasks .size () - 1 && currSubtasks .get (i + 1 ).isCompleted ()) {
696+ getTaskData ().addSubtask (i + 1 , subtask );
697+ return i + 1 ;
698+ } else {
699+ i = (int ) Math .round ((currSubtasks .size () + i ) / 2.0 );
700+ }
701+ }
702+ }
703+
704+ // There are no (incomplete or complete) subtasks
705+ return currSubtasks .size ();
706706 }
707707
708708 public void onCompleteSubtaskClick (View view ) {
@@ -734,7 +734,7 @@ public JSONObject call() {
734734 public void onComplete (JSONObject result ) {
735735 super .onComplete (result );
736736 if (ranOk ()) {
737- EditText subtaskTxt = (EditText ) subtaskRow .getChildAt (1 );
737+ TextView subtaskTxt = (TextView ) subtaskRow .getChildAt (1 );
738738 if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
739739 if (completed == 1 )
740740 setSubtask (subtaskTxt , true );
0 commit comments