mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-09 18:48:51 -06:00
Merge pull request #547 from recheej/rechee/add_notes
Add Notes to Habits.
This commit is contained in:
@@ -87,6 +87,7 @@ dependencies {
|
|||||||
implementation "com.google.code.gson:gson:2.8.5"
|
implementation "com.google.code.gson:gson:2.8.5"
|
||||||
implementation "com.google.code.findbugs:jsr305:3.0.2"
|
implementation "com.google.code.findbugs:jsr305:3.0.2"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$KOTLIN_VERSION"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$KOTLIN_VERSION"
|
||||||
|
implementation "androidx.constraintlayout:constraintlayout:2.0.0-beta4"
|
||||||
|
|
||||||
compileOnly "javax.annotation:jsr250-api:1.0"
|
compileOnly "javax.annotation:jsr250-api:1.0"
|
||||||
compileOnly "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION"
|
compileOnly "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION"
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
@@ -39,6 +39,7 @@ import static androidx.test.uiautomator.UiDevice.*;
|
|||||||
public class BaseUserInterfaceTest
|
public class BaseUserInterfaceTest
|
||||||
{
|
{
|
||||||
private static final String PKG = "org.isoron.uhabits";
|
private static final String PKG = "org.isoron.uhabits";
|
||||||
|
public static final String EMPTY_DESCRIPTION_HABIT_NAME = "Read books";
|
||||||
|
|
||||||
public static UiDevice device;
|
public static UiDevice device;
|
||||||
|
|
||||||
@@ -96,25 +97,29 @@ public class BaseUserInterfaceTest
|
|||||||
|
|
||||||
Habit h1 = fixtures.createEmptyHabit();
|
Habit h1 = fixtures.createEmptyHabit();
|
||||||
h1.setName("Wake up early");
|
h1.setName("Wake up early");
|
||||||
h1.setDescription("Did you wake up early today?");
|
h1.setQuestion("Did you wake up early today?");
|
||||||
|
h1.setDescription("test description 1");
|
||||||
h1.setColor(5);
|
h1.setColor(5);
|
||||||
habitList.update(h1);
|
habitList.update(h1);
|
||||||
|
|
||||||
Habit h2 = fixtures.createShortHabit();
|
Habit h2 = fixtures.createShortHabit();
|
||||||
h2.setName("Track time");
|
h2.setName("Track time");
|
||||||
h2.setDescription("Did you track your time?");
|
h2.setQuestion("Did you track your time?");
|
||||||
|
h2.setDescription("test description 2");
|
||||||
h2.setColor(5);
|
h2.setColor(5);
|
||||||
habitList.update(h2);
|
habitList.update(h2);
|
||||||
|
|
||||||
Habit h3 = fixtures.createLongHabit();
|
Habit h3 = fixtures.createLongHabit();
|
||||||
h3.setName("Meditate");
|
h3.setName("Meditate");
|
||||||
h3.setDescription("Did meditate today?");
|
h3.setQuestion("Did meditate today?");
|
||||||
|
h3.setDescription("test description 3");
|
||||||
h3.setColor(10);
|
h3.setColor(10);
|
||||||
habitList.update(h3);
|
habitList.update(h3);
|
||||||
|
|
||||||
Habit h4 = fixtures.createEmptyHabit();
|
Habit h4 = fixtures.createEmptyHabit();
|
||||||
h4.setName("Read books");
|
h4.setName(EMPTY_DESCRIPTION_HABIT_NAME);
|
||||||
h4.setDescription("Did you read books today?");
|
h4.setQuestion("Did you read books today?");
|
||||||
|
h4.setDescription("");
|
||||||
h4.setColor(2);
|
h4.setColor(2);
|
||||||
habitList.update(h4);
|
habitList.update(h4);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ public class HabitFixtures
|
|||||||
{
|
{
|
||||||
Habit habit = modelFactory.buildHabit();
|
Habit habit = modelFactory.buildHabit();
|
||||||
habit.setName("Meditate");
|
habit.setName("Meditate");
|
||||||
habit.setDescription("Did you meditate this morning?");
|
habit.setQuestion("Did you meditate this morning?");
|
||||||
|
habit.setDescription("This is a test description");
|
||||||
habit.setColor(5);
|
habit.setColor(5);
|
||||||
habit.setFrequency(Frequency.DAILY);
|
habit.setFrequency(Frequency.DAILY);
|
||||||
habit.setId(id);
|
habit.setId(id);
|
||||||
@@ -81,7 +82,7 @@ public class HabitFixtures
|
|||||||
{
|
{
|
||||||
Habit habit = modelFactory.buildHabit();
|
Habit habit = modelFactory.buildHabit();
|
||||||
habit.setName("Take a walk");
|
habit.setName("Take a walk");
|
||||||
habit.setDescription("How many steps did you walk today?");
|
habit.setQuestion("How many steps did you walk today?");
|
||||||
habit.setType(Habit.NUMBER_HABIT);
|
habit.setType(Habit.NUMBER_HABIT);
|
||||||
habit.setTargetType(Habit.AT_LEAST);
|
habit.setTargetType(Habit.AT_LEAST);
|
||||||
habit.setTargetValue(200.0);
|
habit.setTargetValue(200.0);
|
||||||
@@ -103,7 +104,7 @@ public class HabitFixtures
|
|||||||
{
|
{
|
||||||
Habit habit = modelFactory.buildHabit();
|
Habit habit = modelFactory.buildHabit();
|
||||||
habit.setName("Wake up early");
|
habit.setName("Wake up early");
|
||||||
habit.setDescription("Did you wake up before 6am?");
|
habit.setQuestion("Did you wake up before 6am?");
|
||||||
habit.setFrequency(new Frequency(2, 3));
|
habit.setFrequency(new Frequency(2, 3));
|
||||||
habitList.add(habit);
|
habitList.add(habit);
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
package org.isoron.uhabits.acceptance;
|
package org.isoron.uhabits.acceptance;
|
||||||
|
|
||||||
import androidx.test.filters.*;
|
import androidx.test.filters.*;
|
||||||
import androidx.test.runner.*;
|
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
@@ -39,7 +38,16 @@ import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.*;
|
|||||||
public class HabitsTest extends BaseUserInterfaceTest
|
public class HabitsTest extends BaseUserInterfaceTest
|
||||||
{
|
{
|
||||||
@Test
|
@Test
|
||||||
public void shouldCreateHabit() throws Exception
|
public void shouldCreateHabit() throws Exception {
|
||||||
|
shouldCreateHabit("this is a test description");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCreateHabitBlankDescription() throws Exception {
|
||||||
|
shouldCreateHabit("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shouldCreateHabit(String description) throws Exception
|
||||||
{
|
{
|
||||||
launchApp();
|
launchApp();
|
||||||
|
|
||||||
@@ -47,14 +55,16 @@ public class HabitsTest extends BaseUserInterfaceTest
|
|||||||
clickMenu(ADD);
|
clickMenu(ADD);
|
||||||
|
|
||||||
verifyShowsScreen(EDIT_HABIT);
|
verifyShowsScreen(EDIT_HABIT);
|
||||||
typeName("Hello world");
|
String testName = "Hello world";
|
||||||
|
typeName(testName);
|
||||||
typeQuestion("Did you say hello to the world today?");
|
typeQuestion("Did you say hello to the world today?");
|
||||||
|
typeDescription(description);
|
||||||
pickFrequency("Every week");
|
pickFrequency("Every week");
|
||||||
pickColor(5);
|
pickColor(5);
|
||||||
clickSave();
|
clickSave();
|
||||||
|
|
||||||
verifyShowsScreen(LIST_HABITS);
|
verifyShowsScreen(LIST_HABITS);
|
||||||
verifyDisplaysText("Hello world");
|
verifyDisplaysText(testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -81,7 +91,16 @@ public class HabitsTest extends BaseUserInterfaceTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldEditHabit() throws Exception
|
public void shouldEditHabit() throws Exception {
|
||||||
|
shouldEditHabit("this is a test description");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldEditHabitBlankDescription() throws Exception {
|
||||||
|
shouldEditHabit("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shouldEditHabit(String description) throws Exception
|
||||||
{
|
{
|
||||||
launchApp();
|
launchApp();
|
||||||
|
|
||||||
@@ -92,6 +111,7 @@ public class HabitsTest extends BaseUserInterfaceTest
|
|||||||
verifyShowsScreen(EDIT_HABIT);
|
verifyShowsScreen(EDIT_HABIT);
|
||||||
typeName("Take a walk");
|
typeName("Take a walk");
|
||||||
typeQuestion("Did you take a walk today?");
|
typeQuestion("Did you take a walk today?");
|
||||||
|
typeDescription(description);
|
||||||
clickSave();
|
clickSave();
|
||||||
|
|
||||||
verifyShowsScreen(LIST_HABITS);
|
verifyShowsScreen(LIST_HABITS);
|
||||||
@@ -174,4 +194,12 @@ public class HabitsTest extends BaseUserInterfaceTest
|
|||||||
verifyDisplaysText("Track time");
|
verifyDisplaysText("Track time");
|
||||||
verifyDisplaysText("Wake up early");
|
verifyDisplaysText("Wake up early");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldHideNotesCard() throws Exception
|
||||||
|
{
|
||||||
|
launchApp();
|
||||||
|
clickText(EMPTY_DESCRIPTION_HABIT_NAME);
|
||||||
|
verifyShowsScreen(SHOW_HABIT, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,16 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.acceptance.steps;
|
package org.isoron.uhabits.acceptance.steps;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.test.espresso.*;
|
import androidx.test.espresso.*;
|
||||||
import androidx.test.espresso.contrib.*;
|
import androidx.test.espresso.contrib.*;
|
||||||
import androidx.test.uiautomator.*;
|
import androidx.test.uiautomator.*;
|
||||||
import androidx.appcompat.widget.*;
|
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import org.hamcrest.Matcher;
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.activities.habits.list.*;
|
import org.isoron.uhabits.activities.habits.list.*;
|
||||||
@@ -153,7 +155,11 @@ public class CommonSteps extends BaseUserInterfaceTest
|
|||||||
LIST_HABITS, SHOW_HABIT, EDIT_HABIT
|
LIST_HABITS, SHOW_HABIT, EDIT_HABIT
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void verifyShowsScreen(Screen screen)
|
public static void verifyShowsScreen(Screen screen) {
|
||||||
|
verifyShowsScreen(screen, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void verifyShowsScreen(Screen screen, boolean notesCardVisibleExpected)
|
||||||
{
|
{
|
||||||
switch(screen)
|
switch(screen)
|
||||||
{
|
{
|
||||||
@@ -163,10 +169,14 @@ public class CommonSteps extends BaseUserInterfaceTest
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SHOW_HABIT:
|
case SHOW_HABIT:
|
||||||
|
Matcher<View> noteCardViewMatcher = notesCardVisibleExpected ? isDisplayed() :
|
||||||
|
withEffectiveVisibility(Visibility.GONE);
|
||||||
onView(withId(R.id.subtitleCard)).check(matches(isDisplayed()));
|
onView(withId(R.id.subtitleCard)).check(matches(isDisplayed()));
|
||||||
|
onView(withId(R.id.notesCard)).check(matches(noteCardViewMatcher));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EDIT_HABIT:
|
case EDIT_HABIT:
|
||||||
|
onView(withId(R.id.tvQuestion)).check(matches(isDisplayed()));
|
||||||
onView(withId(R.id.tvDescription)).check(matches(isDisplayed()));
|
onView(withId(R.id.tvDescription)).check(matches(isDisplayed()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,12 @@ public class EditHabitSteps
|
|||||||
|
|
||||||
public static void typeQuestion(String name)
|
public static void typeQuestion(String name)
|
||||||
{
|
{
|
||||||
typeTextWithId(R.id.tvDescription, name);
|
typeTextWithId(R.id.tvQuestion, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void typeDescription(String description)
|
||||||
|
{
|
||||||
|
typeTextWithId(R.id.tvDescription, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setReminder()
|
public static void setReminder()
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker 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.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker 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 org.isoron.uhabits.activities.habits.show.views;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.MediumTest;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.BaseViewTest;
|
||||||
|
import org.isoron.uhabits.R;
|
||||||
|
import org.isoron.uhabits.core.models.Habit;
|
||||||
|
import org.isoron.uhabits.core.models.Reminder;
|
||||||
|
import org.isoron.uhabits.core.models.WeekdayList;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@MediumTest
|
||||||
|
public class NotesCardTest extends BaseViewTest
|
||||||
|
{
|
||||||
|
public static final String PATH = "habits/show/NotesCard/";
|
||||||
|
|
||||||
|
private NotesCard view;
|
||||||
|
|
||||||
|
private Habit habit;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
@Override
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
habit = fixtures.createLongHabit();
|
||||||
|
habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
|
||||||
|
|
||||||
|
view = LayoutInflater
|
||||||
|
.from(targetContext)
|
||||||
|
.inflate(R.layout.show_habit, null)
|
||||||
|
.findViewById(R.id.notesCard);
|
||||||
|
|
||||||
|
view.setHabit(habit);
|
||||||
|
view.refreshData();
|
||||||
|
|
||||||
|
measureView(view, 800, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRender() throws Exception
|
||||||
|
{
|
||||||
|
assertRenders(view, PATH + "render.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRenderEmptyDescription() throws Exception
|
||||||
|
{
|
||||||
|
habit.setDescription("");
|
||||||
|
view.refreshData();
|
||||||
|
assertRenders(view, PATH + "render-empty-description.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,7 +49,7 @@ public class SubtitleCardTest extends BaseViewTest
|
|||||||
habit = fixtures.createLongHabit();
|
habit = fixtures.createLongHabit();
|
||||||
habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
|
habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
|
||||||
|
|
||||||
view = (SubtitleCard) LayoutInflater
|
view = LayoutInflater
|
||||||
.from(targetContext)
|
.from(targetContext)
|
||||||
.inflate(R.layout.show_habit, null)
|
.inflate(R.layout.show_habit, null)
|
||||||
.findViewById(R.id.subtitleCard);
|
.findViewById(R.id.subtitleCard);
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ public class EditHabitDialog extends AppCompatDialogFragment
|
|||||||
habit.copyFrom(originalHabit);
|
habit.copyFrom(originalHabit);
|
||||||
habit.setName(namePanel.getName());
|
habit.setName(namePanel.getName());
|
||||||
habit.setDescription(namePanel.getDescription());
|
habit.setDescription(namePanel.getDescription());
|
||||||
|
habit.setQuestion(namePanel.getQuestion());
|
||||||
habit.setColor(namePanel.getColor());
|
habit.setColor(namePanel.getColor());
|
||||||
habit.setReminder(reminderPanel.getReminder());
|
habit.setReminder(reminderPanel.getReminder());
|
||||||
habit.setFrequency(frequencyPanel.getFrequency());
|
habit.setFrequency(frequencyPanel.getFrequency());
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.text.*;
|
|||||||
import android.util.*;
|
import android.util.*;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.widget.AppCompatEditText;
|
import androidx.appcompat.widget.AppCompatEditText;
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ public class ExampleEditText extends AppCompatEditText
|
|||||||
updateText();
|
updateText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRealText(String realText)
|
public void setRealText(@NonNull String realText)
|
||||||
{
|
{
|
||||||
this.realText = realText;
|
this.realText = realText;
|
||||||
updateText();
|
updateText();
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ public class NameDescriptionPanel extends FrameLayout
|
|||||||
@BindView(R.id.tvName)
|
@BindView(R.id.tvName)
|
||||||
EditText tvName;
|
EditText tvName;
|
||||||
|
|
||||||
|
@BindView(R.id.tvQuestion)
|
||||||
|
ExampleEditText tvQuestion;
|
||||||
|
|
||||||
@BindView(R.id.tvDescription)
|
@BindView(R.id.tvDescription)
|
||||||
ExampleEditText tvDescription;
|
ExampleEditText tvDescription;
|
||||||
|
|
||||||
@@ -79,6 +82,12 @@ public class NameDescriptionPanel extends FrameLayout
|
|||||||
return tvDescription.getRealText().trim();
|
return tvDescription.getRealText().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String getQuestion()
|
||||||
|
{
|
||||||
|
return tvQuestion.getRealText().trim();
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public String getName()
|
public String getName()
|
||||||
{
|
{
|
||||||
@@ -90,12 +99,13 @@ public class NameDescriptionPanel extends FrameLayout
|
|||||||
Resources res = getResources();
|
Resources res = getResources();
|
||||||
|
|
||||||
if(habit.isNumerical())
|
if(habit.isNumerical())
|
||||||
tvDescription.setExample(res.getString(R.string.example_question_numerical));
|
tvQuestion.setExample(res.getString(R.string.example_question_numerical));
|
||||||
else
|
else
|
||||||
tvDescription.setExample(res.getString(R.string.example_question_boolean));
|
tvQuestion.setExample(res.getString(R.string.example_question_boolean));
|
||||||
|
|
||||||
setColor(habit.getColor());
|
setColor(habit.getColor());
|
||||||
tvName.setText(habit.getName());
|
tvName.setText(habit.getName());
|
||||||
|
tvQuestion.setRealText(habit.getQuestion());
|
||||||
tvDescription.setRealText(habit.getDescription());
|
tvDescription.setRealText(habit.getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package org.isoron.uhabits.activities.habits.show;
|
|||||||
|
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.widget.*;
|
import androidx.appcompat.widget.*;
|
||||||
@@ -52,6 +53,12 @@ public class ShowHabitRootView extends BaseRootView
|
|||||||
@BindView(R.id.subtitleCard)
|
@BindView(R.id.subtitleCard)
|
||||||
SubtitleCard subtitleCard;
|
SubtitleCard subtitleCard;
|
||||||
|
|
||||||
|
@BindView(R.id.notesCard)
|
||||||
|
NotesCard notesCard;
|
||||||
|
|
||||||
|
@BindView(R.id.habitNotes)
|
||||||
|
TextView habitNotes;
|
||||||
|
|
||||||
@BindView(R.id.overviewCard)
|
@BindView(R.id.overviewCard)
|
||||||
OverviewCard overviewCard;
|
OverviewCard overviewCard;
|
||||||
|
|
||||||
@@ -136,6 +143,7 @@ public class ShowHabitRootView extends BaseRootView
|
|||||||
private void initCards()
|
private void initCards()
|
||||||
{
|
{
|
||||||
subtitleCard.setHabit(habit);
|
subtitleCard.setHabit(habit);
|
||||||
|
notesCard.setHabit(habit);
|
||||||
overviewCard.setHabit(habit);
|
overviewCard.setHabit(habit);
|
||||||
scoreCard.setHabit(habit);
|
scoreCard.setHabit(habit);
|
||||||
historyCard.setHabit(habit);
|
historyCard.setHabit(habit);
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.core.tasks.Task
|
||||||
|
|
||||||
|
class NotesCard(context: Context?, attrs: AttributeSet?) : HabitCard(context, attrs) {
|
||||||
|
|
||||||
|
private val notesTextView: TextView
|
||||||
|
|
||||||
|
init {
|
||||||
|
View.inflate(getContext(), R.layout.show_habit_notes, this)
|
||||||
|
notesTextView = findViewById(R.id.habitNotes)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refreshData() {
|
||||||
|
notesTextView.text = habit.description
|
||||||
|
visibility = if(habit.description.isEmpty()) View.GONE else View.VISIBLE
|
||||||
|
notesTextView.visibility = visibility
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createRefreshTask(): Task = error("refresh task should never be called.")
|
||||||
|
}
|
||||||
@@ -59,12 +59,12 @@ public class SubtitleCard extends HabitCard
|
|||||||
questionLabel.setVisibility(VISIBLE);
|
questionLabel.setVisibility(VISIBLE);
|
||||||
|
|
||||||
questionLabel.setTextColor(color);
|
questionLabel.setTextColor(color);
|
||||||
questionLabel.setText(habit.getDescription());
|
questionLabel.setText(habit.getQuestion());
|
||||||
frequencyLabel.setText(toText(habit.getFrequency()));
|
frequencyLabel.setText(toText(habit.getFrequency()));
|
||||||
|
|
||||||
if (habit.hasReminder()) updateReminderText(habit.getReminder());
|
if (habit.hasReminder()) updateReminderText(habit.getReminder());
|
||||||
|
|
||||||
if (habit.getDescription().isEmpty()) questionLabel.setVisibility(GONE);
|
if (habit.getQuestion().isEmpty()) questionLabel.setVisibility(GONE);
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ class AndroidNotificationTray
|
|||||||
val builder = NotificationCompat.Builder(context, REMINDERS_CHANNEL_ID)
|
val builder = NotificationCompat.Builder(context, REMINDERS_CHANNEL_ID)
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
.setContentTitle(habit.name)
|
.setContentTitle(habit.name)
|
||||||
.setContentText(if(habit.description.isBlank()) defaultText else habit.description)
|
.setContentText(if(habit.question.isBlank()) defaultText else habit.question)
|
||||||
.setContentIntent(pendingIntents.showHabit(habit))
|
.setContentIntent(pendingIntents.showHabit(habit))
|
||||||
.setDeleteIntent(pendingIntents.dismissNotification(habit))
|
.setDeleteIntent(pendingIntents.dismissNotification(habit))
|
||||||
.addAction(addRepetitionAction)
|
.addAction(addRepetitionAction)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
<!--
|
|
||||||
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
~
|
~
|
||||||
~ This file is part of Loop Habit Tracker.
|
~ This file is part of Loop Habit Tracker.
|
||||||
@@ -18,27 +17,29 @@
|
|||||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://isoron.org/android"
|
xmlns:app="http://isoron.org/android"
|
||||||
|
xmlns:app1="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:minWidth="300dp">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
style="@style/dialogFormRow">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/tilName"
|
android:id="@+id/tilName"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="6">
|
app1:layout_constraintEnd_toStartOf="@+id/buttonPickColor"
|
||||||
|
app1:layout_constraintHorizontal_weight="6"
|
||||||
|
app1:layout_constraintStart_toStartOf="parent"
|
||||||
|
app1:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/tvName"
|
android:id="@+id/tvName"
|
||||||
style="@style/dialogFormInput"
|
style="@style/dialogFormInput"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="start"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:hint="@string/name">
|
android:hint="@string/name">
|
||||||
|
|
||||||
<requestFocus />
|
<requestFocus />
|
||||||
@@ -48,23 +49,50 @@
|
|||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/buttonPickColor"
|
android:id="@+id/buttonPickColor"
|
||||||
style="@style/dialogFormInputColor"
|
style="@style/dialogFormInputColor"
|
||||||
android:layout_weight="1"
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@string/color_picker_default_title"
|
android:contentDescription="@string/color_picker_default_title"
|
||||||
android:src="?dialogIconChangeColor"/>
|
android:src="?dialogIconChangeColor"
|
||||||
|
app1:layout_constraintBottom_toBottomOf="@id/tilName"
|
||||||
</LinearLayout>
|
app1:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app1:layout_constraintHorizontal_weight="1"
|
||||||
|
app1:layout_constraintStart_toEndOf="@+id/tilName"
|
||||||
|
app1:layout_constraintTop_toTopOf="@id/tilName" />
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/tilQuestion"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/question"
|
||||||
|
app1:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app1:layout_constraintStart_toStartOf="parent"
|
||||||
|
app1:layout_constraintTop_toBottomOf="@id/tilName">
|
||||||
|
|
||||||
|
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
|
||||||
|
android:id="@+id/tvQuestion"
|
||||||
|
style="@style/dialogFormInput"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
app:example="@string/example_question_numerical" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:hint="@string/notes"
|
||||||
|
app1:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app1:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app1:layout_constraintStart_toStartOf="parent"
|
||||||
|
app1:layout_constraintTop_toBottomOf="@id/tilQuestion">
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
|
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
|
||||||
android:id="@+id/tvDescription"
|
android:id="@+id/tvDescription"
|
||||||
style="@style/dialogFormInputMultiline"
|
style="@style/dialogFormInputMultiline"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/question"
|
android:gravity="top"
|
||||||
app:example="@string/example_question_numerical"/>
|
app:example="@string/example_notes" />
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -38,6 +38,11 @@
|
|||||||
android:id="@+id/subtitleCard"
|
android:id="@+id/subtitleCard"
|
||||||
style="@style/ShowHabit.Subtitle"/>
|
style="@style/ShowHabit.Subtitle"/>
|
||||||
|
|
||||||
|
<org.isoron.uhabits.activities.habits.show.views.NotesCard
|
||||||
|
android:id="@+id/notesCard"
|
||||||
|
style="@style/Card"
|
||||||
|
android:gravity="center" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/headerShadow"
|
android:id="@+id/headerShadow"
|
||||||
style="@style/ToolbarShadow"/>
|
style="@style/ToolbarShadow"/>
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
~
|
||||||
|
~ This file is part of Loop Habit Tracker.
|
||||||
|
~
|
||||||
|
~ Loop Habit Tracker 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.
|
||||||
|
~
|
||||||
|
~ Loop Habit Tracker 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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:layout_height="wrap_content"
|
||||||
|
tools:layout_width="match_parent"
|
||||||
|
tools:orientation="vertical"
|
||||||
|
tools:parentTag="android.widget.LinearLayout">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/habitNotes"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="?highContrastTextColor"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:text="This is some example text for the notes" />
|
||||||
|
</merge>
|
||||||
@@ -18,7 +18,12 @@
|
|||||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:parentTag="android.widget.LinearLayout"
|
||||||
|
tools:orientation="vertical"
|
||||||
|
tools:layout_width="match_parent"
|
||||||
|
tools:layout_height="wrap_content">
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/questionLabel"
|
android:id="@+id/questionLabel"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -26,6 +31,7 @@
|
|||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:textColor="?mediumContrastTextColor"
|
android:textColor="?mediumContrastTextColor"
|
||||||
android:textSize="@dimen/regularTextSize"
|
android:textSize="@dimen/regularTextSize"
|
||||||
|
tools:text="Have you worked out today?"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -33,7 +39,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/frequencyIcon"
|
android:id="@+id/frequencyIcon"
|
||||||
@@ -42,8 +49,7 @@
|
|||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:layout_marginRight="5dp"
|
android:layout_marginRight="5dp"
|
||||||
android:alpha="0.3"
|
android:alpha="0.3"
|
||||||
android:src="?iconFrequency"
|
android:src="?iconFrequency" />
|
||||||
/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/frequencyLabel"
|
android:id="@+id/frequencyLabel"
|
||||||
@@ -51,20 +57,18 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/every_day"
|
android:text="@string/every_day"
|
||||||
android:textColor="?mediumContrastTextColor"
|
android:textColor="?mediumContrastTextColor"
|
||||||
android:textSize="@dimen/smallTextSize"
|
android:textSize="@dimen/smallTextSize" />
|
||||||
/>
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/reminderIcon"
|
android:id="@+id/reminderIcon"
|
||||||
android:layout_width="18dp"
|
android:layout_width="18dp"
|
||||||
android:layout_height="18dp"
|
android:layout_height="18dp"
|
||||||
android:layout_marginEnd="5dp"
|
|
||||||
android:layout_marginLeft="10dp"
|
|
||||||
android:layout_marginRight="5dp"
|
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
android:layout_marginRight="5dp"
|
||||||
android:alpha="0.3"
|
android:alpha="0.3"
|
||||||
android:src="?iconReminder"
|
android:src="?iconReminder" />
|
||||||
/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/reminderLabel"
|
android:id="@+id/reminderLabel"
|
||||||
@@ -72,8 +76,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingTop="1dp"
|
android:paddingTop="1dp"
|
||||||
android:textColor="?mediumContrastTextColor"
|
android:textColor="?mediumContrastTextColor"
|
||||||
android:textSize="@dimen/smallTextSize"
|
android:textSize="@dimen/smallTextSize" />
|
||||||
/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</merge>
|
</merge>
|
||||||
@@ -244,5 +244,7 @@
|
|||||||
<string name="widget_opacity_description">Makes widgets more transparent or more opaque in your home screen.</string>
|
<string name="widget_opacity_description">Makes widgets more transparent or more opaque in your home screen.</string>
|
||||||
<string name="first_day_of_the_week">First day of the week</string>
|
<string name="first_day_of_the_week">First day of the week</string>
|
||||||
<string name="default_reminder_question">Have you completed this habit today?</string>
|
<string name="default_reminder_question">Have you completed this habit today?</string>
|
||||||
|
<string name="notes">Notes</string>
|
||||||
|
<string name="example_notes">You can put whatever you want here!</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'kotlin'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
annotationProcessor "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION"
|
annotationProcessor "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION"
|
||||||
@@ -26,6 +27,7 @@ dependencies {
|
|||||||
implementation('com.opencsv:opencsv:3.10') {
|
implementation('com.opencsv:opencsv:3.10') {
|
||||||
exclude group: 'commons-logging', module: 'commons-logging'
|
exclude group: 'commons-logging', module: 'commons-logging'
|
||||||
}
|
}
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$KOTLIN_VERSION"
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCompatibility = "1.8"
|
sourceCompatibility = "1.8"
|
||||||
|
|||||||
@@ -22,5 +22,5 @@ package org.isoron.uhabits.core;
|
|||||||
public class Config
|
public class Config
|
||||||
{
|
{
|
||||||
public static final String DATABASE_FILENAME = "uhabits.db";
|
public static final String DATABASE_FILENAME = "uhabits.db";
|
||||||
public static int DATABASE_VERSION = 22;
|
public static int DATABASE_VERSION = 23;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public class HabitBullCSVImporter extends AbstractImporter
|
|||||||
{
|
{
|
||||||
h = modelFactory.buildHabit();
|
h = modelFactory.buildHabit();
|
||||||
h.setName(name);
|
h.setName(name);
|
||||||
h.setDescription(description);
|
h.setDescription(description == null ? "" : description);
|
||||||
h.setFrequency(Frequency.DAILY);
|
h.setFrequency(Frequency.DAILY);
|
||||||
habitList.add(h);
|
habitList.add(h);
|
||||||
map.put(name, h);
|
map.put(name, h);
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class RewireDBImporter extends AbstractImporter
|
|||||||
|
|
||||||
Habit habit = modelFactory.buildHabit();
|
Habit habit = modelFactory.buildHabit();
|
||||||
habit.setName(name);
|
habit.setName(name);
|
||||||
habit.setDescription(description);
|
habit.setDescription(description == null ? "" : description);
|
||||||
|
|
||||||
int periods[] = { 7, 31, 365 };
|
int periods[] = { 7, 31, 365 };
|
||||||
int numerator, denominator;
|
int numerator, denominator;
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ public class TickmateDBImporter extends AbstractImporter
|
|||||||
|
|
||||||
Habit habit = modelFactory.buildHabit();
|
Habit habit = modelFactory.buildHabit();
|
||||||
habit.setName(name);
|
habit.setName(name);
|
||||||
habit.setDescription(description);
|
habit.setDescription(description == null ? "" : description);
|
||||||
habit.setFrequency(Frequency.DAILY);
|
habit.setFrequency(Frequency.DAILY);
|
||||||
habitList.add(habit);
|
habitList.add(habit);
|
||||||
|
|
||||||
|
|||||||
@@ -354,6 +354,15 @@ public class Habit
|
|||||||
data.position = newPosition;
|
data.position = newPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String getQuestion() {
|
||||||
|
return data.question;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQuestion(@NonNull String question) {
|
||||||
|
data.question = question;
|
||||||
|
}
|
||||||
|
|
||||||
public static final class HabitData
|
public static final class HabitData
|
||||||
{
|
{
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -362,6 +371,9 @@ public class Habit
|
|||||||
@NonNull
|
@NonNull
|
||||||
public String description;
|
public String description;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public String question;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public Frequency frequency;
|
public Frequency frequency;
|
||||||
|
|
||||||
@@ -391,6 +403,7 @@ public class Habit
|
|||||||
this.type = YES_NO_HABIT;
|
this.type = YES_NO_HABIT;
|
||||||
this.name = "";
|
this.name = "";
|
||||||
this.description = "";
|
this.description = "";
|
||||||
|
this.question = "";
|
||||||
this.targetType = AT_LEAST;
|
this.targetType = AT_LEAST;
|
||||||
this.targetValue = 100;
|
this.targetValue = 100;
|
||||||
this.unit = "";
|
this.unit = "";
|
||||||
@@ -401,6 +414,7 @@ public class Habit
|
|||||||
{
|
{
|
||||||
this.name = model.name;
|
this.name = model.name;
|
||||||
this.description = model.description;
|
this.description = model.description;
|
||||||
|
this.question = model.question;
|
||||||
this.frequency = model.frequency;
|
this.frequency = model.frequency;
|
||||||
this.color = model.color;
|
this.color = model.color;
|
||||||
this.archived = model.archived;
|
this.archived = model.archived;
|
||||||
@@ -427,6 +441,7 @@ public class Habit
|
|||||||
.append("unit", unit)
|
.append("unit", unit)
|
||||||
.append("reminder", reminder)
|
.append("reminder", reminder)
|
||||||
.append("position", position)
|
.append("position", position)
|
||||||
|
.append("question", question)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,6 +466,7 @@ public class Habit
|
|||||||
.append(unit, habitData.unit)
|
.append(unit, habitData.unit)
|
||||||
.append(reminder, habitData.reminder)
|
.append(reminder, habitData.reminder)
|
||||||
.append(position, habitData.position)
|
.append(position, habitData.position)
|
||||||
|
.append(question, habitData.question)
|
||||||
.isEquals();
|
.isEquals();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,6 +485,7 @@ public class Habit
|
|||||||
.append(unit)
|
.append(unit)
|
||||||
.append(reminder)
|
.append(reminder)
|
||||||
.append(position)
|
.append(position)
|
||||||
|
.append(question)
|
||||||
.toHashCode();
|
.toHashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ public abstract class HabitList implements Iterable<Habit>
|
|||||||
String header[] = {
|
String header[] = {
|
||||||
"Position",
|
"Position",
|
||||||
"Name",
|
"Name",
|
||||||
|
"Question",
|
||||||
"Description",
|
"Description",
|
||||||
"NumRepetitions",
|
"NumRepetitions",
|
||||||
"Interval",
|
"Interval",
|
||||||
@@ -228,6 +229,7 @@ public abstract class HabitList implements Iterable<Habit>
|
|||||||
String[] cols = {
|
String[] cols = {
|
||||||
String.format("%03d", indexOf(habit) + 1),
|
String.format("%03d", indexOf(habit) + 1),
|
||||||
habit.getName(),
|
habit.getName(),
|
||||||
|
habit.getQuestion(),
|
||||||
habit.getDescription(),
|
habit.getDescription(),
|
||||||
Integer.toString(freq.getNumerator()),
|
Integer.toString(freq.getNumerator()),
|
||||||
Integer.toString(freq.getDenominator()),
|
Integer.toString(freq.getDenominator()),
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ public class HabitRecord
|
|||||||
@Column
|
@Column
|
||||||
public String description;
|
public String description;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
public String question;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
@@ -91,6 +94,7 @@ public class HabitRecord
|
|||||||
this.targetValue = model.getTargetValue();
|
this.targetValue = model.getTargetValue();
|
||||||
this.unit = model.getUnit();
|
this.unit = model.getUnit();
|
||||||
this.position = model.getPosition();
|
this.position = model.getPosition();
|
||||||
|
this.question = model.getQuestion();
|
||||||
|
|
||||||
Frequency freq = model.getFrequency();
|
Frequency freq = model.getFrequency();
|
||||||
this.freqNum = freq.getNumerator();
|
this.freqNum = freq.getNumerator();
|
||||||
@@ -113,6 +117,7 @@ public class HabitRecord
|
|||||||
habit.setId(this.id);
|
habit.setId(this.id);
|
||||||
habit.setName(this.name);
|
habit.setName(this.name);
|
||||||
habit.setDescription(this.description);
|
habit.setDescription(this.description);
|
||||||
|
habit.setQuestion(this.question);
|
||||||
habit.setFrequency(new Frequency(this.freqNum, this.freqDen));
|
habit.setFrequency(new Frequency(this.freqNum, this.freqDen));
|
||||||
habit.setColor(this.color);
|
habit.setColor(this.color);
|
||||||
habit.setArchived(this.archived != 0);
|
habit.setArchived(this.archived != 0);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class HabitFixtures
|
|||||||
{
|
{
|
||||||
Habit habit = modelFactory.buildHabit();
|
Habit habit = modelFactory.buildHabit();
|
||||||
habit.setName("Meditate");
|
habit.setName("Meditate");
|
||||||
habit.setDescription("Did you meditate this morning?");
|
habit.setQuestion("Did you meditate this morning?");
|
||||||
habit.setColor(3);
|
habit.setColor(3);
|
||||||
habit.setFrequency(Frequency.DAILY);
|
habit.setFrequency(Frequency.DAILY);
|
||||||
saveIfSQLite(habit);
|
saveIfSQLite(habit);
|
||||||
@@ -73,7 +73,7 @@ public class HabitFixtures
|
|||||||
Habit habit = modelFactory.buildHabit();
|
Habit habit = modelFactory.buildHabit();
|
||||||
habit.setType(Habit.NUMBER_HABIT);
|
habit.setType(Habit.NUMBER_HABIT);
|
||||||
habit.setName("Run");
|
habit.setName("Run");
|
||||||
habit.setDescription("How many miles did you run today?");
|
habit.setQuestion("How many miles did you run today?");
|
||||||
habit.setUnit("miles");
|
habit.setUnit("miles");
|
||||||
habit.setTargetType(Habit.AT_LEAST);
|
habit.setTargetType(Habit.AT_LEAST);
|
||||||
habit.setTargetValue(2.0);
|
habit.setTargetValue(2.0);
|
||||||
@@ -98,7 +98,7 @@ public class HabitFixtures
|
|||||||
Habit habit = modelFactory.buildHabit();
|
Habit habit = modelFactory.buildHabit();
|
||||||
habit.setType(Habit.NUMBER_HABIT);
|
habit.setType(Habit.NUMBER_HABIT);
|
||||||
habit.setName("Walk");
|
habit.setName("Walk");
|
||||||
habit.setDescription("How many steps did you walk today?");
|
habit.setQuestion("How many steps did you walk today?");
|
||||||
habit.setUnit("steps");
|
habit.setUnit("steps");
|
||||||
habit.setTargetType(Habit.AT_LEAST);
|
habit.setTargetType(Habit.AT_LEAST);
|
||||||
habit.setTargetValue(100);
|
habit.setTargetValue(100);
|
||||||
@@ -133,7 +133,7 @@ public class HabitFixtures
|
|||||||
{
|
{
|
||||||
Habit habit = modelFactory.buildHabit();
|
Habit habit = modelFactory.buildHabit();
|
||||||
habit.setName("Wake up early");
|
habit.setName("Wake up early");
|
||||||
habit.setDescription("Did you wake up before 6am?");
|
habit.setQuestion("Did you wake up before 6am?");
|
||||||
habit.setFrequency(new Frequency(2, 3));
|
habit.setFrequency(new Frequency(2, 3));
|
||||||
saveIfSQLite(habit);
|
saveIfSQLite(habit);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
alter table Habits add column question text;
|
||||||
|
|
||||||
|
update Habits set question = description;
|
||||||
|
|
||||||
|
update Habits set description = "";
|
||||||
@@ -125,7 +125,7 @@ public class BaseUnitTest
|
|||||||
DriverManager.getConnection("jdbc:sqlite::memory:"));
|
DriverManager.getConnection("jdbc:sqlite::memory:"));
|
||||||
db.execute("pragma user_version=8;");
|
db.execute("pragma user_version=8;");
|
||||||
MigrationHelper helper = new MigrationHelper(db);
|
MigrationHelper helper = new MigrationHelper(db);
|
||||||
helper.migrateTo(21);
|
helper.migrateTo(23);
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (SQLException e)
|
||||||
|
|||||||
@@ -159,21 +159,4 @@ public class Version22Test extends BaseUnitTest
|
|||||||
db.execute("insert into repetitions(habit, timestamp, value)" +
|
db.execute("insert into repetitions(habit, timestamp, value)" +
|
||||||
"values (0, 100, 5)");
|
"values (0, 100, 5)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testKeepHabitsUnchanged() throws Exception
|
|
||||||
{
|
|
||||||
Habit original = fixtures.createLongHabit();
|
|
||||||
Reminder reminder = new Reminder(8, 30, new WeekdayList(100));
|
|
||||||
original.setReminder(reminder);
|
|
||||||
habitList.update(original);
|
|
||||||
|
|
||||||
helper.migrateTo(22);
|
|
||||||
|
|
||||||
((SQLiteHabitList) habitList).reload();
|
|
||||||
Habit modified = habitList.getById(original.getId());
|
|
||||||
assertNotNull(modified);
|
|
||||||
|
|
||||||
assertThat(original.getData(), equalTo(modified.getData()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package org.isoron.uhabits.core.database.migrations
|
||||||
|
|
||||||
|
import org.hamcrest.MatcherAssert
|
||||||
|
import org.hamcrest.Matchers
|
||||||
|
import org.isoron.uhabits.core.BaseUnitTest
|
||||||
|
import org.isoron.uhabits.core.database.Database
|
||||||
|
import org.isoron.uhabits.core.database.MigrationHelper
|
||||||
|
import org.isoron.uhabits.core.models.sqlite.SQLModelFactory
|
||||||
|
import org.isoron.uhabits.core.test.HabitFixtures
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class Version23Test: BaseUnitTest() {
|
||||||
|
|
||||||
|
private lateinit var db: Database
|
||||||
|
|
||||||
|
private lateinit var helper: MigrationHelper
|
||||||
|
|
||||||
|
override fun setUp() {
|
||||||
|
super.setUp()
|
||||||
|
db = openDatabaseResource("/databases/022.db")
|
||||||
|
helper = MigrationHelper(db)
|
||||||
|
modelFactory = SQLModelFactory(db)
|
||||||
|
habitList = modelFactory.buildHabitList()
|
||||||
|
fixtures = HabitFixtures(modelFactory, habitList)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateTo23() = helper.migrateTo(23)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test migrate to 23 creates question column`() {
|
||||||
|
migrateTo23()
|
||||||
|
val cursor = db.query("select question from Habits")
|
||||||
|
cursor.moveToNext()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test migrate to 23 moves description to question column`() {
|
||||||
|
var cursor = db.query("select description from Habits")
|
||||||
|
|
||||||
|
val descriptions = mutableListOf<String?>()
|
||||||
|
while(cursor.moveToNext()){
|
||||||
|
descriptions.add(cursor.getString(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
migrateTo23()
|
||||||
|
cursor = db.query("select question from Habits")
|
||||||
|
|
||||||
|
for(i in 0 until descriptions.size){
|
||||||
|
cursor.moveToNext()
|
||||||
|
MatcherAssert.assertThat(cursor.getString(0), Matchers.equalTo(descriptions[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test migrate to 23 sets description to null`() {
|
||||||
|
migrateTo23()
|
||||||
|
val cursor = db.query("select description from Habits")
|
||||||
|
|
||||||
|
while(cursor.moveToNext()){
|
||||||
|
MatcherAssert.assertThat(cursor.getString(0), Matchers.equalTo(""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -218,13 +218,15 @@ public class HabitListTest extends BaseUnitTest
|
|||||||
|
|
||||||
Habit h1 = fixtures.createEmptyHabit();
|
Habit h1 = fixtures.createEmptyHabit();
|
||||||
h1.setName("Meditate");
|
h1.setName("Meditate");
|
||||||
h1.setDescription("Did you meditate this morning?");
|
h1.setQuestion("Did you meditate this morning?");
|
||||||
|
h1.setDescription("this is a test description");
|
||||||
h1.setFrequency(Frequency.DAILY);
|
h1.setFrequency(Frequency.DAILY);
|
||||||
h1.setColor(3);
|
h1.setColor(3);
|
||||||
|
|
||||||
Habit h2 = fixtures.createEmptyHabit();
|
Habit h2 = fixtures.createEmptyHabit();
|
||||||
h2.setName("Wake up early");
|
h2.setName("Wake up early");
|
||||||
h2.setDescription("Did you wake up before 6am?");
|
h2.setQuestion("Did you wake up before 6am?");
|
||||||
|
h2.setDescription("");
|
||||||
h2.setFrequency(new Frequency(2, 3));
|
h2.setFrequency(new Frequency(2, 3));
|
||||||
h2.setColor(5);
|
h2.setColor(5);
|
||||||
|
|
||||||
@@ -232,9 +234,9 @@ public class HabitListTest extends BaseUnitTest
|
|||||||
list.add(h2);
|
list.add(h2);
|
||||||
|
|
||||||
String expectedCSV =
|
String expectedCSV =
|
||||||
"Position,Name,Description,NumRepetitions,Interval,Color\n" +
|
"Position,Name,Question,Description,NumRepetitions,Interval,Color\n" +
|
||||||
"001,Meditate,Did you meditate this morning?,1,1,#FF8F00\n" +
|
"001,Meditate,Did you meditate this morning?,this is a test description,1,1,#FF8F00\n" +
|
||||||
"002,Wake up early,Did you wake up before 6am?,2,3,#AFB42B\n";
|
"002,Wake up early,Did you wake up before 6am?,,2,3,#AFB42B\n";
|
||||||
|
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
list.writeCSV(writer);
|
list.writeCSV(writer);
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ public class HabitTest extends BaseUnitTest
|
|||||||
" targetValue: 100.0, type: 0, unit: ," +
|
" targetValue: 100.0, type: 0, unit: ," +
|
||||||
" reminder: {hour: 22, minute: 30," +
|
" reminder: {hour: 22, minute: 30," +
|
||||||
" days: {weekdays: [true,true,true,true,true,true,true]}}," +
|
" days: {weekdays: [true,true,true,true,true,true,true]}}," +
|
||||||
" position: 0}}";
|
" position: 0, question: }}";
|
||||||
|
|
||||||
assertThat(h.toString(), equalTo(expected));
|
assertThat(h.toString(), equalTo(expected));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class HabitRecordTest extends BaseUnitTest
|
|||||||
{
|
{
|
||||||
Habit original = modelFactory.buildHabit();
|
Habit original = modelFactory.buildHabit();
|
||||||
original.setName("Hello world");
|
original.setName("Hello world");
|
||||||
original.setDescription("Did you greet the world today?");
|
original.setQuestion("Did you greet the world today?");
|
||||||
original.setColor(1);
|
original.setColor(1);
|
||||||
original.setArchived(true);
|
original.setArchived(true);
|
||||||
original.setFrequency(Frequency.THREE_TIMES_PER_WEEK);
|
original.setFrequency(Frequency.THREE_TIMES_PER_WEEK);
|
||||||
@@ -58,7 +58,7 @@ public class HabitRecordTest extends BaseUnitTest
|
|||||||
{
|
{
|
||||||
Habit original = modelFactory.buildHabit();
|
Habit original = modelFactory.buildHabit();
|
||||||
original.setName("Hello world");
|
original.setName("Hello world");
|
||||||
original.setDescription("Did you greet the world today?");
|
original.setQuestion("Did you greet the world today?");
|
||||||
original.setColor(5);
|
original.setColor(5);
|
||||||
original.setArchived(false);
|
original.setArchived(false);
|
||||||
original.setFrequency(Frequency.DAILY);
|
original.setFrequency(Frequency.DAILY);
|
||||||
|
|||||||
BIN
android/uhabits-core/src/test/resources/databases/022.db
Normal file
BIN
android/uhabits-core/src/test/resources/databases/022.db
Normal file
Binary file not shown.
Reference in New Issue
Block a user