Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Bug Fixes + Goal Creation Functionality #117

Merged
merged 13 commits into from
Mar 15, 2024
28 changes: 25 additions & 3 deletions app/src/main/java/edu/ucsd/cse110/successorator/MainViewModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static edu.ucsd.cse110.successorator.lib.domain.AppMode.PENDING;
import static edu.ucsd.cse110.successorator.lib.domain.AppMode.TODAY;
import static edu.ucsd.cse110.successorator.lib.domain.AppMode.TOMORROW;
import static edu.ucsd.cse110.successorator.lib.util.TimeUtils.nthDayofWeek;

import androidx.lifecycle.ViewModel;
import androidx.lifecycle.viewmodel.ViewModelInitializer;
Expand Down Expand Up @@ -471,6 +472,28 @@ public void addRecurringGoalDateless(String contents, RecurrenceType recurrenceT
handleRecurringGoalGeneration(recurringGoal, currentTime);
}

// Method that adds date text when a recurring goal will reoccur
public String getGoalContent(Goal goal) {
if (currentMode.getValue() == AppMode.RECURRING) {
var startDate = TimeUtils.localize(goal.startDate(), dateConverter);

switch (goal.recurrenceType()) {
case DAILY:
return goal.content() + ", Daily";
case WEEKLY:
return goal.content() + ", Weekly on " + startDate.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.US);
case MONTHLY:
return goal.content() + ", Monthly on " + nthDayofWeek(startDate);
case YEARLY:
return goal.content() + ", Yearly on " + (startDate.get(Calendar.MONTH) + 1) + "/" + startDate.get(Calendar.DAY_OF_MONTH);
default:
return goal.content();
}
} else {
return goal.content();
}
}

// Public for testing
// Only call from a context where it won't recurse into LiveData updates
public void handleRecurringGoalGeneration(Goal recurringGoal, Calendar currentDate) {
Expand Down Expand Up @@ -560,7 +583,6 @@ public void deleteRecurringGoal(int goalId) {
}
}
}


}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,23 @@
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;

import android.view.inputmethod.EditorInfo;
import android.widget.TextView;


import edu.ucsd.cse110.successorator.MainViewModel;
import edu.ucsd.cse110.successorator.databinding.FragmentDialogCreateGoalBinding;
import edu.ucsd.cse110.successorator.lib.domain.AppMode;
import edu.ucsd.cse110.successorator.lib.domain.Context;
import edu.ucsd.cse110.successorator.lib.domain.RecurrenceType;


public class CreateGoalDialogFragment extends DialogFragment {
private FragmentDialogCreateGoalBinding view;
//Not this most flexible name but the least ambiguous.
private MainViewModel mainViewModel;
private RecurrenceType recurrenceType = RecurrenceType.NONE;


private Context context;

Expand Down Expand Up @@ -71,6 +74,19 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState){
}
});

// Create listener for recurrence buttons
this.view.recurrenceRadio.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == this.view.DailyRecurringGoalButton.getId()) {
this.recurrenceType = RecurrenceType.DAILY;
} else if (checkedId == this.view.WeeklyRecurringGoalButton.getId()) {
this.recurrenceType = RecurrenceType.WEEKLY;
} else if (checkedId == this.view.MonthlyRecurringGoalButton.getId()) {
this.recurrenceType = RecurrenceType.MONTHLY;
} else if (checkedId == this.view.YearlyRecurringGoalButton.getId()) {
this.recurrenceType = RecurrenceType.YEARLY;
}
});

//Create listener for enter key.
//Interface containing method called anytime enter key is pressed.
//https://youtu.be/DivBp_9ZeK0?si=8Laea7bnST0mfmtm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@
import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;

import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import android.widget.Toast;

import edu.ucsd.cse110.successorator.MainViewModel;
import edu.ucsd.cse110.successorator.databinding.FragmentDialogCreateRecurringGoalBinding;
import edu.ucsd.cse110.successorator.lib.domain.Context;
Expand Down Expand Up @@ -51,13 +50,12 @@ public void onCreate(@Nullable Bundle savedInstanceState) {

@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState){
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
this.view = FragmentDialogCreateRecurringGoalBinding.inflate(getLayoutInflater());

// Hook up prompt text to the view model


// Create listener for context buttons
// Create listener for recurrence buttons
this.view.recurrenceRadioGroup.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == this.view.dailyRecurringGoalButton.getId()) {
this.recurrenceType = RecurrenceType.DAILY;
Expand Down Expand Up @@ -92,12 +90,9 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState){

String[] parts = view.recurringDatePicker.getText().toString().split("/");
if (parts.length == 3) {
if(actionId == EditorInfo.IME_ACTION_DONE){
if (actionId == EditorInfo.IME_ACTION_DONE) {
String content = view.goalInput.getText().toString();
//Context is defaulted to HOME, Needs US3 to be implemented.

boolean success = mainViewModel.addRecurringGoal(content,Integer.parseInt(parts[2]), Integer.parseInt(parts[0]) - 1, Integer.parseInt(parts[1]),
recurrenceType, context);
boolean success = (boolean) mainViewModel.addRecurringGoal(content, Integer.parseInt(parts[2]), Integer.parseInt(parts[0]) - 1, Integer.parseInt(parts[1]), recurrenceType, context);
if (!success) {
// Display a popup telling the user to correct their date or select a context
// https://stackoverflow.com/questions/2115758/how-do-i-display-an-alert-dialog-on-android
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package edu.ucsd.cse110.successorator.ui;


import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;

import androidx.annotation.NonNull;
Expand All @@ -17,11 +15,12 @@

import edu.ucsd.cse110.successorator.MainViewModel;
import edu.ucsd.cse110.successorator.databinding.ListItemGoalBinding;
import edu.ucsd.cse110.successorator.lib.domain.Goal;
import edu.ucsd.cse110.successorator.lib.domain.Context;
import edu.ucsd.cse110.successorator.lib.domain.Goal;

public class GoalListAdapter extends ArrayAdapter<Goal> {
private MainViewModel mainViewModel;

public GoalListAdapter(@NonNull android.content.Context context, @NonNull List<Goal> goals, MainViewModel mainViewModel) {
super(context, 0, new ArrayList<>(goals));
this.mainViewModel = mainViewModel;
Expand All @@ -45,34 +44,32 @@ public View getView(int position, View convertView, ViewGroup parent) {
Strike through reference:
https://stackoverflow.com/questions/3881553/is-there-an-easy-way-to-strike-through-text-in-an-app-widget/6739637
*/
binding.goalText.setText(goal.content());
binding.goalText.setText(mainViewModel.getGoalContent(goal));
if (goal.completed()) {
binding.goalText.setPaintFlags(binding.goalText.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
binding.background.setBackgroundColor(Color.LTGRAY);
}
else {
} else {
binding.goalText.setPaintFlags(binding.goalText.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
binding.background.setBackgroundColor(Color.WHITE);
}

/*
Logic for color of the list context icon
*/
if (goal.context()==Context.HOME) {
if (goal.context() == Context.HOME) {
binding.imageView.setColorFilter(Color.parseColor("#faf04d"));
}
if (goal.context()==Context.WORK) {
if (goal.context() == Context.WORK) {
binding.imageView.setColorFilter(Color.parseColor("#31c7f8"));
}
if (goal.context()==Context.SCHOOL) {
if (goal.context() == Context.SCHOOL) {
binding.imageView.setColorFilter(Color.parseColor("#c95bf9"));
}
if (goal.context()==Context.ERRANDS) {
if (goal.context() == Context.ERRANDS) {
binding.imageView.setColorFilter(Color.parseColor("#a2cb84"));
}



return binding.getRoot();
}

Expand Down
4 changes: 1 addition & 3 deletions app/src/main/res/layout/fragment_dialog_create_goal.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

Expand Down Expand Up @@ -77,9 +76,8 @@
</RadioGroup>



<RadioGroup
android:id="@+id/radioGroup"
android:id="@+id/recurrenceRadio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="96dp"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package edu.ucsd.cse110.successorator;

import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import org.junit.After;
import org.junit.Before;
Expand Down Expand Up @@ -160,6 +164,26 @@ public void advance24HoursGoalVisibility() {
assertCompleteCount(0);
}

@Test
public void testGetGoalContent() {
goalRepository = MockGoalRepository.createWithAllRecurrenceTypeTestGoals();
mainViewModel = new MainViewModel(goalRepository, dateOffset, dateTicker, localizedCalendar);

mainViewModel.activateTodayView();
assertEquals("Goal 1", mainViewModel.getGoalContent(goalRepository.goals.get(0).getValue()));
assertEquals("Goal 2", mainViewModel.getGoalContent(goalRepository.goals.get(1).getValue()));
assertEquals("Goal 3", mainViewModel.getGoalContent(goalRepository.goals.get(2).getValue()));
assertEquals("Goal 4", mainViewModel.getGoalContent(goalRepository.goals.get(3).getValue()));
assertEquals("Goal 5", mainViewModel.getGoalContent(goalRepository.goals.get(4).getValue()));

mainViewModel.activateRecurringView();
assertEquals("Goal 1", mainViewModel.getGoalContent(goalRepository.goals.get(0).getValue()));
assertEquals("Goal 2, Daily", mainViewModel.getGoalContent(goalRepository.goals.get(1).getValue()));
assertEquals("Goal 3, Weekly on Wednesday", mainViewModel.getGoalContent(goalRepository.goals.get(2).getValue()));
assertEquals("Goal 4, Monthly on 1st Wednesday", mainViewModel.getGoalContent(goalRepository.goals.get(3).getValue()));
assertEquals("Goal 5, Yearly on 2/7", mainViewModel.getGoalContent(goalRepository.goals.get(4).getValue()));
}

@Test
public void testCalendarStreings() {
// Verify that the current date string is correct
Expand Down Expand Up @@ -419,7 +443,7 @@ public void ScenarioBasedSystemTests2() {

//Step 1
//Sets up time to be March 7th, 2024
dateTicker.setValue(TimeUtils.getStartTime()+TimeUtils.DAY_LENGTH*28);
dateTicker.setValue(TimeUtils.getStartTime() + TimeUtils.DAY_LENGTH * 28);
mainViewModel = new MainViewModel(goalRepository, dateOffset, dateTicker, localizedCalendar);

//Steps 2 to 5
Expand All @@ -438,14 +462,14 @@ public void ScenarioBasedSystemTests2() {
mainViewModel.activateTodayView();
var displayedGoals = mainViewModel.getGoalsToDisplay().getValue();
for (int i = 0; i < displayedGoals.size(); i++) {
if (displayedGoals.get(i).content()=="10km run") {
if (displayedGoals.get(i).content() == "10km run") {
assertTrue(mainViewModel.pressGoal(displayedGoals.get(i).id()));
}
}
mainViewModel.activateTomorrowView();
displayedGoals = mainViewModel.getGoalsToDisplay().getValue();
for (int i = 0; i < displayedGoals.size(); i++) {
if (displayedGoals.get(i).content()==" ") {
if (displayedGoals.get(i).content() == " ") {
assertTrue(mainViewModel.pressGoal(displayedGoals.get(i).id()));
break;
}
Expand All @@ -454,7 +478,7 @@ public void ScenarioBasedSystemTests2() {
//Step 7, trying to complete a goal that shouldn't be
displayedGoals = mainViewModel.getGoalsToDisplay().getValue();
for (int i = 0; i < displayedGoals.size(); i++) {
if (displayedGoals.get(i).content()=="push buttons on keyboard") {
if (displayedGoals.get(i).content() == "push buttons on keyboard") {
assertFalse(mainViewModel.pressGoal(displayedGoals.get(i).id()));
break;
}
Expand All @@ -464,15 +488,15 @@ public void ScenarioBasedSystemTests2() {
mainViewModel.activateTodayView();
displayedGoals = mainViewModel.getGoalsToDisplay().getValue();
for (int i = 0; i < displayedGoals.size(); i++) {
if (displayedGoals.get(i).content()=="push buttons on keyboard") {
if (displayedGoals.get(i).content() == "push buttons on keyboard") {
assertTrue(mainViewModel.pressGoal(displayedGoals.get(i).id()));
break;
}
}
mainViewModel.activateTomorrowView();
displayedGoals = mainViewModel.getGoalsToDisplay().getValue();
for (int i = 0; i < displayedGoals.size(); i++) {
if (displayedGoals.get(i).content()=="push buttons on keyboard") {
if (displayedGoals.get(i).content() == "push buttons on keyboard") {
assertTrue(mainViewModel.pressGoal(displayedGoals.get(i).id()));
break;
}
Expand All @@ -492,7 +516,7 @@ public void ScenarioBasedSystemTests2() {
mainViewModel.activateTomorrowView();
displayedGoals = mainViewModel.getGoalsToDisplay().getValue();
for (int i = 0; i < displayedGoals.size(); i++) {
if (displayedGoals.get(i).content()=="push buttons on keyboard") {
if (displayedGoals.get(i).content() == "push buttons on keyboard") {
assertFalse(displayedGoals.get(i).completed());
break;
}
Expand All @@ -519,7 +543,6 @@ public void ScenarioBasedSystemTests3() {
assertIncompleteCount(4);



//WIP logic to filter by context

}
Expand Down Expand Up @@ -917,6 +940,7 @@ public void MS2_US6Scenario2() {
mainViewModel.activateRecurringView();
assertIncompleteCount(1);
}

@Test
public void MS2_US6Scenario3() {
goalRepository = MockGoalRepository.createWithEmptyGoals();
Expand Down Expand Up @@ -1188,6 +1212,4 @@ public void MS2_US8Scenario4() {
}




}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package edu.ucsd.cse110.successorator.lib.domain;

import java.sql.Time;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -39,6 +38,14 @@ public class MockGoalRepository implements GoalRepository {
new Goal(3, "Goal 1", 3, false, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4 + TimeUtils.DAY_LENGTH, false, false, RecurrenceType.NONE, Context.HOME, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4 + TimeUtils.DAY_LENGTH, 2, null, 1, true)
);

private final static List<Goal> ALL_RECURRENCE_TEST_GOALS = List.of(
new Goal(1, "Goal 1", 1, false, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4, false, false, RecurrenceType.NONE, Context.HOME, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4, null, null, null, false),
new Goal(2, "Goal 2", 2, false, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4, false, true, RecurrenceType.DAILY, Context.HOME, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4, null, null, null, false),
new Goal(3, "Goal 3", 3, false, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4, false, true, RecurrenceType.WEEKLY, Context.HOME, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4, null, null, null, false),
new Goal(4, "Goal 4", 4, false, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4, false, true, RecurrenceType.MONTHLY, Context.HOME, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4, null, null, null, false),
new Goal(5, "Goal 5", 5, false, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4, false, true, RecurrenceType.YEARLY, Context.HOME, TimeUtils.START_TIME - TimeUtils.HOUR_LENGTH * 4, null, null, null, false)
);

public static MockGoalRepository createWithDefaultGoals() {
return new MockGoalRepository(DEFAULT_GOALS_SIMPLE_CASE);
}
Expand All @@ -51,12 +58,16 @@ public static MockGoalRepository createWithRecurringTestGoals() {
return new MockGoalRepository(RECCURING_TEST_GOALS);
}

public static MockGoalRepository createWithAllRecurrenceTypeTestGoals() {
return new MockGoalRepository(ALL_RECURRENCE_TEST_GOALS);
}

public static MockGoalRepository createWithEmptyGoals() {
return new MockGoalRepository(new ArrayList<>());
}

public MockGoalRepository(List<Goal> goals) {
this.goals = new ArrayList<>();
this.goals = new ArrayList<>();
for (Goal goal : goals) {
var subject = new SimpleSubject<Goal>();
subject.setValue(goal);
Expand Down
Loading
Loading