diff --git a/android/uhabits-android/build.gradle b/android/uhabits-android/build.gradle index 521f4f19a..39affba4e 100644 --- a/android/uhabits-android/build.gradle +++ b/android/uhabits-android/build.gradle @@ -87,6 +87,7 @@ dependencies { implementation "com.google.code.gson:gson:2.8.5" implementation "com.google.code.findbugs:jsr305:3.0.2" 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 "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION" diff --git a/android/uhabits-android/src/androidTest/assets/views-v26/habits/show/NotesCard/render-empty-description.png b/android/uhabits-android/src/androidTest/assets/views-v26/habits/show/NotesCard/render-empty-description.png new file mode 100644 index 000000000..f9b378f6c Binary files /dev/null and b/android/uhabits-android/src/androidTest/assets/views-v26/habits/show/NotesCard/render-empty-description.png differ diff --git a/android/uhabits-android/src/androidTest/assets/views-v26/habits/show/NotesCard/render.png b/android/uhabits-android/src/androidTest/assets/views-v26/habits/show/NotesCard/render.png new file mode 100644 index 000000000..dafb53f4f Binary files /dev/null and b/android/uhabits-android/src/androidTest/assets/views-v26/habits/show/NotesCard/render.png differ diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseUserInterfaceTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseUserInterfaceTest.java index f8c62a2c6..6b5a1931c 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseUserInterfaceTest.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseUserInterfaceTest.java @@ -39,6 +39,7 @@ import static androidx.test.uiautomator.UiDevice.*; public class BaseUserInterfaceTest { private static final String PKG = "org.isoron.uhabits"; + public static final String EMPTY_DESCRIPTION_HABIT_NAME = "Read books"; public static UiDevice device; @@ -96,25 +97,29 @@ public class BaseUserInterfaceTest Habit h1 = fixtures.createEmptyHabit(); 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); habitList.update(h1); Habit h2 = fixtures.createShortHabit(); 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); habitList.update(h2); Habit h3 = fixtures.createLongHabit(); h3.setName("Meditate"); - h3.setDescription("Did meditate today?"); + h3.setQuestion("Did meditate today?"); + h3.setDescription("test description 3"); h3.setColor(10); habitList.update(h3); Habit h4 = fixtures.createEmptyHabit(); - h4.setName("Read books"); - h4.setDescription("Did you read books today?"); + h4.setName(EMPTY_DESCRIPTION_HABIT_NAME); + h4.setQuestion("Did you read books today?"); + h4.setDescription(""); h4.setColor(2); habitList.update(h4); } diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java index c636f682b..364166de7 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java @@ -52,7 +52,8 @@ public class HabitFixtures { Habit habit = modelFactory.buildHabit(); 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.setFrequency(Frequency.DAILY); habit.setId(id); @@ -81,7 +82,7 @@ public class HabitFixtures { Habit habit = modelFactory.buildHabit(); 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.setTargetType(Habit.AT_LEAST); habit.setTargetValue(200.0); @@ -103,7 +104,7 @@ public class HabitFixtures { Habit habit = modelFactory.buildHabit(); 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)); habitList.add(habit); diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java index 8901f177b..87f38a660 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java @@ -20,7 +20,6 @@ package org.isoron.uhabits.acceptance; import androidx.test.filters.*; -import androidx.test.runner.*; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -39,7 +38,16 @@ import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.*; public class HabitsTest extends BaseUserInterfaceTest { @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(); @@ -47,14 +55,16 @@ public class HabitsTest extends BaseUserInterfaceTest clickMenu(ADD); verifyShowsScreen(EDIT_HABIT); - typeName("Hello world"); + String testName = "Hello world"; + typeName(testName); typeQuestion("Did you say hello to the world today?"); + typeDescription(description); pickFrequency("Every week"); pickColor(5); clickSave(); verifyShowsScreen(LIST_HABITS); - verifyDisplaysText("Hello world"); + verifyDisplaysText(testName); } @Test @@ -81,7 +91,16 @@ public class HabitsTest extends BaseUserInterfaceTest } @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(); @@ -92,6 +111,7 @@ public class HabitsTest extends BaseUserInterfaceTest verifyShowsScreen(EDIT_HABIT); typeName("Take a walk"); typeQuestion("Did you take a walk today?"); + typeDescription(description); clickSave(); verifyShowsScreen(LIST_HABITS); @@ -174,4 +194,12 @@ public class HabitsTest extends BaseUserInterfaceTest verifyDisplaysText("Track time"); verifyDisplaysText("Wake up early"); } + + @Test + public void shouldHideNotesCard() throws Exception + { + launchApp(); + clickText(EMPTY_DESCRIPTION_HABIT_NAME); + verifyShowsScreen(SHOW_HABIT, false); + } } diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java index 967a6b70d..f7ff2119c 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java @@ -19,14 +19,16 @@ package org.isoron.uhabits.acceptance.steps; +import android.view.View; + import androidx.annotation.StringRes; import androidx.test.espresso.*; import androidx.test.espresso.contrib.*; import androidx.test.uiautomator.*; -import androidx.appcompat.widget.*; import androidx.recyclerview.widget.RecyclerView; +import org.hamcrest.Matcher; import org.isoron.uhabits.*; import org.isoron.uhabits.R; import org.isoron.uhabits.activities.habits.list.*; @@ -153,7 +155,11 @@ public class CommonSteps extends BaseUserInterfaceTest 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) { @@ -163,10 +169,14 @@ public class CommonSteps extends BaseUserInterfaceTest break; case SHOW_HABIT: + Matcher noteCardViewMatcher = notesCardVisibleExpected ? isDisplayed() : + withEffectiveVisibility(Visibility.GONE); onView(withId(R.id.subtitleCard)).check(matches(isDisplayed())); + onView(withId(R.id.notesCard)).check(matches(noteCardViewMatcher)); break; case EDIT_HABIT: + onView(withId(R.id.tvQuestion)).check(matches(isDisplayed())); onView(withId(R.id.tvDescription)).check(matches(isDisplayed())); break; } diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/EditHabitSteps.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/EditHabitSteps.java index 90293cc24..deddfbd1d 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/EditHabitSteps.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/EditHabitSteps.java @@ -55,7 +55,12 @@ public class EditHabitSteps 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() diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/NotesCardTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/NotesCardTest.java new file mode 100644 index 000000000..6f91bf4d6 --- /dev/null +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/NotesCardTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * 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 . + */ + +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"); + } +} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.java index 8c0f3763e..63aa74407 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.java @@ -49,7 +49,7 @@ public class SubtitleCardTest extends BaseViewTest habit = fixtures.createLongHabit(); habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY)); - view = (SubtitleCard) LayoutInflater + view = LayoutInflater .from(targetContext) .inflate(R.layout.show_habit, null) .findViewById(R.id.subtitleCard); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitDialog.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitDialog.java index 0a90f7aa4..1a951c0c2 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitDialog.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitDialog.java @@ -187,6 +187,7 @@ public class EditHabitDialog extends AppCompatDialogFragment habit.copyFrom(originalHabit); habit.setName(namePanel.getName()); habit.setDescription(namePanel.getDescription()); + habit.setQuestion(namePanel.getQuestion()); habit.setColor(namePanel.getColor()); habit.setReminder(reminderPanel.getReminder()); habit.setFrequency(frequencyPanel.getFrequency()); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/views/ExampleEditText.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/views/ExampleEditText.java index 276f0cfbe..a3e14387f 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/views/ExampleEditText.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/views/ExampleEditText.java @@ -24,6 +24,7 @@ import android.text.*; import android.util.*; import android.view.*; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatEditText; @@ -82,7 +83,7 @@ public class ExampleEditText extends AppCompatEditText updateText(); } - public void setRealText(String realText) + public void setRealText(@NonNull String realText) { this.realText = realText; updateText(); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/views/NameDescriptionPanel.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/views/NameDescriptionPanel.java index 5eb73a5e1..b08a55a47 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/views/NameDescriptionPanel.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/views/NameDescriptionPanel.java @@ -42,6 +42,9 @@ public class NameDescriptionPanel extends FrameLayout @BindView(R.id.tvName) EditText tvName; + @BindView(R.id.tvQuestion) + ExampleEditText tvQuestion; + @BindView(R.id.tvDescription) ExampleEditText tvDescription; @@ -79,6 +82,12 @@ public class NameDescriptionPanel extends FrameLayout return tvDescription.getRealText().trim(); } + @NonNull + public String getQuestion() + { + return tvQuestion.getRealText().trim(); + } + @NonNull public String getName() { @@ -90,12 +99,13 @@ public class NameDescriptionPanel extends FrameLayout Resources res = getResources(); if(habit.isNumerical()) - tvDescription.setExample(res.getString(R.string.example_question_numerical)); + tvQuestion.setExample(res.getString(R.string.example_question_numerical)); else - tvDescription.setExample(res.getString(R.string.example_question_boolean)); + tvQuestion.setExample(res.getString(R.string.example_question_boolean)); setColor(habit.getColor()); tvName.setText(habit.getName()); + tvQuestion.setRealText(habit.getQuestion()); tvDescription.setRealText(habit.getDescription()); } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitRootView.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitRootView.java index fc0b206fd..9c2963867 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitRootView.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitRootView.java @@ -21,6 +21,7 @@ package org.isoron.uhabits.activities.habits.show; import android.content.*; import android.os.*; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.widget.*; @@ -52,6 +53,12 @@ public class ShowHabitRootView extends BaseRootView @BindView(R.id.subtitleCard) SubtitleCard subtitleCard; + @BindView(R.id.notesCard) + NotesCard notesCard; + + @BindView(R.id.habitNotes) + TextView habitNotes; + @BindView(R.id.overviewCard) OverviewCard overviewCard; @@ -136,6 +143,7 @@ public class ShowHabitRootView extends BaseRootView private void initCards() { subtitleCard.setHabit(habit); + notesCard.setHabit(habit); overviewCard.setHabit(habit); scoreCard.setHabit(habit); historyCard.setHabit(habit); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt new file mode 100644 index 000000000..5e9d6864b --- /dev/null +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt @@ -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.") +} \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.java index ac8605862..4fc43031f 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.java @@ -59,12 +59,12 @@ public class SubtitleCard extends HabitCard questionLabel.setVisibility(VISIBLE); questionLabel.setTextColor(color); - questionLabel.setText(habit.getDescription()); + questionLabel.setText(habit.getQuestion()); frequencyLabel.setText(toText(habit.getFrequency())); if (habit.hasReminder()) updateReminderText(habit.getReminder()); - if (habit.getDescription().isEmpty()) questionLabel.setVisibility(GONE); + if (habit.getQuestion().isEmpty()) questionLabel.setVisibility(GONE); invalidate(); } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt index 3c1b9c220..3fff2b615 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt @@ -112,7 +112,7 @@ class AndroidNotificationTray val builder = NotificationCompat.Builder(context, REMINDERS_CHANNEL_ID) .setSmallIcon(R.drawable.ic_notification) .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)) .setDeleteIntent(pendingIntents.dismissNotification(habit)) .addAction(addRepetitionAction) diff --git a/android/uhabits-android/src/main/res/layout/edit_habit_name.xml b/android/uhabits-android/src/main/res/layout/edit_habit_name.xml index 70a8137b7..f926ac55d 100644 --- a/android/uhabits-android/src/main/res/layout/edit_habit_name.xml +++ b/android/uhabits-android/src/main/res/layout/edit_habit_name.xml @@ -1,5 +1,4 @@ - - - - - - - - - - - - - - - - - + android:layout_height="wrap_content" + android:minWidth="300dp"> + android:id="@+id/tilName" + android:layout_width="0dp" + android:layout_height="wrap_content" + app1:layout_constraintEnd_toStartOf="@+id/buttonPickColor" + app1:layout_constraintHorizontal_weight="6" + app1:layout_constraintStart_toStartOf="parent" + app1:layout_constraintTop_toTopOf="parent"> + + + + + + + + + + + + + + + + android:gravity="top" + app:example="@string/example_notes" /> - \ No newline at end of file + \ No newline at end of file diff --git a/android/uhabits-android/src/main/res/layout/show_habit_inner.xml b/android/uhabits-android/src/main/res/layout/show_habit_inner.xml index 55b66a6cc..3b92b3e26 100644 --- a/android/uhabits-android/src/main/res/layout/show_habit_inner.xml +++ b/android/uhabits-android/src/main/res/layout/show_habit_inner.xml @@ -38,6 +38,11 @@ android:id="@+id/subtitleCard" style="@style/ShowHabit.Subtitle"/> + + diff --git a/android/uhabits-android/src/main/res/layout/show_habit_notes.xml b/android/uhabits-android/src/main/res/layout/show_habit_notes.xml new file mode 100644 index 000000000..ce1da19b5 --- /dev/null +++ b/android/uhabits-android/src/main/res/layout/show_habit_notes.xml @@ -0,0 +1,35 @@ + + + + + + \ No newline at end of file diff --git a/android/uhabits-android/src/main/res/layout/show_habit_subtitle.xml b/android/uhabits-android/src/main/res/layout/show_habit_subtitle.xml index 4c57473c0..9533a5f54 100644 --- a/android/uhabits-android/src/main/res/layout/show_habit_subtitle.xml +++ b/android/uhabits-android/src/main/res/layout/show_habit_subtitle.xml @@ -18,7 +18,12 @@ ~ with this program. If not, see . --> - + + android:orientation="horizontal" + tools:visibility="visible"> + android:src="?iconFrequency" /> + android:textSize="@dimen/smallTextSize" /> + android:src="?iconReminder" /> + android:textSize="@dimen/smallTextSize" /> \ No newline at end of file diff --git a/android/uhabits-android/src/main/res/values/strings.xml b/android/uhabits-android/src/main/res/values/strings.xml index af088952a..d2273b13b 100644 --- a/android/uhabits-android/src/main/res/values/strings.xml +++ b/android/uhabits-android/src/main/res/values/strings.xml @@ -244,5 +244,7 @@ Makes widgets more transparent or more opaque in your home screen. First day of the week Have you completed this habit today? + Notes + You can put whatever you want here! \ No newline at end of file diff --git a/android/uhabits-core/build.gradle b/android/uhabits-core/build.gradle index 1537f0b7a..0e89a2eb7 100644 --- a/android/uhabits-core/build.gradle +++ b/android/uhabits-core/build.gradle @@ -1,5 +1,6 @@ apply plugin: 'idea' apply plugin: 'java' +apply plugin: 'kotlin' dependencies { annotationProcessor "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION" @@ -26,6 +27,7 @@ dependencies { implementation('com.opencsv:opencsv:3.10') { exclude group: 'commons-logging', module: 'commons-logging' } + implementation "org.jetbrains.kotlin:kotlin-stdlib:$KOTLIN_VERSION" } sourceCompatibility = "1.8" diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/Config.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/Config.java index ffb05939f..286755a33 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/Config.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/Config.java @@ -22,5 +22,5 @@ package org.isoron.uhabits.core; public class Config { public static final String DATABASE_FILENAME = "uhabits.db"; - public static int DATABASE_VERSION = 22; + public static int DATABASE_VERSION = 23; } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.java index 3873b4ad8..f2289af65 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.java @@ -87,7 +87,7 @@ public class HabitBullCSVImporter extends AbstractImporter { h = modelFactory.buildHabit(); h.setName(name); - h.setDescription(description); + h.setDescription(description == null ? "" : description); h.setFrequency(Frequency.DAILY); habitList.add(h); map.put(name, h); diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/RewireDBImporter.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/RewireDBImporter.java index 1f0299f40..ac0d83c79 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/RewireDBImporter.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/RewireDBImporter.java @@ -101,7 +101,7 @@ public class RewireDBImporter extends AbstractImporter Habit habit = modelFactory.buildHabit(); habit.setName(name); - habit.setDescription(description); + habit.setDescription(description == null ? "" : description); int periods[] = { 7, 31, 365 }; int numerator, denominator; diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/TickmateDBImporter.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/TickmateDBImporter.java index af7ecb993..e1a0f2508 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/TickmateDBImporter.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/TickmateDBImporter.java @@ -127,7 +127,7 @@ public class TickmateDBImporter extends AbstractImporter Habit habit = modelFactory.buildHabit(); habit.setName(name); - habit.setDescription(description); + habit.setDescription(description == null ? "" : description); habit.setFrequency(Frequency.DAILY); habitList.add(habit); diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Habit.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Habit.java index cee0dabcf..a290b56d9 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Habit.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Habit.java @@ -354,6 +354,15 @@ public class Habit data.position = newPosition; } + @NonNull + public String getQuestion() { + return data.question; + } + + public void setQuestion(@NonNull String question) { + data.question = question; + } + public static final class HabitData { @NonNull @@ -362,6 +371,9 @@ public class Habit @NonNull public String description; + @NonNull + public String question; + @NonNull public Frequency frequency; @@ -391,6 +403,7 @@ public class Habit this.type = YES_NO_HABIT; this.name = ""; this.description = ""; + this.question = ""; this.targetType = AT_LEAST; this.targetValue = 100; this.unit = ""; @@ -401,6 +414,7 @@ public class Habit { this.name = model.name; this.description = model.description; + this.question = model.question; this.frequency = model.frequency; this.color = model.color; this.archived = model.archived; @@ -427,6 +441,7 @@ public class Habit .append("unit", unit) .append("reminder", reminder) .append("position", position) + .append("question", question) .toString(); } @@ -451,6 +466,7 @@ public class Habit .append(unit, habitData.unit) .append(reminder, habitData.reminder) .append(position, habitData.position) + .append(question, habitData.question) .isEquals(); } @@ -469,6 +485,7 @@ public class Habit .append(unit) .append(reminder) .append(position) + .append(question) .toHashCode(); } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/HabitList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/HabitList.java index ae843e8da..84916f322 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/HabitList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/HabitList.java @@ -212,6 +212,7 @@ public abstract class HabitList implements Iterable String header[] = { "Position", "Name", + "Question", "Description", "NumRepetitions", "Interval", @@ -228,6 +229,7 @@ public abstract class HabitList implements Iterable String[] cols = { String.format("%03d", indexOf(habit) + 1), habit.getName(), + habit.getQuestion(), habit.getDescription(), Integer.toString(freq.getNumerator()), Integer.toString(freq.getDenominator()), diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.java index 29e7ffb5c..523da0542 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.java @@ -33,6 +33,9 @@ public class HabitRecord @Column public String description; + @Column + public String question; + @Column public String name; @@ -91,6 +94,7 @@ public class HabitRecord this.targetValue = model.getTargetValue(); this.unit = model.getUnit(); this.position = model.getPosition(); + this.question = model.getQuestion(); Frequency freq = model.getFrequency(); this.freqNum = freq.getNumerator(); @@ -113,6 +117,7 @@ public class HabitRecord habit.setId(this.id); habit.setName(this.name); habit.setDescription(this.description); + habit.setQuestion(this.question); habit.setFrequency(new Frequency(this.freqNum, this.freqDen)); habit.setColor(this.color); habit.setArchived(this.archived != 0); diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/test/HabitFixtures.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/test/HabitFixtures.java index 929367fdc..5e1e3edb5 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/test/HabitFixtures.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/test/HabitFixtures.java @@ -43,7 +43,7 @@ public class HabitFixtures { Habit habit = modelFactory.buildHabit(); habit.setName("Meditate"); - habit.setDescription("Did you meditate this morning?"); + habit.setQuestion("Did you meditate this morning?"); habit.setColor(3); habit.setFrequency(Frequency.DAILY); saveIfSQLite(habit); @@ -73,7 +73,7 @@ public class HabitFixtures Habit habit = modelFactory.buildHabit(); habit.setType(Habit.NUMBER_HABIT); 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.setTargetType(Habit.AT_LEAST); habit.setTargetValue(2.0); @@ -98,7 +98,7 @@ public class HabitFixtures Habit habit = modelFactory.buildHabit(); habit.setType(Habit.NUMBER_HABIT); 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.setTargetType(Habit.AT_LEAST); habit.setTargetValue(100); @@ -133,7 +133,7 @@ public class HabitFixtures { Habit habit = modelFactory.buildHabit(); 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)); saveIfSQLite(habit); diff --git a/android/uhabits-core/src/main/resources/migrations/23.sql b/android/uhabits-core/src/main/resources/migrations/23.sql new file mode 100644 index 000000000..1592c4e49 --- /dev/null +++ b/android/uhabits-core/src/main/resources/migrations/23.sql @@ -0,0 +1,5 @@ +alter table Habits add column question text; + +update Habits set question = description; + +update Habits set description = ""; \ No newline at end of file diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/BaseUnitTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/BaseUnitTest.java index 436e329e6..d16902678 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/BaseUnitTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/BaseUnitTest.java @@ -125,7 +125,7 @@ public class BaseUnitTest DriverManager.getConnection("jdbc:sqlite::memory:")); db.execute("pragma user_version=8;"); MigrationHelper helper = new MigrationHelper(db); - helper.migrateTo(21); + helper.migrateTo(23); return db; } catch (SQLException e) diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/database/migrations/Version22Test.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/database/migrations/Version22Test.java index 395f06c3f..ff7e0969c 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/database/migrations/Version22Test.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/database/migrations/Version22Test.java @@ -159,21 +159,4 @@ public class Version22Test extends BaseUnitTest db.execute("insert into repetitions(habit, timestamp, value)" + "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())); - } } diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/database/migrations/Version23Test.kt b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/database/migrations/Version23Test.kt new file mode 100644 index 000000000..6dc13cd8d --- /dev/null +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/database/migrations/Version23Test.kt @@ -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() + 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("")) + } + } +} \ No newline at end of file diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitListTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitListTest.java index 206caafe6..a7b490b24 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitListTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitListTest.java @@ -218,13 +218,15 @@ public class HabitListTest extends BaseUnitTest Habit h1 = fixtures.createEmptyHabit(); 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.setColor(3); Habit h2 = fixtures.createEmptyHabit(); 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.setColor(5); @@ -232,9 +234,9 @@ public class HabitListTest extends BaseUnitTest list.add(h2); String expectedCSV = - "Position,Name,Description,NumRepetitions,Interval,Color\n" + - "001,Meditate,Did you meditate this morning?,1,1,#FF8F00\n" + - "002,Wake up early,Did you wake up before 6am?,2,3,#AFB42B\n"; + "Position,Name,Question,Description,NumRepetitions,Interval,Color\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"; StringWriter writer = new StringWriter(); list.writeCSV(writer); diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitTest.java index f864703fb..89d39dce5 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitTest.java @@ -155,7 +155,7 @@ public class HabitTest extends BaseUnitTest " targetValue: 100.0, type: 0, unit: ," + " reminder: {hour: 22, minute: 30," + " days: {weekdays: [true,true,true,true,true,true,true]}}," + - " position: 0}}"; + " position: 0, question: }}"; assertThat(h.toString(), equalTo(expected)); } diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecordTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecordTest.java index 30b92af0a..e6b016a66 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecordTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecordTest.java @@ -36,7 +36,7 @@ public class HabitRecordTest extends BaseUnitTest { Habit original = modelFactory.buildHabit(); original.setName("Hello world"); - original.setDescription("Did you greet the world today?"); + original.setQuestion("Did you greet the world today?"); original.setColor(1); original.setArchived(true); original.setFrequency(Frequency.THREE_TIMES_PER_WEEK); @@ -58,7 +58,7 @@ public class HabitRecordTest extends BaseUnitTest { Habit original = modelFactory.buildHabit(); original.setName("Hello world"); - original.setDescription("Did you greet the world today?"); + original.setQuestion("Did you greet the world today?"); original.setColor(5); original.setArchived(false); original.setFrequency(Frequency.DAILY); diff --git a/android/uhabits-core/src/test/resources/databases/022.db b/android/uhabits-core/src/test/resources/databases/022.db new file mode 100644 index 000000000..01237dfc8 Binary files /dev/null and b/android/uhabits-core/src/test/resources/databases/022.db differ